3838 ParamSpecKwargs ,
3939 TypeAliasType ,
4040 Generic ,
41- Union ,
4241 NoDefault ,
4342)
4443
@@ -727,6 +726,81 @@ class FastConnector(Connection):
727726 item = _type_check (parameters , f'{ self } accepts only single type.' , allow_special_forms = True )
728727 return _GenericAlias (self , (item ,))
729728
729+ @_SpecialForm
730+ def Union (self , parameters ):
731+ """Union type; Union[X, Y] is equivalent to X | Y and means either X or Y.
732+
733+ To define a union, use e.g. Union[int, str] or the shorthand int | str.
734+ Using that shorthand is recommended. Details:
735+
736+ * The arguments must be types and there must be at least one.
737+
738+ * Unions of unions are flattened, e.g.::
739+
740+ Union[Union[int, str], float] == Union[int, str, float]
741+
742+ * Unions of a single argument vanish, e.g.::
743+
744+ Union[int] == int # The constructor actually returns int
745+
746+ * Redundant arguments are skipped, e.g.::
747+
748+ Union[int, str, int] == Union[int, str] == int | str
749+
750+ * When comparing unions, the argument order is ignored, e.g.::
751+
752+ Union[int, str] == Union[str, int]
753+
754+ * You cannot subclass or instantiate a ``Union``.
755+
756+ * You cannot write ``Union[X][Y]``.
757+ """
758+ if not parameters :
759+ raise TypeError ("Cannot take a Union of no types." )
760+ if not isinstance (parameters , tuple ):
761+ parameters = (parameters ,)
762+
763+ flattened = []
764+ for p in parameters :
765+ if isinstance (p , types .UnionType ):
766+ flattened .extend (p .__args__ )
767+ elif hasattr (p , '__origin__' ) and p .__origin__ is Union :
768+ flattened .extend (p .__args__ )
769+ else :
770+ flattened .append (p )
771+
772+ unique_args = []
773+ seen = set ()
774+ for arg in flattened :
775+ if arg not in seen :
776+ unique_args .append (arg )
777+ seen .add (arg )
778+
779+ if len (unique_args ) == 0 :
780+ raise TypeError ("Cannot take a Union of no types." )
781+ if len (unique_args ) == 1 :
782+ return unique_args [0 ]
783+
784+ return _UnionGenericAlias (tuple (unique_args ))
785+
786+
787+ def _union_from_types (left , right ):
788+ """Helper function to create union types avoiding recursion."""
789+ try :
790+ if hasattr (left , '__or__' ) and not isinstance (left , _GenericAlias ):
791+ return left | right
792+ elif hasattr (right , '__ror__' ) and not isinstance (right , _GenericAlias ):
793+ return right .__ror__ (left )
794+ else :
795+ if hasattr (left , '__origin__' ):
796+ left = left .__origin__
797+ if hasattr (right , '__origin__' ):
798+ right = right .__origin__
799+ return left | right
800+ except (TypeError , AttributeError ):
801+ return f"Union[{ left } , { right } ]"
802+
803+
730804@_SpecialForm
731805def Optional (self , parameters ):
732806 """Optional[X] is equivalent to Union[X, None]."""
@@ -1334,12 +1408,6 @@ def __eq__(self, other):
13341408 def __hash__ (self ):
13351409 return hash ((self .__origin__ , self .__args__ ))
13361410
1337- def __or__ (self , right ):
1338- return Union [self , right ]
1339-
1340- def __ror__ (self , left ):
1341- return Union [left , self ]
1342-
13431411 @_tp_cache
13441412 def __getitem__ (self , args ):
13451413 # Parameterizes an already-parameterized object.
@@ -1563,12 +1631,6 @@ def __subclasscheck__(self, cls):
15631631 def __reduce__ (self ):
15641632 return self ._name
15651633
1566- def __or__ (self , right ):
1567- return Union [self , right ]
1568-
1569- def __ror__ (self , left ):
1570- return Union [left , self ]
1571-
15721634
15731635class _CallableGenericAlias (_NotIterable , _GenericAlias , _root = True ):
15741636 def __repr__ (self ):
@@ -1634,41 +1696,42 @@ def __getitem__(self, params):
16341696 return self .copy_with (params )
16351697
16361698
1637- class _UnionGenericAliasMeta (type ):
1638- def __instancecheck__ (self , inst : object ) -> bool :
1639- import warnings
1640- warnings ._deprecated ("_UnionGenericAlias" , remove = (3 , 17 ))
1641- return isinstance (inst , Union )
1642-
1643- def __subclasscheck__ (self , inst : type ) -> bool :
1644- import warnings
1645- warnings ._deprecated ("_UnionGenericAlias" , remove = (3 , 17 ))
1646- return issubclass (inst , Union )
1647-
1648- def __eq__ (self , other ):
1649- import warnings
1650- warnings ._deprecated ("_UnionGenericAlias" , remove = (3 , 17 ))
1651- if other is _UnionGenericAlias or other is Union :
1652- return True
1653- return NotImplemented
1654-
1655- def __hash__ (self ):
1656- return hash (Union )
1657-
1658-
1659- class _UnionGenericAlias (metaclass = _UnionGenericAliasMeta ):
1660- """Compatibility hack.
1699+ class _SimpleUnion :
1700+ """Fallback union representation when types.UnionType creation fails."""
1701+ def __init__ (self , args ):
1702+ self .__args__ = args
1703+ self .__origin__ = Union
1704+
1705+ def __repr__ (self ):
1706+ return f"Union{ self .__args__ } "
16611707
1662- A class named _UnionGenericAlias used to be used to implement
1663- typing.Union. This class exists to serve as a shim to preserve
1664- the meaning of some code that used to use _UnionGenericAlias
1665- directly.
16661708
1667- """
1668- def __new__ (cls , self_cls , parameters , / , * , name = None ):
1669- import warnings
1670- warnings ._deprecated ("_UnionGenericAlias" , remove = (3 , 17 ))
1671- return Union [parameters ]
1709+ class _UnionGenericAlias :
1710+ """A placeholder class for union types that wraps types.UnionType functionality."""
1711+
1712+ def __new__ (cls , args ):
1713+ if len (args ) == 1 :
1714+ return args [0 ]
1715+ elif len (args ) == 2 :
1716+ try :
1717+ result = args [0 ] | args [1 ]
1718+ if hasattr (result , '__class__' ) and result .__class__ .__name__ == 'UnionType' :
1719+ return result
1720+ else :
1721+ return _SimpleUnion (args )
1722+ except (TypeError , AttributeError ):
1723+ return _SimpleUnion (args )
1724+ else :
1725+ try :
1726+ result = args [0 ]
1727+ for arg in args [1 :]:
1728+ result = result | arg
1729+ if hasattr (result , '__class__' ) and result .__class__ .__name__ == 'UnionType' :
1730+ return result
1731+ else :
1732+ return _SimpleUnion (args )
1733+ except (TypeError , AttributeError ):
1734+ return _SimpleUnion (args )
16721735
16731736
16741737def _value_and_type_iter (parameters ):
@@ -3463,7 +3526,7 @@ def writelines(self, lines: list[AnyStr]) -> None:
34633526 pass
34643527
34653528 @abstractmethod
3466- def __enter__ (self ) -> IO [AnyStr ]:
3529+ def __enter__ (self ) -> ' IO[AnyStr]' :
34673530 pass
34683531
34693532 @abstractmethod
@@ -3481,7 +3544,7 @@ def write(self, s: bytes | bytearray) -> int:
34813544 pass
34823545
34833546 @abstractmethod
3484- def __enter__ (self ) -> BinaryIO :
3547+ def __enter__ (self ) -> ' BinaryIO' :
34853548 pass
34863549
34873550
@@ -3516,7 +3579,7 @@ def newlines(self) -> Any:
35163579 pass
35173580
35183581 @abstractmethod
3519- def __enter__ (self ) -> TextIO :
3582+ def __enter__ (self ) -> ' TextIO' :
35203583 pass
35213584
35223585
@@ -3550,7 +3613,7 @@ def dataclass_transform(
35503613 order_default : bool = False ,
35513614 kw_only_default : bool = False ,
35523615 frozen_default : bool = False ,
3553- field_specifiers : tuple [type [Any ] | Callable [..., Any ], ...] = (),
3616+ field_specifiers : tuple [Union [ type [Any ], Callable [..., Any ] ], ...] = (),
35543617 ** kwargs : Any ,
35553618) -> _IdentityCallable :
35563619 """Decorator to mark an object as providing dataclass-like behaviour.
0 commit comments