Skip to content

Commit 9ce7619

Browse files
authored
Feat/json serialize or expression (#2565)
<!-- Thanks for opening a pull request! --> <!-- In the case this PR will resolve an issue, please replace ${GITHUB_ISSUE_ID} below with the actual Github issue id. --> Closes #2519 # Rationale for this change ## Are these changes tested? yes ## Are there any user-facing changes? <!-- In the case of user-facing changes, please add the changelog label. -->
1 parent 6d88033 commit 9ce7619

File tree

2 files changed

+24
-4
lines changed

2 files changed

+24
-4
lines changed

pyiceberg/expressions/__init__.py

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@
3333
)
3434
from typing import Literal as TypingLiteral
3535

36-
from pydantic import Field
36+
from pydantic import ConfigDict, Field
3737

3838
from pyiceberg.expressions.literals import (
3939
AboveMax,
@@ -302,12 +302,19 @@ def __getnewargs__(self) -> Tuple[BooleanExpression, BooleanExpression]:
302302
return (self.left, self.right)
303303

304304

305-
class Or(BooleanExpression):
305+
class Or(IcebergBaseModel, BooleanExpression):
306306
"""OR operation expression - logical disjunction."""
307307

308+
model_config = ConfigDict(arbitrary_types_allowed=True)
309+
310+
type: TypingLiteral["or"] = Field(default="or", alias="type")
308311
left: BooleanExpression
309312
right: BooleanExpression
310313

314+
def __init__(self, left: BooleanExpression, right: BooleanExpression, *rest: BooleanExpression) -> None:
315+
if isinstance(self, Or) and not hasattr(self, "left") and not hasattr(self, "right"):
316+
super().__init__(left=left, right=right)
317+
311318
def __new__(cls, left: BooleanExpression, right: BooleanExpression, *rest: BooleanExpression) -> BooleanExpression: # type: ignore
312319
if rest:
313320
return _build_balanced_tree(Or, (left, right, *rest))
@@ -319,10 +326,12 @@ def __new__(cls, left: BooleanExpression, right: BooleanExpression, *rest: Boole
319326
return left
320327
else:
321328
obj = super().__new__(cls)
322-
obj.left = left
323-
obj.right = right
324329
return obj
325330

331+
def __str__(self) -> str:
332+
"""Return the string representation of the Or class."""
333+
return f"{str(self.__class__.__name__)}(left={repr(self.left)}, right={repr(self.right)})"
334+
326335
def __eq__(self, other: Any) -> bool:
327336
"""Return the equality of two instances of the Or class."""
328337
return self.left == other.left and self.right == other.right if isinstance(other, Or) else False

tests/expressions/test_expressions.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -714,6 +714,17 @@ def test_or() -> None:
714714
null | "abc" # type: ignore
715715

716716

717+
def test_or_serialization() -> None:
718+
left = EqualTo("a", 10)
719+
right = EqualTo("b", 20)
720+
or_ = Or(left, right)
721+
722+
assert (
723+
or_.model_dump_json()
724+
== '{"type":"or","left":{"term":"a","type":"eq","value":10},"right":{"term":"b","type":"eq","value":20}}'
725+
)
726+
727+
717728
def test_not() -> None:
718729
null = IsNull(Reference("a"))
719730
not_ = Not(null)

0 commit comments

Comments
 (0)