Yicong-Huang commented on code in PR #4719:
URL: https://github.com/apache/texera/pull/4719#discussion_r3177442941
##########
amber/src/main/python/core/architecture/managers/test_executor_manager.py:
##########
@@ -246,3 +246,132 @@ def test_source_operator_mismatch_raises_error(self,
executor_manager):
language="python",
)
assert "SourceOperator API" in str(exc_info.value)
+
+
+REPLACEMENT_OPERATOR_CODE = """
+from pytexera import *
+
+class ReplacementOperator(UDFOperatorV2):
+ def process_tuple(self, tuple_: Tuple, port: int) ->
Iterator[Optional[TupleLike]]:
+ yield tuple_
+"""
+
+NO_OPERATOR_CODE = """
+def helper():
+ return 42
+"""
+
+TWO_OPERATORS_CODE = """
+from pytexera import *
+
+class FirstOperator(UDFOperatorV2):
+ def process_tuple(self, tuple_: Tuple, port: int) ->
Iterator[Optional[TupleLike]]:
+ yield tuple_
+
+class SecondOperator(UDFOperatorV2):
+ def process_tuple(self, tuple_: Tuple, port: int) ->
Iterator[Optional[TupleLike]]:
+ yield tuple_
+"""
+
+
+class TestUpdateExecutor:
+ """Test suite for ExecutorManager.update_executor.
+
+ Notes on test isolation: the existing TestExecutorManager fixture cannot
+ fully clean up the udf-vN modules it imports (its `hasattr(manager, "_fs")`
+ cleanup guard is buggy — the actual cached_property key is `fs`), so a
+ given udf-v1 module may already live in sys.modules with a path attached
+ to a previous test's tmp filesystem. These tests therefore avoid asserting
+ on attributes baked into a specific operator class and instead use
+ setattr/getattr-only semantics that hold regardless of which cached
+ module satisfies the import.
+ """
+
+ @pytest.fixture
+ def initialized_manager(self):
+ manager = ExecutorManager()
+ manager.initialize_executor(
+ code=SAMPLE_OPERATOR_CODE, is_source=False, language="python"
+ )
+ # Stamp custom attributes on the live instance so the dict-preservation
+ # check works even if the underlying class came from a cached module.
+ manager.executor.runtime_field = "set-after-init"
+ manager.executor.counter = 6
+ yield manager
+ manager.close()
+
+ def test_update_preserves_pre_update_dict_state(self, initialized_manager):
+ before = initialized_manager.executor
+ before_dict = dict(before.__dict__)
+
+ initialized_manager.update_executor(
+ code=REPLACEMENT_OPERATOR_CODE, is_source=False
+ )
+
+ # update_executor reuses the prior __dict__ on a freshly instantiated
+ # operator — verify both halves: a NEW instance, but the OLD state.
+ assert initialized_manager.executor is not before
+ assert initialized_manager.executor.runtime_field == "set-after-init"
+ assert initialized_manager.executor.counter == 6
+ for key, value in before_dict.items():
+ assert initialized_manager.executor.__dict__.get(key) == value
Review Comment:
Tightened in 0eef995912: the loop now asserts `key in after_dict` before
comparing the value, so a key that disappeared from `executor.__dict__` with an
expected value of `None` no longer false-passes via `dict.get()`'s default.
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]