This is an automated email from the ASF dual-hosted git repository.

Yicong-Huang pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/texera.git


The following commit(s) were added to refs/heads/main by this push:
     new b0ee3b72c3 refactor(pyamber): move tests to src/test/python to match 
Maven layout (#4945)
b0ee3b72c3 is described below

commit b0ee3b72c39dc7571bf39a7d1a2f81608a080ed0
Author: Yicong Huang <[email protected]>
AuthorDate: Tue May 5 17:19:31 2026 -0700

    refactor(pyamber): move tests to src/test/python to match Maven layout 
(#4945)
    
    ### What changes were proposed in this PR?
    
    Move Python tests from `amber/src/main/python/` (co-located with
    production) to `amber/src/test/python/` (Maven source-set sibling),
    aligning with the Scala layout already used by amber (`src/main/scala` +
    `src/test/scala`). `pyproject.toml` moves up to `amber/` so a single
    Python config sits at the module root.
    
    Side benefit: the runtime Docker images
    (`bin/computing-unit-master.dockerfile`,
    `bin/computing-unit-worker.dockerfile`) only `COPY src/main/python` into
    the production stage, so 48 test files no longer ship to production
    runtime images.
    
    ### Any related issues, documentation, discussions?
    
    Closes #4943.
    
    ### How was this PR tested?
    
    Local `pytest` from `amber/` collects 462 tests — same set as before.
    Ruff `check` and `format --check` both clean on `src/main/python` and
    `src/test/python`. Five `test_large_binary_manager` failures are
    pre-existing on `upstream/main` (S3 / boto setup, unrelated).
    
    ### Was this PR authored or co-authored using generative AI tooling?
    
    Generated-by: Claude Opus 4.7 (Claude Code)
---
 .github/labeler.yml                                     |  8 +++++---
 .github/workflows/build.yml                             |  6 +++---
 .github/workflows/required-checks.yml                   |  4 ++--
 .gitignore                                              |  3 +++
 amber/build.sbt                                         |  8 ++++----
 amber/{src/main/python => }/pyproject.toml              | 17 ++++++++++++++++-
 .../handlers/control/test_debug_command_handler.py      |  0
 .../control/test_evaluate_expression_handler.py         |  0
 .../control/test_replay_current_tuple_handler.py        |  0
 .../handlers/control/test_update_executor_handler.py    |  0
 .../managers/test_console_message_manager.py            |  0
 .../core/architecture/managers/test_debug_manager.py    |  0
 .../managers/test_embedded_control_message_manager.py   |  0
 .../architecture/managers/test_exception_manager.py     |  0
 .../core/architecture/managers/test_executor_manager.py |  0
 .../core/architecture/managers/test_pause_manager.py    |  0
 .../core/architecture/managers/test_state_manager.py    |  0
 .../managers/test_state_processing_manager.py           |  0
 .../architecture/managers/test_statistics_manager.py    |  0
 .../managers/test_tuple_processing_manager.py           |  0
 .../core/architecture/rpc/test_async_rpc_client.py      |  0
 .../architecture/sendsemantics/test_partitioners.py     |  0
 .../python/core/models/schema/test_schema.py            |  0
 .../{main => test}/python/core/models/test_operator.py  |  0
 .../src/{main => test}/python/core/models/test_state.py |  0
 .../src/{main => test}/python/core/models/test_table.py |  0
 .../src/{main => test}/python/core/models/test_tuple.py |  0
 .../python/core/models/type/test_large_binary.py        |  0
 .../python/core/proxy/test_proxy_client.py              |  4 ++--
 .../python/core/proxy/test_proxy_server.py              |  2 +-
 .../python/core/runnables/test_console_message.py       |  0
 .../python/core/runnables/test_data_processor.py        |  0
 .../python/core/runnables/test_heartbeat.py             |  0
 .../python/core/runnables/test_main_loop.py             |  0
 .../python/core/runnables/test_network_receiver.py      |  0
 .../python/core/runnables/test_network_sender.py        |  0
 .../core/storage/iceberg/test_iceberg_document.py       |  9 +++++++--
 .../core/storage/iceberg/test_iceberg_utils_catalog.py  |  0
 .../storage/iceberg/test_iceberg_utils_large_binary.py  |  0
 .../core/util/console_message/test_replace_print.py     |  0
 .../python/core/util/customized_queue/test_inner.py     |  0
 .../test_linked_blocking_multi_queue.py                 |  0
 .../expression_evaluator/test_expression_evaluator.py   |  2 +-
 .../python/core/util/thread/test_atomic.py              |  0
 .../core/util/virtual_identity/test_virtual_identity.py |  0
 .../pytexera/storage/test_dataset_file_document.py      |  0
 .../pytexera/storage/test_large_binary_input_stream.py  |  0
 .../pytexera/storage/test_large_binary_manager.py       |  0
 .../pytexera/storage/test_large_binary_output_stream.py |  0
 .../pytexera/udf/examples/test_count_batch_operator.py  |  2 +-
 .../python/pytexera/udf/examples/test_echo_operator.py  |  2 +-
 .../pytexera/udf/examples/test_echo_table_operator.py   |  2 +-
 .../udf/examples/test_generator_operator_binary.py      |  2 +-
 .../udf/examples/test_generator_operator_integer.py     |  2 +-
 bin/fix-format.sh                                       | 11 ++++++-----
 55 files changed, 55 insertions(+), 29 deletions(-)

diff --git a/.github/labeler.yml b/.github/labeler.yml
index 5a1b2db0d8..d0973255b1 100644
--- a/.github/labeler.yml
+++ b/.github/labeler.yml
@@ -46,9 +46,9 @@ agent-service:
 
 engine:
   # Non-Python, non-integration parts of amber/. Pure Python changes
-  # under amber/src/main/python/** intentionally fall through to the
-  # `python` label (which the labeler also matches via **/*.py), so
-  # they only trigger the python + amber-integration stacks rather
+  # under amber/src/{main,test}/python/** intentionally fall through to
+  # the `python` label (which the labeler also matches via **/*.py),
+  # so they only trigger the python + amber-integration stacks rather
   # than the full Scala-only `amber` stack. Integration specs live
   # under amber/src/test/integration/** (added to sbt's Test sources
   # via amber/build.sbt) and are caught by the `amber-integration`
@@ -88,6 +88,8 @@ python:
   - changed-files:
       - any-glob-to-any-file:
           - 'amber/src/main/python/**'
+          - 'amber/src/test/python/**'
+          - 'amber/pyproject.toml'
           - '**/*.py'
           - '**/requirements.txt'
           - '**/*-requirements.txt'
diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
index 06be31230e..eede7eba6a 100644
--- a/.github/workflows/build.yml
+++ b/.github/workflows/build.yml
@@ -505,7 +505,7 @@ jobs:
           PGPASSWORD: postgres
       - name: Lint with Ruff
         run: |
-          cd amber/src/main/python && ruff check . && ruff format --check .
+          cd amber && ruff check src/main/python src/test/python && ruff 
format --check src/main/python src/test/python
       - name: Install dev dependencies
         # Test-only deps live in amber/dev-requirements.txt and are
         # installed after the LICENSE-binary snapshot above so they never
@@ -516,13 +516,13 @@ jobs:
           if [ -f amber/dev-requirements.txt ]; then uv pip install --system 
-r amber/dev-requirements.txt; fi
       - name: Test with pytest
         run: |
-          cd amber/src/main/python && pytest --cov=. --cov-report=xml -sv
+          cd amber && pytest --cov=src/main/python --cov-report=xml -sv
       - name: Upload python coverage to Codecov
         if: matrix.python-version == '3.12' && always()
         uses: codecov/codecov-action@75cd11691c0faa626561e295848008c8a7dddffe 
# v5.5.4
         with:
           token: ${{ secrets.CODECOV_TOKEN }}
-          files: ./amber/src/main/python/coverage.xml
+          files: ./amber/coverage.xml
           flags: python
           fail_ci_if_error: false
 
diff --git a/.github/workflows/required-checks.yml 
b/.github/workflows/required-checks.yml
index e7b8968ca4..54c8600638 100644
--- a/.github/workflows/required-checks.yml
+++ b/.github/workflows/required-checks.yml
@@ -137,8 +137,8 @@ jobs:
             // amber-integration runs the Scala tests tagged
             // @org.apache.texera.amber.tags.IntegrationTest (e2e specs that
             // spawn Python UDF workers). The labeler attaches `python` to
-            // any *.py change (including amber/src/main/python/**), so
-            // `engine` does not need to fire the python stack itself —
+            // any *.py change (including amber/src/{main,test}/python/**),
+            // so `engine` does not need to fire the python stack itself —
             // pure-Python amber changes pick up `python` directly. The
             // `amber-integration` label catches *IntegrationSpec.scala
             // edits so a test-only change does not trigger the full
diff --git a/.gitignore b/.gitignore
index d283fc7013..8da9edd67b 100644
--- a/.gitignore
+++ b/.gitignore
@@ -52,6 +52,9 @@ __pycache__/
 *$py.class
 .ipynb_checkpoints
 .pytype/
+.coverage
+coverage.xml
+.pytest_cache/
 
 # Ignoring python generated files
 *.model
diff --git a/amber/build.sbt b/amber/build.sbt
index 6147ba8e25..1f363e73e9 100644
--- a/amber/build.sbt
+++ b/amber/build.sbt
@@ -56,10 +56,10 @@ Compile / unmanagedSourceDirectories += baseDirectory.value 
/ "src" / "main" / "
 
 // `amber/src/test/integration` holds Scala specs that exercise both
 // Scala and Python end-to-end (tagged 
@org.apache.texera.amber.tags.IntegrationTest).
-// Sits next to `src/test/scala` and `src/test/java`; a future 
`src/test/python`
-// can drop in the same way. Adding it to Test/unmanagedSourceDirectories means
-// scalafmtCheckAll / scalafixAll --check naturally cover these sources, and
-// the AMBER_TEST_FILTER env var below routes which tagged subset runs.
+// Sits next to `src/test/scala`, `src/test/java`, and `src/test/python`.
+// Adding it to Test/unmanagedSourceDirectories means scalafmtCheckAll /
+// scalafixAll --check naturally cover these sources, and the
+// AMBER_TEST_FILTER env var below routes which tagged subset runs.
 Test / unmanagedSourceDirectories += baseDirectory.value / "src" / "test" / 
"integration"
 
 // Test-filter switch driven by the AMBER_TEST_FILTER env var so the
diff --git a/amber/src/main/python/pyproject.toml b/amber/pyproject.toml
similarity index 53%
rename from amber/src/main/python/pyproject.toml
rename to amber/pyproject.toml
index 72bfeb5724..46f8c55db6 100644
--- a/amber/src/main/python/pyproject.toml
+++ b/amber/pyproject.toml
@@ -24,4 +24,19 @@ extend-exclude = ["proto"]
 ignore = ["F403", "F405", "E203"]
 
 [tool.ruff.lint.mccabe]
-max-complexity = 10
\ No newline at end of file
+max-complexity = 10
+
+# Layout follows the Maven source-set convention used by Scala
+# (`src/main/scala` + `src/test/scala`): production code lives in
+# `src/main/python` and tests in `src/test/python`. Pytest is invoked
+# from `amber/`, so `pythonpath = ["src/main/python"]` keeps
+# `from core.x import y` and `from pytexera.x import y` working.
+[tool.pytest.ini_options]
+pythonpath = ["src/main/python"]
+testpaths = ["src/test/python"]
+# `importlib` import mode loads each test module by file path without
+# inserting it into a parent package, so `src/test/python` doesn't need
+# to mirror `src/main/python`'s __init__.py layout to avoid duplicate
+# package names. Required for src-style test layouts per the pytest
+# docs (https://docs.pytest.org/en/stable/explanation/goodpractices.html).
+addopts = "--import-mode=importlib"
\ No newline at end of file
diff --git 
a/amber/src/main/python/core/architecture/handlers/control/test_debug_command_handler.py
 
b/amber/src/test/python/core/architecture/handlers/control/test_debug_command_handler.py
similarity index 100%
rename from 
amber/src/main/python/core/architecture/handlers/control/test_debug_command_handler.py
rename to 
amber/src/test/python/core/architecture/handlers/control/test_debug_command_handler.py
diff --git 
a/amber/src/main/python/core/architecture/handlers/control/test_evaluate_expression_handler.py
 
b/amber/src/test/python/core/architecture/handlers/control/test_evaluate_expression_handler.py
similarity index 100%
rename from 
amber/src/main/python/core/architecture/handlers/control/test_evaluate_expression_handler.py
rename to 
amber/src/test/python/core/architecture/handlers/control/test_evaluate_expression_handler.py
diff --git 
a/amber/src/main/python/core/architecture/handlers/control/test_replay_current_tuple_handler.py
 
b/amber/src/test/python/core/architecture/handlers/control/test_replay_current_tuple_handler.py
similarity index 100%
rename from 
amber/src/main/python/core/architecture/handlers/control/test_replay_current_tuple_handler.py
rename to 
amber/src/test/python/core/architecture/handlers/control/test_replay_current_tuple_handler.py
diff --git 
a/amber/src/main/python/core/architecture/handlers/control/test_update_executor_handler.py
 
b/amber/src/test/python/core/architecture/handlers/control/test_update_executor_handler.py
similarity index 100%
rename from 
amber/src/main/python/core/architecture/handlers/control/test_update_executor_handler.py
rename to 
amber/src/test/python/core/architecture/handlers/control/test_update_executor_handler.py
diff --git 
a/amber/src/main/python/core/architecture/managers/test_console_message_manager.py
 
b/amber/src/test/python/core/architecture/managers/test_console_message_manager.py
similarity index 100%
rename from 
amber/src/main/python/core/architecture/managers/test_console_message_manager.py
rename to 
amber/src/test/python/core/architecture/managers/test_console_message_manager.py
diff --git 
a/amber/src/main/python/core/architecture/managers/test_debug_manager.py 
b/amber/src/test/python/core/architecture/managers/test_debug_manager.py
similarity index 100%
rename from 
amber/src/main/python/core/architecture/managers/test_debug_manager.py
rename to amber/src/test/python/core/architecture/managers/test_debug_manager.py
diff --git 
a/amber/src/main/python/core/architecture/managers/test_embedded_control_message_manager.py
 
b/amber/src/test/python/core/architecture/managers/test_embedded_control_message_manager.py
similarity index 100%
rename from 
amber/src/main/python/core/architecture/managers/test_embedded_control_message_manager.py
rename to 
amber/src/test/python/core/architecture/managers/test_embedded_control_message_manager.py
diff --git 
a/amber/src/main/python/core/architecture/managers/test_exception_manager.py 
b/amber/src/test/python/core/architecture/managers/test_exception_manager.py
similarity index 100%
rename from 
amber/src/main/python/core/architecture/managers/test_exception_manager.py
rename to 
amber/src/test/python/core/architecture/managers/test_exception_manager.py
diff --git 
a/amber/src/main/python/core/architecture/managers/test_executor_manager.py 
b/amber/src/test/python/core/architecture/managers/test_executor_manager.py
similarity index 100%
rename from 
amber/src/main/python/core/architecture/managers/test_executor_manager.py
rename to 
amber/src/test/python/core/architecture/managers/test_executor_manager.py
diff --git 
a/amber/src/main/python/core/architecture/managers/test_pause_manager.py 
b/amber/src/test/python/core/architecture/managers/test_pause_manager.py
similarity index 100%
rename from 
amber/src/main/python/core/architecture/managers/test_pause_manager.py
rename to amber/src/test/python/core/architecture/managers/test_pause_manager.py
diff --git 
a/amber/src/main/python/core/architecture/managers/test_state_manager.py 
b/amber/src/test/python/core/architecture/managers/test_state_manager.py
similarity index 100%
rename from 
amber/src/main/python/core/architecture/managers/test_state_manager.py
rename to amber/src/test/python/core/architecture/managers/test_state_manager.py
diff --git 
a/amber/src/main/python/core/architecture/managers/test_state_processing_manager.py
 
b/amber/src/test/python/core/architecture/managers/test_state_processing_manager.py
similarity index 100%
rename from 
amber/src/main/python/core/architecture/managers/test_state_processing_manager.py
rename to 
amber/src/test/python/core/architecture/managers/test_state_processing_manager.py
diff --git 
a/amber/src/main/python/core/architecture/managers/test_statistics_manager.py 
b/amber/src/test/python/core/architecture/managers/test_statistics_manager.py
similarity index 100%
rename from 
amber/src/main/python/core/architecture/managers/test_statistics_manager.py
rename to 
amber/src/test/python/core/architecture/managers/test_statistics_manager.py
diff --git 
a/amber/src/main/python/core/architecture/managers/test_tuple_processing_manager.py
 
b/amber/src/test/python/core/architecture/managers/test_tuple_processing_manager.py
similarity index 100%
rename from 
amber/src/main/python/core/architecture/managers/test_tuple_processing_manager.py
rename to 
amber/src/test/python/core/architecture/managers/test_tuple_processing_manager.py
diff --git 
a/amber/src/main/python/core/architecture/rpc/test_async_rpc_client.py 
b/amber/src/test/python/core/architecture/rpc/test_async_rpc_client.py
similarity index 100%
rename from amber/src/main/python/core/architecture/rpc/test_async_rpc_client.py
rename to amber/src/test/python/core/architecture/rpc/test_async_rpc_client.py
diff --git 
a/amber/src/main/python/core/architecture/sendsemantics/test_partitioners.py 
b/amber/src/test/python/core/architecture/sendsemantics/test_partitioners.py
similarity index 100%
rename from 
amber/src/main/python/core/architecture/sendsemantics/test_partitioners.py
rename to 
amber/src/test/python/core/architecture/sendsemantics/test_partitioners.py
diff --git a/amber/src/main/python/core/models/schema/test_schema.py 
b/amber/src/test/python/core/models/schema/test_schema.py
similarity index 100%
rename from amber/src/main/python/core/models/schema/test_schema.py
rename to amber/src/test/python/core/models/schema/test_schema.py
diff --git a/amber/src/main/python/core/models/test_operator.py 
b/amber/src/test/python/core/models/test_operator.py
similarity index 100%
rename from amber/src/main/python/core/models/test_operator.py
rename to amber/src/test/python/core/models/test_operator.py
diff --git a/amber/src/main/python/core/models/test_state.py 
b/amber/src/test/python/core/models/test_state.py
similarity index 100%
rename from amber/src/main/python/core/models/test_state.py
rename to amber/src/test/python/core/models/test_state.py
diff --git a/amber/src/main/python/core/models/test_table.py 
b/amber/src/test/python/core/models/test_table.py
similarity index 100%
rename from amber/src/main/python/core/models/test_table.py
rename to amber/src/test/python/core/models/test_table.py
diff --git a/amber/src/main/python/core/models/test_tuple.py 
b/amber/src/test/python/core/models/test_tuple.py
similarity index 100%
rename from amber/src/main/python/core/models/test_tuple.py
rename to amber/src/test/python/core/models/test_tuple.py
diff --git a/amber/src/main/python/core/models/type/test_large_binary.py 
b/amber/src/test/python/core/models/type/test_large_binary.py
similarity index 100%
rename from amber/src/main/python/core/models/type/test_large_binary.py
rename to amber/src/test/python/core/models/type/test_large_binary.py
diff --git a/amber/src/main/python/core/proxy/test_proxy_client.py 
b/amber/src/test/python/core/proxy/test_proxy_client.py
similarity index 98%
rename from amber/src/main/python/core/proxy/test_proxy_client.py
rename to amber/src/test/python/core/proxy/test_proxy_client.py
index b28b2cfe99..891c2fda75 100644
--- a/amber/src/main/python/core/proxy/test_proxy_client.py
+++ b/amber/src/test/python/core/proxy/test_proxy_client.py
@@ -20,8 +20,8 @@ from pandas import DataFrame
 from pyarrow import ArrowNotImplementedError, Table
 from queue import Queue
 
-from .proxy_client import ProxyClient
-from .proxy_server import ProxyServer
+from core.proxy.proxy_client import ProxyClient
+from core.proxy.proxy_server import ProxyServer
 
 
 class TestProxyClient:
diff --git a/amber/src/main/python/core/proxy/test_proxy_server.py 
b/amber/src/test/python/core/proxy/test_proxy_server.py
similarity index 98%
rename from amber/src/main/python/core/proxy/test_proxy_server.py
rename to amber/src/test/python/core/proxy/test_proxy_server.py
index a4a422e16f..22aec0cc69 100644
--- a/amber/src/main/python/core/proxy/test_proxy_server.py
+++ b/amber/src/test/python/core/proxy/test_proxy_server.py
@@ -18,7 +18,7 @@
 import pytest
 from pyarrow.flight import Action
 
-from .proxy_server import ProxyServer
+from core.proxy.proxy_server import ProxyServer
 
 
 class TestProxyServer:
diff --git a/amber/src/main/python/core/runnables/test_console_message.py 
b/amber/src/test/python/core/runnables/test_console_message.py
similarity index 100%
rename from amber/src/main/python/core/runnables/test_console_message.py
rename to amber/src/test/python/core/runnables/test_console_message.py
diff --git a/amber/src/main/python/core/runnables/test_data_processor.py 
b/amber/src/test/python/core/runnables/test_data_processor.py
similarity index 100%
rename from amber/src/main/python/core/runnables/test_data_processor.py
rename to amber/src/test/python/core/runnables/test_data_processor.py
diff --git a/amber/src/main/python/core/runnables/test_heartbeat.py 
b/amber/src/test/python/core/runnables/test_heartbeat.py
similarity index 100%
rename from amber/src/main/python/core/runnables/test_heartbeat.py
rename to amber/src/test/python/core/runnables/test_heartbeat.py
diff --git a/amber/src/main/python/core/runnables/test_main_loop.py 
b/amber/src/test/python/core/runnables/test_main_loop.py
similarity index 100%
rename from amber/src/main/python/core/runnables/test_main_loop.py
rename to amber/src/test/python/core/runnables/test_main_loop.py
diff --git a/amber/src/main/python/core/runnables/test_network_receiver.py 
b/amber/src/test/python/core/runnables/test_network_receiver.py
similarity index 100%
rename from amber/src/main/python/core/runnables/test_network_receiver.py
rename to amber/src/test/python/core/runnables/test_network_receiver.py
diff --git a/amber/src/main/python/core/runnables/test_network_sender.py 
b/amber/src/test/python/core/runnables/test_network_sender.py
similarity index 100%
rename from amber/src/main/python/core/runnables/test_network_sender.py
rename to amber/src/test/python/core/runnables/test_network_sender.py
diff --git 
a/amber/src/main/python/core/storage/iceberg/test_iceberg_document.py 
b/amber/src/test/python/core/storage/iceberg/test_iceberg_document.py
similarity index 96%
rename from amber/src/main/python/core/storage/iceberg/test_iceberg_document.py
rename to amber/src/test/python/core/storage/iceberg/test_iceberg_document.py
index 9b374f7d5c..a218c64a2d 100644
--- a/amber/src/main/python/core/storage/iceberg/test_iceberg_document.py
+++ b/amber/src/test/python/core/storage/iceberg/test_iceberg_document.py
@@ -18,6 +18,7 @@
 import datetime
 import pytest
 import random
+import tempfile
 import uuid
 from concurrent.futures import as_completed
 from concurrent.futures.thread import ThreadPoolExecutor
@@ -35,7 +36,11 @@ from proto.org.apache.texera.amber.core import (
     PhysicalOpIdentity,
 )
 
-# Hardcoded storage config only for test purposes.
+# Hardcoded storage config only for test purposes. The iceberg warehouse
+# directory must be a writable absolute path; using `tempfile.mkdtemp()`
+# avoids depending on pytest's cwd (an earlier `"../../../../../../amber/
+# user-resources/..."` value silently relied on CWD = amber/src/main/python
+# and broke when the cwd moved up to amber/).
 StorageConfig.initialize(
     catalog_type="postgres",
     postgres_uri_without_scheme="localhost:5432/texera_iceberg_catalog",
@@ -44,7 +49,7 @@ StorageConfig.initialize(
     rest_catalog_uri="http://localhost:8181/catalog/";,
     rest_catalog_warehouse_name="texera",
     table_result_namespace="operator-port-result",
-    directory_path="../../../../../../amber/user-resources/workflow-results",
+    directory_path=tempfile.mkdtemp(prefix="texera-iceberg-warehouse-"),
     commit_batch_size=4096,
     s3_endpoint="http://localhost:9000";,
     s3_region="us-east-1",
diff --git 
a/amber/src/main/python/core/storage/iceberg/test_iceberg_utils_catalog.py 
b/amber/src/test/python/core/storage/iceberg/test_iceberg_utils_catalog.py
similarity index 100%
rename from 
amber/src/main/python/core/storage/iceberg/test_iceberg_utils_catalog.py
rename to 
amber/src/test/python/core/storage/iceberg/test_iceberg_utils_catalog.py
diff --git 
a/amber/src/main/python/core/storage/iceberg/test_iceberg_utils_large_binary.py 
b/amber/src/test/python/core/storage/iceberg/test_iceberg_utils_large_binary.py
similarity index 100%
rename from 
amber/src/main/python/core/storage/iceberg/test_iceberg_utils_large_binary.py
rename to 
amber/src/test/python/core/storage/iceberg/test_iceberg_utils_large_binary.py
diff --git 
a/amber/src/main/python/core/util/console_message/test_replace_print.py 
b/amber/src/test/python/core/util/console_message/test_replace_print.py
similarity index 100%
rename from 
amber/src/main/python/core/util/console_message/test_replace_print.py
rename to amber/src/test/python/core/util/console_message/test_replace_print.py
diff --git a/amber/src/main/python/core/util/customized_queue/test_inner.py 
b/amber/src/test/python/core/util/customized_queue/test_inner.py
similarity index 100%
rename from amber/src/main/python/core/util/customized_queue/test_inner.py
rename to amber/src/test/python/core/util/customized_queue/test_inner.py
diff --git 
a/amber/src/main/python/core/util/customized_queue/test_linked_blocking_multi_queue.py
 
b/amber/src/test/python/core/util/customized_queue/test_linked_blocking_multi_queue.py
similarity index 100%
rename from 
amber/src/main/python/core/util/customized_queue/test_linked_blocking_multi_queue.py
rename to 
amber/src/test/python/core/util/customized_queue/test_linked_blocking_multi_queue.py
diff --git 
a/amber/src/main/python/core/util/expression_evaluator/test_expression_evaluator.py
 
b/amber/src/test/python/core/util/expression_evaluator/test_expression_evaluator.py
similarity index 99%
rename from 
amber/src/main/python/core/util/expression_evaluator/test_expression_evaluator.py
rename to 
amber/src/test/python/core/util/expression_evaluator/test_expression_evaluator.py
index 19340bdccd..729569f327 100644
--- 
a/amber/src/main/python/core/util/expression_evaluator/test_expression_evaluator.py
+++ 
b/amber/src/test/python/core/util/expression_evaluator/test_expression_evaluator.py
@@ -201,7 +201,7 @@ class TestExpressionEvaluator:
                 expression="a",
                 value_ref="a",
                 value_str=(
-                    
"<core.util.expression_evaluator.test_expression_evaluator."
+                    f"<{A.__module__}."
                     
"TestExpressionEvaluator.test_evaluate_object_expression.<locals>.A"
                     f" object at {hex(id(a))}>"
                 ),
diff --git a/amber/src/main/python/core/util/thread/test_atomic.py 
b/amber/src/test/python/core/util/thread/test_atomic.py
similarity index 100%
rename from amber/src/main/python/core/util/thread/test_atomic.py
rename to amber/src/test/python/core/util/thread/test_atomic.py
diff --git 
a/amber/src/main/python/core/util/virtual_identity/test_virtual_identity.py 
b/amber/src/test/python/core/util/virtual_identity/test_virtual_identity.py
similarity index 100%
rename from 
amber/src/main/python/core/util/virtual_identity/test_virtual_identity.py
rename to 
amber/src/test/python/core/util/virtual_identity/test_virtual_identity.py
diff --git 
a/amber/src/main/python/pytexera/storage/test_dataset_file_document.py 
b/amber/src/test/python/pytexera/storage/test_dataset_file_document.py
similarity index 100%
rename from amber/src/main/python/pytexera/storage/test_dataset_file_document.py
rename to amber/src/test/python/pytexera/storage/test_dataset_file_document.py
diff --git 
a/amber/src/main/python/pytexera/storage/test_large_binary_input_stream.py 
b/amber/src/test/python/pytexera/storage/test_large_binary_input_stream.py
similarity index 100%
rename from 
amber/src/main/python/pytexera/storage/test_large_binary_input_stream.py
rename to 
amber/src/test/python/pytexera/storage/test_large_binary_input_stream.py
diff --git 
a/amber/src/main/python/pytexera/storage/test_large_binary_manager.py 
b/amber/src/test/python/pytexera/storage/test_large_binary_manager.py
similarity index 100%
rename from amber/src/main/python/pytexera/storage/test_large_binary_manager.py
rename to amber/src/test/python/pytexera/storage/test_large_binary_manager.py
diff --git 
a/amber/src/main/python/pytexera/storage/test_large_binary_output_stream.py 
b/amber/src/test/python/pytexera/storage/test_large_binary_output_stream.py
similarity index 100%
rename from 
amber/src/main/python/pytexera/storage/test_large_binary_output_stream.py
rename to 
amber/src/test/python/pytexera/storage/test_large_binary_output_stream.py
diff --git 
a/amber/src/main/python/pytexera/udf/examples/test_count_batch_operator.py 
b/amber/src/test/python/pytexera/udf/examples/test_count_batch_operator.py
similarity index 98%
rename from 
amber/src/main/python/pytexera/udf/examples/test_count_batch_operator.py
rename to 
amber/src/test/python/pytexera/udf/examples/test_count_batch_operator.py
index 9ab084a405..4721861682 100644
--- a/amber/src/main/python/pytexera/udf/examples/test_count_batch_operator.py
+++ b/amber/src/test/python/pytexera/udf/examples/test_count_batch_operator.py
@@ -20,7 +20,7 @@ import pytest
 from collections import deque
 
 from pytexera import *
-from .count_batch_operator import CountBatchOperator
+from pytexera.udf.examples.count_batch_operator import CountBatchOperator
 
 
 class TestCountBatchOperator:
diff --git a/amber/src/main/python/pytexera/udf/examples/test_echo_operator.py 
b/amber/src/test/python/pytexera/udf/examples/test_echo_operator.py
similarity index 95%
rename from amber/src/main/python/pytexera/udf/examples/test_echo_operator.py
rename to amber/src/test/python/pytexera/udf/examples/test_echo_operator.py
index a70b8a0e7c..7741272594 100644
--- a/amber/src/main/python/pytexera/udf/examples/test_echo_operator.py
+++ b/amber/src/test/python/pytexera/udf/examples/test_echo_operator.py
@@ -18,7 +18,7 @@
 import pytest
 
 from pytexera import Tuple
-from .echo_operator import EchoOperator
+from pytexera.udf.examples.echo_operator import EchoOperator
 
 
 class TestEchoOperator:
diff --git 
a/amber/src/main/python/pytexera/udf/examples/test_echo_table_operator.py 
b/amber/src/test/python/pytexera/udf/examples/test_echo_table_operator.py
similarity index 95%
rename from 
amber/src/main/python/pytexera/udf/examples/test_echo_table_operator.py
rename to 
amber/src/test/python/pytexera/udf/examples/test_echo_table_operator.py
index d619f53a66..105308c278 100644
--- a/amber/src/main/python/pytexera/udf/examples/test_echo_table_operator.py
+++ b/amber/src/test/python/pytexera/udf/examples/test_echo_table_operator.py
@@ -20,7 +20,7 @@ from collections import deque
 
 from core.models.table import all_output_to_tuple
 from pytexera import Tuple
-from .echo_table_operator import EchoTableOperator
+from pytexera.udf.examples.echo_table_operator import EchoTableOperator
 
 
 class TestEchoTableOperator:
diff --git 
a/amber/src/main/python/pytexera/udf/examples/test_generator_operator_binary.py 
b/amber/src/test/python/pytexera/udf/examples/test_generator_operator_binary.py
similarity index 93%
rename from 
amber/src/main/python/pytexera/udf/examples/test_generator_operator_binary.py
rename to 
amber/src/test/python/pytexera/udf/examples/test_generator_operator_binary.py
index 4c7e5d8b40..2d19575d2b 100644
--- 
a/amber/src/main/python/pytexera/udf/examples/test_generator_operator_binary.py
+++ 
b/amber/src/test/python/pytexera/udf/examples/test_generator_operator_binary.py
@@ -18,7 +18,7 @@
 import pytest
 
 from pytexera import Tuple
-from .generator_operator_binary import GeneratorOperatorBinary
+from pytexera.udf.examples.generator_operator_binary import 
GeneratorOperatorBinary
 
 
 class TestEchoOperator:
diff --git 
a/amber/src/main/python/pytexera/udf/examples/test_generator_operator_integer.py
 
b/amber/src/test/python/pytexera/udf/examples/test_generator_operator_integer.py
similarity index 93%
rename from 
amber/src/main/python/pytexera/udf/examples/test_generator_operator_integer.py
rename to 
amber/src/test/python/pytexera/udf/examples/test_generator_operator_integer.py
index 3ab1906462..dc50ba0329 100644
--- 
a/amber/src/main/python/pytexera/udf/examples/test_generator_operator_integer.py
+++ 
b/amber/src/test/python/pytexera/udf/examples/test_generator_operator_integer.py
@@ -18,7 +18,7 @@
 import pytest
 
 from pytexera import Tuple
-from .generator_operator_integer import GeneratorOperatorInteger
+from pytexera.udf.examples.generator_operator_integer import 
GeneratorOperatorInteger
 
 
 class TestEchoOperator:
diff --git a/bin/fix-format.sh b/bin/fix-format.sh
index 23a53ac8da..e2cb90a1b6 100755
--- a/bin/fix-format.sh
+++ b/bin/fix-format.sh
@@ -42,10 +42,11 @@ fi
 
 # --- Key directories ---
 FRONTEND_DIR="$TEXERA_HOME/frontend"
-AMBER_PY_DIR="$TEXERA_HOME/amber/src/main/python"
+AMBER_DIR="$TEXERA_HOME/amber"
 
 [[ -d "$FRONTEND_DIR" ]] || { tx_error "Frontend directory not found: 
$FRONTEND_DIR"; exit 1; }
-[[ -d "$AMBER_PY_DIR"  ]] || { tx_error "Amber Python directory not found: 
$AMBER_PY_DIR"; exit 1; }
+[[ -d "$AMBER_DIR/src/main/python"  ]] || { tx_error "Amber Python directory 
not found: $AMBER_DIR/src/main/python"; exit 1; }
+[[ -d "$AMBER_DIR/src/test/python"  ]] || { tx_error "Amber Python test 
directory not found: $AMBER_DIR/src/test/python"; exit 1; }
 
 # --- Argument parsing ---
 TARGET="${1:-all}"
@@ -95,14 +96,14 @@ fi
 
 # --- 3) Python formatting ---
 if $run_python; then
-  tx_info "Running ruff in amber/src/main/python..."
+  tx_info "Running ruff in amber/src/{main,test}/python..."
   if ! command -v ruff >/dev/null 2>&1; then
     tx_error "ruff not found. Install with: pip install ruff"
     exit 1
   fi
   (
-    cd "$AMBER_PY_DIR"
-    ruff format .
+    cd "$AMBER_DIR"
+    ruff format src/main/python src/test/python
   )
   tx_success "Python formatting completed."
 fi

Reply via email to