@@ -309,6 +309,11 @@ def __eq__(self, other: Any) -> bool:
309309 return self .term == other .term
310310 return False
311311
312+ @property
313+ @abstractmethod
314+ def as_unbound (self ) -> Type [UnboundPredicate [Any ]]:
315+ ...
316+
312317
313318class UnboundPredicate (Generic [L ], Unbound [BooleanExpression ], BooleanExpression , ABC ):
314319 term : UnboundTerm [Any ]
@@ -347,6 +352,11 @@ class BoundUnaryPredicate(BoundPredicate[L], ABC):
347352 def __repr__ (self ) -> str :
348353 return f"{ str (self .__class__ .__name__ )} (term={ repr (self .term )} )"
349354
355+ @property
356+ @abstractmethod
357+ def as_unbound (self ) -> Type [UnaryPredicate ]:
358+ ...
359+
350360
351361class BoundIsNull (BoundUnaryPredicate [L ]):
352362 def __new__ (cls , term : BoundTerm [L ]): # pylint: disable=W0221
@@ -357,6 +367,10 @@ def __new__(cls, term: BoundTerm[L]): # pylint: disable=W0221
357367 def __invert__ (self ) -> BoundNotNull [L ]:
358368 return BoundNotNull (self .term )
359369
370+ @property
371+ def as_unbound (self ) -> Type [IsNull ]:
372+ return IsNull
373+
360374
361375class BoundNotNull (BoundUnaryPredicate [L ]):
362376 def __new__ (cls , term : BoundTerm [L ]): # pylint: disable=W0221
@@ -367,6 +381,10 @@ def __new__(cls, term: BoundTerm[L]): # pylint: disable=W0221
367381 def __invert__ (self ) -> BoundIsNull [L ]:
368382 return BoundIsNull (self .term )
369383
384+ @property
385+ def as_unbound (self ) -> Type [NotNull ]:
386+ return NotNull
387+
370388
371389class IsNull (UnaryPredicate ):
372390 def __invert__ (self ) -> NotNull :
@@ -396,6 +414,10 @@ def __new__(cls, term: BoundTerm[L]): # pylint: disable=W0221
396414 def __invert__ (self ) -> BoundNotNaN [L ]:
397415 return BoundNotNaN (self .term )
398416
417+ @property
418+ def as_unbound (self ) -> Type [IsNaN ]:
419+ return IsNaN
420+
399421
400422class BoundNotNaN (BoundUnaryPredicate [L ]):
401423 def __new__ (cls , term : BoundTerm [L ]): # pylint: disable=W0221
@@ -407,6 +429,10 @@ def __new__(cls, term: BoundTerm[L]): # pylint: disable=W0221
407429 def __invert__ (self ) -> BoundIsNaN [L ]:
408430 return BoundIsNaN (self .term )
409431
432+ @property
433+ def as_unbound (self ) -> Type [NotNaN ]:
434+ return NotNaN
435+
410436
411437class IsNaN (UnaryPredicate ):
412438 def __invert__ (self ) -> NotNaN :
@@ -477,6 +503,11 @@ def __repr__(self) -> str:
477503 def __eq__ (self , other : Any ) -> bool :
478504 return self .term == other .term and self .literals == other .literals if isinstance (other , BoundSetPredicate ) else False
479505
506+ @property
507+ @abstractmethod
508+ def as_unbound (self ) -> Type [SetPredicate [L ]]:
509+ ...
510+
480511
481512class BoundIn (BoundSetPredicate [L ]):
482513 def __new__ (cls , term : BoundTerm [L ], literals : Set [Literal [L ]]): # pylint: disable=W0221
@@ -494,6 +525,10 @@ def __invert__(self) -> BoundNotIn[L]:
494525 def __eq__ (self , other : Any ) -> bool :
495526 return self .term == other .term and self .literals == other .literals if isinstance (other , BoundIn ) else False
496527
528+ @property
529+ def as_unbound (self ) -> Type [In [L ]]:
530+ return In
531+
497532
498533class BoundNotIn (BoundSetPredicate [L ]):
499534 def __new__ ( # pylint: disable=W0221
@@ -512,6 +547,10 @@ def __new__( # pylint: disable=W0221
512547 def __invert__ (self ) -> BoundIn [L ]:
513548 return BoundIn (self .term , self .literals )
514549
550+ @property
551+ def as_unbound (self ) -> Type [NotIn [L ]]:
552+ return NotIn
553+
515554
516555class In (SetPredicate [L ]):
517556 def __new__ (
@@ -601,36 +640,65 @@ def __eq__(self, other):
601640 def __repr__ (self ) -> str :
602641 return f"{ str (self .__class__ .__name__ )} (term={ repr (self .term )} , literal={ repr (self .literal )} )"
603642
643+ @property
644+ @abstractmethod
645+ def as_unbound (self ) -> Type [LiteralPredicate [L ]]:
646+ ...
647+
604648
605649class BoundEqualTo (BoundLiteralPredicate [L ]):
606650 def __invert__ (self ) -> BoundNotEqualTo [L ]:
607651 return BoundNotEqualTo [L ](self .term , self .literal )
608652
653+ @property
654+ def as_unbound (self ) -> Type [EqualTo [L ]]:
655+ return EqualTo
656+
609657
610658class BoundNotEqualTo (BoundLiteralPredicate [L ]):
611659 def __invert__ (self ) -> BoundEqualTo [L ]:
612660 return BoundEqualTo [L ](self .term , self .literal )
613661
662+ @property
663+ def as_unbound (self ) -> Type [NotEqualTo [L ]]:
664+ return NotEqualTo
665+
614666
615667class BoundGreaterThanOrEqual (BoundLiteralPredicate [L ]):
616668 def __invert__ (self ) -> BoundLessThan [L ]:
617669 return BoundLessThan [L ](self .term , self .literal )
618670
671+ @property
672+ def as_unbound (self ) -> Type [GreaterThanOrEqual [L ]]:
673+ return GreaterThanOrEqual [L ]
674+
619675
620676class BoundGreaterThan (BoundLiteralPredicate [L ]):
621677 def __invert__ (self ) -> BoundLessThanOrEqual [L ]:
622678 return BoundLessThanOrEqual (self .term , self .literal )
623679
680+ @property
681+ def as_unbound (self ) -> Type [GreaterThan [L ]]:
682+ return GreaterThan [L ]
683+
624684
625685class BoundLessThan (BoundLiteralPredicate [L ]):
626686 def __invert__ (self ) -> BoundGreaterThanOrEqual [L ]:
627687 return BoundGreaterThanOrEqual [L ](self .term , self .literal )
628688
689+ @property
690+ def as_unbound (self ) -> Type [LessThan [L ]]:
691+ return LessThan [L ]
692+
629693
630694class BoundLessThanOrEqual (BoundLiteralPredicate [L ]):
631695 def __invert__ (self ) -> BoundGreaterThan [L ]:
632696 return BoundGreaterThan [L ](self .term , self .literal )
633697
698+ @property
699+ def as_unbound (self ) -> Type [LessThanOrEqual [L ]]:
700+ return LessThanOrEqual [L ]
701+
634702
635703class EqualTo (LiteralPredicate [L ]):
636704 def __invert__ (self ) -> NotEqualTo [L ]:
0 commit comments