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])
@@ -473,9 +476,9 @@ def get_base_generic(cls: Any) -> Any:
473476 >>> get_base_generic(Dict[str, str])
474477 typing.Dict
475478 >>> get_base_generic(Union)
476- typing.Union
479+ <class ' typing.Union'>
477480 >>> get_base_generic(Union[float, int, str])
478- typing.Union
481+ <class ' typing.Union'>
479482 >>> get_base_generic(Set)
480483 typing.Set
481484 >>> get_base_generic(Set[int])
@@ -491,7 +494,7 @@ def get_base_generic(cls: Any) -> Any:
491494
492495 if name is not None :
493496 return getattr (typing , name )
494- elif origin is not None :
497+ elif origin is not None and cls is not typing . Union :
495498 return origin
496499 return cls
497500
@@ -537,10 +540,8 @@ def _is_subtype(sub_type: Any, super_type: Any, context: Dict[str, Any] = None)
537540 False
538541 >>> _is_subtype(List[int], List[Union[int, float]])
539542 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
543+ >>> _is_subtype(List[Union[int, float]], List[int]) if sys.version_info >= (3, 14) else False
544+ False
544545 >>> class Parent: pass
545546 >>> class Child(Parent): pass
546547 >>> _is_subtype(List[Child], List[Parent])
@@ -1033,6 +1034,8 @@ def convert_to_typing_types(x: typing.Type) -> typing.Type:
10331034 typing.Tuple[int]
10341035 >>> convert_to_typing_types(type[int])
10351036 typing.Type[int]
1037+ >>> convert_to_typing_types(type[int | float])
1038+ typing.Type[int | float]
10361039 >>> convert_to_typing_types(tuple[int, float])
10371040 typing.Tuple[int, float]
10381041 >>> convert_to_typing_types(dict[int, float])
@@ -1064,6 +1067,8 @@ def convert_to_typing_types(x: typing.Type) -> typing.Type:
10641067 return typing .FrozenSet [tuple (args )]
10651068 elif origin is type :
10661069 return typing .Type [tuple (args )]
1070+ elif origin is typing .Union :
1071+ return x
10671072
10681073 raise RuntimeError (x )
10691074
0 commit comments