You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@iceberg.apache.org by bl...@apache.org on 2022/10/21 00:10:41 UTC
[iceberg] branch master updated: Python: Split expressions base (#5987)
This is an automated email from the ASF dual-hosted git repository.
blue pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/iceberg.git
The following commit(s) were added to refs/heads/master by this push:
new 16ecf66753 Python: Split expressions base (#5987)
16ecf66753 is described below
commit 16ecf667531d139a397524cc0d44a29083f2877c
Author: Fokko Driesprong <fo...@apache.org>
AuthorDate: Fri Oct 21 02:10:36 2022 +0200
Python: Split expressions base (#5987)
I also played around with a bound.py, but it is so intertwined with the
unbound, that I think it makes more sense to have it into a single file.
---
python/pyiceberg/expressions/__init__.py | 513 ++++++++
.../pyiceberg/expressions/{base.py => visitors.py} | 548 +--------
python/tests/expressions/test_expressions.py | 746 ++++++++++++
.../{test_expressions_base.py => test_visitors.py} | 1276 ++++++--------------
python/tests/test_schema.py | 2 +-
5 files changed, 1633 insertions(+), 1452 deletions(-)
diff --git a/python/pyiceberg/expressions/__init__.py b/python/pyiceberg/expressions/__init__.py
index 13a83393a9..39d4884a51 100644
--- a/python/pyiceberg/expressions/__init__.py
+++ b/python/pyiceberg/expressions/__init__.py
@@ -14,3 +14,516 @@
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
+
+from __future__ import annotations
+
+from abc import ABC, abstractmethod
+from dataclasses import dataclass
+from functools import reduce
+from typing import ClassVar, Generic, TypeVar
+
+from pyiceberg.expressions.literals import Literal
+from pyiceberg.files import StructProtocol
+from pyiceberg.schema import Accessor, Schema
+from pyiceberg.types import DoubleType, FloatType, NestedField
+from pyiceberg.utils.singleton import Singleton
+
+T = TypeVar("T")
+B = TypeVar("B")
+
+
+class BooleanExpression(ABC):
+ """An expression that evaluates to a boolean"""
+
+ @abstractmethod
+ def __invert__(self) -> BooleanExpression:
+ """Transform the Expression into its negated version."""
+
+
+class Term(Generic[T], ABC):
+ """A simple expression that evaluates to a value"""
+
+
+class Bound(ABC):
+ """Represents a bound value expression"""
+
+
+class Unbound(Generic[B], ABC):
+ """Represents an unbound value expression"""
+
+ @abstractmethod
+ def bind(self, schema: Schema, case_sensitive: bool = True) -> B:
+ ... # pragma: no cover
+
+
+class BoundTerm(Term[T], Bound, ABC):
+ """Represents a bound term"""
+
+ @abstractmethod
+ def ref(self) -> BoundReference[T]:
+ """Returns the bound reference"""
+
+ @abstractmethod
+ def eval(self, struct: StructProtocol) -> T: # pylint: disable=W0613
+ """Returns the value at the referenced field's position in an object that abides by the StructProtocol"""
+
+
+@dataclass(frozen=True)
+class BoundReference(BoundTerm[T]):
+ """A reference bound to a field in a schema
+
+ Args:
+ field (NestedField): A referenced field in an Iceberg schema
+ accessor (Accessor): An Accessor object to access the value at the field's position
+ """
+
+ field: NestedField
+ accessor: Accessor
+
+ def eval(self, struct: StructProtocol) -> T:
+ """Returns the value at the referenced field's position in an object that abides by the StructProtocol
+
+ Args:
+ struct (StructProtocol): A row object that abides by the StructProtocol and returns values given a position
+ Returns:
+ Any: The value at the referenced field's position in `struct`
+ """
+ return self.accessor.get(struct)
+
+ def ref(self) -> BoundReference[T]:
+ return self
+
+
+class UnboundTerm(Term[T], Unbound[BoundTerm[T]], ABC):
+ """Represents an unbound term."""
+
+
+@dataclass(frozen=True)
+class Reference(UnboundTerm[T]):
+ """A reference not yet bound to a field in a schema
+
+ Args:
+ name (str): The name of the field
+
+ Note:
+ An unbound reference is sometimes referred to as a "named" reference
+ """
+
+ name: str
+
+ def bind(self, schema: Schema, case_sensitive: bool = True) -> BoundReference[T]:
+ """Bind the reference to an Iceberg schema
+
+ Args:
+ schema (Schema): An Iceberg schema
+ case_sensitive (bool): Whether to consider case when binding the reference to the field
+
+ Raises:
+ ValueError: If an empty name is provided
+
+ Returns:
+ BoundReference: A reference bound to the specific field in the Iceberg schema
+ """
+ field = schema.find_field(name_or_id=self.name, case_sensitive=case_sensitive)
+ accessor = schema.accessor_for_field(field.field_id)
+ return BoundReference(field=field, accessor=accessor)
+
+
+@dataclass(frozen=True, init=False)
+class And(BooleanExpression):
+ """AND operation expression - logical conjunction"""
+
+ left: BooleanExpression
+ right: BooleanExpression
+
+ def __new__(cls, left: BooleanExpression, right: BooleanExpression, *rest: BooleanExpression):
+ if rest:
+ return reduce(And, (left, right, *rest))
+ if left is AlwaysFalse() or right is AlwaysFalse():
+ return AlwaysFalse()
+ elif left is AlwaysTrue():
+ return right
+ elif right is AlwaysTrue():
+ return left
+ else:
+ result = super().__new__(cls)
+ object.__setattr__(result, "left", left)
+ object.__setattr__(result, "right", right)
+ return result
+
+ def __invert__(self) -> Or:
+ return Or(~self.left, ~self.right)
+
+
+@dataclass(frozen=True, init=False)
+class Or(BooleanExpression):
+ """OR operation expression - logical disjunction"""
+
+ left: BooleanExpression
+ right: BooleanExpression
+
+ def __new__(cls, left: BooleanExpression, right: BooleanExpression, *rest: BooleanExpression):
+ if rest:
+ return reduce(Or, (left, right, *rest))
+ if left is AlwaysTrue() or right is AlwaysTrue():
+ return AlwaysTrue()
+ elif left is AlwaysFalse():
+ return right
+ elif right is AlwaysFalse():
+ return left
+ else:
+ result = super().__new__(cls)
+ object.__setattr__(result, "left", left)
+ object.__setattr__(result, "right", right)
+ return result
+
+ def __invert__(self) -> And:
+ return And(~self.left, ~self.right)
+
+
+@dataclass(frozen=True, init=False)
+class Not(BooleanExpression):
+ """NOT operation expression - logical negation"""
+
+ child: BooleanExpression
+
+ def __new__(cls, child: BooleanExpression):
+ if child is AlwaysTrue():
+ return AlwaysFalse()
+ elif child is AlwaysFalse():
+ return AlwaysTrue()
+ elif isinstance(child, Not):
+ return child.child
+ result = super().__new__(cls)
+ object.__setattr__(result, "child", child)
+ return result
+
+ def __invert__(self) -> BooleanExpression:
+ return self.child
+
+
+@dataclass(frozen=True)
+class AlwaysTrue(BooleanExpression, Singleton):
+ """TRUE expression"""
+
+ def __invert__(self) -> AlwaysFalse:
+ return AlwaysFalse()
+
+
+@dataclass(frozen=True)
+class AlwaysFalse(BooleanExpression, Singleton):
+ """FALSE expression"""
+
+ def __invert__(self) -> AlwaysTrue:
+ return AlwaysTrue()
+
+
+@dataclass(frozen=True)
+class BoundPredicate(Generic[T], Bound, BooleanExpression):
+ term: BoundTerm[T]
+
+ def __invert__(self) -> BoundPredicate[T]:
+ """Inverts the predicate"""
+ raise NotImplementedError
+
+
+@dataclass(frozen=True)
+class UnboundPredicate(Generic[T], Unbound[BooleanExpression], BooleanExpression):
+ as_bound: ClassVar[type]
+ term: UnboundTerm[T]
+
+ def __invert__(self) -> UnboundPredicate[T]:
+ """Inverts the predicate"""
+ raise NotImplementedError
+
+ def bind(self, schema: Schema, case_sensitive: bool = True) -> BooleanExpression:
+ """Binds the predicate to a schema"""
+ raise NotImplementedError
+
+
+@dataclass(frozen=True)
+class UnaryPredicate(UnboundPredicate[T]):
+ def bind(self, schema: Schema, case_sensitive: bool = True) -> BooleanExpression:
+ bound_term = self.term.bind(schema, case_sensitive)
+ return self.as_bound(bound_term)
+
+ def __invert__(self) -> UnaryPredicate[T]:
+ """Inverts the unary predicate"""
+ raise NotImplementedError
+
+
+@dataclass(frozen=True)
+class BoundUnaryPredicate(BoundPredicate[T]):
+ def __invert__(self) -> BoundUnaryPredicate[T]:
+ """Inverts the unary predicate"""
+ raise NotImplementedError
+
+
+@dataclass(frozen=True)
+class BoundIsNull(BoundUnaryPredicate[T]):
+ def __new__(cls, term: BoundTerm[T]): # pylint: disable=W0221
+ if term.ref().field.required:
+ return AlwaysFalse()
+ return super().__new__(cls)
+
+ def __invert__(self) -> BoundNotNull[T]:
+ return BoundNotNull(self.term)
+
+
+@dataclass(frozen=True)
+class BoundNotNull(BoundUnaryPredicate[T]):
+ def __new__(cls, term: BoundTerm[T]): # pylint: disable=W0221
+ if term.ref().field.required:
+ return AlwaysTrue()
+ return super().__new__(cls)
+
+ def __invert__(self) -> BoundIsNull:
+ return BoundIsNull(self.term)
+
+
+@dataclass(frozen=True)
+class IsNull(UnaryPredicate[T]):
+ as_bound = BoundIsNull
+
+ def __invert__(self) -> NotNull[T]:
+ return NotNull(self.term)
+
+
+@dataclass(frozen=True)
+class NotNull(UnaryPredicate[T]):
+ as_bound = BoundNotNull
+
+ def __invert__(self) -> IsNull[T]:
+ return IsNull(self.term)
+
+
+@dataclass(frozen=True)
+class BoundIsNaN(BoundUnaryPredicate[T]):
+ def __new__(cls, term: BoundTerm[T]): # pylint: disable=W0221
+ bound_type = term.ref().field.field_type
+ if type(bound_type) in {FloatType, DoubleType}:
+ return super().__new__(cls)
+ return AlwaysFalse()
+
+ def __invert__(self) -> BoundNotNaN[T]:
+ return BoundNotNaN(self.term)
+
+
+@dataclass(frozen=True)
+class BoundNotNaN(BoundUnaryPredicate[T]):
+ def __new__(cls, term: BoundTerm[T]): # pylint: disable=W0221
+ bound_type = term.ref().field.field_type
+ if type(bound_type) in {FloatType, DoubleType}:
+ return super().__new__(cls)
+ return AlwaysTrue()
+
+ def __invert__(self) -> BoundIsNaN[T]:
+ return BoundIsNaN(self.term)
+
+
+@dataclass(frozen=True)
+class IsNaN(UnaryPredicate[T]):
+ as_bound = BoundIsNaN
+
+ def __invert__(self) -> NotNaN[T]:
+ return NotNaN(self.term)
+
+
+@dataclass(frozen=True)
+class NotNaN(UnaryPredicate[T]):
+ as_bound = BoundNotNaN
+
+ def __invert__(self) -> IsNaN[T]:
+ return IsNaN(self.term)
+
+
+@dataclass(frozen=True)
+class SetPredicate(UnboundPredicate[T]):
+ literals: tuple[Literal[T], ...]
+
+ def __invert__(self) -> SetPredicate[T]:
+ """Inverted expression of the SetPredicate"""
+ raise NotImplementedError
+
+ def bind(self, schema: Schema, case_sensitive: bool = True) -> BooleanExpression:
+ bound_term = self.term.bind(schema, case_sensitive)
+ return self.as_bound(bound_term, {lit.to(bound_term.ref().field.field_type) for lit in self.literals})
+
+
+@dataclass(frozen=True)
+class BoundSetPredicate(BoundPredicate[T]):
+ literals: set[Literal[T]]
+
+ def __invert__(self) -> BoundSetPredicate[T]:
+ """Inverted expression of the SetPredicate"""
+ raise NotImplementedError
+
+
+@dataclass(frozen=True)
+class BoundIn(BoundSetPredicate[T]):
+ def __new__(cls, term: BoundTerm[T], literals: set[Literal[T]]): # pylint: disable=W0221
+ count = len(literals)
+ if count == 0:
+ return AlwaysFalse()
+ elif count == 1:
+ return BoundEqualTo(term, next(iter(literals)))
+ else:
+ return super().__new__(cls)
+
+ def __invert__(self) -> BoundNotIn[T]:
+ return BoundNotIn(self.term, self.literals)
+
+
+@dataclass(frozen=True)
+class BoundNotIn(BoundSetPredicate[T]):
+ def __new__(cls, term: BoundTerm[T], literals: set[Literal[T]]): # pylint: disable=W0221
+ count = len(literals)
+ if count == 0:
+ return AlwaysTrue()
+ elif count == 1:
+ return BoundNotEqualTo(term, next(iter(literals)))
+ else:
+ return super().__new__(cls)
+
+ def __invert__(self) -> BoundIn[T]:
+ return BoundIn(self.term, self.literals)
+
+
+@dataclass(frozen=True)
+class In(SetPredicate[T]):
+ as_bound = BoundIn
+
+ def __new__(cls, term: UnboundTerm[T], literals: tuple[Literal[T], ...]): # pylint: disable=W0221
+ count = len(literals)
+ if count == 0:
+ return AlwaysFalse()
+ elif count == 1:
+ return EqualTo(term, literals[0])
+ else:
+ return super().__new__(cls)
+
+ def __invert__(self) -> NotIn[T]:
+ return NotIn(self.term, self.literals)
+
+
+@dataclass(frozen=True)
+class NotIn(SetPredicate[T]):
+ as_bound = BoundNotIn
+
+ def __new__(cls, term: UnboundTerm[T], literals: tuple[Literal[T], ...]): # pylint: disable=W0221
+ count = len(literals)
+ if count == 0:
+ return AlwaysTrue()
+ elif count == 1:
+ return NotEqualTo(term, literals[0])
+ else:
+ return super().__new__(cls)
+
+ def __invert__(self) -> In[T]:
+ return In(self.term, self.literals)
+
+
+@dataclass(frozen=True)
+class LiteralPredicate(UnboundPredicate[T]):
+ literal: Literal[T]
+
+ def bind(self, schema: Schema, case_sensitive: bool = True) -> BooleanExpression:
+ bound_term = self.term.bind(schema, case_sensitive)
+ return self.as_bound(bound_term, self.literal.to(bound_term.ref().field.field_type))
+
+ def __invert__(self) -> LiteralPredicate[T]:
+ """Inverts the literal predicate"""
+ raise NotImplementedError
+
+
+@dataclass(frozen=True)
+class BoundLiteralPredicate(BoundPredicate[T]):
+ literal: Literal[T]
+
+ def __invert__(self) -> BoundLiteralPredicate[T]:
+ """Inverts the bound literal predicate"""
+ raise NotImplementedError
+
+
+@dataclass(frozen=True)
+class BoundEqualTo(BoundLiteralPredicate[T]):
+ def __invert__(self) -> BoundNotEqualTo[T]:
+ return BoundNotEqualTo(self.term, self.literal)
+
+
+@dataclass(frozen=True)
+class BoundNotEqualTo(BoundLiteralPredicate[T]):
+ def __invert__(self) -> BoundEqualTo[T]:
+ return BoundEqualTo(self.term, self.literal)
+
+
+@dataclass(frozen=True)
+class BoundGreaterThanOrEqual(BoundLiteralPredicate[T]):
+ def __invert__(self) -> BoundLessThan[T]:
+ return BoundLessThan(self.term, self.literal)
+
+
+@dataclass(frozen=True)
+class BoundGreaterThan(BoundLiteralPredicate[T]):
+ def __invert__(self) -> BoundLessThanOrEqual[T]:
+ return BoundLessThanOrEqual(self.term, self.literal)
+
+
+@dataclass(frozen=True)
+class BoundLessThan(BoundLiteralPredicate[T]):
+ def __invert__(self) -> BoundGreaterThanOrEqual[T]:
+ return BoundGreaterThanOrEqual(self.term, self.literal)
+
+
+@dataclass(frozen=True)
+class BoundLessThanOrEqual(BoundLiteralPredicate[T]):
+ def __invert__(self) -> BoundGreaterThan[T]:
+ return BoundGreaterThan(self.term, self.literal)
+
+
+@dataclass(frozen=True)
+class EqualTo(LiteralPredicate[T]):
+ as_bound = BoundEqualTo
+
+ def __invert__(self) -> NotEqualTo[T]:
+ return NotEqualTo(self.term, self.literal)
+
+
+@dataclass(frozen=True)
+class NotEqualTo(LiteralPredicate[T]):
+ as_bound = BoundNotEqualTo
+
+ def __invert__(self) -> EqualTo[T]:
+ return EqualTo(self.term, self.literal)
+
+
+@dataclass(frozen=True)
+class LessThan(LiteralPredicate[T]):
+ as_bound = BoundLessThan
+
+ def __invert__(self) -> GreaterThanOrEqual[T]:
+ return GreaterThanOrEqual(self.term, self.literal)
+
+
+@dataclass(frozen=True)
+class GreaterThanOrEqual(LiteralPredicate[T]):
+ as_bound = BoundGreaterThanOrEqual
+
+ def __invert__(self) -> LessThan[T]:
+ return LessThan(self.term, self.literal)
+
+
+@dataclass(frozen=True)
+class GreaterThan(LiteralPredicate[T]):
+ as_bound = BoundGreaterThan
+
+ def __invert__(self) -> LessThanOrEqual[T]:
+ return LessThanOrEqual(self.term, self.literal)
+
+
+@dataclass(frozen=True)
+class LessThanOrEqual(LiteralPredicate[T]):
+ as_bound = BoundLessThanOrEqual
+
+ def __invert__(self) -> GreaterThan[T]:
+ return GreaterThan(self.term, self.literal)
diff --git a/python/pyiceberg/expressions/base.py b/python/pyiceberg/expressions/visitors.py
similarity index 58%
rename from python/pyiceberg/expressions/base.py
rename to python/pyiceberg/expressions/visitors.py
index aabfb0a226..4853490315 100644
--- a/python/pyiceberg/expressions/base.py
+++ b/python/pyiceberg/expressions/visitors.py
@@ -14,533 +14,51 @@
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
-from __future__ import annotations
-
from abc import ABC, abstractmethod
-from dataclasses import dataclass
-from functools import reduce, singledispatch
+from functools import singledispatch
from typing import (
Any,
Callable,
- ClassVar,
Generic,
- TypeVar,
+ List,
+ Set,
)
from pyiceberg.conversions import from_bytes
+from pyiceberg.expressions import (
+ AlwaysFalse,
+ AlwaysTrue,
+ And,
+ BooleanExpression,
+ BoundEqualTo,
+ BoundGreaterThan,
+ BoundGreaterThanOrEqual,
+ BoundIn,
+ BoundIsNaN,
+ BoundIsNull,
+ BoundLessThan,
+ BoundLessThanOrEqual,
+ BoundNotEqualTo,
+ BoundNotIn,
+ BoundNotNaN,
+ BoundNotNull,
+ BoundPredicate,
+ BoundTerm,
+ Not,
+ Or,
+ T,
+ UnboundPredicate,
+)
from pyiceberg.expressions.literals import Literal
-from pyiceberg.files import StructProtocol
from pyiceberg.manifest import ManifestFile, PartitionFieldSummary
-from pyiceberg.schema import Accessor, Schema
+from pyiceberg.schema import Schema
from pyiceberg.table import PartitionSpec
from pyiceberg.types import (
DoubleType,
FloatType,
IcebergType,
- NestedField,
PrimitiveType,
)
-from pyiceberg.utils.singleton import Singleton
-
-T = TypeVar("T")
-B = TypeVar("B")
-
-
-class BooleanExpression(ABC):
- """An expression that evaluates to a boolean"""
-
- @abstractmethod
- def __invert__(self) -> BooleanExpression:
- """Transform the Expression into its negated version."""
-
-
-class Term(Generic[T], ABC):
- """A simple expression that evaluates to a value"""
-
-
-class Bound(ABC):
- """Represents a bound value expression"""
-
-
-class Unbound(Generic[B], ABC):
- """Represents an unbound value expression"""
-
- @abstractmethod
- def bind(self, schema: Schema, case_sensitive: bool = True) -> B:
- ... # pragma: no cover
-
-
-class BoundTerm(Term[T], Bound, ABC):
- """Represents a bound term"""
-
- @abstractmethod
- def ref(self) -> BoundReference[T]:
- """Returns the bound reference"""
-
- @abstractmethod
- def eval(self, struct: StructProtocol) -> T: # pylint: disable=W0613
- """Returns the value at the referenced field's position in an object that abides by the StructProtocol"""
-
-
-@dataclass(frozen=True)
-class BoundReference(BoundTerm[T]):
- """A reference bound to a field in a schema
-
- Args:
- field (NestedField): A referenced field in an Iceberg schema
- accessor (Accessor): An Accessor object to access the value at the field's position
- """
-
- field: NestedField
- accessor: Accessor
-
- def eval(self, struct: StructProtocol) -> T:
- """Returns the value at the referenced field's position in an object that abides by the StructProtocol
-
- Args:
- struct (StructProtocol): A row object that abides by the StructProtocol and returns values given a position
- Returns:
- Any: The value at the referenced field's position in `struct`
- """
- return self.accessor.get(struct)
-
- def ref(self) -> BoundReference[T]:
- return self
-
-
-class UnboundTerm(Term[T], Unbound[BoundTerm[T]], ABC):
- """Represents an unbound term."""
-
-
-@dataclass(frozen=True)
-class Reference(UnboundTerm[T]):
- """A reference not yet bound to a field in a schema
-
- Args:
- name (str): The name of the field
-
- Note:
- An unbound reference is sometimes referred to as a "named" reference
- """
-
- name: str
-
- def bind(self, schema: Schema, case_sensitive: bool = True) -> BoundReference[T]:
- """Bind the reference to an Iceberg schema
-
- Args:
- schema (Schema): An Iceberg schema
- case_sensitive (bool): Whether to consider case when binding the reference to the field
-
- Raises:
- ValueError: If an empty name is provided
-
- Returns:
- BoundReference: A reference bound to the specific field in the Iceberg schema
- """
- field = schema.find_field(name_or_id=self.name, case_sensitive=case_sensitive)
- accessor = schema.accessor_for_field(field.field_id)
- return BoundReference(field=field, accessor=accessor)
-
-
-@dataclass(frozen=True, init=False)
-class And(BooleanExpression):
- """AND operation expression - logical conjunction"""
-
- left: BooleanExpression
- right: BooleanExpression
-
- def __new__(cls, left: BooleanExpression, right: BooleanExpression, *rest: BooleanExpression):
- if rest:
- return reduce(And, (left, right, *rest))
- if left is AlwaysFalse() or right is AlwaysFalse():
- return AlwaysFalse()
- elif left is AlwaysTrue():
- return right
- elif right is AlwaysTrue():
- return left
- else:
- result = super().__new__(cls)
- object.__setattr__(result, "left", left)
- object.__setattr__(result, "right", right)
- return result
-
- def __invert__(self) -> Or:
- return Or(~self.left, ~self.right)
-
-
-@dataclass(frozen=True, init=False)
-class Or(BooleanExpression):
- """OR operation expression - logical disjunction"""
-
- left: BooleanExpression
- right: BooleanExpression
-
- def __new__(cls, left: BooleanExpression, right: BooleanExpression, *rest: BooleanExpression):
- if rest:
- return reduce(Or, (left, right, *rest))
- if left is AlwaysTrue() or right is AlwaysTrue():
- return AlwaysTrue()
- elif left is AlwaysFalse():
- return right
- elif right is AlwaysFalse():
- return left
- else:
- result = super().__new__(cls)
- object.__setattr__(result, "left", left)
- object.__setattr__(result, "right", right)
- return result
-
- def __invert__(self) -> And:
- return And(~self.left, ~self.right)
-
-
-@dataclass(frozen=True, init=False)
-class Not(BooleanExpression):
- """NOT operation expression - logical negation"""
-
- child: BooleanExpression
-
- def __new__(cls, child: BooleanExpression):
- if child is AlwaysTrue():
- return AlwaysFalse()
- elif child is AlwaysFalse():
- return AlwaysTrue()
- elif isinstance(child, Not):
- return child.child
- result = super().__new__(cls)
- object.__setattr__(result, "child", child)
- return result
-
- def __invert__(self) -> BooleanExpression:
- return self.child
-
-
-@dataclass(frozen=True)
-class AlwaysTrue(BooleanExpression, Singleton):
- """TRUE expression"""
-
- def __invert__(self) -> AlwaysFalse:
- return AlwaysFalse()
-
-
-@dataclass(frozen=True)
-class AlwaysFalse(BooleanExpression, Singleton):
- """FALSE expression"""
-
- def __invert__(self) -> AlwaysTrue:
- return AlwaysTrue()
-
-
-@dataclass(frozen=True)
-class BoundPredicate(Generic[T], Bound, BooleanExpression):
- term: BoundTerm[T]
-
- def __invert__(self) -> BoundPredicate[T]:
- """Inverts the predicate"""
- raise NotImplementedError
-
-
-@dataclass(frozen=True)
-class UnboundPredicate(Generic[T], Unbound[BooleanExpression], BooleanExpression):
- as_bound: ClassVar[type]
- term: UnboundTerm[T]
-
- def __invert__(self) -> UnboundPredicate[T]:
- """Inverts the predicate"""
- raise NotImplementedError
-
- def bind(self, schema: Schema, case_sensitive: bool = True) -> BooleanExpression:
- """Binds the predicate to a schema"""
- raise NotImplementedError
-
-
-@dataclass(frozen=True)
-class UnaryPredicate(UnboundPredicate[T]):
- def bind(self, schema: Schema, case_sensitive: bool = True) -> BooleanExpression:
- bound_term = self.term.bind(schema, case_sensitive)
- return self.as_bound(bound_term)
-
- def __invert__(self) -> UnaryPredicate[T]:
- """Inverts the unary predicate"""
- raise NotImplementedError
-
-
-@dataclass(frozen=True)
-class BoundUnaryPredicate(BoundPredicate[T]):
- def __invert__(self) -> BoundUnaryPredicate[T]:
- """Inverts the unary predicate"""
- raise NotImplementedError
-
-
-@dataclass(frozen=True)
-class BoundIsNull(BoundUnaryPredicate[T]):
- def __new__(cls, term: BoundTerm[T]): # pylint: disable=W0221
- if term.ref().field.required:
- return AlwaysFalse()
- return super().__new__(cls)
-
- def __invert__(self) -> BoundNotNull[T]:
- return BoundNotNull(self.term)
-
-
-@dataclass(frozen=True)
-class BoundNotNull(BoundUnaryPredicate[T]):
- def __new__(cls, term: BoundTerm[T]): # pylint: disable=W0221
- if term.ref().field.required:
- return AlwaysTrue()
- return super().__new__(cls)
-
- def __invert__(self) -> BoundIsNull:
- return BoundIsNull(self.term)
-
-
-@dataclass(frozen=True)
-class IsNull(UnaryPredicate[T]):
- as_bound = BoundIsNull
-
- def __invert__(self) -> NotNull[T]:
- return NotNull(self.term)
-
-
-@dataclass(frozen=True)
-class NotNull(UnaryPredicate[T]):
- as_bound = BoundNotNull
-
- def __invert__(self) -> IsNull[T]:
- return IsNull(self.term)
-
-
-@dataclass(frozen=True)
-class BoundIsNaN(BoundUnaryPredicate[T]):
- def __new__(cls, term: BoundTerm[T]): # pylint: disable=W0221
- bound_type = term.ref().field.field_type
- if type(bound_type) in {FloatType, DoubleType}:
- return super().__new__(cls)
- return AlwaysFalse()
-
- def __invert__(self) -> BoundNotNaN[T]:
- return BoundNotNaN(self.term)
-
-
-@dataclass(frozen=True)
-class BoundNotNaN(BoundUnaryPredicate[T]):
- def __new__(cls, term: BoundTerm[T]): # pylint: disable=W0221
- bound_type = term.ref().field.field_type
- if type(bound_type) in {FloatType, DoubleType}:
- return super().__new__(cls)
- return AlwaysTrue()
-
- def __invert__(self) -> BoundIsNaN[T]:
- return BoundIsNaN(self.term)
-
-
-@dataclass(frozen=True)
-class IsNaN(UnaryPredicate[T]):
- as_bound = BoundIsNaN
-
- def __invert__(self) -> NotNaN[T]:
- return NotNaN(self.term)
-
-
-@dataclass(frozen=True)
-class NotNaN(UnaryPredicate[T]):
- as_bound = BoundNotNaN
-
- def __invert__(self) -> IsNaN[T]:
- return IsNaN(self.term)
-
-
-@dataclass(frozen=True)
-class SetPredicate(UnboundPredicate[T]):
- literals: tuple[Literal[T], ...]
-
- def __invert__(self) -> SetPredicate[T]:
- """Inverted expression of the SetPredicate"""
- raise NotImplementedError
-
- def bind(self, schema: Schema, case_sensitive: bool = True) -> BooleanExpression:
- bound_term = self.term.bind(schema, case_sensitive)
- return self.as_bound(bound_term, {lit.to(bound_term.ref().field.field_type) for lit in self.literals})
-
-
-@dataclass(frozen=True)
-class BoundSetPredicate(BoundPredicate[T]):
- literals: set[Literal[T]]
-
- def __invert__(self) -> BoundSetPredicate[T]:
- """Inverted expression of the SetPredicate"""
- raise NotImplementedError
-
-
-@dataclass(frozen=True)
-class BoundIn(BoundSetPredicate[T]):
- def __new__(cls, term: BoundTerm[T], literals: set[Literal[T]]): # pylint: disable=W0221
- count = len(literals)
- if count == 0:
- return AlwaysFalse()
- elif count == 1:
- return BoundEqualTo(term, next(iter(literals)))
- else:
- return super().__new__(cls)
-
- def __invert__(self) -> BoundNotIn[T]:
- return BoundNotIn(self.term, self.literals)
-
-
-@dataclass(frozen=True)
-class BoundNotIn(BoundSetPredicate[T]):
- def __new__(cls, term: BoundTerm[T], literals: set[Literal[T]]): # pylint: disable=W0221
- count = len(literals)
- if count == 0:
- return AlwaysTrue()
- elif count == 1:
- return BoundNotEqualTo(term, next(iter(literals)))
- else:
- return super().__new__(cls)
-
- def __invert__(self) -> BoundIn[T]:
- return BoundIn(self.term, self.literals)
-
-
-@dataclass(frozen=True)
-class In(SetPredicate[T]):
- as_bound = BoundIn
-
- def __new__(cls, term: UnboundTerm[T], literals: tuple[Literal[T], ...]): # pylint: disable=W0221
- count = len(literals)
- if count == 0:
- return AlwaysFalse()
- elif count == 1:
- return EqualTo(term, literals[0])
- else:
- return super().__new__(cls)
-
- def __invert__(self) -> NotIn[T]:
- return NotIn(self.term, self.literals)
-
-
-@dataclass(frozen=True)
-class NotIn(SetPredicate[T]):
- as_bound = BoundNotIn
-
- def __new__(cls, term: UnboundTerm[T], literals: tuple[Literal[T], ...]): # pylint: disable=W0221
- count = len(literals)
- if count == 0:
- return AlwaysTrue()
- elif count == 1:
- return NotEqualTo(term, literals[0])
- else:
- return super().__new__(cls)
-
- def __invert__(self) -> In[T]:
- return In(self.term, self.literals)
-
-
-@dataclass(frozen=True)
-class LiteralPredicate(UnboundPredicate[T]):
- literal: Literal[T]
-
- def bind(self, schema: Schema, case_sensitive: bool = True) -> BooleanExpression:
- bound_term = self.term.bind(schema, case_sensitive)
- return self.as_bound(bound_term, self.literal.to(bound_term.ref().field.field_type))
-
- def __invert__(self) -> LiteralPredicate[T]:
- """Inverts the literal predicate"""
- raise NotImplementedError
-
-
-@dataclass(frozen=True)
-class BoundLiteralPredicate(BoundPredicate[T]):
- literal: Literal[T]
-
- def __invert__(self) -> BoundLiteralPredicate[T]:
- """Inverts the bound literal predicate"""
- raise NotImplementedError
-
-
-@dataclass(frozen=True)
-class BoundEqualTo(BoundLiteralPredicate[T]):
- def __invert__(self) -> BoundNotEqualTo[T]:
- return BoundNotEqualTo(self.term, self.literal)
-
-
-@dataclass(frozen=True)
-class BoundNotEqualTo(BoundLiteralPredicate[T]):
- def __invert__(self) -> BoundEqualTo[T]:
- return BoundEqualTo(self.term, self.literal)
-
-
-@dataclass(frozen=True)
-class BoundGreaterThanOrEqual(BoundLiteralPredicate[T]):
- def __invert__(self) -> BoundLessThan[T]:
- return BoundLessThan(self.term, self.literal)
-
-
-@dataclass(frozen=True)
-class BoundGreaterThan(BoundLiteralPredicate[T]):
- def __invert__(self) -> BoundLessThanOrEqual[T]:
- return BoundLessThanOrEqual(self.term, self.literal)
-
-
-@dataclass(frozen=True)
-class BoundLessThan(BoundLiteralPredicate[T]):
- def __invert__(self) -> BoundGreaterThanOrEqual[T]:
- return BoundGreaterThanOrEqual(self.term, self.literal)
-
-
-@dataclass(frozen=True)
-class BoundLessThanOrEqual(BoundLiteralPredicate[T]):
- def __invert__(self) -> BoundGreaterThan[T]:
- return BoundGreaterThan(self.term, self.literal)
-
-
-@dataclass(frozen=True)
-class EqualTo(LiteralPredicate[T]):
- as_bound = BoundEqualTo
-
- def __invert__(self) -> NotEqualTo[T]:
- return NotEqualTo(self.term, self.literal)
-
-
-@dataclass(frozen=True)
-class NotEqualTo(LiteralPredicate[T]):
- as_bound = BoundNotEqualTo
-
- def __invert__(self) -> EqualTo[T]:
- return EqualTo(self.term, self.literal)
-
-
-@dataclass(frozen=True)
-class LessThan(LiteralPredicate[T]):
- as_bound = BoundLessThan
-
- def __invert__(self) -> GreaterThanOrEqual[T]:
- return GreaterThanOrEqual(self.term, self.literal)
-
-
-@dataclass(frozen=True)
-class GreaterThanOrEqual(LiteralPredicate[T]):
- as_bound = BoundGreaterThanOrEqual
-
- def __invert__(self) -> LessThan[T]:
- return LessThan(self.term, self.literal)
-
-
-@dataclass(frozen=True)
-class GreaterThan(LiteralPredicate[T]):
- as_bound = BoundGreaterThan
-
- def __invert__(self) -> LessThanOrEqual[T]:
- return LessThanOrEqual(self.term, self.literal)
-
-
-@dataclass(frozen=True)
-class LessThanOrEqual(LiteralPredicate[T]):
- as_bound = BoundLessThanOrEqual
-
- def __invert__(self) -> GreaterThan[T]:
- return GreaterThan(self.term, self.literal)
class BooleanExpressionVisitor(Generic[T], ABC):
@@ -720,11 +238,11 @@ class BindVisitor(BooleanExpressionVisitor[BooleanExpression]):
class BoundBooleanExpressionVisitor(BooleanExpressionVisitor[T], ABC):
@abstractmethod
- def visit_in(self, term: BoundTerm[T], literals: set[Literal[Any]]) -> T:
+ def visit_in(self, term: BoundTerm[T], literals: Set[Literal[Any]]) -> T:
"""Visit a bound In predicate"""
@abstractmethod
- def visit_not_in(self, term: BoundTerm[T], literals: set[Literal[Any]]) -> T:
+ def visit_not_in(self, term: BoundTerm[T], literals: Set[Literal[Any]]) -> T:
"""Visit a bound NotIn predicate"""
@abstractmethod
@@ -911,7 +429,7 @@ def _from_byte_buffer(field_type: IcebergType, val: bytes):
class _ManifestEvalVisitor(BoundBooleanExpressionVisitor[bool]):
- partition_fields: list[PartitionFieldSummary]
+ partition_fields: List[PartitionFieldSummary]
partition_filter: BooleanExpression
def __init__(self, partition_struct_schema: Schema, partition_filter: BooleanExpression, case_sensitive: bool = True):
@@ -925,7 +443,7 @@ class _ManifestEvalVisitor(BoundBooleanExpressionVisitor[bool]):
# No partition information
return ROWS_MIGHT_MATCH
- def visit_in(self, term: BoundTerm, literals: set[Literal[Any]]) -> bool:
+ def visit_in(self, term: BoundTerm, literals: Set[Literal[Any]]) -> bool:
pos = term.ref().accessor.position
field = self.partition_fields[pos]
@@ -947,7 +465,7 @@ class _ManifestEvalVisitor(BoundBooleanExpressionVisitor[bool]):
return ROWS_MIGHT_MATCH
- def visit_not_in(self, term: BoundTerm, literals: set[Literal[Any]]) -> bool:
+ def visit_not_in(self, term: BoundTerm, literals: Set[Literal[Any]]) -> bool:
# because the bounds are not necessarily a min or max value, this cannot be answered using
# them. notIn(col, {X, ...}) with (X, Y) doesn't guarantee that X is a value in col.
return ROWS_MIGHT_MATCH
diff --git a/python/tests/expressions/test_expressions.py b/python/tests/expressions/test_expressions.py
new file mode 100644
index 0000000000..6ccada73a4
--- /dev/null
+++ b/python/tests/expressions/test_expressions.py
@@ -0,0 +1,746 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+import uuid
+from decimal import Decimal
+
+import pytest
+
+from pyiceberg.expressions import (
+ AlwaysFalse,
+ AlwaysTrue,
+ And,
+ BooleanExpression,
+ BoundEqualTo,
+ BoundGreaterThan,
+ BoundGreaterThanOrEqual,
+ BoundIn,
+ BoundIsNaN,
+ BoundIsNull,
+ BoundLessThan,
+ BoundLessThanOrEqual,
+ BoundLiteralPredicate,
+ BoundNotEqualTo,
+ BoundNotIn,
+ BoundNotNaN,
+ BoundNotNull,
+ BoundPredicate,
+ BoundReference,
+ BoundSetPredicate,
+ BoundUnaryPredicate,
+ EqualTo,
+ GreaterThan,
+ GreaterThanOrEqual,
+ In,
+ IsNaN,
+ IsNull,
+ LessThan,
+ LessThanOrEqual,
+ LiteralPredicate,
+ Not,
+ NotEqualTo,
+ NotIn,
+ NotNaN,
+ NotNull,
+ Or,
+ Reference,
+ SetPredicate,
+ UnaryPredicate,
+ UnboundPredicate,
+)
+from pyiceberg.expressions.literals import StringLiteral, literal
+from pyiceberg.expressions.visitors import _from_byte_buffer
+from pyiceberg.schema import Accessor, Schema
+from pyiceberg.types import (
+ DoubleType,
+ FloatType,
+ IntegerType,
+ ListType,
+ NestedField,
+ StringType,
+)
+from tests.expressions.test_visitors import ExpressionA, ExpressionB
+
+
+@pytest.mark.parametrize(
+ "op, rep",
+ [
+ (
+ And(ExpressionA(), ExpressionB()),
+ "And(left=ExpressionA(), right=ExpressionB())",
+ ),
+ (
+ Or(ExpressionA(), ExpressionB()),
+ "Or(left=ExpressionA(), right=ExpressionB())",
+ ),
+ (Not(ExpressionA()), "Not(child=ExpressionA())"),
+ ],
+)
+def test_reprs(op: BooleanExpression, rep: str):
+ assert repr(op) == rep
+
+
+def test_isnull_inverse():
+ assert ~IsNull(Reference("a")) == NotNull(Reference("a"))
+
+
+def test_isnull_bind():
+ schema = Schema(NestedField(2, "a", IntegerType()), schema_id=1)
+ bound = BoundIsNull(BoundReference(schema.find_field(2), schema.accessor_for_field(2)))
+ assert IsNull(Reference("a")).bind(schema) == bound
+
+
+def test_invert_is_null_bind():
+ schema = Schema(NestedField(2, "a", IntegerType(), required=False), schema_id=1)
+ assert ~IsNull(Reference("a")).bind(schema) == NotNull(Reference("a")).bind(schema)
+
+
+def test_invert_not_null_bind():
+ schema = Schema(NestedField(2, "a", IntegerType(), required=False), schema_id=1)
+ assert ~NotNull(Reference("a")).bind(schema) == IsNull(Reference("a")).bind(schema)
+
+
+def test_invert_is_nan_bind():
+ schema = Schema(NestedField(2, "a", DoubleType(), required=False), schema_id=1)
+ assert ~IsNaN(Reference("a")).bind(schema) == NotNaN(Reference("a")).bind(schema)
+
+
+def test_invert_not_nan_bind():
+ schema = Schema(NestedField(2, "a", DoubleType(), required=False), schema_id=1)
+ assert ~NotNaN(Reference("a")).bind(schema) == IsNaN(Reference("a")).bind(schema)
+
+
+def test_bind_expr_does_not_exists():
+ schema = Schema(NestedField(2, "a", IntegerType()), schema_id=1)
+ with pytest.raises(ValueError) as exc_info:
+ IsNull(Reference("b")).bind(schema)
+
+ assert str(exc_info.value) == "Could not find field with name b, case_sensitive=True"
+
+
+def test_bind_does_not_exists():
+ schema = Schema(NestedField(2, "a", IntegerType()), schema_id=1)
+ with pytest.raises(ValueError) as exc_info:
+ Reference("b").bind(schema)
+
+ assert str(exc_info.value) == "Could not find field with name b, case_sensitive=True"
+
+
+def test_isnull_bind_required():
+ schema = Schema(NestedField(2, "a", IntegerType(), required=True), schema_id=1)
+ assert IsNull(Reference("a")).bind(schema) == AlwaysFalse()
+
+
+def test_notnull_inverse():
+ assert ~NotNull(Reference("a")) == IsNull(Reference("a"))
+
+
+def test_notnull_bind():
+ schema = Schema(NestedField(2, "a", IntegerType()), schema_id=1)
+ bound = BoundNotNull(BoundReference(schema.find_field(2), schema.accessor_for_field(2)))
+ assert NotNull(Reference("a")).bind(schema) == bound
+
+
+def test_notnull_bind_required():
+ schema = Schema(NestedField(2, "a", IntegerType(), required=True), schema_id=1)
+ assert NotNull(Reference("a")).bind(schema) == AlwaysTrue()
+
+
+def test_isnan_inverse():
+ assert ~IsNaN(Reference("f")) == NotNaN(Reference("f"))
+
+
+def test_isnan_bind_float():
+ schema = Schema(NestedField(2, "f", FloatType()), schema_id=1)
+ bound = BoundIsNaN(BoundReference(schema.find_field(2), schema.accessor_for_field(2)))
+ assert IsNaN(Reference("f")).bind(schema) == bound
+
+
+def test_isnan_bind_double():
+ schema = Schema(NestedField(2, "d", DoubleType()), schema_id=1)
+ bound = BoundIsNaN(BoundReference(schema.find_field(2), schema.accessor_for_field(2)))
+ assert IsNaN(Reference("d")).bind(schema) == bound
+
+
+def test_isnan_bind_nonfloat():
+ schema = Schema(NestedField(2, "i", IntegerType()), schema_id=1)
+ assert IsNaN(Reference("i")).bind(schema) == AlwaysFalse()
+
+
+def test_notnan_inverse():
+ assert ~NotNaN(Reference("f")) == IsNaN(Reference("f"))
+
+
+def test_notnan_bind_float():
+ schema = Schema(NestedField(2, "f", FloatType()), schema_id=1)
+ bound = BoundNotNaN(BoundReference(schema.find_field(2), schema.accessor_for_field(2)))
+ assert NotNaN(Reference("f")).bind(schema) == bound
+
+
+def test_notnan_bind_double():
+ schema = Schema(NestedField(2, "d", DoubleType()), schema_id=1)
+ bound = BoundNotNaN(BoundReference(schema.find_field(2), schema.accessor_for_field(2)))
+ assert NotNaN(Reference("d")).bind(schema) == bound
+
+
+def test_notnan_bind_nonfloat():
+ schema = Schema(NestedField(2, "i", IntegerType()), schema_id=1)
+ assert NotNaN(Reference("i")).bind(schema) == AlwaysTrue()
+
+
+@pytest.mark.parametrize(
+ "op, string",
+ [
+ (And(ExpressionA(), ExpressionB()), "And(left=ExpressionA(), right=ExpressionB())"),
+ (Or(ExpressionA(), ExpressionB()), "Or(left=ExpressionA(), right=ExpressionB())"),
+ (Not(ExpressionA()), "Not(child=ExpressionA())"),
+ ],
+)
+def test_strs(op, string):
+ assert str(op) == string
+
+
+def test_ref_binding_case_sensitive(table_schema_simple: Schema):
+ ref = Reference[str]("foo")
+ bound = BoundReference[str](table_schema_simple.find_field(1), table_schema_simple.accessor_for_field(1))
+ assert ref.bind(table_schema_simple, case_sensitive=True) == bound
+
+
+def test_ref_binding_case_sensitive_failure(table_schema_simple: Schema):
+ ref = Reference[str]("Foo")
+ with pytest.raises(ValueError):
+ ref.bind(table_schema_simple, case_sensitive=True)
+
+
+def test_ref_binding_case_insensitive(table_schema_simple: Schema):
+ ref = Reference[str]("Foo")
+ bound = BoundReference[str](table_schema_simple.find_field(1), table_schema_simple.accessor_for_field(1))
+ assert ref.bind(table_schema_simple, case_sensitive=False) == bound
+
+
+def test_ref_binding_case_insensitive_failure(table_schema_simple: Schema):
+ ref = Reference[str]("Foot")
+ with pytest.raises(ValueError):
+ ref.bind(table_schema_simple, case_sensitive=False)
+
+
+def test_in_to_eq():
+ assert In(Reference("x"), (literal(34.56),)) == EqualTo(Reference("x"), literal(34.56))
+
+
+def test_empty_bind_in(table_schema_simple: Schema):
+ bound = BoundIn[str](BoundReference(table_schema_simple.find_field(1), table_schema_simple.accessor_for_field(1)), set())
+ assert bound == AlwaysFalse()
+
+
+def test_empty_bind_not_in(table_schema_simple: Schema):
+ bound = BoundNotIn(BoundReference[str](table_schema_simple.find_field(1), table_schema_simple.accessor_for_field(1)), set())
+ assert bound == AlwaysTrue()
+
+
+def test_bind_not_in_equal_term(table_schema_simple: Schema):
+ bound = BoundNotIn(
+ BoundReference(table_schema_simple.find_field(1), table_schema_simple.accessor_for_field(1)), {literal("hello")}
+ )
+ assert (
+ BoundNotEqualTo[str](
+ term=BoundReference(
+ field=NestedField(field_id=1, name="foo", field_type=StringType(), required=False),
+ accessor=Accessor(position=0, inner=None),
+ ),
+ literal=StringLiteral("hello"),
+ )
+ == bound
+ )
+
+
+def test_in_empty():
+ assert In(Reference("foo"), ()) == AlwaysFalse()
+
+
+def test_not_in_empty():
+ assert NotIn(Reference("foo"), ()) == AlwaysTrue()
+
+
+def test_not_in_equal():
+ assert NotIn(Reference("foo"), (literal("hello"),)) == NotEqualTo(term=Reference(name="foo"), literal=StringLiteral("hello"))
+
+
+def test_bind_in(table_schema_simple: Schema):
+ bound = BoundIn(
+ BoundReference(table_schema_simple.find_field(1), table_schema_simple.accessor_for_field(1)),
+ {literal("hello"), literal("world")},
+ )
+ assert In(Reference("foo"), (literal("hello"), literal("world"))).bind(table_schema_simple) == bound
+
+
+def test_bind_in_invert(table_schema_simple: Schema):
+ bound = BoundIn(
+ BoundReference(table_schema_simple.find_field(1), table_schema_simple.accessor_for_field(1)),
+ {literal("hello"), literal("world")},
+ )
+ assert ~bound == BoundNotIn(
+ BoundReference(table_schema_simple.find_field(1), table_schema_simple.accessor_for_field(1)),
+ {literal("hello"), literal("world")},
+ )
+
+
+def test_bind_not_in_invert(table_schema_simple: Schema):
+ bound = BoundNotIn(
+ BoundReference(table_schema_simple.find_field(1), table_schema_simple.accessor_for_field(1)),
+ {literal("hello"), literal("world")},
+ )
+ assert ~bound == BoundIn(
+ BoundReference(table_schema_simple.find_field(1), table_schema_simple.accessor_for_field(1)),
+ {literal("hello"), literal("world")},
+ )
+
+
+def test_bind_dedup(table_schema_simple: Schema):
+ bound = BoundIn(
+ BoundReference(table_schema_simple.find_field(1), table_schema_simple.accessor_for_field(1)),
+ {literal("hello"), literal("world")},
+ )
+ assert In(Reference("foo"), (literal("hello"), literal("world"), literal("world"))).bind(table_schema_simple) == bound
+
+
+def test_bind_dedup_to_eq(table_schema_simple: Schema):
+ bound = BoundEqualTo(
+ BoundReference(table_schema_simple.find_field(1), table_schema_simple.accessor_for_field(1)), literal("hello")
+ )
+ assert In(Reference("foo"), (literal("hello"), literal("hello"))).bind(table_schema_simple) == bound
+
+
+def test_bound_equal_to_invert(table_schema_simple: Schema):
+ bound = BoundEqualTo(
+ BoundReference(table_schema_simple.find_field(1), table_schema_simple.accessor_for_field(1)), literal("hello")
+ )
+ assert ~bound == BoundNotEqualTo(
+ term=BoundReference[str](
+ field=NestedField(field_id=1, name="foo", field_type=StringType(), required=False),
+ accessor=Accessor(position=0, inner=None),
+ ),
+ literal=StringLiteral("hello"),
+ )
+
+
+def test_bound_not_equal_to_invert(table_schema_simple: Schema):
+ bound = BoundNotEqualTo(
+ BoundReference(table_schema_simple.find_field(1), table_schema_simple.accessor_for_field(1)), literal("hello")
+ )
+ assert ~bound == BoundEqualTo(
+ term=BoundReference[str](
+ field=NestedField(field_id=1, name="foo", field_type=StringType(), required=False),
+ accessor=Accessor(position=0, inner=None),
+ ),
+ literal=StringLiteral("hello"),
+ )
+
+
+def test_bound_greater_than_or_equal_invert(table_schema_simple: Schema):
+ bound = BoundGreaterThanOrEqual(
+ BoundReference(table_schema_simple.find_field(1), table_schema_simple.accessor_for_field(1)), literal("hello")
+ )
+ assert ~bound == BoundLessThan(
+ term=BoundReference[str](
+ field=NestedField(field_id=1, name="foo", field_type=StringType(), required=False),
+ accessor=Accessor(position=0, inner=None),
+ ),
+ literal=StringLiteral("hello"),
+ )
+
+
+def test_bound_greater_than_invert(table_schema_simple: Schema):
+ bound = BoundGreaterThan(
+ BoundReference(table_schema_simple.find_field(1), table_schema_simple.accessor_for_field(1)), literal("hello")
+ )
+ assert ~bound == BoundLessThanOrEqual(
+ term=BoundReference[str](
+ field=NestedField(field_id=1, name="foo", field_type=StringType(), required=False),
+ accessor=Accessor(position=0, inner=None),
+ ),
+ literal=StringLiteral("hello"),
+ )
+
+
+def test_bound_less_than_invert(table_schema_simple: Schema):
+ bound = BoundLessThan(
+ BoundReference(table_schema_simple.find_field(1), table_schema_simple.accessor_for_field(1)), literal("hello")
+ )
+ assert ~bound == BoundGreaterThanOrEqual(
+ term=BoundReference[str](
+ field=NestedField(field_id=1, name="foo", field_type=StringType(), required=False),
+ accessor=Accessor(position=0, inner=None),
+ ),
+ literal=StringLiteral("hello"),
+ )
+
+
+def test_bound_less_than_or_equal_invert(table_schema_simple: Schema):
+ bound = BoundLessThanOrEqual(
+ BoundReference(table_schema_simple.find_field(1), table_schema_simple.accessor_for_field(1)), literal("hello")
+ )
+ assert ~bound == BoundGreaterThan(
+ term=BoundReference[str](
+ field=NestedField(field_id=1, name="foo", field_type=StringType(), required=False),
+ accessor=Accessor(position=0, inner=None),
+ ),
+ literal=StringLiteral("hello"),
+ )
+
+
+def test_not_equal_to_invert():
+ bound = NotEqualTo(
+ term=BoundReference(
+ field=NestedField(field_id=1, name="foo", field_type=StringType(), required=False),
+ accessor=Accessor(position=0, inner=None),
+ ),
+ literal=StringLiteral("hello"),
+ )
+ assert ~bound == EqualTo(
+ term=BoundReference(
+ field=NestedField(field_id=1, name="foo", field_type=StringType(), required=False),
+ accessor=Accessor(position=0, inner=None),
+ ),
+ literal=StringLiteral("hello"),
+ )
+
+
+def test_greater_than_or_equal_invert():
+ bound = GreaterThanOrEqual(
+ term=BoundReference(
+ field=NestedField(field_id=1, name="foo", field_type=StringType(), required=False),
+ accessor=Accessor(position=0, inner=None),
+ ),
+ literal=StringLiteral("hello"),
+ )
+ assert ~bound == LessThan(
+ term=BoundReference(
+ field=NestedField(field_id=1, name="foo", field_type=StringType(), required=False),
+ accessor=Accessor(position=0, inner=None),
+ ),
+ literal=StringLiteral("hello"),
+ )
+
+
+def test_less_than_or_equal_invert():
+ bound = LessThanOrEqual(
+ term=BoundReference(
+ field=NestedField(field_id=1, name="foo", field_type=StringType(), required=False),
+ accessor=Accessor(position=0, inner=None),
+ ),
+ literal=StringLiteral("hello"),
+ )
+ assert ~bound == GreaterThan(
+ term=BoundReference(
+ field=NestedField(field_id=1, name="foo", field_type=StringType(), required=False),
+ accessor=Accessor(position=0, inner=None),
+ ),
+ literal=StringLiteral("hello"),
+ )
+
+
+@pytest.mark.parametrize(
+ "pred",
+ [
+ NotIn(Reference("foo"), (literal("hello"), literal("world"))),
+ NotEqualTo(Reference("foo"), literal("hello")),
+ EqualTo(Reference("foo"), literal("hello")),
+ GreaterThan(Reference("foo"), literal("hello")),
+ LessThan(Reference("foo"), literal("hello")),
+ GreaterThanOrEqual(Reference("foo"), literal("hello")),
+ LessThanOrEqual(Reference("foo"), literal("hello")),
+ ],
+)
+def test_bind(pred, table_schema_simple: Schema):
+ assert pred.bind(table_schema_simple, case_sensitive=True).term.field == table_schema_simple.find_field(
+ pred.term.name, case_sensitive=True
+ )
+
+
+@pytest.mark.parametrize(
+ "pred",
+ [
+ In(Reference("Bar"), (literal(5), literal(2))),
+ NotIn(Reference("Bar"), (literal(5), literal(2))),
+ NotEqualTo(Reference("Bar"), literal(5)),
+ EqualTo(Reference("Bar"), literal(5)),
+ GreaterThan(Reference("Bar"), literal(5)),
+ LessThan(Reference("Bar"), literal(5)),
+ GreaterThanOrEqual(Reference("Bar"), literal(5)),
+ LessThanOrEqual(Reference("Bar"), literal(5)),
+ ],
+)
+def test_bind_case_insensitive(pred, table_schema_simple: Schema):
+ assert pred.bind(table_schema_simple, case_sensitive=False).term.field == table_schema_simple.find_field(
+ pred.term.name, case_sensitive=False
+ )
+
+
+@pytest.mark.parametrize(
+ "exp, testexpra, testexprb",
+ [
+ (
+ And(ExpressionA(), ExpressionB()),
+ And(ExpressionA(), ExpressionB()),
+ Or(ExpressionA(), ExpressionB()),
+ ),
+ (
+ Or(ExpressionA(), ExpressionB()),
+ Or(ExpressionA(), ExpressionB()),
+ And(ExpressionA(), ExpressionB()),
+ ),
+ (Not(ExpressionA()), Not(ExpressionA()), ExpressionB()),
+ (ExpressionA(), ExpressionA(), ExpressionB()),
+ (ExpressionB(), ExpressionB(), ExpressionA()),
+ (
+ In(Reference("foo"), (literal("hello"), literal("world"))),
+ In(Reference("foo"), (literal("hello"), literal("world"))),
+ In(Reference("not_foo"), (literal("hello"), literal("world"))),
+ ),
+ (
+ In(Reference("foo"), (literal("hello"), literal("world"))),
+ In(Reference("foo"), (literal("hello"), literal("world"))),
+ In(Reference("foo"), (literal("goodbye"), literal("world"))),
+ ),
+ ],
+)
+def test_eq(exp, testexpra, testexprb):
+ assert exp == testexpra and exp != testexprb
+
+
+@pytest.mark.parametrize(
+ "lhs, rhs",
+ [
+ (
+ And(ExpressionA(), ExpressionB()),
+ Or(ExpressionB(), ExpressionA()),
+ ),
+ (
+ Or(ExpressionA(), ExpressionB()),
+ And(ExpressionB(), ExpressionA()),
+ ),
+ (
+ Not(ExpressionA()),
+ ExpressionA(),
+ ),
+ (
+ In(Reference("foo"), (literal("hello"), literal("world"))),
+ NotIn(Reference("foo"), (literal("hello"), literal("world"))),
+ ),
+ (
+ NotIn(Reference("foo"), (literal("hello"), literal("world"))),
+ In(Reference("foo"), (literal("hello"), literal("world"))),
+ ),
+ (GreaterThan(Reference("foo"), literal(5)), LessThanOrEqual(Reference("foo"), literal(5))),
+ (LessThan(Reference("foo"), literal(5)), GreaterThanOrEqual(Reference("foo"), literal(5))),
+ (EqualTo(Reference("foo"), literal(5)), NotEqualTo(Reference("foo"), literal(5))),
+ (
+ ExpressionA(),
+ ExpressionB(),
+ ),
+ ],
+)
+def test_negate(lhs, rhs):
+ assert ~lhs == rhs
+
+
+@pytest.mark.parametrize(
+ "lhs, rhs",
+ [
+ (
+ And(ExpressionA(), ExpressionB(), ExpressionA()),
+ And(And(ExpressionA(), ExpressionB()), ExpressionA()),
+ ),
+ (
+ Or(ExpressionA(), ExpressionB(), ExpressionA()),
+ Or(Or(ExpressionA(), ExpressionB()), ExpressionA()),
+ ),
+ (Not(Not(ExpressionA())), ExpressionA()),
+ ],
+)
+def test_reduce(lhs, rhs):
+ assert lhs == rhs
+
+
+@pytest.mark.parametrize(
+ "lhs, rhs",
+ [
+ (And(AlwaysTrue(), ExpressionB()), ExpressionB()),
+ (And(AlwaysFalse(), ExpressionB()), AlwaysFalse()),
+ (And(ExpressionB(), AlwaysTrue()), ExpressionB()),
+ (Or(AlwaysTrue(), ExpressionB()), AlwaysTrue()),
+ (Or(AlwaysFalse(), ExpressionB()), ExpressionB()),
+ (Or(ExpressionA(), AlwaysFalse()), ExpressionA()),
+ (Not(Not(ExpressionA())), ExpressionA()),
+ (Not(AlwaysTrue()), AlwaysFalse()),
+ (Not(AlwaysFalse()), AlwaysTrue()),
+ ],
+)
+def test_base_AlwaysTrue_base_AlwaysFalse(lhs, rhs):
+ assert lhs == rhs
+
+
+def test_invert_always():
+ assert ~AlwaysFalse() == AlwaysTrue()
+ assert ~AlwaysTrue() == AlwaysFalse()
+
+
+def test_accessor_base_class(foo_struct):
+ """Test retrieving a value at a position of a container using an accessor"""
+
+ uuid_value = uuid.uuid4()
+
+ foo_struct.set(0, "foo")
+ foo_struct.set(1, "bar")
+ foo_struct.set(2, "baz")
+ foo_struct.set(3, 1)
+ foo_struct.set(4, 2)
+ foo_struct.set(5, 3)
+ foo_struct.set(6, 1.234)
+ foo_struct.set(7, Decimal("1.234"))
+ foo_struct.set(8, uuid_value)
+ foo_struct.set(9, True)
+ foo_struct.set(10, False)
+ foo_struct.set(11, b"\x19\x04\x9e?")
+
+ assert Accessor(position=0).get(foo_struct) == "foo"
+ assert Accessor(position=1).get(foo_struct) == "bar"
+ assert Accessor(position=2).get(foo_struct) == "baz"
+ assert Accessor(position=3).get(foo_struct) == 1
+ assert Accessor(position=4).get(foo_struct) == 2
+ assert Accessor(position=5).get(foo_struct) == 3
+ assert Accessor(position=6).get(foo_struct) == 1.234
+ assert Accessor(position=7).get(foo_struct) == Decimal("1.234")
+ assert Accessor(position=8).get(foo_struct) == uuid_value
+ assert Accessor(position=9).get(foo_struct) is True
+ assert Accessor(position=10).get(foo_struct) is False
+ assert Accessor(position=11).get(foo_struct) == b"\x19\x04\x9e?"
+
+
+def test_bound_reference_str_and_repr():
+ """Test str and repr of BoundReference"""
+ field = NestedField(field_id=1, name="foo", field_type=StringType(), required=False)
+ position1_accessor = Accessor(position=1)
+ bound_ref = BoundReference(field=field, accessor=position1_accessor)
+ assert str(bound_ref) == f"BoundReference(field={repr(field)}, accessor={repr(position1_accessor)})"
+ assert repr(bound_ref) == f"BoundReference(field={repr(field)}, accessor={repr(position1_accessor)})"
+
+
+def test_bound_reference_field_property():
+ """Test str and repr of BoundReference"""
+ field = NestedField(field_id=1, name="foo", field_type=StringType(), required=False)
+ position1_accessor = Accessor(position=1)
+ bound_ref = BoundReference(field=field, accessor=position1_accessor)
+ assert bound_ref.field == NestedField(field_id=1, name="foo", field_type=StringType(), required=False)
+
+
+def test_bound_reference(table_schema_simple, foo_struct):
+ """Test creating a BoundReference and evaluating it on a StructProtocol"""
+ foo_struct.set(pos=1, value="foovalue")
+ foo_struct.set(pos=2, value=123)
+ foo_struct.set(pos=3, value=True)
+
+ position1_accessor = Accessor(position=1)
+ position2_accessor = Accessor(position=2)
+ position3_accessor = Accessor(position=3)
+
+ field1 = table_schema_simple.find_field(1)
+ field2 = table_schema_simple.find_field(2)
+ field3 = table_schema_simple.find_field(3)
+
+ bound_ref1 = BoundReference(field=field1, accessor=position1_accessor)
+ bound_ref2 = BoundReference(field=field2, accessor=position2_accessor)
+ bound_ref3 = BoundReference(field=field3, accessor=position3_accessor)
+
+ assert bound_ref1.eval(foo_struct) == "foovalue"
+ assert bound_ref2.eval(foo_struct) == 123
+ assert bound_ref3.eval(foo_struct) is True
+
+
+def test_bound_predicate_invert():
+ with pytest.raises(NotImplementedError):
+ _ = ~BoundPredicate(
+ term=BoundReference(
+ field=NestedField(field_id=1, name="foo", field_type=StringType(), required=False),
+ accessor=Accessor(position=0, inner=None),
+ )
+ )
+
+
+def test_bound_unary_predicate_invert():
+ with pytest.raises(NotImplementedError):
+ _ = ~BoundUnaryPredicate(
+ term=BoundReference(
+ field=NestedField(field_id=1, name="foo", field_type=StringType(), required=False),
+ accessor=Accessor(position=0, inner=None),
+ )
+ )
+
+
+def test_bound_set_predicate_invert():
+ with pytest.raises(NotImplementedError):
+ _ = ~BoundSetPredicate(
+ term=BoundReference(
+ field=NestedField(field_id=1, name="foo", field_type=StringType(), required=False),
+ accessor=Accessor(position=0, inner=None),
+ ),
+ literals={literal("hello"), literal("world")},
+ )
+
+
+def test_bound_literal_predicate_invert():
+ with pytest.raises(NotImplementedError):
+ _ = ~BoundLiteralPredicate(
+ term=BoundReference(
+ field=NestedField(field_id=1, name="foo", field_type=StringType(), required=False),
+ accessor=Accessor(position=0, inner=None),
+ ),
+ literal=literal("world"),
+ )
+
+
+def test_non_primitive_from_byte_buffer():
+ with pytest.raises(ValueError) as exc_info:
+ _ = _from_byte_buffer(ListType(element_id=1, element_type=StringType()), b"\0x00")
+
+ assert str(exc_info.value) == "Expected a PrimitiveType, got: <class 'pyiceberg.types.ListType'>"
+
+
+def test_unbound_predicate_invert():
+ with pytest.raises(NotImplementedError):
+ _ = ~UnboundPredicate(term=Reference("a"))
+
+
+def test_unbound_predicate_bind(table_schema_simple: Schema):
+ with pytest.raises(NotImplementedError):
+ _ = UnboundPredicate(term=Reference("a")).bind(table_schema_simple)
+
+
+def test_unbound_unary_predicate_invert():
+ with pytest.raises(NotImplementedError):
+ _ = ~UnaryPredicate(term=Reference("a"))
+
+
+def test_unbound_set_predicate_invert():
+ with pytest.raises(NotImplementedError):
+ _ = ~SetPredicate(term=Reference("a"), literals=(literal("hello"), literal("world")))
+
+
+def test_unbound_literal_predicate_invert():
+ with pytest.raises(NotImplementedError):
+ _ = ~LiteralPredicate(term=Reference("a"), literal=literal("hello"))
diff --git a/python/tests/expressions/test_expressions_base.py b/python/tests/expressions/test_visitors.py
similarity index 55%
rename from python/tests/expressions/test_expressions_base.py
rename to python/tests/expressions/test_visitors.py
index 6a254c53cc..078dd88747 100644
--- a/python/tests/expressions/test_expressions_base.py
+++ b/python/tests/expressions/test_visitors.py
@@ -15,21 +15,47 @@
# specific language governing permissions and limitations
# under the License.
-import uuid
-from decimal import Decimal
from typing import Any, List, Set
import pytest
from pyiceberg.conversions import to_bytes
-from pyiceberg.expressions import base
-from pyiceberg.expressions.base import (
- IN_PREDICATE_LIMIT,
+from pyiceberg.expressions import (
+ AlwaysFalse,
+ AlwaysTrue,
+ And,
+ BooleanExpression,
+ BoundEqualTo,
+ BoundGreaterThan,
+ BoundGreaterThanOrEqual,
+ BoundIn,
+ BoundIsNaN,
+ BoundIsNull,
+ BoundLessThan,
+ BoundLessThanOrEqual,
+ BoundLiteralPredicate,
+ BoundNotEqualTo,
+ BoundNotIn,
+ BoundNotNaN,
+ BoundNotNull,
BoundPredicate,
- _from_byte_buffer,
- _ManifestEvalVisitor,
- rewrite_not,
- visit_bound_predicate,
+ BoundReference,
+ BoundSetPredicate,
+ BoundTerm,
+ BoundUnaryPredicate,
+ EqualTo,
+ In,
+ IsNull,
+ LessThanOrEqual,
+ LiteralPredicate,
+ Not,
+ NotEqualTo,
+ NotIn,
+ Or,
+ Reference,
+ SetPredicate,
+ UnaryPredicate,
+ UnboundPredicate,
)
from pyiceberg.expressions.literals import (
Literal,
@@ -37,6 +63,16 @@ from pyiceberg.expressions.literals import (
StringLiteral,
literal,
)
+from pyiceberg.expressions.visitors import (
+ IN_PREDICATE_LIMIT,
+ BindVisitor,
+ BooleanExpressionVisitor,
+ BoundBooleanExpressionVisitor,
+ _ManifestEvalVisitor,
+ rewrite_not,
+ visit,
+ visit_bound_predicate,
+)
from pyiceberg.manifest import ManifestFile, PartitionFieldSummary
from pyiceberg.schema import Accessor, Schema
from pyiceberg.types import (
@@ -44,7 +80,6 @@ from pyiceberg.types import (
FloatType,
IcebergType,
IntegerType,
- ListType,
LongType,
NestedField,
PrimitiveType,
@@ -53,7 +88,7 @@ from pyiceberg.types import (
from pyiceberg.utils.singleton import Singleton
-class ExpressionA(base.BooleanExpression, Singleton):
+class ExpressionA(BooleanExpression, Singleton):
def __invert__(self):
return ExpressionB()
@@ -64,7 +99,7 @@ class ExpressionA(base.BooleanExpression, Singleton):
return "testexpra"
-class ExpressionB(base.BooleanExpression, Singleton):
+class ExpressionB(BooleanExpression, Singleton):
def __invert__(self):
return ExpressionA()
@@ -75,7 +110,7 @@ class ExpressionB(base.BooleanExpression, Singleton):
return "testexprb"
-class ExampleVisitor(base.BooleanExpressionVisitor[List]):
+class ExampleVisitor(BooleanExpressionVisitor[List]):
"""A test implementation of a BooleanExpressionVisitor
As this visitor visits each node, it appends an element to a `visit_history` list. This enables testing that a given expression is
@@ -122,19 +157,19 @@ class ExampleVisitor(base.BooleanExpressionVisitor[List]):
return self.visit_history
-@base.visit.register(ExpressionA)
+@visit.register(ExpressionA)
def _(obj: ExpressionA, visitor: ExampleVisitor) -> List:
"""Visit a ExpressionA with a BooleanExpressionVisitor"""
return visitor.visit_test_expression_a()
-@base.visit.register(ExpressionB)
+@visit.register(ExpressionB)
def _(obj: ExpressionB, visitor: ExampleVisitor) -> List:
"""Visit a ExpressionB with a BooleanExpressionVisitor"""
return visitor.visit_test_expression_b()
-class FooBoundBooleanExpressionVisitor(base.BoundBooleanExpressionVisitor[List]):
+class FooBoundBooleanExpressionVisitor(BoundBooleanExpressionVisitor[List]):
"""A test implementation of a BoundBooleanExpressionVisitor
As this visitor visits each node, it appends an element to a `visit_history` list. This enables testing that a given bound expression is
visited in an expected order by the `visit` method.
@@ -143,51 +178,51 @@ class FooBoundBooleanExpressionVisitor(base.BoundBooleanExpressionVisitor[List])
def __init__(self):
self.visit_history: List = []
- def visit_in(self, term: base.BoundTerm, literals: Set) -> List:
+ def visit_in(self, term: BoundTerm, literals: Set) -> List:
self.visit_history.append("IN")
return self.visit_history
- def visit_not_in(self, term: base.BoundTerm, literals: Set) -> List:
+ def visit_not_in(self, term: BoundTerm, literals: Set) -> List:
self.visit_history.append("NOT_IN")
return self.visit_history
- def visit_is_nan(self, term: base.BoundTerm) -> List:
+ def visit_is_nan(self, term: BoundTerm) -> List:
self.visit_history.append("IS_NAN")
return self.visit_history
- def visit_not_nan(self, term: base.BoundTerm) -> List:
+ def visit_not_nan(self, term: BoundTerm) -> List:
self.visit_history.append("NOT_NAN")
return self.visit_history
- def visit_is_null(self, term: base.BoundTerm) -> List:
+ def visit_is_null(self, term: BoundTerm) -> List:
self.visit_history.append("IS_NULL")
return self.visit_history
- def visit_not_null(self, term: base.BoundTerm) -> List:
+ def visit_not_null(self, term: BoundTerm) -> List:
self.visit_history.append("NOT_NULL")
return self.visit_history
- def visit_equal(self, term: base.BoundTerm, literal: Literal) -> List: # pylint: disable=redefined-outer-name
+ def visit_equal(self, term: BoundTerm, literal: Literal) -> List: # pylint: disable=redefined-outer-name
self.visit_history.append("EQUAL")
return self.visit_history
- def visit_not_equal(self, term: base.BoundTerm, literal: Literal) -> List: # pylint: disable=redefined-outer-name
+ def visit_not_equal(self, term: BoundTerm, literal: Literal) -> List: # pylint: disable=redefined-outer-name
self.visit_history.append("NOT_EQUAL")
return self.visit_history
- def visit_greater_than_or_equal(self, term: base.BoundTerm, literal: Literal) -> List: # pylint: disable=redefined-outer-name
+ def visit_greater_than_or_equal(self, term: BoundTerm, literal: Literal) -> List: # pylint: disable=redefined-outer-name
self.visit_history.append("GREATER_THAN_OR_EQUAL")
return self.visit_history
- def visit_greater_than(self, term: base.BoundTerm, literal: Literal) -> List: # pylint: disable=redefined-outer-name
+ def visit_greater_than(self, term: BoundTerm, literal: Literal) -> List: # pylint: disable=redefined-outer-name
self.visit_history.append("GREATER_THAN")
return self.visit_history
- def visit_less_than(self, term: base.BoundTerm, literal: Literal) -> List: # pylint: disable=redefined-outer-name
+ def visit_less_than(self, term: BoundTerm, literal: Literal) -> List: # pylint: disable=redefined-outer-name
self.visit_history.append("LESS_THAN")
return self.visit_history
- def visit_less_than_or_equal(self, term: base.BoundTerm, literal: Literal) -> List: # pylint: disable=redefined-outer-name
+ def visit_less_than_or_equal(self, term: BoundTerm, literal: Literal) -> List: # pylint: disable=redefined-outer-name
self.visit_history.append("LESS_THAN_OR_EQUAL")
return self.visit_history
@@ -212,619 +247,15 @@ class FooBoundBooleanExpressionVisitor(base.BoundBooleanExpressionVisitor[List])
return self.visit_history
-@pytest.mark.parametrize(
- "op, rep",
- [
- (
- base.And(ExpressionA(), ExpressionB()),
- "And(left=ExpressionA(), right=ExpressionB())",
- ),
- (
- base.Or(ExpressionA(), ExpressionB()),
- "Or(left=ExpressionA(), right=ExpressionB())",
- ),
- (base.Not(ExpressionA()), "Not(child=ExpressionA())"),
- ],
-)
-def test_reprs(op: base.BooleanExpression, rep: str):
- assert repr(op) == rep
-
-
-def test_isnull_inverse():
- assert ~base.IsNull(base.Reference("a")) == base.NotNull(base.Reference("a"))
-
-
-def test_isnull_bind():
- schema = Schema(NestedField(2, "a", IntegerType()), schema_id=1)
- bound = base.BoundIsNull(base.BoundReference(schema.find_field(2), schema.accessor_for_field(2)))
- assert base.IsNull(base.Reference("a")).bind(schema) == bound
-
-
-def test_invert_is_null_bind():
- schema = Schema(NestedField(2, "a", IntegerType(), required=False), schema_id=1)
- assert ~base.IsNull(base.Reference("a")).bind(schema) == base.NotNull(base.Reference("a")).bind(schema)
-
-
-def test_invert_not_null_bind():
- schema = Schema(NestedField(2, "a", IntegerType(), required=False), schema_id=1)
- assert ~base.NotNull(base.Reference("a")).bind(schema) == base.IsNull(base.Reference("a")).bind(schema)
-
-
-def test_invert_is_nan_bind():
- schema = Schema(NestedField(2, "a", DoubleType(), required=False), schema_id=1)
- assert ~base.IsNaN(base.Reference("a")).bind(schema) == base.NotNaN(base.Reference("a")).bind(schema)
-
-
-def test_invert_not_nan_bind():
- schema = Schema(NestedField(2, "a", DoubleType(), required=False), schema_id=1)
- assert ~base.NotNaN(base.Reference("a")).bind(schema) == base.IsNaN(base.Reference("a")).bind(schema)
-
-
-def test_bind_expr_does_not_exists():
- schema = Schema(NestedField(2, "a", IntegerType()), schema_id=1)
- with pytest.raises(ValueError) as exc_info:
- base.IsNull(base.Reference("b")).bind(schema)
-
- assert str(exc_info.value) == "Could not find field with name b, case_sensitive=True"
-
-
-def test_bind_does_not_exists():
- schema = Schema(NestedField(2, "a", IntegerType()), schema_id=1)
- with pytest.raises(ValueError) as exc_info:
- base.Reference("b").bind(schema)
-
- assert str(exc_info.value) == "Could not find field with name b, case_sensitive=True"
-
-
-def test_isnull_bind_required():
- schema = Schema(NestedField(2, "a", IntegerType(), required=True), schema_id=1)
- assert base.IsNull(base.Reference("a")).bind(schema) == base.AlwaysFalse()
-
-
-def test_notnull_inverse():
- assert ~base.NotNull(base.Reference("a")) == base.IsNull(base.Reference("a"))
-
-
-def test_notnull_bind():
- schema = Schema(NestedField(2, "a", IntegerType()), schema_id=1)
- bound = base.BoundNotNull(base.BoundReference(schema.find_field(2), schema.accessor_for_field(2)))
- assert base.NotNull(base.Reference("a")).bind(schema) == bound
-
-
-def test_notnull_bind_required():
- schema = Schema(NestedField(2, "a", IntegerType(), required=True), schema_id=1)
- assert base.NotNull(base.Reference("a")).bind(schema) == base.AlwaysTrue()
-
-
-def test_isnan_inverse():
- assert ~base.IsNaN(base.Reference("f")) == base.NotNaN(base.Reference("f"))
-
-
-def test_isnan_bind_float():
- schema = Schema(NestedField(2, "f", FloatType()), schema_id=1)
- bound = base.BoundIsNaN(base.BoundReference(schema.find_field(2), schema.accessor_for_field(2)))
- assert base.IsNaN(base.Reference("f")).bind(schema) == bound
-
-
-def test_isnan_bind_double():
- schema = Schema(NestedField(2, "d", DoubleType()), schema_id=1)
- bound = base.BoundIsNaN(base.BoundReference(schema.find_field(2), schema.accessor_for_field(2)))
- assert base.IsNaN(base.Reference("d")).bind(schema) == bound
-
-
-def test_isnan_bind_nonfloat():
- schema = Schema(NestedField(2, "i", IntegerType()), schema_id=1)
- assert base.IsNaN(base.Reference("i")).bind(schema) == base.AlwaysFalse()
-
-
-def test_notnan_inverse():
- assert ~base.NotNaN(base.Reference("f")) == base.IsNaN(base.Reference("f"))
-
-
-def test_notnan_bind_float():
- schema = Schema(NestedField(2, "f", FloatType()), schema_id=1)
- bound = base.BoundNotNaN(base.BoundReference(schema.find_field(2), schema.accessor_for_field(2)))
- assert base.NotNaN(base.Reference("f")).bind(schema) == bound
-
-
-def test_notnan_bind_double():
- schema = Schema(NestedField(2, "d", DoubleType()), schema_id=1)
- bound = base.BoundNotNaN(base.BoundReference(schema.find_field(2), schema.accessor_for_field(2)))
- assert base.NotNaN(base.Reference("d")).bind(schema) == bound
-
-
-def test_notnan_bind_nonfloat():
- schema = Schema(NestedField(2, "i", IntegerType()), schema_id=1)
- assert base.NotNaN(base.Reference("i")).bind(schema) == base.AlwaysTrue()
-
-
-@pytest.mark.parametrize(
- "op, string",
- [
- (base.And(ExpressionA(), ExpressionB()), "And(left=ExpressionA(), right=ExpressionB())"),
- (base.Or(ExpressionA(), ExpressionB()), "Or(left=ExpressionA(), right=ExpressionB())"),
- (base.Not(ExpressionA()), "Not(child=ExpressionA())"),
- ],
-)
-def test_strs(op, string):
- assert str(op) == string
-
-
-def test_ref_binding_case_sensitive(table_schema_simple: Schema):
- ref = base.Reference[str]("foo")
- bound = base.BoundReference[str](table_schema_simple.find_field(1), table_schema_simple.accessor_for_field(1))
- assert ref.bind(table_schema_simple, case_sensitive=True) == bound
-
-
-def test_ref_binding_case_sensitive_failure(table_schema_simple: Schema):
- ref = base.Reference[str]("Foo")
- with pytest.raises(ValueError):
- ref.bind(table_schema_simple, case_sensitive=True)
-
-
-def test_ref_binding_case_insensitive(table_schema_simple: Schema):
- ref = base.Reference[str]("Foo")
- bound = base.BoundReference[str](table_schema_simple.find_field(1), table_schema_simple.accessor_for_field(1))
- assert ref.bind(table_schema_simple, case_sensitive=False) == bound
-
-
-def test_ref_binding_case_insensitive_failure(table_schema_simple: Schema):
- ref = base.Reference[str]("Foot")
- with pytest.raises(ValueError):
- ref.bind(table_schema_simple, case_sensitive=False)
-
-
-def test_in_to_eq():
- assert base.In(base.Reference("x"), (literal(34.56),)) == base.EqualTo(base.Reference("x"), literal(34.56))
-
-
-def test_empty_bind_in(table_schema_simple: Schema):
- bound = base.BoundIn[str](
- base.BoundReference(table_schema_simple.find_field(1), table_schema_simple.accessor_for_field(1)), set()
- )
- assert bound == base.AlwaysFalse()
-
-
-def test_empty_bind_not_in(table_schema_simple: Schema):
- bound = base.BoundNotIn(
- base.BoundReference[str](table_schema_simple.find_field(1), table_schema_simple.accessor_for_field(1)), set()
- )
- assert bound == base.AlwaysTrue()
-
-
-def test_bind_not_in_equal_term(table_schema_simple: Schema):
- bound = base.BoundNotIn(
- base.BoundReference(table_schema_simple.find_field(1), table_schema_simple.accessor_for_field(1)), {literal("hello")}
- )
- assert (
- base.BoundNotEqualTo[str](
- term=base.BoundReference(
- field=NestedField(field_id=1, name="foo", field_type=StringType(), required=False),
- accessor=Accessor(position=0, inner=None),
- ),
- literal=StringLiteral("hello"),
- )
- == bound
- )
-
-
-def test_in_empty():
- assert base.In(base.Reference("foo"), ()) == base.AlwaysFalse()
-
-
-def test_not_in_empty():
- assert base.NotIn(base.Reference("foo"), ()) == base.AlwaysTrue()
-
-
-def test_not_in_equal():
- assert base.NotIn(base.Reference("foo"), (literal("hello"),)) == base.NotEqualTo(
- term=base.Reference(name="foo"), literal=StringLiteral("hello")
- )
-
-
-def test_bind_in(table_schema_simple: Schema):
- bound = base.BoundIn(
- base.BoundReference(table_schema_simple.find_field(1), table_schema_simple.accessor_for_field(1)),
- {literal("hello"), literal("world")},
- )
- assert base.In(base.Reference("foo"), (literal("hello"), literal("world"))).bind(table_schema_simple) == bound
-
-
-def test_bind_in_invert(table_schema_simple: Schema):
- bound = base.BoundIn(
- base.BoundReference(table_schema_simple.find_field(1), table_schema_simple.accessor_for_field(1)),
- {literal("hello"), literal("world")},
- )
- assert ~bound == base.BoundNotIn(
- base.BoundReference(table_schema_simple.find_field(1), table_schema_simple.accessor_for_field(1)),
- {literal("hello"), literal("world")},
- )
-
-
-def test_bind_not_in_invert(table_schema_simple: Schema):
- bound = base.BoundNotIn(
- base.BoundReference(table_schema_simple.find_field(1), table_schema_simple.accessor_for_field(1)),
- {literal("hello"), literal("world")},
- )
- assert ~bound == base.BoundIn(
- base.BoundReference(table_schema_simple.find_field(1), table_schema_simple.accessor_for_field(1)),
- {literal("hello"), literal("world")},
- )
-
-
-def test_bind_dedup(table_schema_simple: Schema):
- bound = base.BoundIn(
- base.BoundReference(table_schema_simple.find_field(1), table_schema_simple.accessor_for_field(1)),
- {literal("hello"), literal("world")},
- )
- assert (
- base.In(base.Reference("foo"), (literal("hello"), literal("world"), literal("world"))).bind(table_schema_simple) == bound
- )
-
-
-def test_bind_dedup_to_eq(table_schema_simple: Schema):
- bound = base.BoundEqualTo(
- base.BoundReference(table_schema_simple.find_field(1), table_schema_simple.accessor_for_field(1)), literal("hello")
- )
- assert base.In(base.Reference("foo"), (literal("hello"), literal("hello"))).bind(table_schema_simple) == bound
-
-
-def test_bound_equal_to_invert(table_schema_simple: Schema):
- bound = base.BoundEqualTo(
- base.BoundReference(table_schema_simple.find_field(1), table_schema_simple.accessor_for_field(1)), literal("hello")
- )
- assert ~bound == base.BoundNotEqualTo(
- term=base.BoundReference[str](
- field=NestedField(field_id=1, name="foo", field_type=StringType(), required=False),
- accessor=Accessor(position=0, inner=None),
- ),
- literal=StringLiteral("hello"),
- )
-
-
-def test_bound_not_equal_to_invert(table_schema_simple: Schema):
- bound = base.BoundNotEqualTo(
- base.BoundReference(table_schema_simple.find_field(1), table_schema_simple.accessor_for_field(1)), literal("hello")
- )
- assert ~bound == base.BoundEqualTo(
- term=base.BoundReference[str](
- field=NestedField(field_id=1, name="foo", field_type=StringType(), required=False),
- accessor=Accessor(position=0, inner=None),
- ),
- literal=StringLiteral("hello"),
- )
-
-
-def test_bound_greater_than_or_equal_invert(table_schema_simple: Schema):
- bound = base.BoundGreaterThanOrEqual(
- base.BoundReference(table_schema_simple.find_field(1), table_schema_simple.accessor_for_field(1)), literal("hello")
- )
- assert ~bound == base.BoundLessThan(
- term=base.BoundReference[str](
- field=NestedField(field_id=1, name="foo", field_type=StringType(), required=False),
- accessor=Accessor(position=0, inner=None),
- ),
- literal=StringLiteral("hello"),
- )
-
-
-def test_bound_greater_than_invert(table_schema_simple: Schema):
- bound = base.BoundGreaterThan(
- base.BoundReference(table_schema_simple.find_field(1), table_schema_simple.accessor_for_field(1)), literal("hello")
- )
- assert ~bound == base.BoundLessThanOrEqual(
- term=base.BoundReference[str](
- field=NestedField(field_id=1, name="foo", field_type=StringType(), required=False),
- accessor=Accessor(position=0, inner=None),
- ),
- literal=StringLiteral("hello"),
- )
-
-
-def test_bound_less_than_invert(table_schema_simple: Schema):
- bound = base.BoundLessThan(
- base.BoundReference(table_schema_simple.find_field(1), table_schema_simple.accessor_for_field(1)), literal("hello")
- )
- assert ~bound == base.BoundGreaterThanOrEqual(
- term=base.BoundReference[str](
- field=NestedField(field_id=1, name="foo", field_type=StringType(), required=False),
- accessor=Accessor(position=0, inner=None),
- ),
- literal=StringLiteral("hello"),
- )
-
-
-def test_bound_less_than_or_equal_invert(table_schema_simple: Schema):
- bound = base.BoundLessThanOrEqual(
- base.BoundReference(table_schema_simple.find_field(1), table_schema_simple.accessor_for_field(1)), literal("hello")
- )
- assert ~bound == base.BoundGreaterThan(
- term=base.BoundReference[str](
- field=NestedField(field_id=1, name="foo", field_type=StringType(), required=False),
- accessor=Accessor(position=0, inner=None),
- ),
- literal=StringLiteral("hello"),
- )
-
-
-def test_not_equal_to_invert():
- bound = base.NotEqualTo(
- term=base.BoundReference(
- field=NestedField(field_id=1, name="foo", field_type=StringType(), required=False),
- accessor=Accessor(position=0, inner=None),
- ),
- literal=StringLiteral("hello"),
- )
- assert ~bound == base.EqualTo(
- term=base.BoundReference(
- field=NestedField(field_id=1, name="foo", field_type=StringType(), required=False),
- accessor=Accessor(position=0, inner=None),
- ),
- literal=StringLiteral("hello"),
- )
-
-
-def test_greater_than_or_equal_invert():
- bound = base.GreaterThanOrEqual(
- term=base.BoundReference(
- field=NestedField(field_id=1, name="foo", field_type=StringType(), required=False),
- accessor=Accessor(position=0, inner=None),
- ),
- literal=StringLiteral("hello"),
- )
- assert ~bound == base.LessThan(
- term=base.BoundReference(
- field=NestedField(field_id=1, name="foo", field_type=StringType(), required=False),
- accessor=Accessor(position=0, inner=None),
- ),
- literal=StringLiteral("hello"),
- )
-
-
-def test_less_than_or_equal_invert():
- bound = base.LessThanOrEqual(
- term=base.BoundReference(
- field=NestedField(field_id=1, name="foo", field_type=StringType(), required=False),
- accessor=Accessor(position=0, inner=None),
- ),
- literal=StringLiteral("hello"),
- )
- assert ~bound == base.GreaterThan(
- term=base.BoundReference(
- field=NestedField(field_id=1, name="foo", field_type=StringType(), required=False),
- accessor=Accessor(position=0, inner=None),
- ),
- literal=StringLiteral("hello"),
- )
-
-
-@pytest.mark.parametrize(
- "pred",
- [
- base.NotIn(base.Reference("foo"), (literal("hello"), literal("world"))),
- base.NotEqualTo(base.Reference("foo"), literal("hello")),
- base.EqualTo(base.Reference("foo"), literal("hello")),
- base.GreaterThan(base.Reference("foo"), literal("hello")),
- base.LessThan(base.Reference("foo"), literal("hello")),
- base.GreaterThanOrEqual(base.Reference("foo"), literal("hello")),
- base.LessThanOrEqual(base.Reference("foo"), literal("hello")),
- ],
-)
-def test_bind(pred, table_schema_simple: Schema):
- assert pred.bind(table_schema_simple, case_sensitive=True).term.field == table_schema_simple.find_field(
- pred.term.name, case_sensitive=True
- )
-
-
-@pytest.mark.parametrize(
- "pred",
- [
- base.In(base.Reference("Bar"), (literal(5), literal(2))),
- base.NotIn(base.Reference("Bar"), (literal(5), literal(2))),
- base.NotEqualTo(base.Reference("Bar"), literal(5)),
- base.EqualTo(base.Reference("Bar"), literal(5)),
- base.GreaterThan(base.Reference("Bar"), literal(5)),
- base.LessThan(base.Reference("Bar"), literal(5)),
- base.GreaterThanOrEqual(base.Reference("Bar"), literal(5)),
- base.LessThanOrEqual(base.Reference("Bar"), literal(5)),
- ],
-)
-def test_bind_case_insensitive(pred, table_schema_simple: Schema):
- assert pred.bind(table_schema_simple, case_sensitive=False).term.field == table_schema_simple.find_field(
- pred.term.name, case_sensitive=False
- )
-
-
-@pytest.mark.parametrize(
- "exp, testexpra, testexprb",
- [
- (
- base.And(ExpressionA(), ExpressionB()),
- base.And(ExpressionA(), ExpressionB()),
- base.Or(ExpressionA(), ExpressionB()),
- ),
- (
- base.Or(ExpressionA(), ExpressionB()),
- base.Or(ExpressionA(), ExpressionB()),
- base.And(ExpressionA(), ExpressionB()),
- ),
- (base.Not(ExpressionA()), base.Not(ExpressionA()), ExpressionB()),
- (ExpressionA(), ExpressionA(), ExpressionB()),
- (ExpressionB(), ExpressionB(), ExpressionA()),
- (
- base.In(base.Reference("foo"), (literal("hello"), literal("world"))),
- base.In(base.Reference("foo"), (literal("hello"), literal("world"))),
- base.In(base.Reference("not_foo"), (literal("hello"), literal("world"))),
- ),
- (
- base.In(base.Reference("foo"), (literal("hello"), literal("world"))),
- base.In(base.Reference("foo"), (literal("hello"), literal("world"))),
- base.In(base.Reference("foo"), (literal("goodbye"), literal("world"))),
- ),
- ],
-)
-def test_eq(exp, testexpra, testexprb):
- assert exp == testexpra and exp != testexprb
-
-
-@pytest.mark.parametrize(
- "lhs, rhs",
- [
- (
- base.And(ExpressionA(), ExpressionB()),
- base.Or(ExpressionB(), ExpressionA()),
- ),
- (
- base.Or(ExpressionA(), ExpressionB()),
- base.And(ExpressionB(), ExpressionA()),
- ),
- (
- base.Not(ExpressionA()),
- ExpressionA(),
- ),
- (
- base.In(base.Reference("foo"), (literal("hello"), literal("world"))),
- base.NotIn(base.Reference("foo"), (literal("hello"), literal("world"))),
- ),
- (
- base.NotIn(base.Reference("foo"), (literal("hello"), literal("world"))),
- base.In(base.Reference("foo"), (literal("hello"), literal("world"))),
- ),
- (base.GreaterThan(base.Reference("foo"), literal(5)), base.LessThanOrEqual(base.Reference("foo"), literal(5))),
- (base.LessThan(base.Reference("foo"), literal(5)), base.GreaterThanOrEqual(base.Reference("foo"), literal(5))),
- (base.EqualTo(base.Reference("foo"), literal(5)), base.NotEqualTo(base.Reference("foo"), literal(5))),
- (
- ExpressionA(),
- ExpressionB(),
- ),
- ],
-)
-def test_negate(lhs, rhs):
- assert ~lhs == rhs
-
-
-@pytest.mark.parametrize(
- "lhs, rhs",
- [
- (
- base.And(ExpressionA(), ExpressionB(), ExpressionA()),
- base.And(base.And(ExpressionA(), ExpressionB()), ExpressionA()),
- ),
- (
- base.Or(ExpressionA(), ExpressionB(), ExpressionA()),
- base.Or(base.Or(ExpressionA(), ExpressionB()), ExpressionA()),
- ),
- (base.Not(base.Not(ExpressionA())), ExpressionA()),
- ],
-)
-def test_reduce(lhs, rhs):
- assert lhs == rhs
-
-
-@pytest.mark.parametrize(
- "lhs, rhs",
- [
- (base.And(base.AlwaysTrue(), ExpressionB()), ExpressionB()),
- (base.And(base.AlwaysFalse(), ExpressionB()), base.AlwaysFalse()),
- (base.And(ExpressionB(), base.AlwaysTrue()), ExpressionB()),
- (base.Or(base.AlwaysTrue(), ExpressionB()), base.AlwaysTrue()),
- (base.Or(base.AlwaysFalse(), ExpressionB()), ExpressionB()),
- (base.Or(ExpressionA(), base.AlwaysFalse()), ExpressionA()),
- (base.Not(base.Not(ExpressionA())), ExpressionA()),
- (base.Not(base.AlwaysTrue()), base.AlwaysFalse()),
- (base.Not(base.AlwaysFalse()), base.AlwaysTrue()),
- ],
-)
-def test_base_AlwaysTrue_base_AlwaysFalse(lhs, rhs):
- assert lhs == rhs
-
-
-def test_invert_always():
- assert ~base.AlwaysFalse() == base.AlwaysTrue()
- assert ~base.AlwaysTrue() == base.AlwaysFalse()
-
-
-def test_accessor_base_class(foo_struct):
- """Test retrieving a value at a position of a container using an accessor"""
-
- uuid_value = uuid.uuid4()
-
- foo_struct.set(0, "foo")
- foo_struct.set(1, "bar")
- foo_struct.set(2, "baz")
- foo_struct.set(3, 1)
- foo_struct.set(4, 2)
- foo_struct.set(5, 3)
- foo_struct.set(6, 1.234)
- foo_struct.set(7, Decimal("1.234"))
- foo_struct.set(8, uuid_value)
- foo_struct.set(9, True)
- foo_struct.set(10, False)
- foo_struct.set(11, b"\x19\x04\x9e?")
-
- assert base.Accessor(position=0).get(foo_struct) == "foo"
- assert base.Accessor(position=1).get(foo_struct) == "bar"
- assert base.Accessor(position=2).get(foo_struct) == "baz"
- assert base.Accessor(position=3).get(foo_struct) == 1
- assert base.Accessor(position=4).get(foo_struct) == 2
- assert base.Accessor(position=5).get(foo_struct) == 3
- assert base.Accessor(position=6).get(foo_struct) == 1.234
- assert base.Accessor(position=7).get(foo_struct) == Decimal("1.234")
- assert base.Accessor(position=8).get(foo_struct) == uuid_value
- assert base.Accessor(position=9).get(foo_struct) is True
- assert base.Accessor(position=10).get(foo_struct) is False
- assert base.Accessor(position=11).get(foo_struct) == b"\x19\x04\x9e?"
-
-
-def test_bound_reference_str_and_repr():
- """Test str and repr of BoundReference"""
- field = NestedField(field_id=1, name="foo", field_type=StringType(), required=False)
- position1_accessor = base.Accessor(position=1)
- bound_ref = base.BoundReference(field=field, accessor=position1_accessor)
- assert str(bound_ref) == f"BoundReference(field={repr(field)}, accessor={repr(position1_accessor)})"
- assert repr(bound_ref) == f"BoundReference(field={repr(field)}, accessor={repr(position1_accessor)})"
-
-
-def test_bound_reference_field_property():
- """Test str and repr of BoundReference"""
- field = NestedField(field_id=1, name="foo", field_type=StringType(), required=False)
- position1_accessor = base.Accessor(position=1)
- bound_ref = base.BoundReference(field=field, accessor=position1_accessor)
- assert bound_ref.field == NestedField(field_id=1, name="foo", field_type=StringType(), required=False)
-
-
-def test_bound_reference(table_schema_simple, foo_struct):
- """Test creating a BoundReference and evaluating it on a StructProtocol"""
- foo_struct.set(pos=1, value="foovalue")
- foo_struct.set(pos=2, value=123)
- foo_struct.set(pos=3, value=True)
-
- position1_accessor = base.Accessor(position=1)
- position2_accessor = base.Accessor(position=2)
- position3_accessor = base.Accessor(position=3)
-
- field1 = table_schema_simple.find_field(1)
- field2 = table_schema_simple.find_field(2)
- field3 = table_schema_simple.find_field(3)
-
- bound_ref1 = base.BoundReference(field=field1, accessor=position1_accessor)
- bound_ref2 = base.BoundReference(field=field2, accessor=position2_accessor)
- bound_ref3 = base.BoundReference(field=field3, accessor=position3_accessor)
-
- assert bound_ref1.eval(foo_struct) == "foovalue"
- assert bound_ref2.eval(foo_struct) == 123
- assert bound_ref3.eval(foo_struct) is True
-
-
def test_boolean_expression_visitor():
"""Test post-order traversal of boolean expression visit method"""
- expr = base.And(
- base.Or(base.Not(ExpressionA()), base.Not(ExpressionB()), ExpressionA(), ExpressionB()),
- base.Not(ExpressionA()),
+ expr = And(
+ Or(Not(ExpressionA()), Not(ExpressionB()), ExpressionA(), ExpressionB()),
+ Not(ExpressionA()),
ExpressionB(),
)
visitor = ExampleVisitor()
- result = base.visit(expr, visitor=visitor)
+ result = visit(expr, visitor=visitor)
assert result == [
"ExpressionA",
"NOT",
@@ -847,17 +278,17 @@ def test_boolean_expression_visit_raise_not_implemented_error():
"""Test raise NotImplementedError when visiting an unsupported object type"""
visitor = ExampleVisitor()
with pytest.raises(NotImplementedError) as exc_info:
- base.visit("foo", visitor=visitor)
+ visit("foo", visitor=visitor)
assert str(exc_info.value) == "Cannot visit unsupported expression: foo"
def test_bind_visitor_already_bound(table_schema_simple: Schema):
- bound = base.BoundEqualTo(
- base.BoundReference(table_schema_simple.find_field(1), table_schema_simple.accessor_for_field(1)), literal("hello")
+ bound = BoundEqualTo(
+ BoundReference(table_schema_simple.find_field(1), table_schema_simple.accessor_for_field(1)), literal("hello")
)
with pytest.raises(TypeError) as exc_info:
- base.BindVisitor(base.visit(bound, visitor=base.BindVisitor(schema=table_schema_simple))) # type: ignore
+ BindVisitor(visit(bound, visitor=BindVisitor(schema=table_schema_simple))) # type: ignore
assert (
"Found already bound predicate: BoundEqualTo(term=BoundReference(field=NestedField(field_id=1, name='foo', field_type=StringType(), required=False), accessor=Accessor(position=0,inner=None)), literal=StringLiteral(hello))"
== str(exc_info.value)
@@ -872,50 +303,50 @@ def test_visit_bound_visitor_unknown_predicate():
def test_always_true_expression_binding(table_schema_simple: Schema):
"""Test that visiting an always-true expression returns always-true"""
- unbound_expression = base.AlwaysTrue()
- bound_expression = base.visit(unbound_expression, visitor=base.BindVisitor(schema=table_schema_simple))
- assert bound_expression == base.AlwaysTrue()
+ unbound_expression = AlwaysTrue()
+ bound_expression = visit(unbound_expression, visitor=BindVisitor(schema=table_schema_simple))
+ assert bound_expression == AlwaysTrue()
def test_always_false_expression_binding(table_schema_simple: Schema):
"""Test that visiting an always-false expression returns always-false"""
- unbound_expression = base.AlwaysFalse()
- bound_expression = base.visit(unbound_expression, visitor=base.BindVisitor(schema=table_schema_simple))
- assert bound_expression == base.AlwaysFalse()
+ unbound_expression = AlwaysFalse()
+ bound_expression = visit(unbound_expression, visitor=BindVisitor(schema=table_schema_simple))
+ assert bound_expression == AlwaysFalse()
def test_always_false_and_always_true_expression_binding(table_schema_simple: Schema):
"""Test that visiting both an always-true AND always-false expression returns always-false"""
- unbound_expression = base.And(base.AlwaysTrue(), base.AlwaysFalse())
- bound_expression = base.visit(unbound_expression, visitor=base.BindVisitor(schema=table_schema_simple))
- assert bound_expression == base.AlwaysFalse()
+ unbound_expression = And(AlwaysTrue(), AlwaysFalse())
+ bound_expression = visit(unbound_expression, visitor=BindVisitor(schema=table_schema_simple))
+ assert bound_expression == AlwaysFalse()
def test_always_false_or_always_true_expression_binding(table_schema_simple: Schema):
"""Test that visiting always-true OR always-false expression returns always-true"""
- unbound_expression = base.Or(base.AlwaysTrue(), base.AlwaysFalse())
- bound_expression = base.visit(unbound_expression, visitor=base.BindVisitor(schema=table_schema_simple))
- assert bound_expression == base.AlwaysTrue()
+ unbound_expression = Or(AlwaysTrue(), AlwaysFalse())
+ bound_expression = visit(unbound_expression, visitor=BindVisitor(schema=table_schema_simple))
+ assert bound_expression == AlwaysTrue()
@pytest.mark.parametrize(
"unbound_and_expression,expected_bound_expression",
[
(
- base.And(
- base.In(base.Reference("foo"), (literal("foo"), literal("bar"))),
- base.In(base.Reference("bar"), (literal(1), literal(2), literal(3))),
+ And(
+ In(Reference("foo"), (literal("foo"), literal("bar"))),
+ In(Reference("bar"), (literal(1), literal(2), literal(3))),
),
- base.And(
- base.BoundIn[str](
- base.BoundReference(
+ And(
+ BoundIn[str](
+ BoundReference(
field=NestedField(field_id=1, name="foo", field_type=StringType(), required=False),
accessor=Accessor(position=0, inner=None),
),
{StringLiteral("foo"), StringLiteral("bar")},
),
- base.BoundIn[int](
- base.BoundReference(
+ BoundIn[int](
+ BoundReference(
field=NestedField(field_id=2, name="bar", field_type=IntegerType(), required=True),
accessor=Accessor(position=1, inner=None),
),
@@ -924,36 +355,36 @@ def test_always_false_or_always_true_expression_binding(table_schema_simple: Sch
),
),
(
- base.And(
- base.In(base.Reference("foo"), (literal("bar"), literal("baz"))),
- base.In(
- base.Reference("bar"),
+ And(
+ In(Reference("foo"), (literal("bar"), literal("baz"))),
+ In(
+ Reference("bar"),
(literal(1),),
),
- base.In(
- base.Reference("foo"),
+ In(
+ Reference("foo"),
(literal("baz"),),
),
),
- base.And(
- base.And(
- base.BoundIn[str](
- base.BoundReference(
+ And(
+ And(
+ BoundIn[str](
+ BoundReference(
field=NestedField(field_id=1, name="foo", field_type=StringType(), required=False),
accessor=Accessor(position=0, inner=None),
),
{StringLiteral("bar"), StringLiteral("baz")},
),
- base.BoundEqualTo[int](
- base.BoundReference(
+ BoundEqualTo[int](
+ BoundReference(
field=NestedField(field_id=2, name="bar", field_type=IntegerType(), required=True),
accessor=Accessor(position=1, inner=None),
),
LongLiteral(1),
),
),
- base.BoundEqualTo[str](
- base.BoundReference(
+ BoundEqualTo[str](
+ BoundReference(
field=NestedField(field_id=1, name="foo", field_type=StringType(), required=False),
accessor=Accessor(position=0, inner=None),
),
@@ -965,7 +396,7 @@ def test_always_false_or_always_true_expression_binding(table_schema_simple: Sch
)
def test_and_expression_binding(unbound_and_expression, expected_bound_expression, table_schema_simple):
"""Test that visiting an unbound AND expression with a bind-visitor returns the expected bound expression"""
- bound_expression = base.visit(unbound_and_expression, visitor=base.BindVisitor(schema=table_schema_simple))
+ bound_expression = visit(unbound_and_expression, visitor=BindVisitor(schema=table_schema_simple))
assert bound_expression == expected_bound_expression
@@ -973,20 +404,20 @@ def test_and_expression_binding(unbound_and_expression, expected_bound_expressio
"unbound_or_expression,expected_bound_expression",
[
(
- base.Or(
- base.In(base.Reference("foo"), (literal("foo"), literal("bar"))),
- base.In(base.Reference("bar"), (literal(1), literal(2), literal(3))),
+ Or(
+ In(Reference("foo"), (literal("foo"), literal("bar"))),
+ In(Reference("bar"), (literal(1), literal(2), literal(3))),
),
- base.Or(
- base.BoundIn[str](
- base.BoundReference(
+ Or(
+ BoundIn[str](
+ BoundReference(
field=NestedField(field_id=1, name="foo", field_type=StringType(), required=False),
accessor=Accessor(position=0, inner=None),
),
{StringLiteral("foo"), StringLiteral("bar")},
),
- base.BoundIn[int](
- base.BoundReference(
+ BoundIn[int](
+ BoundReference(
field=NestedField(field_id=2, name="bar", field_type=IntegerType(), required=True),
accessor=Accessor(position=1, inner=None),
),
@@ -995,36 +426,36 @@ def test_and_expression_binding(unbound_and_expression, expected_bound_expressio
),
),
(
- base.Or(
- base.In(base.Reference("foo"), (literal("bar"), literal("baz"))),
- base.In(
- base.Reference("foo"),
+ Or(
+ In(Reference("foo"), (literal("bar"), literal("baz"))),
+ In(
+ Reference("foo"),
(literal("bar"),),
),
- base.In(
- base.Reference("foo"),
+ In(
+ Reference("foo"),
(literal("baz"),),
),
),
- base.Or(
- base.Or(
- base.BoundIn[str](
- base.BoundReference(
+ Or(
+ Or(
+ BoundIn[str](
+ BoundReference(
field=NestedField(field_id=1, name="foo", field_type=StringType(), required=False),
accessor=Accessor(position=0, inner=None),
),
{StringLiteral("bar"), StringLiteral("baz")},
),
- base.BoundIn[str](
- base.BoundReference(
+ BoundIn[str](
+ BoundReference(
field=NestedField(field_id=1, name="foo", field_type=StringType(), required=False),
accessor=Accessor(position=0, inner=None),
),
{StringLiteral("bar")},
),
),
- base.BoundIn[str](
- base.BoundReference(
+ BoundIn[str](
+ BoundReference(
field=NestedField(field_id=1, name="foo", field_type=StringType(), required=False),
accessor=Accessor(position=0, inner=None),
),
@@ -1033,31 +464,31 @@ def test_and_expression_binding(unbound_and_expression, expected_bound_expressio
),
),
(
- base.Or(
- base.AlwaysTrue(),
- base.AlwaysFalse(),
+ Or(
+ AlwaysTrue(),
+ AlwaysFalse(),
),
- base.AlwaysTrue(),
+ AlwaysTrue(),
),
(
- base.Or(
- base.AlwaysTrue(),
- base.AlwaysTrue(),
+ Or(
+ AlwaysTrue(),
+ AlwaysTrue(),
),
- base.AlwaysTrue(),
+ AlwaysTrue(),
),
(
- base.Or(
- base.AlwaysFalse(),
- base.AlwaysFalse(),
+ Or(
+ AlwaysFalse(),
+ AlwaysFalse(),
),
- base.AlwaysFalse(),
+ AlwaysFalse(),
),
],
)
def test_or_expression_binding(unbound_or_expression, expected_bound_expression, table_schema_simple):
"""Test that visiting an unbound OR expression with a bind-visitor returns the expected bound expression"""
- bound_expression = base.visit(unbound_or_expression, visitor=base.BindVisitor(schema=table_schema_simple))
+ bound_expression = visit(unbound_or_expression, visitor=BindVisitor(schema=table_schema_simple))
assert bound_expression == expected_bound_expression
@@ -1065,9 +496,9 @@ def test_or_expression_binding(unbound_or_expression, expected_bound_expression,
"unbound_in_expression,expected_bound_expression",
[
(
- base.In(base.Reference("foo"), (literal("foo"), literal("bar"))),
- base.BoundIn[str](
- base.BoundReference[str](
+ In(Reference("foo"), (literal("foo"), literal("bar"))),
+ BoundIn[str](
+ BoundReference[str](
field=NestedField(field_id=1, name="foo", field_type=StringType(), required=False),
accessor=Accessor(position=0, inner=None),
),
@@ -1075,9 +506,9 @@ def test_or_expression_binding(unbound_or_expression, expected_bound_expression,
),
),
(
- base.In(base.Reference("foo"), (literal("bar"), literal("baz"))),
- base.BoundIn[str](
- base.BoundReference[str](
+ In(Reference("foo"), (literal("bar"), literal("baz"))),
+ BoundIn[str](
+ BoundReference[str](
field=NestedField(field_id=1, name="foo", field_type=StringType(), required=False),
accessor=Accessor(position=0, inner=None),
),
@@ -1085,12 +516,12 @@ def test_or_expression_binding(unbound_or_expression, expected_bound_expression,
),
),
(
- base.In(
- base.Reference("foo"),
+ In(
+ Reference("foo"),
(literal("bar"),),
),
- base.BoundEqualTo(
- base.BoundReference[str](
+ BoundEqualTo(
+ BoundReference[str](
field=NestedField(field_id=1, name="foo", field_type=StringType(), required=False),
accessor=Accessor(position=0, inner=None),
),
@@ -1101,7 +532,7 @@ def test_or_expression_binding(unbound_or_expression, expected_bound_expression,
)
def test_in_expression_binding(unbound_in_expression, expected_bound_expression, table_schema_simple):
"""Test that visiting an unbound IN expression with a bind-visitor returns the expected bound expression"""
- bound_expression = base.visit(unbound_in_expression, visitor=base.BindVisitor(schema=table_schema_simple))
+ bound_expression = visit(unbound_in_expression, visitor=BindVisitor(schema=table_schema_simple))
assert bound_expression == expected_bound_expression
@@ -1109,10 +540,10 @@ def test_in_expression_binding(unbound_in_expression, expected_bound_expression,
"unbound_not_expression,expected_bound_expression",
[
(
- base.Not(base.In(base.Reference("foo"), (literal("foo"), literal("bar")))),
- base.Not(
- base.BoundIn[str](
- base.BoundReference[str](
+ Not(In(Reference("foo"), (literal("foo"), literal("bar")))),
+ Not(
+ BoundIn[str](
+ BoundReference[str](
field=NestedField(field_id=1, name="foo", field_type=StringType(), required=False),
accessor=Accessor(position=0, inner=None),
),
@@ -1121,23 +552,23 @@ def test_in_expression_binding(unbound_in_expression, expected_bound_expression,
),
),
(
- base.Not(
- base.Or(
- base.In(base.Reference("foo"), (literal("foo"), literal("bar"))),
- base.In(base.Reference("foo"), (literal("foo"), literal("bar"), literal("baz"))),
+ Not(
+ Or(
+ In(Reference("foo"), (literal("foo"), literal("bar"))),
+ In(Reference("foo"), (literal("foo"), literal("bar"), literal("baz"))),
)
),
- base.Not(
- base.Or(
- base.BoundIn[str](
- base.BoundReference(
+ Not(
+ Or(
+ BoundIn[str](
+ BoundReference(
field=NestedField(field_id=1, name="foo", field_type=StringType(), required=False),
accessor=Accessor(position=0, inner=None),
),
{StringLiteral("foo"), StringLiteral("bar")},
),
- base.BoundIn[str](
- base.BoundReference(
+ BoundIn[str](
+ BoundReference(
field=NestedField(field_id=1, name="foo", field_type=StringType(), required=False),
accessor=Accessor(position=0, inner=None),
),
@@ -1150,22 +581,22 @@ def test_in_expression_binding(unbound_in_expression, expected_bound_expression,
)
def test_not_expression_binding(unbound_not_expression, expected_bound_expression, table_schema_simple):
"""Test that visiting an unbound NOT expression with a bind-visitor returns the expected bound expression"""
- bound_expression = base.visit(unbound_not_expression, visitor=base.BindVisitor(schema=table_schema_simple))
+ bound_expression = visit(unbound_not_expression, visitor=BindVisitor(schema=table_schema_simple))
assert bound_expression == expected_bound_expression
def test_bound_boolean_expression_visitor_and_in():
"""Test visiting an And and In expression with a bound boolean expression visitor"""
- bound_expression = base.And(
- base.BoundIn[str](
- term=base.BoundReference(
+ bound_expression = And(
+ BoundIn[str](
+ term=BoundReference(
field=NestedField(field_id=1, name="foo", field_type=StringType(), required=False),
accessor=Accessor(position=0, inner=None),
),
literals=(StringLiteral("foo"), StringLiteral("bar")),
),
- base.BoundIn[str](
- term=base.BoundReference(
+ BoundIn[str](
+ term=BoundReference(
field=NestedField(field_id=2, name="bar", field_type=StringType(), required=False),
accessor=Accessor(position=1, inner=None),
),
@@ -1173,25 +604,25 @@ def test_bound_boolean_expression_visitor_and_in():
),
)
visitor = FooBoundBooleanExpressionVisitor()
- result = base.visit(bound_expression, visitor=visitor)
+ result = visit(bound_expression, visitor=visitor)
assert result == ["IN", "IN", "AND"]
def test_bound_boolean_expression_visitor_or():
"""Test visiting an Or expression with a bound boolean expression visitor"""
- bound_expression = base.Or(
- base.Not(
- base.BoundIn[str](
- base.BoundReference[str](
+ bound_expression = Or(
+ Not(
+ BoundIn[str](
+ BoundReference[str](
field=NestedField(field_id=1, name="foo", field_type=StringType(), required=False),
accessor=Accessor(position=0, inner=None),
),
{StringLiteral("foo"), StringLiteral("bar")},
)
),
- base.Not(
- base.BoundIn[str](
- base.BoundReference[str](
+ Not(
+ BoundIn[str](
+ BoundReference[str](
field=NestedField(field_id=2, name="bar", field_type=StringType(), required=False),
accessor=Accessor(position=1, inner=None),
),
@@ -1200,184 +631,184 @@ def test_bound_boolean_expression_visitor_or():
),
)
visitor = FooBoundBooleanExpressionVisitor()
- result = base.visit(bound_expression, visitor=visitor)
+ result = visit(bound_expression, visitor=visitor)
assert result == ["IN", "NOT", "IN", "NOT", "OR"]
def test_bound_boolean_expression_visitor_equal():
- bound_expression = base.BoundEqualTo[str](
- term=base.BoundReference(
+ bound_expression = BoundEqualTo[str](
+ term=BoundReference(
field=NestedField(field_id=2, name="bar", field_type=StringType(), required=False),
accessor=Accessor(position=1, inner=None),
),
literal=StringLiteral("foo"),
)
visitor = FooBoundBooleanExpressionVisitor()
- result = base.visit(bound_expression, visitor=visitor)
+ result = visit(bound_expression, visitor=visitor)
assert result == ["EQUAL"]
def test_bound_boolean_expression_visitor_not_equal():
- bound_expression = base.BoundNotEqualTo[str](
- term=base.BoundReference(
+ bound_expression = BoundNotEqualTo[str](
+ term=BoundReference(
field=NestedField(field_id=1, name="foo", field_type=StringType(), required=False),
accessor=Accessor(position=0, inner=None),
),
literal=StringLiteral("foo"),
)
visitor = FooBoundBooleanExpressionVisitor()
- result = base.visit(bound_expression, visitor=visitor)
+ result = visit(bound_expression, visitor=visitor)
assert result == ["NOT_EQUAL"]
def test_bound_boolean_expression_visitor_always_true():
- bound_expression = base.AlwaysTrue()
+ bound_expression = AlwaysTrue()
visitor = FooBoundBooleanExpressionVisitor()
- result = base.visit(bound_expression, visitor=visitor)
+ result = visit(bound_expression, visitor=visitor)
assert result == ["TRUE"]
def test_bound_boolean_expression_visitor_always_false():
- bound_expression = base.AlwaysFalse()
+ bound_expression = AlwaysFalse()
visitor = FooBoundBooleanExpressionVisitor()
- result = base.visit(bound_expression, visitor=visitor)
+ result = visit(bound_expression, visitor=visitor)
assert result == ["FALSE"]
def test_bound_boolean_expression_visitor_in():
- bound_expression = base.BoundIn[str](
- term=base.BoundReference(
+ bound_expression = BoundIn[str](
+ term=BoundReference(
field=NestedField(field_id=1, name="foo", field_type=StringType(), required=False),
accessor=Accessor(position=0, inner=None),
),
literals=(StringLiteral("foo"), StringLiteral("bar")),
)
visitor = FooBoundBooleanExpressionVisitor()
- result = base.visit(bound_expression, visitor=visitor)
+ result = visit(bound_expression, visitor=visitor)
assert result == ["IN"]
def test_bound_boolean_expression_visitor_not_in():
- bound_expression = base.BoundNotIn[str](
- term=base.BoundReference(
+ bound_expression = BoundNotIn[str](
+ term=BoundReference(
field=NestedField(field_id=1, name="foo", field_type=StringType(), required=False),
accessor=Accessor(position=0, inner=None),
),
literals=(StringLiteral("foo"), StringLiteral("bar")),
)
visitor = FooBoundBooleanExpressionVisitor()
- result = base.visit(bound_expression, visitor=visitor)
+ result = visit(bound_expression, visitor=visitor)
assert result == ["NOT_IN"]
def test_bound_boolean_expression_visitor_is_nan():
- bound_expression = base.BoundIsNaN[str](
- term=base.BoundReference(
+ bound_expression = BoundIsNaN[str](
+ term=BoundReference(
field=NestedField(field_id=3, name="baz", field_type=FloatType(), required=False),
accessor=Accessor(position=0, inner=None),
),
)
visitor = FooBoundBooleanExpressionVisitor()
- result = base.visit(bound_expression, visitor=visitor)
+ result = visit(bound_expression, visitor=visitor)
assert result == ["IS_NAN"]
def test_bound_boolean_expression_visitor_not_nan():
- bound_expression = base.BoundNotNaN[str](
- term=base.BoundReference(
+ bound_expression = BoundNotNaN[str](
+ term=BoundReference(
field=NestedField(field_id=3, name="baz", field_type=FloatType(), required=False),
accessor=Accessor(position=0, inner=None),
),
)
visitor = FooBoundBooleanExpressionVisitor()
- result = base.visit(bound_expression, visitor=visitor)
+ result = visit(bound_expression, visitor=visitor)
assert result == ["NOT_NAN"]
def test_bound_boolean_expression_visitor_is_null():
- bound_expression = base.BoundIsNull[str](
- term=base.BoundReference(
+ bound_expression = BoundIsNull[str](
+ term=BoundReference(
field=NestedField(field_id=1, name="foo", field_type=StringType(), required=False),
accessor=Accessor(position=0, inner=None),
),
)
visitor = FooBoundBooleanExpressionVisitor()
- result = base.visit(bound_expression, visitor=visitor)
+ result = visit(bound_expression, visitor=visitor)
assert result == ["IS_NULL"]
def test_bound_boolean_expression_visitor_not_null():
- bound_expression = base.BoundNotNull[str](
- term=base.BoundReference(
+ bound_expression = BoundNotNull[str](
+ term=BoundReference(
field=NestedField(field_id=1, name="foo", field_type=StringType(), required=False),
accessor=Accessor(position=0, inner=None),
),
)
visitor = FooBoundBooleanExpressionVisitor()
- result = base.visit(bound_expression, visitor=visitor)
+ result = visit(bound_expression, visitor=visitor)
assert result == ["NOT_NULL"]
def test_bound_boolean_expression_visitor_greater_than():
- bound_expression = base.BoundGreaterThan[str](
- term=base.BoundReference(
+ bound_expression = BoundGreaterThan[str](
+ term=BoundReference(
field=NestedField(field_id=1, name="foo", field_type=StringType(), required=False),
accessor=Accessor(position=0, inner=None),
),
literal=StringLiteral("foo"),
)
visitor = FooBoundBooleanExpressionVisitor()
- result = base.visit(bound_expression, visitor=visitor)
+ result = visit(bound_expression, visitor=visitor)
assert result == ["GREATER_THAN"]
def test_bound_boolean_expression_visitor_greater_than_or_equal():
- bound_expression = base.BoundGreaterThanOrEqual[str](
- term=base.BoundReference(
+ bound_expression = BoundGreaterThanOrEqual[str](
+ term=BoundReference(
field=NestedField(field_id=1, name="foo", field_type=StringType(), required=False),
accessor=Accessor(position=0, inner=None),
),
literal=StringLiteral("foo"),
)
visitor = FooBoundBooleanExpressionVisitor()
- result = base.visit(bound_expression, visitor=visitor)
+ result = visit(bound_expression, visitor=visitor)
assert result == ["GREATER_THAN_OR_EQUAL"]
def test_bound_boolean_expression_visitor_less_than():
- bound_expression = base.BoundLessThan[str](
- term=base.BoundReference(
+ bound_expression = BoundLessThan[str](
+ term=BoundReference(
field=NestedField(field_id=1, name="foo", field_type=StringType(), required=False),
accessor=Accessor(position=0, inner=None),
),
literal=StringLiteral("foo"),
)
visitor = FooBoundBooleanExpressionVisitor()
- result = base.visit(bound_expression, visitor=visitor)
+ result = visit(bound_expression, visitor=visitor)
assert result == ["LESS_THAN"]
def test_bound_boolean_expression_visitor_less_than_or_equal():
- bound_expression = base.BoundLessThanOrEqual[str](
- term=base.BoundReference(
+ bound_expression = BoundLessThanOrEqual[str](
+ term=BoundReference(
field=NestedField(field_id=1, name="foo", field_type=StringType(), required=False),
accessor=Accessor(position=0, inner=None),
),
literal=StringLiteral("foo"),
)
visitor = FooBoundBooleanExpressionVisitor()
- result = base.visit(bound_expression, visitor=visitor)
+ result = visit(bound_expression, visitor=visitor)
assert result == ["LESS_THAN_OR_EQUAL"]
def test_bound_boolean_expression_visitor_raise_on_unbound_predicate():
- bound_expression = base.LessThanOrEqual[str](
- term=base.Reference("foo"),
+ bound_expression = LessThanOrEqual[str](
+ term=Reference("foo"),
literal=StringLiteral("foo"),
)
visitor = FooBoundBooleanExpressionVisitor()
with pytest.raises(TypeError) as exc_info:
- base.visit(bound_expression, visitor=visitor)
+ visit(bound_expression, visitor=visitor)
assert "Not a bound predicate" in str(exc_info.value)
@@ -1399,15 +830,15 @@ def _to_manifest_file(*partitions: PartitionFieldSummary) -> ManifestFile:
def _create_manifest_evaluator(bound_expr: BoundPredicate) -> _ManifestEvalVisitor:
"""For testing. Creates a bogus evaluator, and then replaces the expression"""
evaluator = _ManifestEvalVisitor(
- Schema(NestedField(1, "id", LongType())), base.EqualTo(term=base.Reference("id"), literal=literal("foo"))
+ Schema(NestedField(1, "id", LongType())), EqualTo(term=Reference("id"), literal=literal("foo"))
)
evaluator.partition_filter = bound_expr
return evaluator
def test_manifest_evaluator_less_than_no_overlap():
- expr = base.BoundLessThan(
- term=base.BoundReference(
+ expr = BoundLessThan(
+ term=BoundReference(
field=NestedField(field_id=1, name="foo", field_type=StringType(), required=False),
accessor=Accessor(position=0, inner=None),
),
@@ -1427,8 +858,8 @@ def test_manifest_evaluator_less_than_no_overlap():
def test_manifest_evaluator_less_than_overlap():
- expr = base.BoundLessThan(
- term=base.BoundReference(
+ expr = BoundLessThan(
+ term=BoundReference(
field=NestedField(field_id=1, name="foo", field_type=StringType(), required=False),
accessor=Accessor(position=0, inner=None),
),
@@ -1448,8 +879,8 @@ def test_manifest_evaluator_less_than_overlap():
def test_manifest_evaluator_less_than_all_null():
- expr = base.BoundLessThan(
- term=base.BoundReference(
+ expr = BoundLessThan(
+ term=BoundReference(
field=NestedField(field_id=1, name="foo", field_type=StringType(), required=False),
accessor=Accessor(position=0, inner=None),
),
@@ -1465,8 +896,8 @@ def test_manifest_evaluator_less_than_all_null():
def test_manifest_evaluator_less_than_no_match():
- expr = base.BoundLessThan(
- term=base.BoundReference(
+ expr = BoundLessThan(
+ term=BoundReference(
field=NestedField(field_id=1, name="foo", field_type=StringType(), required=False),
accessor=Accessor(position=0, inner=None),
),
@@ -1486,8 +917,8 @@ def test_manifest_evaluator_less_than_no_match():
def test_manifest_evaluator_less_than_or_equal_no_overlap():
- expr = base.BoundLessThanOrEqual(
- term=base.BoundReference(
+ expr = BoundLessThanOrEqual(
+ term=BoundReference(
field=NestedField(field_id=1, name="foo", field_type=StringType(), required=False),
accessor=Accessor(position=0, inner=None),
),
@@ -1507,8 +938,8 @@ def test_manifest_evaluator_less_than_or_equal_no_overlap():
def test_manifest_evaluator_less_than_or_equal_overlap():
- expr = base.BoundLessThanOrEqual(
- term=base.BoundReference(
+ expr = BoundLessThanOrEqual(
+ term=BoundReference(
field=NestedField(field_id=1, name="foo", field_type=StringType(), required=False),
accessor=Accessor(position=0, inner=None),
),
@@ -1528,8 +959,8 @@ def test_manifest_evaluator_less_than_or_equal_overlap():
def test_manifest_evaluator_less_than_or_equal_all_null():
- expr = base.BoundLessThanOrEqual(
- term=base.BoundReference(
+ expr = BoundLessThanOrEqual(
+ term=BoundReference(
field=NestedField(field_id=1, name="foo", field_type=StringType(), required=False),
accessor=Accessor(position=0, inner=None),
),
@@ -1545,8 +976,8 @@ def test_manifest_evaluator_less_than_or_equal_all_null():
def test_manifest_evaluator_less_than_or_equal_no_match():
- expr = base.BoundLessThanOrEqual(
- term=base.BoundReference(
+ expr = BoundLessThanOrEqual(
+ term=BoundReference(
field=NestedField(field_id=1, name="foo", field_type=StringType(), required=False),
accessor=Accessor(position=0, inner=None),
),
@@ -1566,8 +997,8 @@ def test_manifest_evaluator_less_than_or_equal_no_match():
def test_manifest_evaluator_equal_no_overlap():
- expr = base.BoundEqualTo(
- term=base.BoundReference(
+ expr = BoundEqualTo(
+ term=BoundReference(
field=NestedField(field_id=1, name="foo", field_type=StringType(), required=False),
accessor=Accessor(position=0, inner=None),
),
@@ -1587,8 +1018,8 @@ def test_manifest_evaluator_equal_no_overlap():
def test_manifest_evaluator_equal_overlap():
- expr = base.BoundEqualTo(
- term=base.BoundReference(
+ expr = BoundEqualTo(
+ term=BoundReference(
field=NestedField(field_id=1, name="foo", field_type=StringType(), required=False),
accessor=Accessor(position=0, inner=None),
),
@@ -1613,8 +1044,8 @@ def test_manifest_evaluator_equal_overlap():
def test_manifest_evaluator_equal_all_null():
- expr = base.BoundEqualTo(
- term=base.BoundReference(
+ expr = BoundEqualTo(
+ term=BoundReference(
field=NestedField(field_id=1, name="foo", field_type=StringType(), required=False),
accessor=Accessor(position=0, inner=None),
),
@@ -1630,8 +1061,8 @@ def test_manifest_evaluator_equal_all_null():
def test_manifest_evaluator_equal_no_match():
- expr = base.BoundEqualTo(
- term=base.BoundReference(
+ expr = BoundEqualTo(
+ term=BoundReference(
field=NestedField(field_id=1, name="foo", field_type=StringType(), required=False),
accessor=Accessor(position=0, inner=None),
),
@@ -1651,8 +1082,8 @@ def test_manifest_evaluator_equal_no_match():
def test_manifest_evaluator_greater_than_no_overlap():
- expr = base.BoundGreaterThan(
- term=base.BoundReference(
+ expr = BoundGreaterThan(
+ term=BoundReference(
field=NestedField(field_id=1, name="foo", field_type=StringType(), required=False),
accessor=Accessor(position=0, inner=None),
),
@@ -1672,8 +1103,8 @@ def test_manifest_evaluator_greater_than_no_overlap():
def test_manifest_evaluator_greater_than_overlap():
- expr = base.BoundGreaterThan(
- term=base.BoundReference(
+ expr = BoundGreaterThan(
+ term=BoundReference(
field=NestedField(field_id=1, name="foo", field_type=StringType(), required=False),
accessor=Accessor(position=0, inner=None),
),
@@ -1693,8 +1124,8 @@ def test_manifest_evaluator_greater_than_overlap():
def test_manifest_evaluator_greater_than_all_null():
- expr = base.BoundGreaterThan(
- term=base.BoundReference(
+ expr = BoundGreaterThan(
+ term=BoundReference(
field=NestedField(field_id=1, name="foo", field_type=StringType(), required=False),
accessor=Accessor(position=0, inner=None),
),
@@ -1710,8 +1141,8 @@ def test_manifest_evaluator_greater_than_all_null():
def test_manifest_evaluator_greater_than_no_match():
- expr = base.BoundGreaterThan(
- term=base.BoundReference(
+ expr = BoundGreaterThan(
+ term=BoundReference(
field=NestedField(field_id=1, name="foo", field_type=StringType(), required=False),
accessor=Accessor(position=0, inner=None),
),
@@ -1731,8 +1162,8 @@ def test_manifest_evaluator_greater_than_no_match():
def test_manifest_evaluator_greater_than_or_equal_no_overlap():
- expr = base.BoundGreaterThanOrEqual(
- term=base.BoundReference(
+ expr = BoundGreaterThanOrEqual(
+ term=BoundReference(
field=NestedField(field_id=1, name="foo", field_type=StringType(), required=False),
accessor=Accessor(position=0, inner=None),
),
@@ -1752,8 +1183,8 @@ def test_manifest_evaluator_greater_than_or_equal_no_overlap():
def test_manifest_evaluator_greater_than_or_equal_overlap():
- expr = base.BoundGreaterThanOrEqual(
- term=base.BoundReference(
+ expr = BoundGreaterThanOrEqual(
+ term=BoundReference(
field=NestedField(field_id=1, name="foo", field_type=StringType(), required=False),
accessor=Accessor(position=0, inner=None),
),
@@ -1773,8 +1204,8 @@ def test_manifest_evaluator_greater_than_or_equal_overlap():
def test_manifest_evaluator_greater_than_or_equal_all_null():
- expr = base.BoundGreaterThanOrEqual(
- term=base.BoundReference(
+ expr = BoundGreaterThanOrEqual(
+ term=BoundReference(
field=NestedField(field_id=1, name="foo", field_type=StringType(), required=False),
accessor=Accessor(position=0, inner=None),
),
@@ -1790,8 +1221,8 @@ def test_manifest_evaluator_greater_than_or_equal_all_null():
def test_manifest_evaluator_greater_than_or_equal_no_match():
- expr = base.BoundGreaterThanOrEqual(
- term=base.BoundReference(
+ expr = BoundGreaterThanOrEqual(
+ term=BoundReference(
field=NestedField(field_id=1, name="foo", field_type=StringType(), required=False),
accessor=Accessor(position=0, inner=None),
),
@@ -1811,8 +1242,8 @@ def test_manifest_evaluator_greater_than_or_equal_no_match():
def test_manifest_evaluator_is_nan():
- expr = base.BoundIsNaN(
- term=base.BoundReference(
+ expr = BoundIsNaN(
+ term=BoundReference(
field=NestedField(field_id=1, name="foo", field_type=DoubleType(), required=False),
accessor=Accessor(position=0, inner=None),
)
@@ -1826,8 +1257,8 @@ def test_manifest_evaluator_is_nan():
def test_manifest_evaluator_is_nan_inverse():
- expr = base.BoundIsNaN(
- term=base.BoundReference(
+ expr = BoundIsNaN(
+ term=BoundReference(
field=NestedField(field_id=1, name="foo", field_type=DoubleType(), required=False),
accessor=Accessor(position=0, inner=None),
)
@@ -1846,8 +1277,8 @@ def test_manifest_evaluator_is_nan_inverse():
def test_manifest_evaluator_not_nan():
- expr = base.BoundNotNaN(
- term=base.BoundReference(
+ expr = BoundNotNaN(
+ term=BoundReference(
field=NestedField(field_id=1, name="foo", field_type=DoubleType(), required=False),
accessor=Accessor(position=0, inner=None),
)
@@ -1866,8 +1297,8 @@ def test_manifest_evaluator_not_nan():
def test_manifest_evaluator_not_nan_inverse():
- expr = base.BoundNotNaN(
- term=base.BoundReference(
+ expr = BoundNotNaN(
+ term=BoundReference(
field=NestedField(field_id=1, name="foo", field_type=DoubleType(), required=False),
accessor=Accessor(position=0, inner=None),
)
@@ -1881,8 +1312,8 @@ def test_manifest_evaluator_not_nan_inverse():
def test_manifest_evaluator_is_null():
- expr = base.BoundIsNull(
- term=base.BoundReference(
+ expr = BoundIsNull(
+ term=BoundReference(
field=NestedField(field_id=1, name="foo", field_type=StringType(), required=False),
accessor=Accessor(position=0, inner=None),
),
@@ -1901,8 +1332,8 @@ def test_manifest_evaluator_is_null():
def test_manifest_evaluator_is_null_inverse():
- expr = base.BoundIsNull(
- term=base.BoundReference(
+ expr = BoundIsNull(
+ term=BoundReference(
field=NestedField(field_id=1, name="foo", field_type=StringType(), required=False),
accessor=Accessor(position=0, inner=None),
),
@@ -1916,8 +1347,8 @@ def test_manifest_evaluator_is_null_inverse():
def test_manifest_evaluator_not_null():
- expr = base.BoundNotNull(
- term=base.BoundReference(
+ expr = BoundNotNull(
+ term=BoundReference(
field=NestedField(field_id=1, name="foo", field_type=StringType(), required=False),
accessor=Accessor(position=0, inner=None),
),
@@ -1931,8 +1362,8 @@ def test_manifest_evaluator_not_null():
def test_manifest_evaluator_not_null_nan():
- expr = base.BoundNotNull(
- term=base.BoundReference(
+ expr = BoundNotNull(
+ term=BoundReference(
field=NestedField(field_id=1, name="foo", field_type=DoubleType(), required=False),
accessor=Accessor(position=0, inner=None),
),
@@ -1946,8 +1377,8 @@ def test_manifest_evaluator_not_null_nan():
def test_manifest_evaluator_not_null_inverse():
- expr = base.BoundNotNull(
- term=base.BoundReference(
+ expr = BoundNotNull(
+ term=BoundReference(
field=NestedField(field_id=1, name="foo", field_type=StringType(), required=False),
accessor=Accessor(position=0, inner=None),
),
@@ -1959,8 +1390,8 @@ def test_manifest_evaluator_not_null_inverse():
def test_manifest_evaluator_not_equal_to():
- expr = base.BoundNotEqualTo(
- term=base.BoundReference(
+ expr = BoundNotEqualTo(
+ term=BoundReference(
field=NestedField(field_id=1, name="foo", field_type=StringType(), required=False),
accessor=Accessor(position=0, inner=None),
),
@@ -1973,8 +1404,8 @@ def test_manifest_evaluator_not_equal_to():
def test_manifest_evaluator_in():
- expr = base.BoundIn(
- term=base.BoundReference(
+ expr = BoundIn(
+ term=BoundReference(
field=NestedField(field_id=1, name="foo", field_type=LongType(), required=False),
accessor=Accessor(position=0, inner=None),
),
@@ -1994,8 +1425,8 @@ def test_manifest_evaluator_in():
def test_manifest_evaluator_not_in():
- expr = base.BoundNotIn(
- term=base.BoundReference(
+ expr = BoundNotIn(
+ term=BoundReference(
field=NestedField(field_id=1, name="foo", field_type=LongType(), required=False),
accessor=Accessor(position=0, inner=None),
),
@@ -2015,8 +1446,8 @@ def test_manifest_evaluator_not_in():
def test_manifest_evaluator_in_null():
- expr = base.BoundIn(
- term=base.BoundReference(
+ expr = BoundIn(
+ term=BoundReference(
field=NestedField(field_id=1, name="foo", field_type=LongType(), required=False),
accessor=Accessor(position=0, inner=None),
),
@@ -2036,8 +1467,8 @@ def test_manifest_evaluator_in_null():
def test_manifest_evaluator_in_inverse():
- expr = base.BoundIn(
- term=base.BoundReference(
+ expr = BoundIn(
+ term=BoundReference(
field=NestedField(field_id=1, name="foo", field_type=LongType(), required=False),
accessor=Accessor(position=0, inner=None),
),
@@ -2057,8 +1488,8 @@ def test_manifest_evaluator_in_inverse():
def test_manifest_evaluator_in_overflow():
- expr = base.BoundIn(
- term=base.BoundReference(
+ expr = BoundIn(
+ term=BoundReference(
field=NestedField(field_id=1, name="foo", field_type=LongType(), required=False),
accessor=Accessor(position=0, inner=None),
),
@@ -2078,8 +1509,8 @@ def test_manifest_evaluator_in_overflow():
def test_manifest_evaluator_less_than_lower_bound():
- expr = base.BoundIn(
- term=base.BoundReference(
+ expr = BoundIn(
+ term=BoundReference(
field=NestedField(field_id=1, name="foo", field_type=LongType(), required=False),
accessor=Accessor(position=0, inner=None),
),
@@ -2099,8 +1530,8 @@ def test_manifest_evaluator_less_than_lower_bound():
def test_manifest_evaluator_greater_than_upper_bound():
- expr = base.BoundIn(
- term=base.BoundReference(
+ expr = BoundIn(
+ term=BoundReference(
field=NestedField(field_id=1, name="foo", field_type=LongType(), required=False),
accessor=Accessor(position=0, inner=None),
),
@@ -2120,7 +1551,7 @@ def test_manifest_evaluator_greater_than_upper_bound():
def test_manifest_evaluator_true():
- expr = base.AlwaysTrue()
+ expr = AlwaysTrue()
manifest = _to_manifest_file(PartitionFieldSummary(contains_null=True, contains_nan=True, lower_bound=None, upper_bound=None))
@@ -2128,7 +1559,7 @@ def test_manifest_evaluator_true():
def test_manifest_evaluator_false():
- expr = base.AlwaysFalse()
+ expr = AlwaysFalse()
manifest = _to_manifest_file(PartitionFieldSummary(contains_null=True, contains_nan=True, lower_bound=None, upper_bound=None))
@@ -2136,9 +1567,9 @@ def test_manifest_evaluator_false():
def test_manifest_evaluator_not():
- expr = base.Not(
- base.BoundIn(
- term=base.BoundReference(
+ expr = Not(
+ BoundIn(
+ term=BoundReference(
field=NestedField(field_id=1, name="foo", field_type=LongType(), required=False),
accessor=Accessor(position=0, inner=None),
),
@@ -2158,16 +1589,16 @@ def test_manifest_evaluator_not():
def test_manifest_evaluator_and():
- expr = base.And(
- base.BoundIn(
- term=base.BoundReference(
+ expr = And(
+ BoundIn(
+ term=BoundReference(
field=NestedField(field_id=1, name="foo", field_type=LongType(), required=False),
accessor=Accessor(position=0, inner=None),
),
literals={LongLiteral(i) for i in range(22)},
),
- base.BoundIn(
- term=base.BoundReference(
+ BoundIn(
+ term=BoundReference(
field=NestedField(field_id=1, name="foo", field_type=LongType(), required=False),
accessor=Accessor(position=0, inner=None),
),
@@ -2187,16 +1618,16 @@ def test_manifest_evaluator_and():
def test_manifest_evaluator_or():
- expr = base.Or(
- base.BoundIn(
- term=base.BoundReference(
+ expr = Or(
+ BoundIn(
+ term=BoundReference(
field=NestedField(field_id=1, name="foo", field_type=LongType(), required=False),
accessor=Accessor(position=0, inner=None),
),
literals={LongLiteral(i) for i in range(22)},
),
- base.BoundIn(
- term=base.BoundReference(
+ BoundIn(
+ term=BoundReference(
field=NestedField(field_id=1, name="foo", field_type=LongType(), required=False),
accessor=Accessor(position=0, inner=None),
),
@@ -2218,8 +1649,8 @@ def test_manifest_evaluator_or():
def test_bound_predicate_invert():
with pytest.raises(NotImplementedError):
- _ = ~base.BoundPredicate(
- term=base.BoundReference(
+ _ = ~BoundPredicate(
+ term=BoundReference(
field=NestedField(field_id=1, name="foo", field_type=StringType(), required=False),
accessor=Accessor(position=0, inner=None),
)
@@ -2228,8 +1659,8 @@ def test_bound_predicate_invert():
def test_bound_unary_predicate_invert():
with pytest.raises(NotImplementedError):
- _ = ~base.BoundUnaryPredicate(
- term=base.BoundReference(
+ _ = ~BoundUnaryPredicate(
+ term=BoundReference(
field=NestedField(field_id=1, name="foo", field_type=StringType(), required=False),
accessor=Accessor(position=0, inner=None),
)
@@ -2238,8 +1669,8 @@ def test_bound_unary_predicate_invert():
def test_bound_set_predicate_invert():
with pytest.raises(NotImplementedError):
- _ = ~base.BoundSetPredicate(
- term=base.BoundReference(
+ _ = ~BoundSetPredicate(
+ term=BoundReference(
field=NestedField(field_id=1, name="foo", field_type=StringType(), required=False),
accessor=Accessor(position=0, inner=None),
),
@@ -2249,8 +1680,8 @@ def test_bound_set_predicate_invert():
def test_bound_literal_predicate_invert():
with pytest.raises(NotImplementedError):
- _ = ~base.BoundLiteralPredicate(
- term=base.BoundReference(
+ _ = ~BoundLiteralPredicate(
+ term=BoundReference(
field=NestedField(field_id=1, name="foo", field_type=StringType(), required=False),
accessor=Accessor(position=0, inner=None),
),
@@ -2258,96 +1689,69 @@ def test_bound_literal_predicate_invert():
)
-def test_non_primitive_from_byte_buffer():
- with pytest.raises(ValueError) as exc_info:
- _ = _from_byte_buffer(ListType(element_id=1, element_type=StringType()), b"\0x00")
-
- assert str(exc_info.value) == "Expected a PrimitiveType, got: <class 'pyiceberg.types.ListType'>"
-
-
def test_unbound_predicate_invert():
with pytest.raises(NotImplementedError):
- _ = ~base.UnboundPredicate(term=base.Reference("a"))
+ _ = ~UnboundPredicate(term=Reference("a"))
def test_unbound_predicate_bind(table_schema_simple: Schema):
with pytest.raises(NotImplementedError):
- _ = base.UnboundPredicate(term=base.Reference("a")).bind(table_schema_simple)
+ _ = UnboundPredicate(term=Reference("a")).bind(table_schema_simple)
def test_unbound_unary_predicate_invert():
with pytest.raises(NotImplementedError):
- _ = ~base.UnaryPredicate(term=base.Reference("a"))
+ _ = ~UnaryPredicate(term=Reference("a"))
def test_unbound_set_predicate_invert():
with pytest.raises(NotImplementedError):
- _ = ~base.SetPredicate(term=base.Reference("a"), literals=(literal("hello"), literal("world")))
+ _ = ~SetPredicate(term=Reference("a"), literals=(literal("hello"), literal("world")))
def test_unbound_literal_predicate_invert():
with pytest.raises(NotImplementedError):
- _ = ~base.LiteralPredicate(term=base.Reference("a"), literal=literal("hello"))
+ _ = ~LiteralPredicate(term=Reference("a"), literal=literal("hello"))
def test_rewrite_not_equal_to():
- assert rewrite_not(base.Not(base.EqualTo(base.Reference("x"), literal(34.56)))) == base.NotEqualTo(
- base.Reference("x"), literal(34.56)
- )
+ assert rewrite_not(Not(EqualTo(Reference("x"), literal(34.56)))) == NotEqualTo(Reference("x"), literal(34.56))
def test_rewrite_not_not_equal_to():
- assert rewrite_not(base.Not(base.NotEqualTo(base.Reference("x"), literal(34.56)))) == base.EqualTo(
- base.Reference("x"), literal(34.56)
- )
+ assert rewrite_not(Not(NotEqualTo(Reference("x"), literal(34.56)))) == EqualTo(Reference("x"), literal(34.56))
def test_rewrite_not_in():
- assert rewrite_not(base.Not(base.In(base.Reference("x"), (literal(34.56),)))) == base.NotIn(
- base.Reference("x"), (literal(34.56),)
- )
+ assert rewrite_not(Not(In(Reference("x"), (literal(34.56),)))) == NotIn(Reference("x"), (literal(34.56),))
def test_rewrite_and():
- assert rewrite_not(
- base.Not(
- base.And(
- base.EqualTo(base.Reference("x"), literal(34.56)),
- base.EqualTo(base.Reference("y"), literal(34.56)),
- )
- )
- ) == base.Or(
- base.NotEqualTo(term=base.Reference(name="x"), literal=literal(34.56)),
- base.NotEqualTo(term=base.Reference(name="y"), literal=literal(34.56)),
+ assert rewrite_not(Not(And(EqualTo(Reference("x"), literal(34.56)), EqualTo(Reference("y"), literal(34.56)),))) == Or(
+ NotEqualTo(term=Reference(name="x"), literal=literal(34.56)),
+ NotEqualTo(term=Reference(name="y"), literal=literal(34.56)),
)
def test_rewrite_or():
- assert rewrite_not(
- base.Not(
- base.Or(
- base.EqualTo(base.Reference("x"), literal(34.56)),
- base.EqualTo(base.Reference("y"), literal(34.56)),
- )
- )
- ) == base.And(
- base.NotEqualTo(term=base.Reference(name="x"), literal=literal(34.56)),
- base.NotEqualTo(term=base.Reference(name="y"), literal=literal(34.56)),
+ assert rewrite_not(Not(Or(EqualTo(Reference("x"), literal(34.56)), EqualTo(Reference("y"), literal(34.56)),))) == And(
+ NotEqualTo(term=Reference(name="x"), literal=literal(34.56)),
+ NotEqualTo(term=Reference(name="y"), literal=literal(34.56)),
)
def test_rewrite_always_false():
- assert rewrite_not(base.Not(base.AlwaysFalse())) == base.AlwaysTrue()
+ assert rewrite_not(Not(AlwaysFalse())) == AlwaysTrue()
def test_rewrite_always_true():
- assert rewrite_not(base.Not(base.AlwaysTrue())) == base.AlwaysFalse()
+ assert rewrite_not(Not(AlwaysTrue())) == AlwaysFalse()
def test_rewrite_bound():
schema = Schema(NestedField(2, "a", IntegerType(), required=False), schema_id=1)
- assert rewrite_not(base.IsNull(base.Reference("a")).bind(schema)) == base.BoundIsNull(
- term=base.BoundReference(
+ assert rewrite_not(IsNull(Reference("a")).bind(schema)) == BoundIsNull(
+ term=BoundReference(
field=NestedField(field_id=2, name="a", field_type=IntegerType(), required=False),
accessor=Accessor(position=0, inner=None),
)
diff --git a/python/tests/test_schema.py b/python/tests/test_schema.py
index 0017760ed2..5b64d95d6b 100644
--- a/python/tests/test_schema.py
+++ b/python/tests/test_schema.py
@@ -21,7 +21,7 @@ from typing import Any, Dict
import pytest
from pyiceberg import schema
-from pyiceberg.expressions.base import Accessor
+from pyiceberg.expressions import Accessor
from pyiceberg.files import StructProtocol
from pyiceberg.schema import Schema, build_position_accessors, prune_columns
from pyiceberg.typedef import EMPTY_DICT