Skip to content

Commit ca61255

Browse files
committed
Try another approach
1 parent 0b60b08 commit ca61255

File tree

1 file changed

+36
-14
lines changed

1 file changed

+36
-14
lines changed

pyiceberg/expressions/__init__.py

Lines changed: 36 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -20,10 +20,10 @@
2020
from abc import ABC, abstractmethod
2121
from collections.abc import Callable, Iterable, Sequence
2222
from functools import cached_property
23-
from typing import Any
23+
from typing import Annotated, Any, TypeAlias
2424
from typing import Literal as TypingLiteral
2525

26-
from pydantic import ConfigDict, Field, model_validator
26+
from pydantic import ConfigDict, Discriminator, Field, Tag, model_validator
2727
from pydantic_core.core_schema import ValidatorFunctionWrapHandler
2828

2929
from pyiceberg.expressions.literals import AboveMax, BelowMin, Literal, literal
@@ -290,16 +290,42 @@ def as_bound(self) -> type[BoundReference]:
290290
return BoundReference
291291

292292

293+
Predicates: TypeAlias = Annotated[
294+
Annotated["IsNull", Tag("is-null")]
295+
| Annotated["NotNull", Tag("not-null")]
296+
| Annotated["IsNaN", Tag("is-nan")]
297+
| Annotated["NotNaN", Tag("not-nan")]
298+
| Annotated["EqualTo", Tag("eq")]
299+
| Annotated["NotEqualTo", Tag("not-eq")]
300+
| Annotated["LessThan", Tag("lt")]
301+
| Annotated["LessThanOrEqual", Tag("lt-eq")]
302+
| Annotated["GreaterThan", Tag("gt")]
303+
| Annotated["GreaterThanOrEqual", Tag("gt-eq")]
304+
| Annotated["StartsWith", Tag("starts-with")]
305+
| Annotated["NotStartsWith", Tag("not-starts-with")]
306+
| Annotated["In", Tag("in")]
307+
| Annotated["NotIn", Tag("not-in")]
308+
| Annotated["And", Tag("and")]
309+
| Annotated["Or", Tag("or")]
310+
| Annotated["Not", Tag("not")],
311+
Discriminator("type"),
312+
]
313+
314+
293315
class And(BooleanExpression):
294316
"""AND operation expression - logical conjunction."""
295317

296318
model_config = ConfigDict(arbitrary_types_allowed=True)
297319

298320
type: TypingLiteral["and"] = Field(default="and", alias="type")
299-
left: BooleanExpression
300-
right: BooleanExpression
321+
left: Predicates
322+
right: Predicates
301323

302-
def __new__(cls, left: BooleanExpression, right: BooleanExpression, *rest: BooleanExpression) -> BooleanExpression:
324+
def __init__(self, left: BooleanExpression, right: BooleanExpression, *rest: BooleanExpression, **_: Any) -> None:
325+
if isinstance(self, And) and not hasattr(self, "left") and not hasattr(self, "right"):
326+
super().__init__(left=left, right=right)
327+
328+
def __new__(cls, left: BooleanExpression, right: BooleanExpression, *rest: BooleanExpression, **_: Any) -> BooleanExpression:
303329
if rest:
304330
return _build_balanced_tree(And, (left, right, *rest))
305331
if left is AlwaysFalse() or right is AlwaysFalse():
@@ -311,10 +337,6 @@ def __new__(cls, left: BooleanExpression, right: BooleanExpression, *rest: Boole
311337
else:
312338
return super().__new__(cls)
313339

314-
def __init__(self, left: BooleanExpression, right: BooleanExpression, *rest: BooleanExpression) -> None:
315-
if isinstance(self, And) and not hasattr(self, "left") and not hasattr(self, "right"):
316-
super().__init__(left=left, right=right)
317-
318340
def __eq__(self, other: Any) -> bool:
319341
"""Return the equality of two instances of the And class."""
320342
return self.left == other.left and self.right == other.right if isinstance(other, And) else False
@@ -343,8 +365,8 @@ class Or(BooleanExpression):
343365
model_config = ConfigDict(arbitrary_types_allowed=True)
344366

345367
type: TypingLiteral["or"] = Field(default="or", alias="type")
346-
left: BooleanExpression
347-
right: BooleanExpression
368+
left: Predicates
369+
right: Predicates
348370

349371
def __init__(self, left: BooleanExpression, right: BooleanExpression, *rest: BooleanExpression) -> None:
350372
if isinstance(self, Or) and not hasattr(self, "left") and not hasattr(self, "right"):
@@ -390,7 +412,7 @@ class Not(BooleanExpression):
390412
model_config = ConfigDict(arbitrary_types_allowed=True)
391413

392414
type: TypingLiteral["not"] = Field(default="not")
393-
child: BooleanExpression = Field()
415+
child: Predicates = Field()
394416

395417
def __init__(self, child: BooleanExpression, **_: Any) -> None:
396418
super().__init__(child=child)
@@ -402,8 +424,8 @@ def __new__(cls, child: BooleanExpression, **_: Any) -> BooleanExpression:
402424
return AlwaysTrue()
403425
elif isinstance(child, Not):
404426
return child.child
405-
obj = super().__new__(cls)
406-
return obj
427+
else:
428+
return super().__new__(cls)
407429

408430
def __str__(self) -> str:
409431
"""Return the string representation of the Not class."""

0 commit comments

Comments
 (0)