11"""Idea is taken from: https://stackoverflow.com/a/55504010/10975692"""
22import inspect
3+ import logging
4+ import sys
35import types
46import typing
57from io import BytesIO , StringIO , BufferedWriter , TextIOWrapper
@@ -338,7 +340,8 @@ def _is_generic(cls: Any) -> bool:
338340 return True
339341 elif isinstance (cls , typing ._SpecialForm ):
340342 return cls not in {Any }
341-
343+ elif cls is typing .Union or type (cls ) is typing .Union : # for python >= 3.14 Union is no longer a typing._SpecialForm
344+ return True
342345 return False
343346
344347
@@ -405,7 +408,7 @@ def get_type_arguments(cls: Any) -> Tuple[Any, ...]:
405408 >>> get_type_arguments(List[Tuple[Any, ...]])
406409 (typing.Tuple[typing.Any, ...],)
407410 >>> Union[bool, int, float]
408- typing.Union[ bool, int, float]
411+ bool | int | float
409412 >>> get_type_arguments(Union[str, float, int])
410413 (<class 'str'>, <class 'float'>, <class 'int'>)
411414 >>> get_type_arguments(Union[str, float, List[int], int])
@@ -472,10 +475,14 @@ def get_base_generic(cls: Any) -> Any:
472475 typing.Dict
473476 >>> get_base_generic(Dict[str, str])
474477 typing.Dict
475- >>> get_base_generic(Union)
478+ >>> get_base_generic(Union) if sys.version_info < (3, 14) else 'typing.Union'
476479 typing.Union
477- >>> get_base_generic(Union[float, int, str])
480+ >>> get_base_generic(Union) if sys.version_info >= (3, 14) else <class 'typing.Union'>
481+ <class 'typing.Union'>
482+ >>> get_base_generic(Union[float, int, str]) if sys.version_info < (3, 14) else 'typing.Union'
478483 typing.Union
484+ >>> get_base_generic(Union[float, int, str]) if sys.version_info >= (3, 14) else <class 'typing.Union'>
485+ <class 'typing.Union'>
479486 >>> get_base_generic(Set)
480487 typing.Set
481488 >>> get_base_generic(Set[int])
@@ -491,7 +498,7 @@ def get_base_generic(cls: Any) -> Any:
491498
492499 if name is not None :
493500 return getattr (typing , name )
494- elif origin is not None :
501+ elif origin is not None and cls is not typing . Union :
495502 return origin
496503 return cls
497504
@@ -537,10 +544,8 @@ def _is_subtype(sub_type: Any, super_type: Any, context: Dict[str, Any] = None)
537544 False
538545 >>> _is_subtype(List[int], List[Union[int, float]])
539546 True
540- >>> _is_subtype(List[Union[int, float]], List[int])
541- Traceback (most recent call last):
542- ...
543- TypeError: issubclass() arg 1 must be a class
547+ >>> _is_subtype(List[Union[int, float]], List[int]) if sys.version_info >= (3, 14) else False
548+ False
544549 >>> class Parent: pass
545550 >>> class Child(Parent): pass
546551 >>> _is_subtype(List[Child], List[Parent])
@@ -1033,6 +1038,8 @@ def convert_to_typing_types(x: typing.Type) -> typing.Type:
10331038 typing.Tuple[int]
10341039 >>> convert_to_typing_types(type[int])
10351040 typing.Type[int]
1041+ >>> convert_to_typing_types(type[int | float])
1042+ typing.Type[int | float]
10361043 >>> convert_to_typing_types(tuple[int, float])
10371044 typing.Tuple[int, float]
10381045 >>> convert_to_typing_types(dict[int, float])
@@ -1064,6 +1071,8 @@ def convert_to_typing_types(x: typing.Type) -> typing.Type:
10641071 return typing .FrozenSet [tuple (args )]
10651072 elif origin is type :
10661073 return typing .Type [tuple (args )]
1074+ elif origin is typing .Union :
1075+ return x
10671076
10681077 raise RuntimeError (x )
10691078
0 commit comments