diff options
Diffstat (limited to '.venv/lib/python3.12/site-packages/typing_inspect.py')
-rw-r--r-- | .venv/lib/python3.12/site-packages/typing_inspect.py | 851 |
1 files changed, 851 insertions, 0 deletions
diff --git a/.venv/lib/python3.12/site-packages/typing_inspect.py b/.venv/lib/python3.12/site-packages/typing_inspect.py new file mode 100644 index 00000000..03450665 --- /dev/null +++ b/.venv/lib/python3.12/site-packages/typing_inspect.py @@ -0,0 +1,851 @@ +"""Defines experimental API for runtime inspection of types defined +in the standard "typing" module. + +Example usage:: + from typing_inspect import is_generic_type +""" + +# NOTE: This module must support Python 2.7 in addition to Python 3.x + +import sys +import types +import typing +import typing_extensions + +from mypy_extensions import _TypedDictMeta as _TypedDictMeta_Mypy + +# See comments in typing_extensions source on why the switch is at 3.9.2 +if (3, 4, 0) <= sys.version_info[:3] < (3, 9, 2): + from typing_extensions import _TypedDictMeta as _TypedDictMeta_TE +elif sys.version_info[:3] >= (3, 9, 2): + # Situation with typing_extensions.TypedDict is complicated. + # Use the one defined in typing_extentions, and if there is none, + # fall back to typing. + try: + from typing_extensions import _TypedDictMeta as _TypedDictMeta_TE + except ImportError: + from typing import _TypedDictMeta as _TypedDictMeta_TE +else: + # typing_extensions.TypedDict is a re-export from typing. + from typing import TypedDict + _TypedDictMeta_TE = type(TypedDict) + +NEW_TYPING = sys.version_info[:3] >= (3, 7, 0) # PEP 560 +if NEW_TYPING: + import collections.abc + +WITH_FINAL = True +WITH_LITERAL = True +WITH_CLASSVAR = True +WITH_NEWTYPE = True +LEGACY_TYPING = False + +if NEW_TYPING: + from typing import ( + Generic, Callable, Union, TypeVar, ClassVar, Tuple, _GenericAlias, + ForwardRef, NewType, + ) + from typing_extensions import Final, Literal + if sys.version_info[:3] >= (3, 9, 0): + from typing import _SpecialGenericAlias + typingGenericAlias = (_GenericAlias, _SpecialGenericAlias, types.GenericAlias) + else: + typingGenericAlias = (_GenericAlias,) +else: + from typing import ( + Callable, CallableMeta, Union, Tuple, TupleMeta, TypeVar, GenericMeta, + _ForwardRef, + ) + try: + from typing import _Union, _ClassVar + except ImportError: + # support for very old typing module <=3.5.3 + _Union = type(Union) + WITH_CLASSVAR = False + LEGACY_TYPING = True + + try: # python 3.6 + from typing_extensions import _Final + except ImportError: # python 2.7 + try: + from typing import _Final + except ImportError: + WITH_FINAL = False + + try: # python 3.6 + from typing_extensions import Literal + except ImportError: # python 2.7 + try: + from typing import Literal + except ImportError: + WITH_LITERAL = False + + try: # python < 3.5.2 + from typing_extensions import NewType + except ImportError: + try: + from typing import NewType + except ImportError: + WITH_NEWTYPE = False + + +def _gorg(cls): + """This function exists for compatibility with old typing versions.""" + assert isinstance(cls, GenericMeta) + if hasattr(cls, '_gorg'): + return cls._gorg + while cls.__origin__ is not None: + cls = cls.__origin__ + return cls + + +def is_generic_type(tp): + """Test if the given type is a generic type. This includes Generic itself, but + excludes special typing constructs such as Union, Tuple, Callable, ClassVar. + Examples:: + + is_generic_type(int) == False + is_generic_type(Union[int, str]) == False + is_generic_type(Union[int, T]) == False + is_generic_type(ClassVar[List[int]]) == False + is_generic_type(Callable[..., T]) == False + + is_generic_type(Generic) == True + is_generic_type(Generic[T]) == True + is_generic_type(Iterable[int]) == True + is_generic_type(Mapping) == True + is_generic_type(MutableMapping[T, List[int]]) == True + is_generic_type(Sequence[Union[str, bytes]]) == True + """ + if NEW_TYPING: + return (isinstance(tp, type) and issubclass(tp, Generic) or + isinstance(tp, typingGenericAlias) and + tp.__origin__ not in (Union, tuple, ClassVar, collections.abc.Callable)) + return (isinstance(tp, GenericMeta) and not + isinstance(tp, (CallableMeta, TupleMeta))) + + +def is_callable_type(tp): + """Test if the type is a generic callable type, including subclasses + excluding non-generic types and callables. + Examples:: + + is_callable_type(int) == False + is_callable_type(type) == False + is_callable_type(Callable) == True + is_callable_type(Callable[..., int]) == True + is_callable_type(Callable[[int, int], Iterable[str]]) == True + class MyClass(Callable[[int], int]): + ... + is_callable_type(MyClass) == True + + For more general tests use callable(), for more precise test + (excluding subclasses) use:: + + get_origin(tp) is collections.abc.Callable # Callable prior to Python 3.7 + """ + if NEW_TYPING: + return (tp is Callable or isinstance(tp, typingGenericAlias) and + tp.__origin__ is collections.abc.Callable or + isinstance(tp, type) and issubclass(tp, Generic) and + issubclass(tp, collections.abc.Callable)) + return type(tp) is CallableMeta + + +def is_tuple_type(tp): + """Test if the type is a generic tuple type, including subclasses excluding + non-generic classes. + Examples:: + + is_tuple_type(int) == False + is_tuple_type(tuple) == False + is_tuple_type(Tuple) == True + is_tuple_type(Tuple[str, int]) == True + class MyClass(Tuple[str, int]): + ... + is_tuple_type(MyClass) == True + + For more general tests use issubclass(..., tuple), for more precise test + (excluding subclasses) use:: + + get_origin(tp) is tuple # Tuple prior to Python 3.7 + """ + if NEW_TYPING: + return (tp is Tuple or isinstance(tp, typingGenericAlias) and + tp.__origin__ is tuple or + isinstance(tp, type) and issubclass(tp, Generic) and + issubclass(tp, tuple)) + return type(tp) is TupleMeta + + +def is_optional_type(tp): + """Test if the type is type(None), or is a direct union with it, such as Optional[T]. + + NOTE: this method inspects nested `Union` arguments but not `TypeVar` definition + bounds and constraints. So it will return `False` if + - `tp` is a `TypeVar` bound, or constrained to, an optional type + - `tp` is a `Union` to a `TypeVar` bound or constrained to an optional type, + - `tp` refers to a *nested* `Union` containing an optional type or one of the above. + + Users wishing to check for optionality in types relying on type variables might wish + to use this method in combination with `get_constraints` and `get_bound` + """ + + if tp is type(None): # noqa + return True + elif is_union_type(tp): + return any(is_optional_type(tt) for tt in get_args(tp, evaluate=True)) + else: + return False + + +def is_final_type(tp): + """Test if the type is a final type. Examples:: + + is_final_type(int) == False + is_final_type(Final) == True + is_final_type(Final[int]) == True + """ + if NEW_TYPING: + return (tp is Final or + isinstance(tp, typingGenericAlias) and tp.__origin__ is Final) + return WITH_FINAL and type(tp) is _Final + + +try: + MaybeUnionType = types.UnionType +except AttributeError: + MaybeUnionType = None + + +def is_union_type(tp): + """Test if the type is a union type. Examples:: + + is_union_type(int) == False + is_union_type(Union) == True + is_union_type(Union[int, int]) == False + is_union_type(Union[T, int]) == True + is_union_type(int | int) == False + is_union_type(T | int) == True + """ + if NEW_TYPING: + return (tp is Union or + (isinstance(tp, typingGenericAlias) and tp.__origin__ is Union) or + (MaybeUnionType and isinstance(tp, MaybeUnionType))) + return type(tp) is _Union + + +LITERALS = {Literal} +if hasattr(typing, "Literal"): + LITERALS.add(typing.Literal) + + +def is_literal_type(tp): + if NEW_TYPING: + return (tp in LITERALS or + isinstance(tp, typingGenericAlias) and tp.__origin__ in LITERALS) + return WITH_LITERAL and type(tp) is type(Literal) + + +def is_typevar(tp): + """Test if the type represents a type variable. Examples:: + + is_typevar(int) == False + is_typevar(T) == True + is_typevar(Union[T, int]) == False + """ + + return type(tp) is TypeVar + + +def is_classvar(tp): + """Test if the type represents a class variable. Examples:: + + is_classvar(int) == False + is_classvar(ClassVar) == True + is_classvar(ClassVar[int]) == True + is_classvar(ClassVar[List[T]]) == True + """ + if NEW_TYPING: + return (tp is ClassVar or + isinstance(tp, typingGenericAlias) and tp.__origin__ is ClassVar) + elif WITH_CLASSVAR: + return type(tp) is _ClassVar + else: + return False + + +def is_new_type(tp): + """Tests if the type represents a distinct type. Examples:: + + is_new_type(int) == False + is_new_type(NewType) == True + is_new_type(NewType('Age', int)) == True + is_new_type(NewType('Scores', List[Dict[str, float]])) == True + """ + if not WITH_NEWTYPE: + return False + elif sys.version_info[:3] >= (3, 10, 0) and sys.version_info.releaselevel != 'beta': + return (tp in (NewType, typing_extensions.NewType) or + isinstance(tp, (NewType, typing_extensions.NewType))) + elif sys.version_info[:3] >= (3, 0, 0): + try: + res = isinstance(tp, typing_extensions.NewType) + except TypeError: + pass + else: + if res: + return res + return (tp in (NewType, typing_extensions.NewType) or + (getattr(tp, '__supertype__', None) is not None and + getattr(tp, '__qualname__', '') == 'NewType.<locals>.new_type' and + tp.__module__ in ('typing', 'typing_extensions'))) + else: # python 2 + # __qualname__ is not available in python 2, so we simplify the test here + return (tp is NewType or + (getattr(tp, '__supertype__', None) is not None and + tp.__module__ in ('typing', 'typing_extensions'))) + + +def is_forward_ref(tp): + """Tests if the type is a :class:`typing.ForwardRef`. Examples:: + + u = Union["Milk", Way] + args = get_args(u) + is_forward_ref(args[0]) == True + is_forward_ref(args[1]) == False + """ + if not NEW_TYPING: + return isinstance(tp, _ForwardRef) + return isinstance(tp, ForwardRef) + + +def get_last_origin(tp): + """Get the last base of (multiply) subscripted type. Supports generic types, + Union, Callable, and Tuple. Returns None for unsupported types. + Examples:: + + get_last_origin(int) == None + get_last_origin(ClassVar[int]) == None + get_last_origin(Generic[T]) == Generic + get_last_origin(Union[T, int][str]) == Union[T, int] + get_last_origin(List[Tuple[T, T]][int]) == List[Tuple[T, T]] + get_last_origin(List) == List + """ + if NEW_TYPING: + raise ValueError('This function is only supported in Python 3.6,' + ' use get_origin instead') + sentinel = object() + origin = getattr(tp, '__origin__', sentinel) + if origin is sentinel: + return None + if origin is None: + return tp + return origin + + +def get_origin(tp): + """Get the unsubscripted version of a type. Supports generic types, Union, + Callable, and Tuple. Returns None for unsupported types. Examples:: + + get_origin(int) == None + get_origin(ClassVar[int]) == None + get_origin(Generic) == Generic + get_origin(Generic[T]) == Generic + get_origin(Union[T, int]) == Union + get_origin(List[Tuple[T, T]][int]) == list # List prior to Python 3.7 + """ + if NEW_TYPING: + if isinstance(tp, typingGenericAlias): + return tp.__origin__ if tp.__origin__ is not ClassVar else None + if tp is Generic: + return Generic + return None + if isinstance(tp, GenericMeta): + return _gorg(tp) + if is_union_type(tp): + return Union + if is_tuple_type(tp): + return Tuple + if is_literal_type(tp): + if NEW_TYPING: + return tp.__origin__ or tp + return Literal + + return None + + +def get_parameters(tp): + """Return type parameters of a parameterizable type as a tuple + in lexicographic order. Parameterizable types are generic types, + unions, tuple types and callable types. Examples:: + + get_parameters(int) == () + get_parameters(Generic) == () + get_parameters(Union) == () + get_parameters(List[int]) == () + + get_parameters(Generic[T]) == (T,) + get_parameters(Tuple[List[T], List[S_co]]) == (T, S_co) + get_parameters(Union[S_co, Tuple[T, T]][int, U]) == (U,) + get_parameters(Mapping[T, Tuple[S_co, T]]) == (T, S_co) + """ + if LEGACY_TYPING: + # python <= 3.5.2 + if is_union_type(tp): + params = [] + for arg in (tp.__union_params__ if tp.__union_params__ is not None else ()): + params += get_parameters(arg) + return tuple(params) + elif is_tuple_type(tp): + params = [] + for arg in (tp.__tuple_params__ if tp.__tuple_params__ is not None else ()): + params += get_parameters(arg) + return tuple(params) + elif is_generic_type(tp): + params = [] + base_params = tp.__parameters__ + if base_params is None: + return () + for bp_ in base_params: + for bp in (get_args(bp_) if is_tuple_type(bp_) else (bp_,)): + if _has_type_var(bp) and not isinstance(bp, TypeVar): + raise TypeError( + "Cannot inherit from a generic class " + "parameterized with " + "non-type-variable %s" % bp) + if params is None: + params = [] + if bp not in params: + params.append(bp) + if params is not None: + return tuple(params) + else: + return () + else: + return () + elif NEW_TYPING: + if ( + ( + isinstance(tp, typingGenericAlias) and + hasattr(tp, '__parameters__') + ) or + isinstance(tp, type) and issubclass(tp, Generic) and + tp is not Generic): + return tp.__parameters__ + else: + return () + elif ( + is_generic_type(tp) or is_union_type(tp) or + is_callable_type(tp) or is_tuple_type(tp) + ): + return tp.__parameters__ if tp.__parameters__ is not None else () + else: + return () + + +def get_last_args(tp): + """Get last arguments of (multiply) subscripted type. + Parameters for Callable are flattened. Examples:: + + get_last_args(int) == () + get_last_args(Union) == () + get_last_args(ClassVar[int]) == (int,) + get_last_args(Union[T, int]) == (T, int) + get_last_args(Iterable[Tuple[T, S]][int, T]) == (int, T) + get_last_args(Callable[[T], int]) == (T, int) + get_last_args(Callable[[], int]) == (int,) + """ + if NEW_TYPING: + raise ValueError('This function is only supported in Python 3.6,' + ' use get_args instead') + elif is_classvar(tp): + return (tp.__type__,) if tp.__type__ is not None else () + elif is_generic_type(tp): + try: + if tp.__args__ is not None and len(tp.__args__) > 0: + return tp.__args__ + except AttributeError: + # python 3.5.1 + pass + return tp.__parameters__ if tp.__parameters__ is not None else () + elif is_union_type(tp): + try: + return tp.__args__ if tp.__args__ is not None else () + except AttributeError: + # python 3.5.2 + return tp.__union_params__ if tp.__union_params__ is not None else () + elif is_callable_type(tp): + return tp.__args__ if tp.__args__ is not None else () + elif is_tuple_type(tp): + try: + return tp.__args__ if tp.__args__ is not None else () + except AttributeError: + # python 3.5.2 + return tp.__tuple_params__ if tp.__tuple_params__ is not None else () + else: + return () + + +def _eval_args(args): + """Internal helper for get_args.""" + res = [] + for arg in args: + if not isinstance(arg, tuple): + res.append(arg) + elif is_callable_type(arg[0]): + callable_args = _eval_args(arg[1:]) + if len(arg) == 2: + res.append(Callable[[], callable_args[0]]) + elif arg[1] is Ellipsis: + res.append(Callable[..., callable_args[1]]) + else: + res.append(Callable[list(callable_args[:-1]), callable_args[-1]]) + else: + res.append(type(arg[0]).__getitem__(arg[0], _eval_args(arg[1:]))) + return tuple(res) + + +def get_args(tp, evaluate=None): + """Get type arguments with all substitutions performed. For unions, + basic simplifications used by Union constructor are performed. + On versions prior to 3.7 if `evaluate` is False (default), + report result as nested tuple, this matches + the internal representation of types. If `evaluate` is True + (or if Python version is 3.7 or greater), then all + type parameters are applied (this could be time and memory expensive). + Examples:: + + get_args(int) == () + get_args(Union[int, Union[T, int], str][int]) == (int, str) + get_args(Union[int, Tuple[T, int]][str]) == (int, (Tuple, str, int)) + + get_args(Union[int, Tuple[T, int]][str], evaluate=True) == \ + (int, Tuple[str, int]) + get_args(Dict[int, Tuple[T, T]][Optional[int]], evaluate=True) == \ + (int, Tuple[Optional[int], Optional[int]]) + get_args(Callable[[], T][int], evaluate=True) == ([], int,) + """ + if NEW_TYPING: + if evaluate is not None and not evaluate: + raise ValueError('evaluate can only be True in Python >= 3.7') + # Note special aliases on Python 3.9 don't have __args__. + if isinstance(tp, typingGenericAlias) and hasattr(tp, '__args__'): + res = tp.__args__ + if get_origin(tp) is collections.abc.Callable and res[0] is not Ellipsis: + res = (list(res[:-1]), res[-1]) + return res + if MaybeUnionType and isinstance(tp, MaybeUnionType): + return tp.__args__ + return () + if is_classvar(tp) or is_final_type(tp): + return (tp.__type__,) if tp.__type__ is not None else () + if is_literal_type(tp): + return tp.__values__ or () + if ( + is_generic_type(tp) or is_union_type(tp) or + is_callable_type(tp) or is_tuple_type(tp) + ): + try: + tree = tp._subs_tree() + except AttributeError: + # Old python typing module <= 3.5.3 + if is_union_type(tp): + # backport of union's subs_tree + tree = _union_subs_tree(tp) + elif is_generic_type(tp): + # backport of GenericMeta's subs_tree + tree = _generic_subs_tree(tp) + elif is_tuple_type(tp): + # ad-hoc (inspired by union) + tree = _tuple_subs_tree(tp) + else: + # tree = _subs_tree(tp) + return () + + if isinstance(tree, tuple) and len(tree) > 1: + if not evaluate: + return tree[1:] + res = _eval_args(tree[1:]) + if get_origin(tp) is Callable and res[0] is not Ellipsis: + res = (list(res[:-1]), res[-1]) + return res + + return () + + +def get_bound(tp): + """Return the type bound to a `TypeVar` if any. + + It the type is not a `TypeVar`, a `TypeError` is raised. + Examples:: + + get_bound(TypeVar('T')) == None + get_bound(TypeVar('T', bound=int)) == int + """ + + if is_typevar(tp): + return getattr(tp, '__bound__', None) + else: + raise TypeError("type is not a `TypeVar`: " + str(tp)) + + +def get_constraints(tp): + """Returns the constraints of a `TypeVar` if any. + + It the type is not a `TypeVar`, a `TypeError` is raised + Examples:: + + get_constraints(TypeVar('T')) == () + get_constraints(TypeVar('T', int, str)) == (int, str) + """ + + if is_typevar(tp): + return getattr(tp, '__constraints__', ()) + else: + raise TypeError("type is not a `TypeVar`: " + str(tp)) + + +def get_generic_type(obj): + """Get the generic type of an object if possible, or runtime class otherwise. + Examples:: + + class Node(Generic[T]): + ... + type(Node[int]()) == Node + get_generic_type(Node[int]()) == Node[int] + get_generic_type(Node[T]()) == Node[T] + get_generic_type(1) == int + """ + + gen_type = getattr(obj, '__orig_class__', None) + return gen_type if gen_type is not None else type(obj) + + +def get_generic_bases(tp): + """Get generic base types of a type or empty tuple if not possible. + Example:: + + class MyClass(List[int], Mapping[str, List[int]]): + ... + MyClass.__bases__ == (List, Mapping) + get_generic_bases(MyClass) == (List[int], Mapping[str, List[int]]) + """ + if LEGACY_TYPING: + return tuple(t for t in tp.__bases__ if isinstance(t, GenericMeta)) + else: + return getattr(tp, '__orig_bases__', ()) + + +def typed_dict_keys(td): + """If td is a TypedDict class, return a dictionary mapping the typed keys to types. + Otherwise, return None. Examples:: + + class TD(TypedDict): + x: int + y: int + class Other(dict): + x: int + y: int + + typed_dict_keys(TD) == {'x': int, 'y': int} + typed_dict_keys(dict) == None + typed_dict_keys(Other) == None + """ + if isinstance(td, (_TypedDictMeta_Mypy, _TypedDictMeta_TE)): + return td.__annotations__.copy() + return None + + +def get_forward_arg(fr): + """ + If fr is a ForwardRef, return the string representation of the forward reference. + Otherwise return None. Examples:: + + tp = List["FRef"] + fr = get_args(tp)[0] + get_forward_arg(fr) == "FRef" + get_forward_arg(tp) == None + """ + return fr.__forward_arg__ if is_forward_ref(fr) else None + + +# A few functions backported and adapted for the LEGACY_TYPING context, and used above + +def _replace_arg(arg, tvars, args): + """backport of _replace_arg""" + if tvars is None: + tvars = [] + # if hasattr(arg, '_subs_tree') and isinstance(arg, (GenericMeta, _TypingBase)): + # return arg._subs_tree(tvars, args) + if is_union_type(arg): + return _union_subs_tree(arg, tvars, args) + if is_tuple_type(arg): + return _tuple_subs_tree(arg, tvars, args) + if is_generic_type(arg): + return _generic_subs_tree(arg, tvars, args) + if isinstance(arg, TypeVar): + for i, tvar in enumerate(tvars): + if arg == tvar: + return args[i] + return arg + + +def _remove_dups_flatten(parameters): + """backport of _remove_dups_flatten""" + + # Flatten out Union[Union[...], ...]. + params = [] + for p in parameters: + if isinstance(p, _Union): # and p.__origin__ is Union: + params.extend(p.__union_params__) # p.__args__) + elif isinstance(p, tuple) and len(p) > 0 and p[0] is Union: + params.extend(p[1:]) + else: + params.append(p) + # Weed out strict duplicates, preserving the first of each occurrence. + all_params = set(params) + if len(all_params) < len(params): + new_params = [] + for t in params: + if t in all_params: + new_params.append(t) + all_params.remove(t) + params = new_params + assert not all_params, all_params + # Weed out subclasses. + # E.g. Union[int, Employee, Manager] == Union[int, Employee]. + # If object is present it will be sole survivor among proper classes. + # Never discard type variables. + # (In particular, Union[str, AnyStr] != AnyStr.) + all_params = set(params) + for t1 in params: + if not isinstance(t1, type): + continue + if any(isinstance(t2, type) and issubclass(t1, t2) + for t2 in all_params - {t1} + if (not (isinstance(t2, GenericMeta) and + get_origin(t2) is not None) and + not isinstance(t2, TypeVar))): + all_params.remove(t1) + return tuple(t for t in params if t in all_params) + + +def _subs_tree(cls, tvars=None, args=None): + """backport of typing._subs_tree, adapted for legacy versions """ + def _get_origin(cls): + try: + return cls.__origin__ + except AttributeError: + return None + + current = _get_origin(cls) + if current is None: + if not is_union_type(cls) and not is_tuple_type(cls): + return cls + + # Make of chain of origins (i.e. cls -> cls.__origin__) + orig_chain = [] + while _get_origin(current) is not None: + orig_chain.append(current) + current = _get_origin(current) + + # Replace type variables in __args__ if asked ... + tree_args = [] + + def _get_args(cls): + if is_union_type(cls): + cls_args = cls.__union_params__ + elif is_tuple_type(cls): + cls_args = cls.__tuple_params__ + else: + try: + cls_args = cls.__args__ + except AttributeError: + cls_args = () + return cls_args if cls_args is not None else () + + for arg in _get_args(cls): + tree_args.append(_replace_arg(arg, tvars, args)) + # ... then continue replacing down the origin chain. + for ocls in orig_chain: + new_tree_args = [] + for arg in _get_args(ocls): + new_tree_args.append(_replace_arg(arg, get_parameters(ocls), tree_args)) + tree_args = new_tree_args + return tree_args + + +def _union_subs_tree(tp, tvars=None, args=None): + """ backport of Union._subs_tree """ + if tp is Union: + return Union # Nothing to substitute + tree_args = _subs_tree(tp, tvars, args) + # tree_args = tp.__union_params__ if tp.__union_params__ is not None else () + tree_args = _remove_dups_flatten(tree_args) + if len(tree_args) == 1: + return tree_args[0] # Union of a single type is that type + return (Union,) + tree_args + + +def _generic_subs_tree(tp, tvars=None, args=None): + """ backport of GenericMeta._subs_tree """ + if tp.__origin__ is None: + return tp + tree_args = _subs_tree(tp, tvars, args) + return (_gorg(tp),) + tuple(tree_args) + + +def _tuple_subs_tree(tp, tvars=None, args=None): + """ ad-hoc function (inspired by union) for legacy typing """ + if tp is Tuple: + return Tuple # Nothing to substitute + tree_args = _subs_tree(tp, tvars, args) + return (Tuple,) + tuple(tree_args) + + +def _has_type_var(t): + if t is None: + return False + elif is_union_type(t): + return _union_has_type_var(t) + elif is_tuple_type(t): + return _tuple_has_type_var(t) + elif is_generic_type(t): + return _generic_has_type_var(t) + elif is_callable_type(t): + return _callable_has_type_var(t) + else: + return False + + +def _union_has_type_var(tp): + if tp.__union_params__: + for t in tp.__union_params__: + if _has_type_var(t): + return True + return False + + +def _tuple_has_type_var(tp): + if tp.__tuple_params__: + for t in tp.__tuple_params__: + if _has_type_var(t): + return True + return False + + +def _callable_has_type_var(tp): + if tp.__args__: + for t in tp.__args__: + if _has_type_var(t): + return True + return _has_type_var(tp.__result__) + + +def _generic_has_type_var(tp): + if tp.__parameters__: + for t in tp.__parameters__: + if _has_type_var(t): + return True + return False |