rdblue commented on code in PR #5303:
URL: https://github.com/apache/iceberg/pull/5303#discussion_r975755647


##########
python/pyiceberg/expressions/base.py:
##########
@@ -672,3 +683,166 @@ def visit_unbound_predicate(self, predicate) -> 
BooleanExpression:
 
     def visit_bound_predicate(self, predicate) -> BooleanExpression:
         raise TypeError(f"Found already bound predicate: {predicate}")
+
+
+class BoundBooleanExpressionVisitor(BooleanExpressionVisitor[T], ABC):
+    @abstractmethod
+    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:
+        """Visit a bound NotIn predicate"""
+
+    @abstractmethod
+    def visit_is_nan(self, term: BoundTerm[T]) -> T:
+        """Visit a bound IsNan predicate"""
+
+    @abstractmethod
+    def visit_not_nan(self, term: BoundTerm[T]) -> T:
+        """Visit a bound NotNan predicate"""
+
+    @abstractmethod
+    def visit_is_null(self, term: BoundTerm[T]) -> T:
+        """Visit a bound IsNull predicate"""
+
+    @abstractmethod
+    def visit_not_null(self, term: BoundTerm[T]) -> T:
+        """Visit a bound NotNull predicate"""
+
+    @abstractmethod
+    def visit_equal(self, term: BoundTerm[T], literal: Literal[Any]) -> T:
+        """Visit a bound Equal predicate"""
+
+    @abstractmethod
+    def visit_not_equal(self, term: BoundTerm[T], literal: Literal[Any]) -> T:
+        """Visit a bound NotEqual predicate"""
+
+    @abstractmethod
+    def visit_greater_than_or_equal(self, term: BoundTerm[T], literal: 
Literal[Any]) -> T:
+        """Visit a bound GreaterThanOrEqual predicate"""
+
+    @abstractmethod
+    def visit_greater_than(self, term: BoundTerm[T], literal: Literal[Any]) -> 
T:
+        """Visit a bound GreaterThan predicate"""
+
+    @abstractmethod
+    def visit_less_than(self, term: BoundTerm[T], literal: Literal[Any]) -> T:
+        """Visit a bound LessThan predicate"""
+
+    @abstractmethod
+    def visit_less_than_or_equal(self, term: BoundTerm[T], literal: 
Literal[Any]) -> T:
+        """Visit a bound LessThanOrEqual predicate"""
+
+    @abstractmethod
+    def visit_true(self) -> T:
+        """Visit a bound True predicate"""
+
+    @abstractmethod
+    def visit_false(self) -> T:
+        """Visit a bound False predicate"""
+
+    @abstractmethod
+    def visit_not(self, child_result: T) -> T:
+        """Visit a bound Not predicate"""
+
+    @abstractmethod
+    def visit_and(self, left_result: T, right_result: T) -> T:
+        """Visit a bound And predicate"""
+
+    @abstractmethod
+    def visit_or(self, left_result: T, right_result: T) -> T:
+        """Visit a bound Or predicate"""
+
+    def visit_unbound_predicate(self, predicate: UnboundPredicate[T]):
+        """Visit an unbound predicate
+        Args:
+            predicate (UnboundPredicate[T]): An unbound predicate
+        Raises:
+            TypeError: This always raises since an unbound predicate is not 
expected in a bound boolean expression
+        """
+        raise TypeError(f"Not a bound predicate: {predicate}")
+
+    def visit_bound_predicate(self, predicate: BoundPredicate[T]) -> T:
+        """Visit a bound predicate
+        Args:
+            predicate (BoundPredicate[T]): A bound predicate
+        """
+        return visit_bound_predicate(predicate, self)
+
+
+@singledispatch
+def visit_bound_predicate(obj, visitor: BooleanExpressionVisitor[T]) -> T:  # 
pylint: disable=unused-argument
+    pass
+
+
+@visit_bound_predicate.register(BoundIn)
+def _(obj: BoundIn, visitor: BoundBooleanExpressionVisitor[T]) -> T:
+    """Visit a bound In predicate"""
+    return visitor.visit_in(term=obj.term, literals=obj.literals)
+
+
+@visit_bound_predicate.register(BoundNotIn)
+def _(obj: BoundNotIn, visitor: BoundBooleanExpressionVisitor[T]) -> T:
+    """Visit a bound NotIn predicate"""
+    return visitor.visit_not_in(term=obj.term, literals=obj.literals)
+
+
+@visit_bound_predicate.register(BoundIsNaN)
+def _(obj: BoundIsNaN, visitor: BoundBooleanExpressionVisitor[T]) -> T:
+    """Visit a bound IsNan predicate"""
+    return visitor.visit_is_nan(term=obj.term)
+
+
+@visit_bound_predicate.register(BoundNotNaN)
+def _(obj: BoundNotNaN, visitor: BoundBooleanExpressionVisitor[T]) -> T:
+    """Visit a bound NotNan predicate"""
+    return visitor.visit_not_nan(term=obj.term)
+
+
+@visit_bound_predicate.register(BoundIsNull)
+def _(obj: BoundIsNull, visitor: BoundBooleanExpressionVisitor[T]) -> T:
+    """Visit a bound IsNull predicate"""
+    return visitor.visit_is_null(term=obj.term)
+
+
+@visit_bound_predicate.register(BoundNotNull)
+def _(obj: BoundNotNull, visitor: BoundBooleanExpressionVisitor[T]) -> T:
+    """Visit a bound NotNull predicate"""
+    return visitor.visit_not_null(term=obj.term)
+
+
+@visit_bound_predicate.register(BoundEqualTo)
+def _(obj: BoundEqualTo, visitor: BoundBooleanExpressionVisitor[T]) -> T:
+    """Visit a bound EqualTo predicate"""

Review Comment:
   Are these doc strings visible anywhere? It seems pretty clear what's 
happening and since this is a `@singledispatch` method I'm not sure when we'd 
ever see them.



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to