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 3344022f6f fix: SourceOperator is_source default broken by name
mangling (#5007)
3344022f6f is described below
commit 3344022f6f6646ddc66bf7b25e51e8525779f260
Author: Matthew B. <[email protected]>
AuthorDate: Sun May 10 17:13:31 2026 -0700
fix: SourceOperator is_source default broken by name mangling (#5007)
### What changes were proposed in this PR?
Fixes a name-mangling bug in
amber/src/main/python/core/models/operator.py.
Operator declared __internal_is_source (double underscore), which Python
rewrites per class. So SourceOperator.__internal_is_source = True was
stored as _SourceOperator__internal_is_source, while the property kept
reading
_Operator__internal_is_source. Result: SourceOperator subclasses
defaulted to is_source = False, and only worked because ExecutorManager
called the setter afterward.
Fix:
in SourceOperator and TableOperator.__init__, write to the base-class
mangled slot directly via _Operator__internal_is_source. Operator keeps
the __internal_is_source double-underscore form. Also removed a dead,
mangled line in TableOperator.__init__.
### Any related issues, documentation, or discussions?
Closes: #4736
### How was this PR tested?
Updated amber/src/test/python/core/models/test_operator.py:
- Removed the bug-pinning test that asserted on the old divergent
mangled attributes.
- Removed the xfail marker from the contract test, which now passes:
SourceOperator() reports is_source is True.
All 29 tests in test_operator.py pass.
### Was this PR authored or co-authored using generative AI tooling?
Co-authored with Claude Opus 4.7 in Compliance with ASF
---
amber/src/main/python/core/models/operator.py | 4 ++--
amber/src/test/python/core/models/test_operator.py | 25 +---------------------
2 files changed, 3 insertions(+), 26 deletions(-)
diff --git a/amber/src/main/python/core/models/operator.py
b/amber/src/main/python/core/models/operator.py
index 952e2a12c8..71da570c7f 100644
--- a/amber/src/main/python/core/models/operator.py
+++ b/amber/src/main/python/core/models/operator.py
@@ -164,7 +164,7 @@ class TupleOperatorV2(Operator):
class SourceOperator(TupleOperatorV2):
- __internal_is_source = True
+ _Operator__internal_is_source = True
@abstractmethod
def produce(self) -> Iterator[Union[TupleLike, TableLike, None]]:
@@ -267,7 +267,7 @@ class TableOperator(TupleOperatorV2):
def __init__(self):
super().__init__()
- self.__internal_is_source: bool = False
+ self._Operator__internal_is_source: bool = False
self.__table_data: Mapping[int, List[Tuple]] = defaultdict(list)
@overrides.final
diff --git a/amber/src/test/python/core/models/test_operator.py
b/amber/src/test/python/core/models/test_operator.py
index d33077ffde..d8d387a9ad 100644
--- a/amber/src/test/python/core/models/test_operator.py
+++ b/amber/src/test/python/core/models/test_operator.py
@@ -154,30 +154,7 @@ class TestIsSourceProperty:
op.is_source = False
assert op.is_source is False
- def test_source_operator_class_attr_storage_diverges_from_property_read(
- self,
- ):
- # Documents the underlying defect without claiming a contract: the
class
- # attribute is stored under one mangled name, the property reads from
- # another, so they cannot agree. Asserting the two attributes directly
- # decouples this from the eventual is_source-on-SourceOperator fix.
- src = _ConcreteSource()
- # The mangled attribute SourceOperator set — present but unused:
- assert getattr(src, "_SourceOperator__internal_is_source") is True
- # The attribute Operator.is_source actually reads — still the default:
- assert getattr(src, "_Operator__internal_is_source") is False
-
- @pytest.mark.xfail(
- strict=True,
- reason=(
- "Known bug: SourceOperator's __internal_is_source class attribute "
- "is name-mangled to _SourceOperator__internal_is_source, while "
- "Operator.is_source reads _Operator__internal_is_source. The "
- "intended contract is is_source=True on SourceOperator instances; "
- "this xfail flips to XPASS when the bug is fixed."
- ),
- )
- def test_source_operator_subclass_should_report_is_source_true(self):
+ def test_source_operator_subclass_reports_is_source_true(self):
src = _ConcreteSource()
assert src.is_source is True