Make Not expression JSON serializable (#2593)
#2520
This PR makes the `Not` boolean expression in `pyiceberg` JSON
serializable using Pydantic
Please let me know if my approach or fix needs any improvements . I’m
open to feedback and happy to make changes based on suggestions.
Thank you !
---------
Co-authored-by: Fokko Driesprong <fokko@apache.org>
diff --git a/pyiceberg/expressions/__init__.py b/pyiceberg/expressions/__init__.py
index 8de5a28..0491a1f 100644
--- a/pyiceberg/expressions/__init__.py
+++ b/pyiceberg/expressions/__init__.py
@@ -350,12 +350,18 @@
return (self.left, self.right)
-class Not(BooleanExpression):
+class Not(IcebergBaseModel, BooleanExpression):
"""NOT operation expression - logical negation."""
- child: BooleanExpression
+ model_config = ConfigDict(arbitrary_types_allowed=True)
- def __new__(cls, child: BooleanExpression) -> BooleanExpression: # type: ignore
+ type: TypingLiteral["not"] = Field(default="not")
+ child: BooleanExpression = Field()
+
+ def __init__(self, child: BooleanExpression, **_: Any) -> None:
+ super().__init__(child=child)
+
+ def __new__(cls, child: BooleanExpression, **_: Any) -> BooleanExpression: # type: ignore
if child is AlwaysTrue():
return AlwaysFalse()
elif child is AlwaysFalse():
@@ -363,9 +369,12 @@
elif isinstance(child, Not):
return child.child
obj = super().__new__(cls)
- obj.child = child
return obj
+ def __str__(self) -> str:
+ """Return the string representation of the Not class."""
+ return f"Not(child={self.child})"
+
def __repr__(self) -> str:
"""Return the string representation of the Not class."""
return f"Not(child={repr(self.child)})"
diff --git a/tests/expressions/test_expressions.py b/tests/expressions/test_expressions.py
index 45addd8..57a39e0 100644
--- a/tests/expressions/test_expressions.py
+++ b/tests/expressions/test_expressions.py
@@ -711,6 +711,12 @@
assert not_ == pickle.loads(pickle.dumps(not_))
+def test_not_json_serialization_and_deserialization() -> None:
+ not_expr = Not(GreaterThan("a", 22))
+ json_str = not_expr.model_dump_json()
+ assert json_str == """{"type":"not","child":{"term":"a","type":"gt","value":22}}"""
+
+
def test_always_true() -> None:
always_true = AlwaysTrue()
assert always_true.model_dump_json() == '"true"'