From b052df7b68323e4b6d83a31775df0eb030fabf16 Mon Sep 17 00:00:00 2001 From: hedger9487 Date: Wed, 26 Aug 2026 09:38:31 +0800 Subject: [PATCH 1/3] Fix TruncateTransform.satisfies_order_of for different widths (#3680) --- pyiceberg/transforms.py | 6 +----- tests/test_transforms.py | 8 ++++++++ 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/pyiceberg/transforms.py b/pyiceberg/transforms.py index 5e0027a829..b1e7c59716 100644 --- a/pyiceberg/transforms.py +++ b/pyiceberg/transforms.py @@ -896,11 +896,7 @@ def truncate_func(v: Any) -> Any: def satisfies_order_of(self, other: Transform[S, T]) -> bool: if self == other: return True - elif ( - isinstance(self.source_type, StringType) - and isinstance(other, TruncateTransform) - and isinstance(other.source_type, StringType) - ): + elif isinstance(other, TruncateTransform): return self.width >= other.width return False diff --git a/tests/test_transforms.py b/tests/test_transforms.py index c977fcea14..8645cfa4ca 100644 --- a/tests/test_transforms.py +++ b/tests/test_transforms.py @@ -513,6 +513,14 @@ def test_truncate_method(type_var: PrimitiveType, value: Any, expected_human_str assert truncate_transform.satisfies_order_of(truncate_transform) +def test_truncate_satisfies_order_of() -> None: + assert TruncateTransform(5).satisfies_order_of(TruncateTransform(3)) + assert TruncateTransform(5).satisfies_order_of(TruncateTransform(5)) + assert not TruncateTransform(3).satisfies_order_of(TruncateTransform(5)) + assert not TruncateTransform(5).satisfies_order_of(BucketTransform(5)) + assert not TruncateTransform(5).satisfies_order_of(IdentityTransform()) + + def test_unknown_transform() -> None: unknown_transform = UnknownTransform("unknown") # type: ignore assert str(unknown_transform) == str(eval(repr(unknown_transform))) From 23d77d4e95e5ecfb4e5326df190cf56f0b9d59ac Mon Sep 17 00:00:00 2001 From: hedger9487 Date: Thu, 27 Aug 2026 13:21:15 +0800 Subject: [PATCH 2/3] refactor: Remove unused source_type from TruncateTransform --- pyiceberg/transforms.py | 5 ----- tests/test_transforms.py | 23 +++++++++++++++++++++++ 2 files changed, 23 insertions(+), 5 deletions(-) diff --git a/pyiceberg/transforms.py b/pyiceberg/transforms.py index b1e7c59716..06663843e9 100644 --- a/pyiceberg/transforms.py +++ b/pyiceberg/transforms.py @@ -779,7 +779,6 @@ class TruncateTransform(Transform[S, S]): """ root: str = Field() - _source_type: IcebergType = PrivateAttr() _width: PositiveInt = PrivateAttr() def __init__(self, width: int, **data: Any): @@ -796,10 +795,6 @@ def result_type(self, source: IcebergType) -> IcebergType: def preserves_order(self) -> bool: return True - @property - def source_type(self) -> IcebergType: - return self._source_type - def project(self, name: str, pred: BoundPredicate) -> UnboundPredicate | None: field_type = pred.term.ref().field.field_type diff --git a/tests/test_transforms.py b/tests/test_transforms.py index 8645cfa4ca..a70e2ca104 100644 --- a/tests/test_transforms.py +++ b/tests/test_transforms.py @@ -514,11 +514,34 @@ def test_truncate_method(type_var: PrimitiveType, value: Any, expected_human_str def test_truncate_satisfies_order_of() -> None: + # Width comparison assert TruncateTransform(5).satisfies_order_of(TruncateTransform(3)) assert TruncateTransform(5).satisfies_order_of(TruncateTransform(5)) assert not TruncateTransform(3).satisfies_order_of(TruncateTransform(5)) + assert TruncateTransform(10).satisfies_order_of(TruncateTransform(1)) + assert not TruncateTransform(1).satisfies_order_of(TruncateTransform(10)) + assert TruncateTransform(1).satisfies_order_of(TruncateTransform(1)) + + # Cross-transform comparisons assert not TruncateTransform(5).satisfies_order_of(BucketTransform(5)) assert not TruncateTransform(5).satisfies_order_of(IdentityTransform()) + assert not TruncateTransform(5).satisfies_order_of(VoidTransform()) + assert not TruncateTransform(5).satisfies_order_of(DayTransform()) + assert not TruncateTransform(5).satisfies_order_of(YearTransform()) + assert not TruncateTransform(5).satisfies_order_of(UnknownTransform("unknown")) + + # Non-transform comparisons + assert not TruncateTransform(5).satisfies_order_of(None) # type: ignore + assert not TruncateTransform(5).satisfies_order_of("truncate[5]") # type: ignore + assert not TruncateTransform(5).satisfies_order_of(5) # type: ignore + + # Identity naturally satisfies TruncateTransform because Truncate preserves order + assert IdentityTransform().satisfies_order_of(TruncateTransform(5)) + + # Verify unused source_type was cleanly removed + t = TruncateTransform(5) + assert not hasattr(t, "source_type") + assert not hasattr(t, "_source_type") def test_unknown_transform() -> None: From 6ccb30d06e46d50085337a723fabc2e528631695 Mon Sep 17 00:00:00 2001 From: hedger9487 Date: Fri, 28 Aug 2026 03:51:25 +0800 Subject: [PATCH 3/3] test: Remove non-transform assertions and type ignores in test_transforms --- tests/test_transforms.py | 5 ----- 1 file changed, 5 deletions(-) diff --git a/tests/test_transforms.py b/tests/test_transforms.py index a70e2ca104..66c184a423 100644 --- a/tests/test_transforms.py +++ b/tests/test_transforms.py @@ -530,11 +530,6 @@ def test_truncate_satisfies_order_of() -> None: assert not TruncateTransform(5).satisfies_order_of(YearTransform()) assert not TruncateTransform(5).satisfies_order_of(UnknownTransform("unknown")) - # Non-transform comparisons - assert not TruncateTransform(5).satisfies_order_of(None) # type: ignore - assert not TruncateTransform(5).satisfies_order_of("truncate[5]") # type: ignore - assert not TruncateTransform(5).satisfies_order_of(5) # type: ignore - # Identity naturally satisfies TruncateTransform because Truncate preserves order assert IdentityTransform().satisfies_order_of(TruncateTransform(5))