Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.8/site-packages/typing_inspect.py: 16%
411 statements
« prev ^ index » next coverage.py v7.3.1, created at 2023-09-25 06:43 +0000
« prev ^ index » next coverage.py v7.3.1, created at 2023-09-25 06:43 +0000
1"""Defines experimental API for runtime inspection of types defined
2in the standard "typing" module.
4Example usage::
5 from typing_inspect import is_generic_type
6"""
8# NOTE: This module must support Python 2.7 in addition to Python 3.x
10import sys
11import types
12import typing
13import typing_extensions
15from mypy_extensions import _TypedDictMeta as _TypedDictMeta_Mypy
17# See comments in typing_extensions source on why the switch is at 3.9.2
18if (3, 4, 0) <= sys.version_info[:3] < (3, 9, 2):
19 from typing_extensions import _TypedDictMeta as _TypedDictMeta_TE
20elif sys.version_info[:3] >= (3, 9, 2):
21 # Situation with typing_extensions.TypedDict is complicated.
22 # Use the one defined in typing_extentions, and if there is none,
23 # fall back to typing.
24 try:
25 from typing_extensions import _TypedDictMeta as _TypedDictMeta_TE
26 except ImportError:
27 from typing import _TypedDictMeta as _TypedDictMeta_TE
28else:
29 # typing_extensions.TypedDict is a re-export from typing.
30 from typing import TypedDict
31 _TypedDictMeta_TE = type(TypedDict)
33NEW_TYPING = sys.version_info[:3] >= (3, 7, 0) # PEP 560
34if NEW_TYPING:
35 import collections.abc
37WITH_FINAL = True
38WITH_LITERAL = True
39WITH_CLASSVAR = True
40WITH_NEWTYPE = True
41LEGACY_TYPING = False
43if NEW_TYPING:
44 from typing import (
45 Generic, Callable, Union, TypeVar, ClassVar, Tuple, _GenericAlias,
46 ForwardRef, NewType,
47 )
48 from typing_extensions import Final, Literal
49 if sys.version_info[:3] >= (3, 9, 0):
50 from typing import _SpecialGenericAlias
51 typingGenericAlias = (_GenericAlias, _SpecialGenericAlias, types.GenericAlias)
52 else:
53 typingGenericAlias = (_GenericAlias,)
54else:
55 from typing import (
56 Callable, CallableMeta, Union, Tuple, TupleMeta, TypeVar, GenericMeta,
57 _ForwardRef,
58 )
59 try:
60 from typing import _Union, _ClassVar
61 except ImportError:
62 # support for very old typing module <=3.5.3
63 _Union = type(Union)
64 WITH_CLASSVAR = False
65 LEGACY_TYPING = True
67 try: # python 3.6
68 from typing_extensions import _Final
69 except ImportError: # python 2.7
70 try:
71 from typing import _Final
72 except ImportError:
73 WITH_FINAL = False
75 try: # python 3.6
76 from typing_extensions import Literal
77 except ImportError: # python 2.7
78 try:
79 from typing import Literal
80 except ImportError:
81 WITH_LITERAL = False
83 try: # python < 3.5.2
84 from typing_extensions import NewType
85 except ImportError:
86 try:
87 from typing import NewType
88 except ImportError:
89 WITH_NEWTYPE = False
92def _gorg(cls):
93 """This function exists for compatibility with old typing versions."""
94 assert isinstance(cls, GenericMeta)
95 if hasattr(cls, '_gorg'):
96 return cls._gorg
97 while cls.__origin__ is not None:
98 cls = cls.__origin__
99 return cls
102def is_generic_type(tp):
103 """Test if the given type is a generic type. This includes Generic itself, but
104 excludes special typing constructs such as Union, Tuple, Callable, ClassVar.
105 Examples::
107 is_generic_type(int) == False
108 is_generic_type(Union[int, str]) == False
109 is_generic_type(Union[int, T]) == False
110 is_generic_type(ClassVar[List[int]]) == False
111 is_generic_type(Callable[..., T]) == False
113 is_generic_type(Generic) == True
114 is_generic_type(Generic[T]) == True
115 is_generic_type(Iterable[int]) == True
116 is_generic_type(Mapping) == True
117 is_generic_type(MutableMapping[T, List[int]]) == True
118 is_generic_type(Sequence[Union[str, bytes]]) == True
119 """
120 if NEW_TYPING:
121 return (isinstance(tp, type) and issubclass(tp, Generic) or
122 isinstance(tp, typingGenericAlias) and
123 tp.__origin__ not in (Union, tuple, ClassVar, collections.abc.Callable))
124 return (isinstance(tp, GenericMeta) and not
125 isinstance(tp, (CallableMeta, TupleMeta)))
128def is_callable_type(tp):
129 """Test if the type is a generic callable type, including subclasses
130 excluding non-generic types and callables.
131 Examples::
133 is_callable_type(int) == False
134 is_callable_type(type) == False
135 is_callable_type(Callable) == True
136 is_callable_type(Callable[..., int]) == True
137 is_callable_type(Callable[[int, int], Iterable[str]]) == True
138 class MyClass(Callable[[int], int]):
139 ...
140 is_callable_type(MyClass) == True
142 For more general tests use callable(), for more precise test
143 (excluding subclasses) use::
145 get_origin(tp) is collections.abc.Callable # Callable prior to Python 3.7
146 """
147 if NEW_TYPING:
148 return (tp is Callable or isinstance(tp, typingGenericAlias) and
149 tp.__origin__ is collections.abc.Callable or
150 isinstance(tp, type) and issubclass(tp, Generic) and
151 issubclass(tp, collections.abc.Callable))
152 return type(tp) is CallableMeta
155def is_tuple_type(tp):
156 """Test if the type is a generic tuple type, including subclasses excluding
157 non-generic classes.
158 Examples::
160 is_tuple_type(int) == False
161 is_tuple_type(tuple) == False
162 is_tuple_type(Tuple) == True
163 is_tuple_type(Tuple[str, int]) == True
164 class MyClass(Tuple[str, int]):
165 ...
166 is_tuple_type(MyClass) == True
168 For more general tests use issubclass(..., tuple), for more precise test
169 (excluding subclasses) use::
171 get_origin(tp) is tuple # Tuple prior to Python 3.7
172 """
173 if NEW_TYPING:
174 return (tp is Tuple or isinstance(tp, typingGenericAlias) and
175 tp.__origin__ is tuple or
176 isinstance(tp, type) and issubclass(tp, Generic) and
177 issubclass(tp, tuple))
178 return type(tp) is TupleMeta
181def is_optional_type(tp):
182 """Test if the type is type(None), or is a direct union with it, such as Optional[T].
184 NOTE: this method inspects nested `Union` arguments but not `TypeVar` definition
185 bounds and constraints. So it will return `False` if
186 - `tp` is a `TypeVar` bound, or constrained to, an optional type
187 - `tp` is a `Union` to a `TypeVar` bound or constrained to an optional type,
188 - `tp` refers to a *nested* `Union` containing an optional type or one of the above.
190 Users wishing to check for optionality in types relying on type variables might wish
191 to use this method in combination with `get_constraints` and `get_bound`
192 """
194 if tp is type(None): # noqa
195 return True
196 elif is_union_type(tp):
197 return any(is_optional_type(tt) for tt in get_args(tp, evaluate=True))
198 else:
199 return False
202def is_final_type(tp):
203 """Test if the type is a final type. Examples::
205 is_final_type(int) == False
206 is_final_type(Final) == True
207 is_final_type(Final[int]) == True
208 """
209 if NEW_TYPING:
210 return (tp is Final or
211 isinstance(tp, typingGenericAlias) and tp.__origin__ is Final)
212 return WITH_FINAL and type(tp) is _Final
215try:
216 MaybeUnionType = types.UnionType
217except AttributeError:
218 MaybeUnionType = None
221def is_union_type(tp):
222 """Test if the type is a union type. Examples::
224 is_union_type(int) == False
225 is_union_type(Union) == True
226 is_union_type(Union[int, int]) == False
227 is_union_type(Union[T, int]) == True
228 is_union_type(int | int) == False
229 is_union_type(T | int) == True
230 """
231 if NEW_TYPING:
232 return (tp is Union or
233 (isinstance(tp, typingGenericAlias) and tp.__origin__ is Union) or
234 (MaybeUnionType and isinstance(tp, MaybeUnionType)))
235 return type(tp) is _Union
238LITERALS = {Literal}
239if hasattr(typing, "Literal"):
240 LITERALS.add(typing.Literal)
243def is_literal_type(tp):
244 if NEW_TYPING:
245 return (tp in LITERALS or
246 isinstance(tp, typingGenericAlias) and tp.__origin__ in LITERALS)
247 return WITH_LITERAL and type(tp) is type(Literal)
250def is_typevar(tp):
251 """Test if the type represents a type variable. Examples::
253 is_typevar(int) == False
254 is_typevar(T) == True
255 is_typevar(Union[T, int]) == False
256 """
258 return type(tp) is TypeVar
261def is_classvar(tp):
262 """Test if the type represents a class variable. Examples::
264 is_classvar(int) == False
265 is_classvar(ClassVar) == True
266 is_classvar(ClassVar[int]) == True
267 is_classvar(ClassVar[List[T]]) == True
268 """
269 if NEW_TYPING:
270 return (tp is ClassVar or
271 isinstance(tp, typingGenericAlias) and tp.__origin__ is ClassVar)
272 elif WITH_CLASSVAR:
273 return type(tp) is _ClassVar
274 else:
275 return False
278def is_new_type(tp):
279 """Tests if the type represents a distinct type. Examples::
281 is_new_type(int) == False
282 is_new_type(NewType) == True
283 is_new_type(NewType('Age', int)) == True
284 is_new_type(NewType('Scores', List[Dict[str, float]])) == True
285 """
286 if not WITH_NEWTYPE:
287 return False
288 elif sys.version_info[:3] >= (3, 10, 0) and sys.version_info.releaselevel != 'beta':
289 return (tp in (NewType, typing_extensions.NewType) or
290 isinstance(tp, (NewType, typing_extensions.NewType)))
291 elif sys.version_info[:3] >= (3, 0, 0):
292 try:
293 res = isinstance(tp, typing_extensions.NewType)
294 except TypeError:
295 pass
296 else:
297 if res:
298 return res
299 return (tp in (NewType, typing_extensions.NewType) or
300 (getattr(tp, '__supertype__', None) is not None and
301 getattr(tp, '__qualname__', '') == 'NewType.<locals>.new_type' and
302 tp.__module__ in ('typing', 'typing_extensions')))
303 else: # python 2
304 # __qualname__ is not available in python 2, so we simplify the test here
305 return (tp is NewType or
306 (getattr(tp, '__supertype__', None) is not None and
307 tp.__module__ in ('typing', 'typing_extensions')))
310def is_forward_ref(tp):
311 """Tests if the type is a :class:`typing.ForwardRef`. Examples::
313 u = Union["Milk", Way]
314 args = get_args(u)
315 is_forward_ref(args[0]) == True
316 is_forward_ref(args[1]) == False
317 """
318 if not NEW_TYPING:
319 return isinstance(tp, _ForwardRef)
320 return isinstance(tp, ForwardRef)
323def get_last_origin(tp):
324 """Get the last base of (multiply) subscripted type. Supports generic types,
325 Union, Callable, and Tuple. Returns None for unsupported types.
326 Examples::
328 get_last_origin(int) == None
329 get_last_origin(ClassVar[int]) == None
330 get_last_origin(Generic[T]) == Generic
331 get_last_origin(Union[T, int][str]) == Union[T, int]
332 get_last_origin(List[Tuple[T, T]][int]) == List[Tuple[T, T]]
333 get_last_origin(List) == List
334 """
335 if NEW_TYPING:
336 raise ValueError('This function is only supported in Python 3.6,'
337 ' use get_origin instead')
338 sentinel = object()
339 origin = getattr(tp, '__origin__', sentinel)
340 if origin is sentinel:
341 return None
342 if origin is None:
343 return tp
344 return origin
347def get_origin(tp):
348 """Get the unsubscripted version of a type. Supports generic types, Union,
349 Callable, and Tuple. Returns None for unsupported types. Examples::
351 get_origin(int) == None
352 get_origin(ClassVar[int]) == None
353 get_origin(Generic) == Generic
354 get_origin(Generic[T]) == Generic
355 get_origin(Union[T, int]) == Union
356 get_origin(List[Tuple[T, T]][int]) == list # List prior to Python 3.7
357 """
358 if NEW_TYPING:
359 if isinstance(tp, typingGenericAlias):
360 return tp.__origin__ if tp.__origin__ is not ClassVar else None
361 if tp is Generic:
362 return Generic
363 return None
364 if isinstance(tp, GenericMeta):
365 return _gorg(tp)
366 if is_union_type(tp):
367 return Union
368 if is_tuple_type(tp):
369 return Tuple
370 if is_literal_type(tp):
371 if NEW_TYPING:
372 return tp.__origin__ or tp
373 return Literal
375 return None
378def get_parameters(tp):
379 """Return type parameters of a parameterizable type as a tuple
380 in lexicographic order. Parameterizable types are generic types,
381 unions, tuple types and callable types. Examples::
383 get_parameters(int) == ()
384 get_parameters(Generic) == ()
385 get_parameters(Union) == ()
386 get_parameters(List[int]) == ()
388 get_parameters(Generic[T]) == (T,)
389 get_parameters(Tuple[List[T], List[S_co]]) == (T, S_co)
390 get_parameters(Union[S_co, Tuple[T, T]][int, U]) == (U,)
391 get_parameters(Mapping[T, Tuple[S_co, T]]) == (T, S_co)
392 """
393 if LEGACY_TYPING:
394 # python <= 3.5.2
395 if is_union_type(tp):
396 params = []
397 for arg in (tp.__union_params__ if tp.__union_params__ is not None else ()):
398 params += get_parameters(arg)
399 return tuple(params)
400 elif is_tuple_type(tp):
401 params = []
402 for arg in (tp.__tuple_params__ if tp.__tuple_params__ is not None else ()):
403 params += get_parameters(arg)
404 return tuple(params)
405 elif is_generic_type(tp):
406 params = []
407 base_params = tp.__parameters__
408 if base_params is None:
409 return ()
410 for bp_ in base_params:
411 for bp in (get_args(bp_) if is_tuple_type(bp_) else (bp_,)):
412 if _has_type_var(bp) and not isinstance(bp, TypeVar):
413 raise TypeError(
414 "Cannot inherit from a generic class "
415 "parameterized with "
416 "non-type-variable %s" % bp)
417 if params is None:
418 params = []
419 if bp not in params:
420 params.append(bp)
421 if params is not None:
422 return tuple(params)
423 else:
424 return ()
425 else:
426 return ()
427 elif NEW_TYPING:
428 if (
429 (
430 isinstance(tp, typingGenericAlias) and
431 hasattr(tp, '__parameters__')
432 ) or
433 isinstance(tp, type) and issubclass(tp, Generic) and
434 tp is not Generic):
435 return tp.__parameters__
436 else:
437 return ()
438 elif (
439 is_generic_type(tp) or is_union_type(tp) or
440 is_callable_type(tp) or is_tuple_type(tp)
441 ):
442 return tp.__parameters__ if tp.__parameters__ is not None else ()
443 else:
444 return ()
447def get_last_args(tp):
448 """Get last arguments of (multiply) subscripted type.
449 Parameters for Callable are flattened. Examples::
451 get_last_args(int) == ()
452 get_last_args(Union) == ()
453 get_last_args(ClassVar[int]) == (int,)
454 get_last_args(Union[T, int]) == (T, int)
455 get_last_args(Iterable[Tuple[T, S]][int, T]) == (int, T)
456 get_last_args(Callable[[T], int]) == (T, int)
457 get_last_args(Callable[[], int]) == (int,)
458 """
459 if NEW_TYPING:
460 raise ValueError('This function is only supported in Python 3.6,'
461 ' use get_args instead')
462 elif is_classvar(tp):
463 return (tp.__type__,) if tp.__type__ is not None else ()
464 elif is_generic_type(tp):
465 try:
466 if tp.__args__ is not None and len(tp.__args__) > 0:
467 return tp.__args__
468 except AttributeError:
469 # python 3.5.1
470 pass
471 return tp.__parameters__ if tp.__parameters__ is not None else ()
472 elif is_union_type(tp):
473 try:
474 return tp.__args__ if tp.__args__ is not None else ()
475 except AttributeError:
476 # python 3.5.2
477 return tp.__union_params__ if tp.__union_params__ is not None else ()
478 elif is_callable_type(tp):
479 return tp.__args__ if tp.__args__ is not None else ()
480 elif is_tuple_type(tp):
481 try:
482 return tp.__args__ if tp.__args__ is not None else ()
483 except AttributeError:
484 # python 3.5.2
485 return tp.__tuple_params__ if tp.__tuple_params__ is not None else ()
486 else:
487 return ()
490def _eval_args(args):
491 """Internal helper for get_args."""
492 res = []
493 for arg in args:
494 if not isinstance(arg, tuple):
495 res.append(arg)
496 elif is_callable_type(arg[0]):
497 callable_args = _eval_args(arg[1:])
498 if len(arg) == 2:
499 res.append(Callable[[], callable_args[0]])
500 elif arg[1] is Ellipsis:
501 res.append(Callable[..., callable_args[1]])
502 else:
503 res.append(Callable[list(callable_args[:-1]), callable_args[-1]])
504 else:
505 res.append(type(arg[0]).__getitem__(arg[0], _eval_args(arg[1:])))
506 return tuple(res)
509def get_args(tp, evaluate=None):
510 """Get type arguments with all substitutions performed. For unions,
511 basic simplifications used by Union constructor are performed.
512 On versions prior to 3.7 if `evaluate` is False (default),
513 report result as nested tuple, this matches
514 the internal representation of types. If `evaluate` is True
515 (or if Python version is 3.7 or greater), then all
516 type parameters are applied (this could be time and memory expensive).
517 Examples::
519 get_args(int) == ()
520 get_args(Union[int, Union[T, int], str][int]) == (int, str)
521 get_args(Union[int, Tuple[T, int]][str]) == (int, (Tuple, str, int))
523 get_args(Union[int, Tuple[T, int]][str], evaluate=True) == \
524 (int, Tuple[str, int])
525 get_args(Dict[int, Tuple[T, T]][Optional[int]], evaluate=True) == \
526 (int, Tuple[Optional[int], Optional[int]])
527 get_args(Callable[[], T][int], evaluate=True) == ([], int,)
528 """
529 if NEW_TYPING:
530 if evaluate is not None and not evaluate:
531 raise ValueError('evaluate can only be True in Python >= 3.7')
532 # Note special aliases on Python 3.9 don't have __args__.
533 if isinstance(tp, typingGenericAlias) and hasattr(tp, '__args__'):
534 res = tp.__args__
535 if get_origin(tp) is collections.abc.Callable and res[0] is not Ellipsis:
536 res = (list(res[:-1]), res[-1])
537 return res
538 if MaybeUnionType and isinstance(tp, MaybeUnionType):
539 return tp.__args__
540 return ()
541 if is_classvar(tp) or is_final_type(tp):
542 return (tp.__type__,) if tp.__type__ is not None else ()
543 if is_literal_type(tp):
544 return tp.__values__ or ()
545 if (
546 is_generic_type(tp) or is_union_type(tp) or
547 is_callable_type(tp) or is_tuple_type(tp)
548 ):
549 try:
550 tree = tp._subs_tree()
551 except AttributeError:
552 # Old python typing module <= 3.5.3
553 if is_union_type(tp):
554 # backport of union's subs_tree
555 tree = _union_subs_tree(tp)
556 elif is_generic_type(tp):
557 # backport of GenericMeta's subs_tree
558 tree = _generic_subs_tree(tp)
559 elif is_tuple_type(tp):
560 # ad-hoc (inspired by union)
561 tree = _tuple_subs_tree(tp)
562 else:
563 # tree = _subs_tree(tp)
564 return ()
566 if isinstance(tree, tuple) and len(tree) > 1:
567 if not evaluate:
568 return tree[1:]
569 res = _eval_args(tree[1:])
570 if get_origin(tp) is Callable and res[0] is not Ellipsis:
571 res = (list(res[:-1]), res[-1])
572 return res
574 return ()
577def get_bound(tp):
578 """Return the type bound to a `TypeVar` if any.
580 It the type is not a `TypeVar`, a `TypeError` is raised.
581 Examples::
583 get_bound(TypeVar('T')) == None
584 get_bound(TypeVar('T', bound=int)) == int
585 """
587 if is_typevar(tp):
588 return getattr(tp, '__bound__', None)
589 else:
590 raise TypeError("type is not a `TypeVar`: " + str(tp))
593def get_constraints(tp):
594 """Returns the constraints of a `TypeVar` if any.
596 It the type is not a `TypeVar`, a `TypeError` is raised
597 Examples::
599 get_constraints(TypeVar('T')) == ()
600 get_constraints(TypeVar('T', int, str)) == (int, str)
601 """
603 if is_typevar(tp):
604 return getattr(tp, '__constraints__', ())
605 else:
606 raise TypeError("type is not a `TypeVar`: " + str(tp))
609def get_generic_type(obj):
610 """Get the generic type of an object if possible, or runtime class otherwise.
611 Examples::
613 class Node(Generic[T]):
614 ...
615 type(Node[int]()) == Node
616 get_generic_type(Node[int]()) == Node[int]
617 get_generic_type(Node[T]()) == Node[T]
618 get_generic_type(1) == int
619 """
621 gen_type = getattr(obj, '__orig_class__', None)
622 return gen_type if gen_type is not None else type(obj)
625def get_generic_bases(tp):
626 """Get generic base types of a type or empty tuple if not possible.
627 Example::
629 class MyClass(List[int], Mapping[str, List[int]]):
630 ...
631 MyClass.__bases__ == (List, Mapping)
632 get_generic_bases(MyClass) == (List[int], Mapping[str, List[int]])
633 """
634 if LEGACY_TYPING:
635 return tuple(t for t in tp.__bases__ if isinstance(t, GenericMeta))
636 else:
637 return getattr(tp, '__orig_bases__', ())
640def typed_dict_keys(td):
641 """If td is a TypedDict class, return a dictionary mapping the typed keys to types.
642 Otherwise, return None. Examples::
644 class TD(TypedDict):
645 x: int
646 y: int
647 class Other(dict):
648 x: int
649 y: int
651 typed_dict_keys(TD) == {'x': int, 'y': int}
652 typed_dict_keys(dict) == None
653 typed_dict_keys(Other) == None
654 """
655 if isinstance(td, (_TypedDictMeta_Mypy, _TypedDictMeta_TE)):
656 return td.__annotations__.copy()
657 return None
660def get_forward_arg(fr):
661 """
662 If fr is a ForwardRef, return the string representation of the forward reference.
663 Otherwise return None. Examples::
665 tp = List["FRef"]
666 fr = get_args(tp)[0]
667 get_forward_arg(fr) == "FRef"
668 get_forward_arg(tp) == None
669 """
670 return fr.__forward_arg__ if is_forward_ref(fr) else None
673# A few functions backported and adapted for the LEGACY_TYPING context, and used above
675def _replace_arg(arg, tvars, args):
676 """backport of _replace_arg"""
677 if tvars is None:
678 tvars = []
679 # if hasattr(arg, '_subs_tree') and isinstance(arg, (GenericMeta, _TypingBase)):
680 # return arg._subs_tree(tvars, args)
681 if is_union_type(arg):
682 return _union_subs_tree(arg, tvars, args)
683 if is_tuple_type(arg):
684 return _tuple_subs_tree(arg, tvars, args)
685 if is_generic_type(arg):
686 return _generic_subs_tree(arg, tvars, args)
687 if isinstance(arg, TypeVar):
688 for i, tvar in enumerate(tvars):
689 if arg == tvar:
690 return args[i]
691 return arg
694def _remove_dups_flatten(parameters):
695 """backport of _remove_dups_flatten"""
697 # Flatten out Union[Union[...], ...].
698 params = []
699 for p in parameters:
700 if isinstance(p, _Union): # and p.__origin__ is Union:
701 params.extend(p.__union_params__) # p.__args__)
702 elif isinstance(p, tuple) and len(p) > 0 and p[0] is Union:
703 params.extend(p[1:])
704 else:
705 params.append(p)
706 # Weed out strict duplicates, preserving the first of each occurrence.
707 all_params = set(params)
708 if len(all_params) < len(params):
709 new_params = []
710 for t in params:
711 if t in all_params:
712 new_params.append(t)
713 all_params.remove(t)
714 params = new_params
715 assert not all_params, all_params
716 # Weed out subclasses.
717 # E.g. Union[int, Employee, Manager] == Union[int, Employee].
718 # If object is present it will be sole survivor among proper classes.
719 # Never discard type variables.
720 # (In particular, Union[str, AnyStr] != AnyStr.)
721 all_params = set(params)
722 for t1 in params:
723 if not isinstance(t1, type):
724 continue
725 if any(isinstance(t2, type) and issubclass(t1, t2)
726 for t2 in all_params - {t1}
727 if (not (isinstance(t2, GenericMeta) and
728 get_origin(t2) is not None) and
729 not isinstance(t2, TypeVar))):
730 all_params.remove(t1)
731 return tuple(t for t in params if t in all_params)
734def _subs_tree(cls, tvars=None, args=None):
735 """backport of typing._subs_tree, adapted for legacy versions """
736 def _get_origin(cls):
737 try:
738 return cls.__origin__
739 except AttributeError:
740 return None
742 current = _get_origin(cls)
743 if current is None:
744 if not is_union_type(cls) and not is_tuple_type(cls):
745 return cls
747 # Make of chain of origins (i.e. cls -> cls.__origin__)
748 orig_chain = []
749 while _get_origin(current) is not None:
750 orig_chain.append(current)
751 current = _get_origin(current)
753 # Replace type variables in __args__ if asked ...
754 tree_args = []
756 def _get_args(cls):
757 if is_union_type(cls):
758 cls_args = cls.__union_params__
759 elif is_tuple_type(cls):
760 cls_args = cls.__tuple_params__
761 else:
762 try:
763 cls_args = cls.__args__
764 except AttributeError:
765 cls_args = ()
766 return cls_args if cls_args is not None else ()
768 for arg in _get_args(cls):
769 tree_args.append(_replace_arg(arg, tvars, args))
770 # ... then continue replacing down the origin chain.
771 for ocls in orig_chain:
772 new_tree_args = []
773 for arg in _get_args(ocls):
774 new_tree_args.append(_replace_arg(arg, get_parameters(ocls), tree_args))
775 tree_args = new_tree_args
776 return tree_args
779def _union_subs_tree(tp, tvars=None, args=None):
780 """ backport of Union._subs_tree """
781 if tp is Union:
782 return Union # Nothing to substitute
783 tree_args = _subs_tree(tp, tvars, args)
784 # tree_args = tp.__union_params__ if tp.__union_params__ is not None else ()
785 tree_args = _remove_dups_flatten(tree_args)
786 if len(tree_args) == 1:
787 return tree_args[0] # Union of a single type is that type
788 return (Union,) + tree_args
791def _generic_subs_tree(tp, tvars=None, args=None):
792 """ backport of GenericMeta._subs_tree """
793 if tp.__origin__ is None:
794 return tp
795 tree_args = _subs_tree(tp, tvars, args)
796 return (_gorg(tp),) + tuple(tree_args)
799def _tuple_subs_tree(tp, tvars=None, args=None):
800 """ ad-hoc function (inspired by union) for legacy typing """
801 if tp is Tuple:
802 return Tuple # Nothing to substitute
803 tree_args = _subs_tree(tp, tvars, args)
804 return (Tuple,) + tuple(tree_args)
807def _has_type_var(t):
808 if t is None:
809 return False
810 elif is_union_type(t):
811 return _union_has_type_var(t)
812 elif is_tuple_type(t):
813 return _tuple_has_type_var(t)
814 elif is_generic_type(t):
815 return _generic_has_type_var(t)
816 elif is_callable_type(t):
817 return _callable_has_type_var(t)
818 else:
819 return False
822def _union_has_type_var(tp):
823 if tp.__union_params__:
824 for t in tp.__union_params__:
825 if _has_type_var(t):
826 return True
827 return False
830def _tuple_has_type_var(tp):
831 if tp.__tuple_params__:
832 for t in tp.__tuple_params__:
833 if _has_type_var(t):
834 return True
835 return False
838def _callable_has_type_var(tp):
839 if tp.__args__:
840 for t in tp.__args__:
841 if _has_type_var(t):
842 return True
843 return _has_type_var(tp.__result__)
846def _generic_has_type_var(tp):
847 if tp.__parameters__:
848 for t in tp.__parameters__:
849 if _has_type_var(t):
850 return True
851 return False