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