Skip to content

Commit 369cbe3

Browse files
Aniketsygeruh
authored andcommitted
Make And expression JSON serializable using Pydantic
1 parent 9610b41 commit 369cbe3

2 files changed

Lines changed: 18 additions & 2 deletions

File tree

pyiceberg/expressions/__init__.py

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -237,12 +237,19 @@ def as_bound(self) -> type[BoundReference]:
237237
return BoundReference
238238

239239

240-
class And(BooleanExpression):
240+
class And(IcebergBaseModel, BooleanExpression):
241241
"""AND operation expression - logical conjunction."""
242242

243+
model_config = ConfigDict(arbitrary_types_allowed=True)
244+
245+
type: TypingLiteral["and"] = Field(default="and", alias="type")
243246
left: BooleanExpression
244247
right: BooleanExpression
245248

249+
def __init__(self, left: BooleanExpression, right: BooleanExpression, *rest: BooleanExpression) -> None:
250+
if isinstance(self, And) and not hasattr(self, "left") and not hasattr(self, "right"):
251+
super().__init__(left=left, right=right)
252+
246253
def __new__(cls, left: BooleanExpression, right: BooleanExpression, *rest: BooleanExpression) -> BooleanExpression: # type: ignore
247254
if rest:
248255
return _build_balanced_tree(And, (left, right, *rest))
@@ -254,6 +261,7 @@ def __new__(cls, left: BooleanExpression, right: BooleanExpression, *rest: Boole
254261
return left
255262
else:
256263
obj = super().__new__(cls)
264+
obj.__pydantic_fields_set__ = set()
257265
obj.left = left
258266
obj.right = right
259267
return obj
@@ -264,7 +272,7 @@ def __eq__(self, other: Any) -> bool:
264272

265273
def __str__(self) -> str:
266274
"""Return the string representation of the And class."""
267-
return f"And(left={str(self.left)}, right={str(self.right)})"
275+
return f"{str(self.__class__.__name__)}(left={repr(self.left)}, right={repr(self.right)})"
268276

269277
def __repr__(self) -> str:
270278
"""Return the string representation of the And class."""

tests/table/test_partitioning.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121

2222
import pytest
2323

24+
from pyiceberg.expressions import And, EqualTo
2425
from pyiceberg.partitioning import UNPARTITIONED_PARTITION_SPEC, PartitionField, PartitionSpec
2526
from pyiceberg.schema import Schema
2627
from pyiceberg.transforms import (
@@ -125,6 +126,13 @@ def test_serialize_partition_spec() -> None:
125126
)
126127

127128

129+
def test_serialize_and_expression() -> None:
130+
expr = And(EqualTo("foo", 1), EqualTo("bar", 2))
131+
assert expr.model_dump_json(by_alias=True) == (
132+
'{"type":"and","left":{"type":"equal_to","term":"foo","literal":1},"right":{"type":"equal_to","term":"bar","literal":2}}'
133+
)
134+
135+
128136
def test_deserialize_unpartition_spec() -> None:
129137
json_partition_spec = """{"spec-id":0,"fields":[]}"""
130138
spec = PartitionSpec.model_validate_json(json_partition_spec)

0 commit comments

Comments
 (0)