diff options
| author | orivej <[email protected]> | 2022-02-10 16:45:01 +0300 |
|---|---|---|
| committer | Daniil Cherednik <[email protected]> | 2022-02-10 16:45:01 +0300 |
| commit | 2d37894b1b037cf24231090eda8589bbb44fb6fc (patch) | |
| tree | be835aa92c6248212e705f25388ebafcf84bc7a1 /contrib/tools/python3/src/Lib/typing.py | |
| parent | 718c552901d703c502ccbefdfc3c9028d608b947 (diff) | |
Restoring authorship annotation for <[email protected]>. Commit 2 of 2.
Diffstat (limited to 'contrib/tools/python3/src/Lib/typing.py')
| -rw-r--r-- | contrib/tools/python3/src/Lib/typing.py | 2218 |
1 files changed, 1109 insertions, 1109 deletions
diff --git a/contrib/tools/python3/src/Lib/typing.py b/contrib/tools/python3/src/Lib/typing.py index 325443da6c5..da70d4115fa 100644 --- a/contrib/tools/python3/src/Lib/typing.py +++ b/contrib/tools/python3/src/Lib/typing.py @@ -1,100 +1,100 @@ -""" -The typing module: Support for gradual typing as defined by PEP 484. - -At large scale, the structure of the module is following: -* Imports and exports, all public names should be explicitly added to __all__. -* Internal helper functions: these should never be used in code outside this module. -* _SpecialForm and its instances (special forms): Any, NoReturn, ClassVar, Union, Optional -* Two classes whose instances can be type arguments in addition to types: ForwardRef and TypeVar -* The core of internal generics API: _GenericAlias and _VariadicGenericAlias, the latter is - currently only used by Tuple and Callable. All subscripted types like X[int], Union[int, str], - etc., are instances of either of these classes. +""" +The typing module: Support for gradual typing as defined by PEP 484. + +At large scale, the structure of the module is following: +* Imports and exports, all public names should be explicitly added to __all__. +* Internal helper functions: these should never be used in code outside this module. +* _SpecialForm and its instances (special forms): Any, NoReturn, ClassVar, Union, Optional +* Two classes whose instances can be type arguments in addition to types: ForwardRef and TypeVar +* The core of internal generics API: _GenericAlias and _VariadicGenericAlias, the latter is + currently only used by Tuple and Callable. All subscripted types like X[int], Union[int, str], + etc., are instances of either of these classes. * The public counterpart of the generics API consists of two classes: Generic and Protocol. -* Public helper functions: get_type_hints, overload, cast, no_type_check, - no_type_check_decorator. -* Generic aliases for collections.abc ABCs and few additional protocols. +* Public helper functions: get_type_hints, overload, cast, no_type_check, + no_type_check_decorator. +* Generic aliases for collections.abc ABCs and few additional protocols. * Special types: NewType, NamedTuple, TypedDict. -* Wrapper submodules for re and io related types. -""" - +* Wrapper submodules for re and io related types. +""" + from abc import abstractmethod, ABCMeta -import collections -import collections.abc -import contextlib -import functools -import operator -import re as stdlib_re # Avoid confusion with the re we export. -import sys -import types +import collections +import collections.abc +import contextlib +import functools +import operator +import re as stdlib_re # Avoid confusion with the re we export. +import sys +import types from types import WrapperDescriptorType, MethodWrapperType, MethodDescriptorType, GenericAlias - -# Please keep __all__ alphabetized within each category. -__all__ = [ - # Super-special typing primitives. + +# Please keep __all__ alphabetized within each category. +__all__ = [ + # Super-special typing primitives. 'Annotated', - 'Any', - 'Callable', - 'ClassVar', + 'Any', + 'Callable', + 'ClassVar', 'Final', 'ForwardRef', - 'Generic', + 'Generic', 'Literal', - 'Optional', + 'Optional', 'Protocol', - 'Tuple', - 'Type', - 'TypeVar', - 'Union', - - # ABCs (from collections.abc). - 'AbstractSet', # collections.abc.Set. - 'ByteString', - 'Container', - 'ContextManager', - 'Hashable', - 'ItemsView', - 'Iterable', - 'Iterator', - 'KeysView', - 'Mapping', - 'MappingView', - 'MutableMapping', - 'MutableSequence', - 'MutableSet', - 'Sequence', - 'Sized', - 'ValuesView', - 'Awaitable', - 'AsyncIterator', - 'AsyncIterable', - 'Coroutine', - 'Collection', - 'AsyncGenerator', - 'AsyncContextManager', - - # Structural checks, a.k.a. protocols. - 'Reversible', - 'SupportsAbs', - 'SupportsBytes', - 'SupportsComplex', - 'SupportsFloat', + 'Tuple', + 'Type', + 'TypeVar', + 'Union', + + # ABCs (from collections.abc). + 'AbstractSet', # collections.abc.Set. + 'ByteString', + 'Container', + 'ContextManager', + 'Hashable', + 'ItemsView', + 'Iterable', + 'Iterator', + 'KeysView', + 'Mapping', + 'MappingView', + 'MutableMapping', + 'MutableSequence', + 'MutableSet', + 'Sequence', + 'Sized', + 'ValuesView', + 'Awaitable', + 'AsyncIterator', + 'AsyncIterable', + 'Coroutine', + 'Collection', + 'AsyncGenerator', + 'AsyncContextManager', + + # Structural checks, a.k.a. protocols. + 'Reversible', + 'SupportsAbs', + 'SupportsBytes', + 'SupportsComplex', + 'SupportsFloat', 'SupportsIndex', - 'SupportsInt', - 'SupportsRound', - - # Concrete collection types. + 'SupportsInt', + 'SupportsRound', + + # Concrete collection types. 'ChainMap', - 'Counter', - 'Deque', - 'Dict', - 'DefaultDict', - 'List', + 'Counter', + 'Deque', + 'Dict', + 'DefaultDict', + 'List', 'OrderedDict', - 'Set', - 'FrozenSet', - 'NamedTuple', # Not really a type. + 'Set', + 'FrozenSet', + 'NamedTuple', # Not really a type. 'TypedDict', # Not really a type. - 'Generator', + 'Generator', # Other concrete types. 'BinaryIO', @@ -102,29 +102,29 @@ __all__ = [ 'Match', 'Pattern', 'TextIO', - - # One-off things. - 'AnyStr', - 'cast', + + # One-off things. + 'AnyStr', + 'cast', 'final', 'get_args', 'get_origin', - 'get_type_hints', - 'NewType', - 'no_type_check', - 'no_type_check_decorator', - 'NoReturn', - 'overload', + 'get_type_hints', + 'NewType', + 'no_type_check', + 'no_type_check_decorator', + 'NoReturn', + 'overload', 'runtime_checkable', - 'Text', - 'TYPE_CHECKING', -] - -# The pseudo-submodules 're' and 'io' are part of the public -# namespace, but excluded from __all__ because they might stomp on -# legitimate imports of those modules. - - + 'Text', + 'TYPE_CHECKING', +] + +# The pseudo-submodules 're' and 'io' are part of the public +# namespace, but excluded from __all__ because they might stomp on +# legitimate imports of those modules. + + def _type_convert(arg, module=None): """For converting None to type(None), and strings to ForwardRef.""" if arg is None: @@ -135,86 +135,86 @@ def _type_convert(arg, module=None): def _type_check(arg, msg, is_argument=True, module=None, *, is_class=False): - """Check that the argument is a type, and return it (internal helper). - - As a special case, accept None and return type(None) instead. Also wrap strings - into ForwardRef instances. Consider several corner cases, for example plain - special forms like Union are not valid, while Union[int, str] is OK, etc. - The msg argument is a human-readable error message, e.g:: - - "Union[arg, ...]: arg should be a type." - - We append the repr() of the actual value (truncated to 100 chars). - """ + """Check that the argument is a type, and return it (internal helper). + + As a special case, accept None and return type(None) instead. Also wrap strings + into ForwardRef instances. Consider several corner cases, for example plain + special forms like Union are not valid, while Union[int, str] is OK, etc. + The msg argument is a human-readable error message, e.g:: + + "Union[arg, ...]: arg should be a type." + + We append the repr() of the actual value (truncated to 100 chars). + """ invalid_generic_forms = (Generic, Protocol) if not is_class: invalid_generic_forms += (ClassVar,) if is_argument: invalid_generic_forms += (Final,) - + arg = _type_convert(arg, module=module) - if (isinstance(arg, _GenericAlias) and - arg.__origin__ in invalid_generic_forms): - raise TypeError(f"{arg} is not valid as type argument") + if (isinstance(arg, _GenericAlias) and + arg.__origin__ in invalid_generic_forms): + raise TypeError(f"{arg} is not valid as type argument") if arg in (Any, NoReturn, Final): return arg if isinstance(arg, _SpecialForm) or arg in (Generic, Protocol): - raise TypeError(f"Plain {arg} is not valid as type argument") - if isinstance(arg, (type, TypeVar, ForwardRef)): - return arg - if not callable(arg): - raise TypeError(f"{msg} Got {arg!r:.100}.") - return arg - - -def _type_repr(obj): - """Return the repr() of an object, special-casing types (internal helper). - - If obj is a type, we return a shorter version than the default - type.__repr__, based on the module and qualified name, which is - typically enough to uniquely identify a type. For everything - else, we fall back on repr(obj). - """ + raise TypeError(f"Plain {arg} is not valid as type argument") + if isinstance(arg, (type, TypeVar, ForwardRef)): + return arg + if not callable(arg): + raise TypeError(f"{msg} Got {arg!r:.100}.") + return arg + + +def _type_repr(obj): + """Return the repr() of an object, special-casing types (internal helper). + + If obj is a type, we return a shorter version than the default + type.__repr__, based on the module and qualified name, which is + typically enough to uniquely identify a type. For everything + else, we fall back on repr(obj). + """ if isinstance(obj, types.GenericAlias): return repr(obj) - if isinstance(obj, type): - if obj.__module__ == 'builtins': - return obj.__qualname__ - return f'{obj.__module__}.{obj.__qualname__}' - if obj is ...: - return('...') - if isinstance(obj, types.FunctionType): - return obj.__name__ - return repr(obj) - - -def _collect_type_vars(types): - """Collect all type variable contained in types in order of - first appearance (lexicographic order). For example:: - - _collect_type_vars((T, List[S, T])) == (T, S) - """ - tvars = [] - for t in types: - if isinstance(t, TypeVar) and t not in tvars: - tvars.append(t) + if isinstance(obj, type): + if obj.__module__ == 'builtins': + return obj.__qualname__ + return f'{obj.__module__}.{obj.__qualname__}' + if obj is ...: + return('...') + if isinstance(obj, types.FunctionType): + return obj.__name__ + return repr(obj) + + +def _collect_type_vars(types): + """Collect all type variable contained in types in order of + first appearance (lexicographic order). For example:: + + _collect_type_vars((T, List[S, T])) == (T, S) + """ + tvars = [] + for t in types: + if isinstance(t, TypeVar) and t not in tvars: + tvars.append(t) if isinstance(t, (_GenericAlias, GenericAlias)): - tvars.extend([t for t in t.__parameters__ if t not in tvars]) - return tuple(tvars) - - + tvars.extend([t for t in t.__parameters__ if t not in tvars]) + return tuple(tvars) + + def _check_generic(cls, parameters, elen): - """Check correct count for parameters of a generic cls (internal helper). - This gives a nice error message in case of count mismatch. - """ + """Check correct count for parameters of a generic cls (internal helper). + This gives a nice error message in case of count mismatch. + """ if not elen: - raise TypeError(f"{cls} is not a generic class") - alen = len(parameters) - if alen != elen: - raise TypeError(f"Too {'many' if alen > elen else 'few'} parameters for {cls};" - f" actual {alen}, expected {elen}") - - + raise TypeError(f"{cls} is not a generic class") + alen = len(parameters) + if alen != elen: + raise TypeError(f"Too {'many' if alen > elen else 'few'} parameters for {cls};" + f" actual {alen}, expected {elen}") + + def _deduplicate(params): # Weed out strict duplicates, preserving the first of each occurrence. all_params = set(params) @@ -229,19 +229,19 @@ def _deduplicate(params): return params -def _remove_dups_flatten(parameters): - """An internal helper for Union creation and substitution: flatten Unions - among parameters, then remove duplicates. - """ - # Flatten out Union[Union[...], ...]. - params = [] - for p in parameters: +def _remove_dups_flatten(parameters): + """An internal helper for Union creation and substitution: flatten Unions + among parameters, then remove duplicates. + """ + # Flatten out Union[Union[...], ...]. + params = [] + for p in parameters: if isinstance(p, _UnionGenericAlias): - params.extend(p.__args__) - elif isinstance(p, tuple) and len(p) > 0 and p[0] is Union: - params.extend(p[1:]) - else: - params.append(p) + params.extend(p.__args__) + elif isinstance(p, tuple) and len(p) > 0 and p[0] is Union: + params.extend(p[1:]) + else: + params.append(p) return tuple(_deduplicate(params)) @@ -254,20 +254,20 @@ def _flatten_literal_params(parameters): params.extend(p.__args__) else: params.append(p) - return tuple(params) - - -_cleanups = [] - - + return tuple(params) + + +_cleanups = [] + + def _tp_cache(func=None, /, *, typed=False): - """Internal wrapper caching __getitem__ of generic types with a fallback to - original function for non-hashable arguments. - """ + """Internal wrapper caching __getitem__ of generic types with a fallback to + original function for non-hashable arguments. + """ def decorator(func): cached = functools.lru_cache(typed=typed)(func) _cleanups.append(cached.cache_clear) - + @functools.wraps(func) def inner(*args, **kwds): try: @@ -276,84 +276,84 @@ def _tp_cache(func=None, /, *, typed=False): pass # All real errors (not unhashable args) are raised below. return func(*args, **kwds) return inner - + if func is not None: return decorator(func) - + return decorator def _eval_type(t, globalns, localns, recursive_guard=frozenset()): """Evaluate all forward references in the given type t. - For use of globalns and localns see the docstring for get_type_hints(). + For use of globalns and localns see the docstring for get_type_hints(). recursive_guard is used to prevent prevent infinite recursion with recursive ForwardRef. - """ - if isinstance(t, ForwardRef): + """ + if isinstance(t, ForwardRef): return t._evaluate(globalns, localns, recursive_guard) if isinstance(t, (_GenericAlias, GenericAlias)): ev_args = tuple(_eval_type(a, globalns, localns, recursive_guard) for a in t.__args__) - if ev_args == t.__args__: - return t + if ev_args == t.__args__: + return t if isinstance(t, GenericAlias): return GenericAlias(t.__origin__, ev_args) else: return t.copy_with(ev_args) - return t - - -class _Final: - """Mixin to prohibit subclassing""" - - __slots__ = ('__weakref__',) - + return t + + +class _Final: + """Mixin to prohibit subclassing""" + + __slots__ = ('__weakref__',) + def __init_subclass__(self, /, *args, **kwds): - if '_root' not in kwds: - raise TypeError("Cannot subclass special typing classes") - -class _Immutable: - """Mixin to indicate that object should not be copied.""" + if '_root' not in kwds: + raise TypeError("Cannot subclass special typing classes") + +class _Immutable: + """Mixin to indicate that object should not be copied.""" __slots__ = () - - def __copy__(self): - return self - - def __deepcopy__(self, memo): - return self - - + + def __copy__(self): + return self + + def __deepcopy__(self, memo): + return self + + # Internal indicator of special typing constructs. # See __doc__ instance attribute for specific docs. class _SpecialForm(_Final, _root=True): __slots__ = ('_name', '__doc__', '_getitem') - + def __init__(self, getitem): self._getitem = getitem self._name = getitem.__name__ self.__doc__ = getitem.__doc__ - + def __mro_entries__(self, bases): raise TypeError(f"Cannot subclass {self!r}") - - def __repr__(self): - return 'typing.' + self._name - - def __reduce__(self): - return self._name - - def __call__(self, *args, **kwds): - raise TypeError(f"Cannot instantiate {self!r}") - - def __instancecheck__(self, obj): - raise TypeError(f"{self} cannot be used with isinstance()") - - def __subclasscheck__(self, cls): - raise TypeError(f"{self} cannot be used with issubclass()") - - @_tp_cache - def __getitem__(self, parameters): + + def __repr__(self): + return 'typing.' + self._name + + def __reduce__(self): + return self._name + + def __call__(self, *args, **kwds): + raise TypeError(f"Cannot instantiate {self!r}") + + def __instancecheck__(self, obj): + raise TypeError(f"{self} cannot be used with isinstance()") + + def __subclasscheck__(self, cls): + raise TypeError(f"{self} cannot be used with issubclass()") + + @_tp_cache + def __getitem__(self, parameters): return self._getitem(self, parameters) - - + + class _LiteralSpecialForm(_SpecialForm, _root=True): def __getitem__(self, parameters): if not isinstance(parameters, tuple): @@ -363,53 +363,53 @@ class _LiteralSpecialForm(_SpecialForm, _root=True): @_SpecialForm def Any(self, parameters): - """Special type indicating an unconstrained type. - - - Any is compatible with every type. - - Any assumed to have all methods. - - All values assumed to be instances of Any. - - Note that all the above statements are true from the point of view of - static type checkers. At runtime, Any should not be used with instance - or class checks. + """Special type indicating an unconstrained type. + + - Any is compatible with every type. + - Any assumed to have all methods. + - All values assumed to be instances of Any. + + Note that all the above statements are true from the point of view of + static type checkers. At runtime, Any should not be used with instance + or class checks. """ raise TypeError(f"{self} is not subscriptable") - + @_SpecialForm def NoReturn(self, parameters): - """Special type indicating functions that never return. - Example:: - - from typing import NoReturn - - def stop() -> NoReturn: - raise Exception('no way') - - This type is invalid in other positions, e.g., ``List[NoReturn]`` - will fail in static type checkers. + """Special type indicating functions that never return. + Example:: + + from typing import NoReturn + + def stop() -> NoReturn: + raise Exception('no way') + + This type is invalid in other positions, e.g., ``List[NoReturn]`` + will fail in static type checkers. """ raise TypeError(f"{self} is not subscriptable") - + @_SpecialForm def ClassVar(self, parameters): - """Special type construct to mark class variables. - - An annotation wrapped in ClassVar indicates that a given - attribute is intended to be used as a class variable and - should not be set on instances of that class. Usage:: - - class Starship: - stats: ClassVar[Dict[str, int]] = {} # class variable - damage: int = 10 # instance variable - - ClassVar accepts only types and cannot be further subscribed. - - Note that ClassVar is not a class itself, and should not - be used with isinstance() or issubclass(). + """Special type construct to mark class variables. + + An annotation wrapped in ClassVar indicates that a given + attribute is intended to be used as a class variable and + should not be set on instances of that class. Usage:: + + class Starship: + stats: ClassVar[Dict[str, int]] = {} # class variable + damage: int = 10 # instance variable + + ClassVar accepts only types and cannot be further subscribed. + + Note that ClassVar is not a class itself, and should not + be used with isinstance() or issubclass(). """ item = _type_check(parameters, f'{self} accepts only single type.') return _GenericAlias(self, (item,)) - + @_SpecialForm def Final(self, parameters): """Special typing construct to indicate final names to type checkers. @@ -433,30 +433,30 @@ def Final(self, parameters): @_SpecialForm def Union(self, parameters): - """Union type; Union[X, Y] means either X or Y. - - To define a union, use e.g. Union[int, str]. Details: - - The arguments must be types and there must be at least one. - - None as an argument is a special case and is replaced by - type(None). - - Unions of unions are flattened, e.g.:: - - Union[Union[int, str], float] == Union[int, str, float] - - - Unions of a single argument vanish, e.g.:: - - Union[int] == int # The constructor actually returns int - - - Redundant arguments are skipped, e.g.:: - - Union[int, str, int] == Union[int, str] - - - When comparing unions, the argument order is ignored, e.g.:: - - Union[int, str] == Union[str, int] - - - You cannot subclass or instantiate a union. - - You can use Optional[X] as a shorthand for Union[X, None]. + """Union type; Union[X, Y] means either X or Y. + + To define a union, use e.g. Union[int, str]. Details: + - The arguments must be types and there must be at least one. + - None as an argument is a special case and is replaced by + type(None). + - Unions of unions are flattened, e.g.:: + + Union[Union[int, str], float] == Union[int, str, float] + + - Unions of a single argument vanish, e.g.:: + + Union[int] == int # The constructor actually returns int + + - Redundant arguments are skipped, e.g.:: + + Union[int, str, int] == Union[int, str] + + - When comparing unions, the argument order is ignored, e.g.:: + + Union[int, str] == Union[str, int] + + - You cannot subclass or instantiate a union. + - You can use Optional[X] as a shorthand for Union[X, None]. """ if parameters == (): raise TypeError("Cannot take a Union of no types.") @@ -468,21 +468,21 @@ def Union(self, parameters): if len(parameters) == 1: return parameters[0] return _UnionGenericAlias(self, parameters) - + @_SpecialForm def Optional(self, parameters): - """Optional type. - - Optional[X] is equivalent to Union[X, None]. + """Optional type. + + Optional[X] is equivalent to Union[X, None]. """ arg = _type_check(parameters, f"{self} requires a single type.") return Union[arg, type(None)] - + @_LiteralSpecialForm @_tp_cache(typed=True) def Literal(self, *parameters): """Special typing form to define literal types (a.k.a. value types). - + This form can be used to indicate to type checkers that the corresponding variable or function parameter has a value equivalent to the provided literal (or one of several literals): @@ -513,169 +513,169 @@ def Literal(self, *parameters): return _LiteralGenericAlias(self, parameters) -class ForwardRef(_Final, _root=True): - """Internal wrapper to hold a forward reference.""" - - __slots__ = ('__forward_arg__', '__forward_code__', - '__forward_evaluated__', '__forward_value__', +class ForwardRef(_Final, _root=True): + """Internal wrapper to hold a forward reference.""" + + __slots__ = ('__forward_arg__', '__forward_code__', + '__forward_evaluated__', '__forward_value__', '__forward_is_argument__', '__forward_is_class__', '__forward_module__') - + def __init__(self, arg, is_argument=True, module=None, *, is_class=False): - if not isinstance(arg, str): - raise TypeError(f"Forward reference must be a string -- got {arg!r}") - try: - code = compile(arg, '<string>', 'eval') - except SyntaxError: - raise SyntaxError(f"Forward reference must be an expression -- got {arg!r}") - self.__forward_arg__ = arg - self.__forward_code__ = code - self.__forward_evaluated__ = False - self.__forward_value__ = None - self.__forward_is_argument__ = is_argument + if not isinstance(arg, str): + raise TypeError(f"Forward reference must be a string -- got {arg!r}") + try: + code = compile(arg, '<string>', 'eval') + except SyntaxError: + raise SyntaxError(f"Forward reference must be an expression -- got {arg!r}") + self.__forward_arg__ = arg + self.__forward_code__ = code + self.__forward_evaluated__ = False + self.__forward_value__ = None + self.__forward_is_argument__ = is_argument self.__forward_is_class__ = is_class self.__forward_module__ = module - + def _evaluate(self, globalns, localns, recursive_guard): if self.__forward_arg__ in recursive_guard: return self - if not self.__forward_evaluated__ or localns is not globalns: - if globalns is None and localns is None: - globalns = localns = {} - elif globalns is None: - globalns = localns - elif localns is None: - localns = globalns + if not self.__forward_evaluated__ or localns is not globalns: + if globalns is None and localns is None: + globalns = localns = {} + elif globalns is None: + globalns = localns + elif localns is None: + localns = globalns if self.__forward_module__ is not None: globalns = getattr( sys.modules.get(self.__forward_module__, None), '__dict__', globalns ) type_ = _type_check( - eval(self.__forward_code__, globalns, localns), - "Forward references must evaluate to types.", + eval(self.__forward_code__, globalns, localns), + "Forward references must evaluate to types.", is_argument=self.__forward_is_argument__, is_class=self.__forward_is_class__, ) self.__forward_value__ = _eval_type( type_, globalns, localns, recursive_guard | {self.__forward_arg__} ) - self.__forward_evaluated__ = True - return self.__forward_value__ - - def __eq__(self, other): - if not isinstance(other, ForwardRef): - return NotImplemented + self.__forward_evaluated__ = True + return self.__forward_value__ + + def __eq__(self, other): + if not isinstance(other, ForwardRef): + return NotImplemented if self.__forward_evaluated__ and other.__forward_evaluated__: return (self.__forward_arg__ == other.__forward_arg__ and self.__forward_value__ == other.__forward_value__) return self.__forward_arg__ == other.__forward_arg__ - - def __hash__(self): + + def __hash__(self): return hash(self.__forward_arg__) - - def __repr__(self): - return f'ForwardRef({self.__forward_arg__!r})' - - -class TypeVar(_Final, _Immutable, _root=True): - """Type variable. - - Usage:: - - T = TypeVar('T') # Can be anything - A = TypeVar('A', str, bytes) # Must be str or bytes - - Type variables exist primarily for the benefit of static type - checkers. They serve as the parameters for generic types as well - as for generic function definitions. See class Generic for more - information on generic types. Generic functions work as follows: - - def repeat(x: T, n: int) -> List[T]: - '''Return a list containing n references to x.''' - return [x]*n - - def longest(x: A, y: A) -> A: - '''Return the longest of two strings.''' - return x if len(x) >= len(y) else y - - The latter example's signature is essentially the overloading - of (str, str) -> str and (bytes, bytes) -> bytes. Also note - that if the arguments are instances of some subclass of str, - the return type is still plain str. - - At runtime, isinstance(x, T) and issubclass(C, T) will raise TypeError. - - Type variables defined with covariant=True or contravariant=True - can be used to declare covariant or contravariant generic types. - See PEP 484 for more details. By default generic types are invariant - in all type variables. - - Type variables can be introspected. e.g.: - - T.__name__ == 'T' - T.__constraints__ == () - T.__covariant__ == False - T.__contravariant__ = False - A.__constraints__ == (str, bytes) - - Note that only type variables defined in global scope can be pickled. - """ - - __slots__ = ('__name__', '__bound__', '__constraints__', + + def __repr__(self): + return f'ForwardRef({self.__forward_arg__!r})' + + +class TypeVar(_Final, _Immutable, _root=True): + """Type variable. + + Usage:: + + T = TypeVar('T') # Can be anything + A = TypeVar('A', str, bytes) # Must be str or bytes + + Type variables exist primarily for the benefit of static type + checkers. They serve as the parameters for generic types as well + as for generic function definitions. See class Generic for more + information on generic types. Generic functions work as follows: + + def repeat(x: T, n: int) -> List[T]: + '''Return a list containing n references to x.''' + return [x]*n + + def longest(x: A, y: A) -> A: + '''Return the longest of two strings.''' + return x if len(x) >= len(y) else y + + The latter example's signature is essentially the overloading + of (str, str) -> str and (bytes, bytes) -> bytes. Also note + that if the arguments are instances of some subclass of str, + the return type is still plain str. + + At runtime, isinstance(x, T) and issubclass(C, T) will raise TypeError. + + Type variables defined with covariant=True or contravariant=True + can be used to declare covariant or contravariant generic types. + See PEP 484 for more details. By default generic types are invariant + in all type variables. + + Type variables can be introspected. e.g.: + + T.__name__ == 'T' + T.__constraints__ == () + T.__covariant__ == False + T.__contravariant__ = False + A.__constraints__ == (str, bytes) + + Note that only type variables defined in global scope can be pickled. + """ + + __slots__ = ('__name__', '__bound__', '__constraints__', '__covariant__', '__contravariant__', '__dict__') - - def __init__(self, name, *constraints, bound=None, - covariant=False, contravariant=False): - self.__name__ = name - if covariant and contravariant: - raise ValueError("Bivariant types are not supported.") - self.__covariant__ = bool(covariant) - self.__contravariant__ = bool(contravariant) - if constraints and bound is not None: - raise TypeError("Constraints cannot be combined with bound=...") - if constraints and len(constraints) == 1: - raise TypeError("A single constraint is not allowed") - msg = "TypeVar(name, constraint, ...): constraints must be types." - self.__constraints__ = tuple(_type_check(t, msg) for t in constraints) - if bound: - self.__bound__ = _type_check(bound, "Bound must be a type.") - else: - self.__bound__ = None + + def __init__(self, name, *constraints, bound=None, + covariant=False, contravariant=False): + self.__name__ = name + if covariant and contravariant: + raise ValueError("Bivariant types are not supported.") + self.__covariant__ = bool(covariant) + self.__contravariant__ = bool(contravariant) + if constraints and bound is not None: + raise TypeError("Constraints cannot be combined with bound=...") + if constraints and len(constraints) == 1: + raise TypeError("A single constraint is not allowed") + msg = "TypeVar(name, constraint, ...): constraints must be types." + self.__constraints__ = tuple(_type_check(t, msg) for t in constraints) + if bound: + self.__bound__ = _type_check(bound, "Bound must be a type.") + else: + self.__bound__ = None try: def_mod = sys._getframe(1).f_globals.get('__name__', '__main__') # for pickling except (AttributeError, ValueError): def_mod = None - if def_mod != 'typing': - self.__module__ = def_mod - - def __repr__(self): - if self.__covariant__: - prefix = '+' - elif self.__contravariant__: - prefix = '-' - else: - prefix = '~' - return prefix + self.__name__ - - def __reduce__(self): - return self.__name__ - - -def _is_dunder(attr): - return attr.startswith('__') and attr.endswith('__') - + if def_mod != 'typing': + self.__module__ = def_mod + + def __repr__(self): + if self.__covariant__: + prefix = '+' + elif self.__contravariant__: + prefix = '-' + else: + prefix = '~' + return prefix + self.__name__ + + def __reduce__(self): + return self.__name__ + + +def _is_dunder(attr): + return attr.startswith('__') and attr.endswith('__') + class _BaseGenericAlias(_Final, _root=True): - """The central part of internal API. - - This represents a generic version of type 'origin' with type arguments 'params'. - There are two kind of these aliases: user defined and special. The special ones - are wrappers around builtin collections and ABCs in collections.abc. These must - have 'name' always set. If 'inst' is False, then the alias can't be instantiated, - this is used by e.g. typing.List and typing.Dict. - """ + """The central part of internal API. + + This represents a generic version of type 'origin' with type arguments 'params'. + There are two kind of these aliases: user defined and special. The special ones + are wrappers around builtin collections and ABCs in collections.abc. These must + have 'name' always set. If 'inst' is False, then the alias can't be instantiated, + this is used by e.g. typing.List and typing.Dict. + """ def __init__(self, origin, *, inst=True, name=None): - self._inst = inst - self._name = name + self._inst = inst + self._name = name self.__origin__ = origin self.__slots__ = None # This is not documented. @@ -737,15 +737,15 @@ class _BaseGenericAlias(_Final, _root=True): class _GenericAlias(_BaseGenericAlias, _root=True): def __init__(self, origin, params, *, inst=True, name=None): super().__init__(origin, inst=inst, name=name) - if not isinstance(params, tuple): - params = (params,) - self.__args__ = tuple(... if a is _TypingEllipsis else - () if a is _TypingEmpty else - a for a in params) - self.__parameters__ = _collect_type_vars(params) - if not name: - self.__module__ = origin.__module__ - + if not isinstance(params, tuple): + params = (params,) + self.__args__ = tuple(... if a is _TypingEllipsis else + () if a is _TypingEmpty else + a for a in params) + self.__parameters__ = _collect_type_vars(params) + if not name: + self.__module__ = origin.__module__ + def __eq__(self, other): if not isinstance(other, _GenericAlias): return NotImplemented @@ -755,17 +755,17 @@ class _GenericAlias(_BaseGenericAlias, _root=True): def __hash__(self): return hash((self.__origin__, self.__args__)) - @_tp_cache - def __getitem__(self, params): + @_tp_cache + def __getitem__(self, params): if self.__origin__ in (Generic, Protocol): # Can't subscript Generic[...] or Protocol[...]. - raise TypeError(f"Cannot subscript already-subscripted {self}") - if not isinstance(params, tuple): - params = (params,) - msg = "Parameters to generic types must be types." - params = tuple(_type_check(p, msg) for p in params) + raise TypeError(f"Cannot subscript already-subscripted {self}") + if not isinstance(params, tuple): + params = (params,) + msg = "Parameters to generic types must be types." + params = tuple(_type_check(p, msg) for p in params) _check_generic(self, params, len(self.__parameters__)) - + subst = dict(zip(self.__parameters__, params)) new_args = [] for arg in self.__args__: @@ -779,17 +779,17 @@ class _GenericAlias(_BaseGenericAlias, _root=True): new_args.append(arg) return self.copy_with(tuple(new_args)) - def copy_with(self, params): + def copy_with(self, params): return self.__class__(self.__origin__, params, name=self._name, inst=self._inst) - - def __repr__(self): + + def __repr__(self): if self._name: name = 'typing.' + self._name else: name = _type_repr(self.__origin__) args = ", ".join([_type_repr(a) for a in self.__args__]) return f'{name}[{args}]' - + def __reduce__(self): if self._name: origin = globals()[self._name] @@ -799,20 +799,20 @@ class _GenericAlias(_BaseGenericAlias, _root=True): if len(args) == 1 and not isinstance(args[0], tuple): args, = args return operator.getitem, (origin, args) - - def __mro_entries__(self, bases): - if self._name: # generic version of an ABC or built-in class + + def __mro_entries__(self, bases): + if self._name: # generic version of an ABC or built-in class return super().__mro_entries__(bases) - if self.__origin__ is Generic: + if self.__origin__ is Generic: if Protocol in bases: return () - i = bases.index(self) - for b in bases[i+1:]: + i = bases.index(self) + for b in bases[i+1:]: if isinstance(b, _BaseGenericAlias) and b is not self: - return () - return (self.__origin__,) - - + return () + return (self.__origin__,) + + # _nparams is the number of accepted parameters, e.g. 0 for Hashable, # 1 for List and 2 for Dict. It may be -1 if variable number of # parameters are accepted (needs custom __getitem__). @@ -825,9 +825,9 @@ class _SpecialGenericAlias(_BaseGenericAlias, _root=True): self._nparams = nparams if origin.__module__ == 'builtins': self.__doc__ = f'A generic version of {origin.__qualname__}.' - else: + else: self.__doc__ = f'A generic version of {origin.__module__}.{origin.__qualname__}.' - + @_tp_cache def __getitem__(self, params): if not isinstance(params, tuple): @@ -836,7 +836,7 @@ class _SpecialGenericAlias(_BaseGenericAlias, _root=True): params = tuple(_type_check(p, msg) for p in params) _check_generic(self, params, self._nparams) return self.copy_with(params) - + def copy_with(self, params): return _GenericAlias(self.__origin__, params, name=self._name, inst=self._inst) @@ -844,17 +844,17 @@ class _SpecialGenericAlias(_BaseGenericAlias, _root=True): def __repr__(self): return 'typing.' + self._name - def __subclasscheck__(self, cls): + def __subclasscheck__(self, cls): if isinstance(cls, _SpecialGenericAlias): return issubclass(cls.__origin__, self.__origin__) if not isinstance(cls, _GenericAlias): return issubclass(cls, self.__origin__) return super().__subclasscheck__(cls) - - def __reduce__(self): + + def __reduce__(self): return self._name - - + + class _CallableGenericAlias(_GenericAlias, _root=True): def __repr__(self): assert self._name == 'Callable' @@ -863,7 +863,7 @@ class _CallableGenericAlias(_GenericAlias, _root=True): return (f'typing.Callable' f'[[{", ".join([_type_repr(a) for a in self.__args__[:-1]])}], ' f'{_type_repr(self.__args__[-1])}]') - + def __reduce__(self): args = self.__args__ if not (len(args) == 2 and args[0] is ...): @@ -876,22 +876,22 @@ class _CallableType(_SpecialGenericAlias, _root=True): return _CallableGenericAlias(self.__origin__, params, name=self._name, inst=self._inst) - def __getitem__(self, params): - if not isinstance(params, tuple) or len(params) != 2: - raise TypeError("Callable must be used as " - "Callable[[arg, ...], result].") - args, result = params + def __getitem__(self, params): + if not isinstance(params, tuple) or len(params) != 2: + raise TypeError("Callable must be used as " + "Callable[[arg, ...], result].") + args, result = params # This relaxes what args can be on purpose to allow things like # PEP 612 ParamSpec. Responsibility for whether a user is using # Callable[...] properly is deferred to static type checkers. if isinstance(args, list): params = (tuple(args), result) - else: + else: params = (args, result) - return self.__getitem_inner__(params) - - @_tp_cache - def __getitem_inner__(self, params): + return self.__getitem_inner__(params) + + @_tp_cache + def __getitem_inner__(self, params): args, result = params msg = "Callable[args, result]: result must be a type." result = _type_check(result, msg) @@ -902,8 +902,8 @@ class _CallableType(_SpecialGenericAlias, _root=True): args = tuple(_type_convert(arg) for arg in args) params = args + (result,) return self.copy_with(params) - - + + class _TupleType(_SpecialGenericAlias, _root=True): @_tp_cache def __getitem__(self, params): @@ -958,98 +958,98 @@ class _LiteralGenericAlias(_GenericAlias, _root=True): return hash(frozenset(_value_and_type_iter(self.__args__))) -class Generic: - """Abstract base class for generic types. - - A generic type is typically declared by inheriting from - this class parameterized with one or more type variables. - For example, a generic mapping type might be defined as:: - - class Mapping(Generic[KT, VT]): - def __getitem__(self, key: KT) -> VT: - ... - # Etc. - - This class can then be used as follows:: - - def lookup_name(mapping: Mapping[KT, VT], key: KT, default: VT) -> VT: - try: - return mapping[key] - except KeyError: - return default - """ - __slots__ = () +class Generic: + """Abstract base class for generic types. + + A generic type is typically declared by inheriting from + this class parameterized with one or more type variables. + For example, a generic mapping type might be defined as:: + + class Mapping(Generic[KT, VT]): + def __getitem__(self, key: KT) -> VT: + ... + # Etc. + + This class can then be used as follows:: + + def lookup_name(mapping: Mapping[KT, VT], key: KT, default: VT) -> VT: + try: + return mapping[key] + except KeyError: + return default + """ + __slots__ = () _is_protocol = False - - @_tp_cache - def __class_getitem__(cls, params): - if not isinstance(params, tuple): - params = (params,) - if not params and cls is not Tuple: - raise TypeError( - f"Parameter list to {cls.__qualname__}[...] cannot be empty") - msg = "Parameters to generic types must be types." - params = tuple(_type_check(p, msg) for p in params) + + @_tp_cache + def __class_getitem__(cls, params): + if not isinstance(params, tuple): + params = (params,) + if not params and cls is not Tuple: + raise TypeError( + f"Parameter list to {cls.__qualname__}[...] cannot be empty") + msg = "Parameters to generic types must be types." + params = tuple(_type_check(p, msg) for p in params) if cls in (Generic, Protocol): # Generic and Protocol can only be subscripted with unique type variables. - if not all(isinstance(p, TypeVar) for p in params): - raise TypeError( + if not all(isinstance(p, TypeVar) for p in params): + raise TypeError( f"Parameters to {cls.__name__}[...] must all be type variables") - if len(set(params)) != len(params): - raise TypeError( + if len(set(params)) != len(params): + raise TypeError( f"Parameters to {cls.__name__}[...] must all be unique") - else: - # Subscripting a regular Generic subclass. + else: + # Subscripting a regular Generic subclass. _check_generic(cls, params, len(cls.__parameters__)) - return _GenericAlias(cls, params) - - def __init_subclass__(cls, *args, **kwargs): - super().__init_subclass__(*args, **kwargs) - tvars = [] - if '__orig_bases__' in cls.__dict__: - error = Generic in cls.__orig_bases__ - else: + return _GenericAlias(cls, params) + + def __init_subclass__(cls, *args, **kwargs): + super().__init_subclass__(*args, **kwargs) + tvars = [] + if '__orig_bases__' in cls.__dict__: + error = Generic in cls.__orig_bases__ + else: error = Generic in cls.__bases__ and cls.__name__ != 'Protocol' - if error: - raise TypeError("Cannot inherit from plain Generic") - if '__orig_bases__' in cls.__dict__: - tvars = _collect_type_vars(cls.__orig_bases__) - # Look for Generic[T1, ..., Tn]. - # If found, tvars must be a subset of it. - # If not found, tvars is it. - # Also check for and reject plain Generic, - # and reject multiple Generic[...]. - gvars = None - for base in cls.__orig_bases__: - if (isinstance(base, _GenericAlias) and - base.__origin__ is Generic): - if gvars is not None: - raise TypeError( - "Cannot inherit from Generic[...] multiple types.") - gvars = base.__parameters__ + if error: + raise TypeError("Cannot inherit from plain Generic") + if '__orig_bases__' in cls.__dict__: + tvars = _collect_type_vars(cls.__orig_bases__) + # Look for Generic[T1, ..., Tn]. + # If found, tvars must be a subset of it. + # If not found, tvars is it. + # Also check for and reject plain Generic, + # and reject multiple Generic[...]. + gvars = None + for base in cls.__orig_bases__: + if (isinstance(base, _GenericAlias) and + base.__origin__ is Generic): + if gvars is not None: + raise TypeError( + "Cannot inherit from Generic[...] multiple types.") + gvars = base.__parameters__ if gvars is not None: - tvarset = set(tvars) - gvarset = set(gvars) - if not tvarset <= gvarset: - s_vars = ', '.join(str(t) for t in tvars if t not in gvarset) - s_args = ', '.join(str(g) for g in gvars) - raise TypeError(f"Some type variables ({s_vars}) are" - f" not listed in Generic[{s_args}]") - tvars = gvars - cls.__parameters__ = tuple(tvars) - - -class _TypingEmpty: - """Internal placeholder for () or []. Used by TupleMeta and CallableMeta - to allow empty list/tuple in specific places, without allowing them - to sneak in where prohibited. - """ - - -class _TypingEllipsis: - """Internal placeholder for ... (ellipsis).""" - - + tvarset = set(tvars) + gvarset = set(gvars) + if not tvarset <= gvarset: + s_vars = ', '.join(str(t) for t in tvars if t not in gvarset) + s_args = ', '.join(str(g) for g in gvars) + raise TypeError(f"Some type variables ({s_vars}) are" + f" not listed in Generic[{s_args}]") + tvars = gvars + cls.__parameters__ = tuple(tvars) + + +class _TypingEmpty: + """Internal placeholder for () or []. Used by TupleMeta and CallableMeta + to allow empty list/tuple in specific places, without allowing them + to sneak in where prohibited. + """ + + +class _TypingEllipsis: + """Internal placeholder for ... (ellipsis).""" + + _TYPING_INTERNALS = ['__parameters__', '__orig_bases__', '__orig_class__', '_is_protocol', '_is_runtime_protocol'] @@ -1371,121 +1371,121 @@ def runtime_checkable(cls): return cls -def cast(typ, val): - """Cast a value to a type. - - This returns the value unchanged. To the type checker this - signals that the return value has the designated type, but at - runtime we intentionally don't check anything (we want this - to be as fast as possible). - """ - return val - - -def _get_defaults(func): - """Internal helper to extract the default arguments, by name.""" - try: - code = func.__code__ - except AttributeError: - # Some built-in functions don't have __code__, __defaults__, etc. - return {} - pos_count = code.co_argcount - arg_names = code.co_varnames - arg_names = arg_names[:pos_count] - defaults = func.__defaults__ or () - kwdefaults = func.__kwdefaults__ - res = dict(kwdefaults) if kwdefaults else {} - pos_offset = pos_count - len(defaults) - for name, value in zip(arg_names[pos_offset:], defaults): - assert name not in res - res[name] = value - return res - - -_allowed_types = (types.FunctionType, types.BuiltinFunctionType, - types.MethodType, types.ModuleType, - WrapperDescriptorType, MethodWrapperType, MethodDescriptorType) - - +def cast(typ, val): + """Cast a value to a type. + + This returns the value unchanged. To the type checker this + signals that the return value has the designated type, but at + runtime we intentionally don't check anything (we want this + to be as fast as possible). + """ + return val + + +def _get_defaults(func): + """Internal helper to extract the default arguments, by name.""" + try: + code = func.__code__ + except AttributeError: + # Some built-in functions don't have __code__, __defaults__, etc. + return {} + pos_count = code.co_argcount + arg_names = code.co_varnames + arg_names = arg_names[:pos_count] + defaults = func.__defaults__ or () + kwdefaults = func.__kwdefaults__ + res = dict(kwdefaults) if kwdefaults else {} + pos_offset = pos_count - len(defaults) + for name, value in zip(arg_names[pos_offset:], defaults): + assert name not in res + res[name] = value + return res + + +_allowed_types = (types.FunctionType, types.BuiltinFunctionType, + types.MethodType, types.ModuleType, + WrapperDescriptorType, MethodWrapperType, MethodDescriptorType) + + def get_type_hints(obj, globalns=None, localns=None, include_extras=False): - """Return type hints for an object. - - This is often the same as obj.__annotations__, but it handles + """Return type hints for an object. + + This is often the same as obj.__annotations__, but it handles forward references encoded as string literals, adds Optional[t] if a default value equal to None is set and recursively replaces all 'Annotated[T, ...]' with 'T' (unless 'include_extras=True'). - - The argument may be a module, class, method, or function. The annotations - are returned as a dictionary. For classes, annotations include also - inherited members. - - TypeError is raised if the argument is not of a type that can contain - annotations, and an empty dictionary is returned if no annotations are - present. - - BEWARE -- the behavior of globalns and localns is counterintuitive - (unless you are familiar with how eval() and exec() work). The - search order is locals first, then globals. - - - If no dict arguments are passed, an attempt is made to use the - globals from obj (or the respective module's globals for classes), - and these are also used as the locals. If the object does not appear - to have globals, an empty dictionary is used. - - - If one dict argument is passed, it is used for both globals and - locals. - - - If two dict arguments are passed, they specify globals and - locals, respectively. - """ - - if getattr(obj, '__no_type_check__', None): - return {} - # Classes require a special treatment. - if isinstance(obj, type): - hints = {} - for base in reversed(obj.__mro__): - if globalns is None: - base_globals = sys.modules[base.__module__].__dict__ - else: - base_globals = globalns - ann = base.__dict__.get('__annotations__', {}) - for name, value in ann.items(): - if value is None: - value = type(None) - if isinstance(value, str): + + The argument may be a module, class, method, or function. The annotations + are returned as a dictionary. For classes, annotations include also + inherited members. + + TypeError is raised if the argument is not of a type that can contain + annotations, and an empty dictionary is returned if no annotations are + present. + + BEWARE -- the behavior of globalns and localns is counterintuitive + (unless you are familiar with how eval() and exec() work). The + search order is locals first, then globals. + + - If no dict arguments are passed, an attempt is made to use the + globals from obj (or the respective module's globals for classes), + and these are also used as the locals. If the object does not appear + to have globals, an empty dictionary is used. + + - If one dict argument is passed, it is used for both globals and + locals. + + - If two dict arguments are passed, they specify globals and + locals, respectively. + """ + + if getattr(obj, '__no_type_check__', None): + return {} + # Classes require a special treatment. + if isinstance(obj, type): + hints = {} + for base in reversed(obj.__mro__): + if globalns is None: + base_globals = sys.modules[base.__module__].__dict__ + else: + base_globals = globalns + ann = base.__dict__.get('__annotations__', {}) + for name, value in ann.items(): + if value is None: + value = type(None) + if isinstance(value, str): value = ForwardRef(value, is_argument=False, is_class=True) - value = _eval_type(value, base_globals, localns) - hints[name] = value + value = _eval_type(value, base_globals, localns) + hints[name] = value return hints if include_extras else {k: _strip_annotations(t) for k, t in hints.items()} - - if globalns is None: - if isinstance(obj, types.ModuleType): - globalns = obj.__dict__ - else: + + if globalns is None: + if isinstance(obj, types.ModuleType): + globalns = obj.__dict__ + else: nsobj = obj # Find globalns for the unwrapped object. while hasattr(nsobj, '__wrapped__'): nsobj = nsobj.__wrapped__ globalns = getattr(nsobj, '__globals__', {}) - if localns is None: - localns = globalns - elif localns is None: - localns = globalns - hints = getattr(obj, '__annotations__', None) - if hints is None: - # Return empty annotations for something that _could_ have them. - if isinstance(obj, _allowed_types): - return {} - else: - raise TypeError('{!r} is not a module, class, method, ' - 'or function.'.format(obj)) - defaults = _get_defaults(obj) - hints = dict(hints) - for name, value in hints.items(): - if value is None: - value = type(None) - if isinstance(value, str): + if localns is None: + localns = globalns + elif localns is None: + localns = globalns + hints = getattr(obj, '__annotations__', None) + if hints is None: + # Return empty annotations for something that _could_ have them. + if isinstance(obj, _allowed_types): + return {} + else: + raise TypeError('{!r} is not a module, class, method, ' + 'or function.'.format(obj)) + defaults = _get_defaults(obj) + hints = dict(hints) + for name, value in hints.items(): + if value is None: + value = type(None) + if isinstance(value, str): # class-level forward refs were handled above, this must be either # a module-level annotation or a function argument annotation value = ForwardRef( @@ -1493,13 +1493,13 @@ def get_type_hints(obj, globalns=None, localns=None, include_extras=False): is_argument=not isinstance(obj, types.ModuleType), is_class=False, ) - value = _eval_type(value, globalns, localns) - if name in defaults and defaults[name] is None: - value = Optional[value] - hints[name] = value + value = _eval_type(value, globalns, localns) + if name in defaults and defaults[name] is None: + value = Optional[value] + hints[name] = value return hints if include_extras else {k: _strip_annotations(t) for k, t in hints.items()} - - + + def _strip_annotations(t): """Strips the annotations from a given type. """ @@ -1562,93 +1562,93 @@ def get_args(tp): return () -def no_type_check(arg): - """Decorator to indicate that annotations are not type hints. - - The argument must be a class or function; if it is a class, it - applies recursively to all methods and classes defined in that class - (but not to methods defined in its superclasses or subclasses). - - This mutates the function(s) or class(es) in place. - """ - if isinstance(arg, type): - arg_attrs = arg.__dict__.copy() - for attr, val in arg.__dict__.items(): - if val in arg.__bases__ + (arg,): - arg_attrs.pop(attr) - for obj in arg_attrs.values(): - if isinstance(obj, types.FunctionType): - obj.__no_type_check__ = True - if isinstance(obj, type): - no_type_check(obj) - try: - arg.__no_type_check__ = True - except TypeError: # built-in classes - pass - return arg - - -def no_type_check_decorator(decorator): - """Decorator to give another decorator the @no_type_check effect. - - This wraps the decorator with something that wraps the decorated - function in @no_type_check. - """ - - @functools.wraps(decorator) - def wrapped_decorator(*args, **kwds): - func = decorator(*args, **kwds) - func = no_type_check(func) - return func - - return wrapped_decorator - - -def _overload_dummy(*args, **kwds): - """Helper for @overload to raise when called.""" - raise NotImplementedError( - "You should not call an overloaded function. " - "A series of @overload-decorated functions " - "outside a stub module should always be followed " - "by an implementation that is not @overload-ed.") - - -def overload(func): - """Decorator for overloaded functions/methods. - - In a stub file, place two or more stub definitions for the same - function in a row, each decorated with @overload. For example: - - @overload - def utf8(value: None) -> None: ... - @overload - def utf8(value: bytes) -> bytes: ... - @overload - def utf8(value: str) -> bytes: ... - - In a non-stub file (i.e. a regular .py file), do the same but - follow it with an implementation. The implementation should *not* - be decorated with @overload. For example: - - @overload - def utf8(value: None) -> None: ... - @overload - def utf8(value: bytes) -> bytes: ... - @overload - def utf8(value: str) -> bytes: ... - def utf8(value): - # implementation goes here - """ - return _overload_dummy - - +def no_type_check(arg): + """Decorator to indicate that annotations are not type hints. + + The argument must be a class or function; if it is a class, it + applies recursively to all methods and classes defined in that class + (but not to methods defined in its superclasses or subclasses). + + This mutates the function(s) or class(es) in place. + """ + if isinstance(arg, type): + arg_attrs = arg.__dict__.copy() + for attr, val in arg.__dict__.items(): + if val in arg.__bases__ + (arg,): + arg_attrs.pop(attr) + for obj in arg_attrs.values(): + if isinstance(obj, types.FunctionType): + obj.__no_type_check__ = True + if isinstance(obj, type): + no_type_check(obj) + try: + arg.__no_type_check__ = True + except TypeError: # built-in classes + pass + return arg + + +def no_type_check_decorator(decorator): + """Decorator to give another decorator the @no_type_check effect. + + This wraps the decorator with something that wraps the decorated + function in @no_type_check. + """ + + @functools.wraps(decorator) + def wrapped_decorator(*args, **kwds): + func = decorator(*args, **kwds) + func = no_type_check(func) + return func + + return wrapped_decorator + + +def _overload_dummy(*args, **kwds): + """Helper for @overload to raise when called.""" + raise NotImplementedError( + "You should not call an overloaded function. " + "A series of @overload-decorated functions " + "outside a stub module should always be followed " + "by an implementation that is not @overload-ed.") + + +def overload(func): + """Decorator for overloaded functions/methods. + + In a stub file, place two or more stub definitions for the same + function in a row, each decorated with @overload. For example: + + @overload + def utf8(value: None) -> None: ... + @overload + def utf8(value: bytes) -> bytes: ... + @overload + def utf8(value: str) -> bytes: ... + + In a non-stub file (i.e. a regular .py file), do the same but + follow it with an implementation. The implementation should *not* + be decorated with @overload. For example: + + @overload + def utf8(value: None) -> None: ... + @overload + def utf8(value: bytes) -> bytes: ... + @overload + def utf8(value: str) -> bytes: ... + def utf8(value): + # implementation goes here + """ + return _overload_dummy + + def final(f): """A decorator to indicate final methods and final classes. - + Use this decorator to indicate to type checkers that the decorated method cannot be overridden, and decorated class cannot be subclassed. For example: - + class Base: @final def done(self) -> None: @@ -1656,38 +1656,38 @@ def final(f): class Sub(Base): def done(self) -> None: # Error reported by type checker ... - + @final class Leaf: ... class Other(Leaf): # Error reported by type checker ... - + There is no runtime checking of these properties. - """ + """ return f - - -# Some unconstrained type variables. These are used by the container types. -# (These are not for export.) -T = TypeVar('T') # Any type. -KT = TypeVar('KT') # Key type. -VT = TypeVar('VT') # Value type. -T_co = TypeVar('T_co', covariant=True) # Any type covariant containers. -V_co = TypeVar('V_co', covariant=True) # Any type covariant containers. -VT_co = TypeVar('VT_co', covariant=True) # Value type covariant containers. -T_contra = TypeVar('T_contra', contravariant=True) # Ditto contravariant. -# Internal type variable used for Type[]. -CT_co = TypeVar('CT_co', covariant=True, bound=type) - -# A useful type variable with constraints. This represents string types. -# (This one *is* for export!) -AnyStr = TypeVar('AnyStr', bytes, str) - - -# Various ABCs mimicking those in collections.abc. + + +# Some unconstrained type variables. These are used by the container types. +# (These are not for export.) +T = TypeVar('T') # Any type. +KT = TypeVar('KT') # Key type. +VT = TypeVar('VT') # Value type. +T_co = TypeVar('T_co', covariant=True) # Any type covariant containers. +V_co = TypeVar('V_co', covariant=True) # Any type covariant containers. +VT_co = TypeVar('VT_co', covariant=True) # Value type covariant containers. +T_contra = TypeVar('T_contra', contravariant=True) # Ditto contravariant. +# Internal type variable used for Type[]. +CT_co = TypeVar('CT_co', covariant=True, bound=type) + +# A useful type variable with constraints. This represents string types. +# (This one *is* for export!) +AnyStr = TypeVar('AnyStr', bytes, str) + + +# Various ABCs mimicking those in collections.abc. _alias = _SpecialGenericAlias - + Hashable = _alias(collections.abc.Hashable, 0) # Not generic. Awaitable = _alias(collections.abc.Awaitable, 1) Coroutine = _alias(collections.abc.Coroutine, 3) @@ -1700,19 +1700,19 @@ Sized = _alias(collections.abc.Sized, 0) # Not generic. Container = _alias(collections.abc.Container, 1) Collection = _alias(collections.abc.Collection, 1) Callable = _CallableType(collections.abc.Callable, 2) -Callable.__doc__ = \ - """Callable type; Callable[[int], str] is a function of (int) -> str. - - The subscription syntax must always be used with exactly two - values: the argument list and the return type. The argument list - must be a list of types or ellipsis; the return type must be a single type. - - There is no syntax to indicate optional or keyword arguments, - such function types are rarely used as callback types. - """ +Callable.__doc__ = \ + """Callable type; Callable[[int], str] is a function of (int) -> str. + + The subscription syntax must always be used with exactly two + values: the argument list and the return type. The argument list + must be a list of types or ellipsis; the return type must be a single type. + + There is no syntax to indicate optional or keyword arguments, + such function types are rarely used as callback types. + """ AbstractSet = _alias(collections.abc.Set, 1, name='AbstractSet') MutableSet = _alias(collections.abc.MutableSet, 1) -# NOTE: Mapping is only covariant in the value type. +# NOTE: Mapping is only covariant in the value type. Mapping = _alias(collections.abc.Mapping, 2) MutableMapping = _alias(collections.abc.MutableMapping, 2) Sequence = _alias(collections.abc.Sequence, 1) @@ -1720,15 +1720,15 @@ MutableSequence = _alias(collections.abc.MutableSequence, 1) ByteString = _alias(collections.abc.ByteString, 0) # Not generic # Tuple accepts variable number of parameters. Tuple = _TupleType(tuple, -1, inst=False, name='Tuple') -Tuple.__doc__ = \ - """Tuple type; Tuple[X, Y] is the cross-product type of X and Y. - - Example: Tuple[T1, T2] is a tuple of two elements corresponding - to type variables T1 and T2. Tuple[int, float, str] is a tuple - of an int, a float and a string. - - To specify a variable-length tuple of homogeneous type, use Tuple[T, ...]. - """ +Tuple.__doc__ = \ + """Tuple type; Tuple[X, Y] is the cross-product type of X and Y. + + Example: Tuple[T1, T2] is a tuple of two elements corresponding + to type variables T1 and T2. Tuple[int, float, str] is a tuple + of an int, a float and a string. + + To specify a variable-length tuple of homogeneous type, use Tuple[T, ...]. + """ List = _alias(list, 1, inst=False, name='List') Deque = _alias(collections.deque, 1, name='Deque') Set = _alias(set, 1, inst=False, name='Set') @@ -1747,71 +1747,71 @@ ChainMap = _alias(collections.ChainMap, 2) Generator = _alias(collections.abc.Generator, 3) AsyncGenerator = _alias(collections.abc.AsyncGenerator, 2) Type = _alias(type, 1, inst=False, name='Type') -Type.__doc__ = \ - """A special construct usable to annotate class objects. - - For example, suppose we have the following classes:: - - class User: ... # Abstract base for User classes - class BasicUser(User): ... - class ProUser(User): ... - class TeamUser(User): ... - - And a function that takes a class argument that's a subclass of - User and returns an instance of the corresponding class:: - - U = TypeVar('U', bound=User) - def new_user(user_class: Type[U]) -> U: - user = user_class() - # (Here we could write the user object to a database) - return user - - joe = new_user(BasicUser) - - At this point the type checker knows that joe has type BasicUser. - """ - - +Type.__doc__ = \ + """A special construct usable to annotate class objects. + + For example, suppose we have the following classes:: + + class User: ... # Abstract base for User classes + class BasicUser(User): ... + class ProUser(User): ... + class TeamUser(User): ... + + And a function that takes a class argument that's a subclass of + User and returns an instance of the corresponding class:: + + U = TypeVar('U', bound=User) + def new_user(user_class: Type[U]) -> U: + user = user_class() + # (Here we could write the user object to a database) + return user + + joe = new_user(BasicUser) + + At this point the type checker knows that joe has type BasicUser. + """ + + @runtime_checkable class SupportsInt(Protocol): """An ABC with one abstract method __int__.""" - __slots__ = () - - @abstractmethod - def __int__(self) -> int: - pass - - + __slots__ = () + + @abstractmethod + def __int__(self) -> int: + pass + + @runtime_checkable class SupportsFloat(Protocol): """An ABC with one abstract method __float__.""" - __slots__ = () - - @abstractmethod - def __float__(self) -> float: - pass - - + __slots__ = () + + @abstractmethod + def __float__(self) -> float: + pass + + @runtime_checkable class SupportsComplex(Protocol): """An ABC with one abstract method __complex__.""" - __slots__ = () - - @abstractmethod - def __complex__(self) -> complex: - pass - - + __slots__ = () + + @abstractmethod + def __complex__(self) -> complex: + pass + + @runtime_checkable class SupportsBytes(Protocol): """An ABC with one abstract method __bytes__.""" - __slots__ = () - - @abstractmethod - def __bytes__(self) -> bytes: - pass - - + __slots__ = () + + @abstractmethod + def __bytes__(self) -> bytes: + pass + + @runtime_checkable class SupportsIndex(Protocol): """An ABC with one abstract method __index__.""" @@ -1825,23 +1825,23 @@ class SupportsIndex(Protocol): @runtime_checkable class SupportsAbs(Protocol[T_co]): """An ABC with one abstract method __abs__ that is covariant in its return type.""" - __slots__ = () - - @abstractmethod - def __abs__(self) -> T_co: - pass - - + __slots__ = () + + @abstractmethod + def __abs__(self) -> T_co: + pass + + @runtime_checkable class SupportsRound(Protocol[T_co]): """An ABC with one abstract method __round__ that is covariant in its return type.""" - __slots__ = () - - @abstractmethod - def __round__(self, ndigits: int = 0) -> T_co: - pass - - + __slots__ = () + + @abstractmethod + def __round__(self, ndigits: int = 0) -> T_co: + pass + + def _make_nmtuple(name, types, module, defaults = ()): fields = [n for n, t in types] types = {n: _type_check(t, f"field {n} annotation must be a type") @@ -1849,25 +1849,25 @@ def _make_nmtuple(name, types, module, defaults = ()): nm_tpl = collections.namedtuple(name, fields, defaults=defaults, module=module) nm_tpl.__annotations__ = nm_tpl.__new__.__annotations__ = types - return nm_tpl - - -# attributes prohibited to set in NamedTuple class syntax + return nm_tpl + + +# attributes prohibited to set in NamedTuple class syntax _prohibited = frozenset({'__new__', '__init__', '__slots__', '__getnewargs__', '_fields', '_field_defaults', '_make', '_replace', '_asdict', '_source'}) - + _special = frozenset({'__module__', '__name__', '__annotations__'}) - - -class NamedTupleMeta(type): - - def __new__(cls, typename, bases, ns): + + +class NamedTupleMeta(type): + + def __new__(cls, typename, bases, ns): assert bases[0] is _NamedTuple - types = ns.get('__annotations__', {}) + types = ns.get('__annotations__', {}) default_names = [] - for field_name in types: - if field_name in ns: + for field_name in types: + if field_name in ns: default_names.append(field_name) elif default_names: raise TypeError(f"Non-default namedtuple field {field_name} " @@ -1877,39 +1877,39 @@ class NamedTupleMeta(type): nm_tpl = _make_nmtuple(typename, types.items(), defaults=[ns[n] for n in default_names], module=ns['__module__']) - # update from user namespace without overriding special namedtuple attributes - for key in ns: - if key in _prohibited: - raise AttributeError("Cannot overwrite NamedTuple attribute " + key) - elif key not in _special and key not in nm_tpl._fields: - setattr(nm_tpl, key, ns[key]) - return nm_tpl - - + # update from user namespace without overriding special namedtuple attributes + for key in ns: + if key in _prohibited: + raise AttributeError("Cannot overwrite NamedTuple attribute " + key) + elif key not in _special and key not in nm_tpl._fields: + setattr(nm_tpl, key, ns[key]) + return nm_tpl + + def NamedTuple(typename, fields=None, /, **kwargs): - """Typed version of namedtuple. - - Usage in Python versions >= 3.6:: - - class Employee(NamedTuple): - name: str - id: int - - This is equivalent to:: - - Employee = collections.namedtuple('Employee', ['name', 'id']) - + """Typed version of namedtuple. + + Usage in Python versions >= 3.6:: + + class Employee(NamedTuple): + name: str + id: int + + This is equivalent to:: + + Employee = collections.namedtuple('Employee', ['name', 'id']) + The resulting class has an extra __annotations__ attribute, giving a dict that maps field names to types. (The field names are also in the _fields attribute, which is part of the namedtuple API.) Alternative equivalent keyword syntax is also accepted:: - - Employee = NamedTuple('Employee', name=str, id=int) - - In Python versions <= 3.5 use:: - - Employee = NamedTuple('Employee', [('name', str), ('id', int)]) - """ + + Employee = NamedTuple('Employee', name=str, id=int) + + In Python versions <= 3.5 use:: + + Employee = NamedTuple('Employee', [('name', str), ('id', int)]) + """ if fields is None: fields = kwargs.items() elif kwargs: @@ -2046,211 +2046,211 @@ _TypedDict = type.__new__(_TypedDictMeta, 'TypedDict', (), {}) TypedDict.__mro_entries__ = lambda bases: (_TypedDict,) -def NewType(name, tp): - """NewType creates simple unique types with almost zero - runtime overhead. NewType(name, tp) is considered a subtype of tp - by static type checkers. At runtime, NewType(name, tp) returns - a dummy function that simply returns its argument. Usage:: - - UserId = NewType('UserId', int) - - def name_by_id(user_id: UserId) -> str: - ... - - UserId('user') # Fails type check - - name_by_id(42) # Fails type check - name_by_id(UserId(42)) # OK - - num = UserId(5) + 1 # type: int - """ - - def new_type(x): - return x - - new_type.__name__ = name - new_type.__supertype__ = tp - return new_type - - -# Python-version-specific alias (Python 2: unicode; Python 3: str) -Text = str - - -# Constant that's True when type checking, but False here. -TYPE_CHECKING = False - - -class IO(Generic[AnyStr]): - """Generic base class for TextIO and BinaryIO. - - This is an abstract, generic version of the return of open(). - - NOTE: This does not distinguish between the different possible - classes (text vs. binary, read vs. write vs. read/write, - append-only, unbuffered). The TextIO and BinaryIO subclasses - below capture the distinctions between text vs. binary, which is - pervasive in the interface; however we currently do not offer a - way to track the other distinctions in the type system. - """ - - __slots__ = () - +def NewType(name, tp): + """NewType creates simple unique types with almost zero + runtime overhead. NewType(name, tp) is considered a subtype of tp + by static type checkers. At runtime, NewType(name, tp) returns + a dummy function that simply returns its argument. Usage:: + + UserId = NewType('UserId', int) + + def name_by_id(user_id: UserId) -> str: + ... + + UserId('user') # Fails type check + + name_by_id(42) # Fails type check + name_by_id(UserId(42)) # OK + + num = UserId(5) + 1 # type: int + """ + + def new_type(x): + return x + + new_type.__name__ = name + new_type.__supertype__ = tp + return new_type + + +# Python-version-specific alias (Python 2: unicode; Python 3: str) +Text = str + + +# Constant that's True when type checking, but False here. +TYPE_CHECKING = False + + +class IO(Generic[AnyStr]): + """Generic base class for TextIO and BinaryIO. + + This is an abstract, generic version of the return of open(). + + NOTE: This does not distinguish between the different possible + classes (text vs. binary, read vs. write vs. read/write, + append-only, unbuffered). The TextIO and BinaryIO subclasses + below capture the distinctions between text vs. binary, which is + pervasive in the interface; however we currently do not offer a + way to track the other distinctions in the type system. + """ + + __slots__ = () + @property @abstractmethod - def mode(self) -> str: - pass - + def mode(self) -> str: + pass + @property @abstractmethod - def name(self) -> str: - pass - - @abstractmethod - def close(self) -> None: - pass - + def name(self) -> str: + pass + + @abstractmethod + def close(self) -> None: + pass + @property @abstractmethod - def closed(self) -> bool: - pass - - @abstractmethod - def fileno(self) -> int: - pass - - @abstractmethod - def flush(self) -> None: - pass - - @abstractmethod - def isatty(self) -> bool: - pass - - @abstractmethod - def read(self, n: int = -1) -> AnyStr: - pass - - @abstractmethod - def readable(self) -> bool: - pass - - @abstractmethod - def readline(self, limit: int = -1) -> AnyStr: - pass - - @abstractmethod - def readlines(self, hint: int = -1) -> List[AnyStr]: - pass - - @abstractmethod - def seek(self, offset: int, whence: int = 0) -> int: - pass - - @abstractmethod - def seekable(self) -> bool: - pass - - @abstractmethod - def tell(self) -> int: - pass - - @abstractmethod - def truncate(self, size: int = None) -> int: - pass - - @abstractmethod - def writable(self) -> bool: - pass - - @abstractmethod - def write(self, s: AnyStr) -> int: - pass - - @abstractmethod - def writelines(self, lines: List[AnyStr]) -> None: - pass - - @abstractmethod - def __enter__(self) -> 'IO[AnyStr]': - pass - - @abstractmethod - def __exit__(self, type, value, traceback) -> None: - pass - - -class BinaryIO(IO[bytes]): - """Typed version of the return of open() in binary mode.""" - - __slots__ = () - - @abstractmethod - def write(self, s: Union[bytes, bytearray]) -> int: - pass - - @abstractmethod - def __enter__(self) -> 'BinaryIO': - pass - - -class TextIO(IO[str]): - """Typed version of the return of open() in text mode.""" - - __slots__ = () - + def closed(self) -> bool: + pass + + @abstractmethod + def fileno(self) -> int: + pass + + @abstractmethod + def flush(self) -> None: + pass + + @abstractmethod + def isatty(self) -> bool: + pass + + @abstractmethod + def read(self, n: int = -1) -> AnyStr: + pass + + @abstractmethod + def readable(self) -> bool: + pass + + @abstractmethod + def readline(self, limit: int = -1) -> AnyStr: + pass + + @abstractmethod + def readlines(self, hint: int = -1) -> List[AnyStr]: + pass + + @abstractmethod + def seek(self, offset: int, whence: int = 0) -> int: + pass + + @abstractmethod + def seekable(self) -> bool: + pass + + @abstractmethod + def tell(self) -> int: + pass + + @abstractmethod + def truncate(self, size: int = None) -> int: + pass + + @abstractmethod + def writable(self) -> bool: + pass + + @abstractmethod + def write(self, s: AnyStr) -> int: + pass + + @abstractmethod + def writelines(self, lines: List[AnyStr]) -> None: + pass + + @abstractmethod + def __enter__(self) -> 'IO[AnyStr]': + pass + + @abstractmethod + def __exit__(self, type, value, traceback) -> None: + pass + + +class BinaryIO(IO[bytes]): + """Typed version of the return of open() in binary mode.""" + + __slots__ = () + + @abstractmethod + def write(self, s: Union[bytes, bytearray]) -> int: + pass + + @abstractmethod + def __enter__(self) -> 'BinaryIO': + pass + + +class TextIO(IO[str]): + """Typed version of the return of open() in text mode.""" + + __slots__ = () + @property @abstractmethod - def buffer(self) -> BinaryIO: - pass - + def buffer(self) -> BinaryIO: + pass + @property @abstractmethod - def encoding(self) -> str: - pass - + def encoding(self) -> str: + pass + @property @abstractmethod - def errors(self) -> Optional[str]: - pass - + def errors(self) -> Optional[str]: + pass + @property @abstractmethod - def line_buffering(self) -> bool: - pass - + def line_buffering(self) -> bool: + pass + @property @abstractmethod - def newlines(self) -> Any: - pass - - @abstractmethod - def __enter__(self) -> 'TextIO': - pass - - -class io: - """Wrapper namespace for IO generic classes.""" - - __all__ = ['IO', 'TextIO', 'BinaryIO'] - IO = IO - TextIO = TextIO - BinaryIO = BinaryIO - - -io.__name__ = __name__ + '.io' -sys.modules[io.__name__] = io - + def newlines(self) -> Any: + pass + + @abstractmethod + def __enter__(self) -> 'TextIO': + pass + + +class io: + """Wrapper namespace for IO generic classes.""" + + __all__ = ['IO', 'TextIO', 'BinaryIO'] + IO = IO + TextIO = TextIO + BinaryIO = BinaryIO + + +io.__name__ = __name__ + '.io' +sys.modules[io.__name__] = io + Pattern = _alias(stdlib_re.Pattern, 1) Match = _alias(stdlib_re.Match, 1) - -class re: - """Wrapper namespace for re type aliases.""" - - __all__ = ['Pattern', 'Match'] - Pattern = Pattern - Match = Match - - -re.__name__ = __name__ + '.re' -sys.modules[re.__name__] = re + +class re: + """Wrapper namespace for re type aliases.""" + + __all__ = ['Pattern', 'Match'] + Pattern = Pattern + Match = Match + + +re.__name__ = __name__ + '.re' +sys.modules[re.__name__] = re |
