123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283 |
- import abc
- import typing
- from typing import ( # noqa
- # These are imported for re-export.
- ClassVar, Type, Generic, Callable, GenericMeta, TypingMeta,
- Counter, DefaultDict, Deque, TypeVar, Tuple, Final, final,
- NewType, overload, Text, TYPE_CHECKING, Literal, TypedDict, Protocol,
- SupportsIndex,
- runtime_checkable,
- # We use internal typing helpers here, but this significantly reduces
- # code duplication. (Also this is only until Protocol is in typing.)
- _type_vars, _tp_cache, _type_check,
- )
- # Please keep __all__ alphabetized within each category.
- __all__ = [
- # Super-special typing primitives.
- 'ClassVar',
- 'Final',
- 'Protocol',
- 'Type',
- 'TypedDict',
- # Concrete collection types.
- 'ContextManager',
- 'Counter',
- 'Deque',
- 'DefaultDict',
- # Structural checks, a.k.a. protocols.
- 'SupportsIndex',
- # One-off things.
- 'final',
- 'IntVar',
- 'Literal',
- 'NewType',
- 'overload',
- 'runtime_checkable',
- 'Text',
- 'TYPE_CHECKING',
- ]
- if hasattr(typing, 'NoReturn'):
- NoReturn = typing.NoReturn
- else:
- # TODO: Remove once typing.py has been updated
- class _NoReturnMeta(typing.TypingMeta):
- """Metaclass for NoReturn."""
- def __new__(cls, name, bases, namespace):
- cls.assert_no_subclassing(bases)
- self = super(_NoReturnMeta, cls).__new__(cls, name, bases, namespace)
- return self
- class _NoReturn(typing._FinalTypingBase):
- """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.
- """
- __metaclass__ = _NoReturnMeta
- __slots__ = ()
- def __instancecheck__(self, obj):
- raise TypeError("NoReturn cannot be used with isinstance().")
- def __subclasscheck__(self, cls):
- raise TypeError("NoReturn cannot be used with issubclass().")
- NoReturn = _NoReturn(_root=True)
- T_co = typing.TypeVar('T_co', covariant=True)
- if hasattr(typing, 'ContextManager'):
- ContextManager = typing.ContextManager
- else:
- # TODO: Remove once typing.py has been updated
- class ContextManager(typing.Generic[T_co]):
- __slots__ = ()
- def __enter__(self):
- return self
- @abc.abstractmethod
- def __exit__(self, exc_type, exc_value, traceback):
- return None
- @classmethod
- def __subclasshook__(cls, C):
- if cls is ContextManager:
- # In Python 3.6+, it is possible to set a method to None to
- # explicitly indicate that the class does not implement an ABC
- # (https://bugs.python.org/issue25958), but we do not support
- # that pattern here because this fallback class is only used
- # in Python 3.5 and earlier.
- if (any("__enter__" in B.__dict__ for B in C.__mro__) and
- any("__exit__" in B.__dict__ for B in C.__mro__)):
- return True
- return NotImplemented
- def IntVar(name):
- return TypeVar(name)
- def _is_dunder(name):
- """Returns True if name is a __dunder_variable_name__."""
- return len(name) > 4 and name.startswith('__') and name.endswith('__')
- class AnnotatedMeta(GenericMeta):
- """Metaclass for Annotated"""
- def __new__(cls, name, bases, namespace, **kwargs):
- if any(b is not object for b in bases):
- raise TypeError("Cannot subclass %s" % Annotated)
- return super(AnnotatedMeta, cls).__new__(cls, name, bases, namespace, **kwargs)
- @property
- def __metadata__(self):
- return self._subs_tree()[2]
- def _tree_repr(self, tree):
- cls, origin, metadata = tree
- if not isinstance(origin, tuple):
- tp_repr = typing._type_repr(origin)
- else:
- tp_repr = origin[0]._tree_repr(origin)
- metadata_reprs = ", ".join(repr(arg) for arg in metadata)
- return '%s[%s, %s]' % (cls, tp_repr, metadata_reprs)
- def _subs_tree(self, tvars=None, args=None):
- if self is Annotated:
- return Annotated
- res = super(AnnotatedMeta, self)._subs_tree(tvars=tvars, args=args)
- # Flatten nested Annotated
- if isinstance(res[1], tuple) and res[1][0] is Annotated:
- sub_tp = res[1][1]
- sub_annot = res[1][2]
- return (Annotated, sub_tp, sub_annot + res[2])
- return res
- def _get_cons(self):
- """Return the class used to create instance of this type."""
- if self.__origin__ is None:
- raise TypeError("Cannot get the underlying type of a non-specialized "
- "Annotated type.")
- tree = self._subs_tree()
- while isinstance(tree, tuple) and tree[0] is Annotated:
- tree = tree[1]
- if isinstance(tree, tuple):
- return tree[0]
- else:
- return tree
- @_tp_cache
- def __getitem__(self, params):
- if not isinstance(params, tuple):
- params = (params,)
- if self.__origin__ is not None: # specializing an instantiated type
- return super(AnnotatedMeta, self).__getitem__(params)
- elif not isinstance(params, tuple) or len(params) < 2:
- raise TypeError("Annotated[...] should be instantiated with at "
- "least two arguments (a type and an annotation).")
- else:
- msg = "Annotated[t, ...]: t must be a type."
- tp = typing._type_check(params[0], msg)
- metadata = tuple(params[1:])
- return self.__class__(
- self.__name__,
- self.__bases__,
- dict(self.__dict__),
- tvars=_type_vars((tp,)),
- # Metadata is a tuple so it won't be touched by _replace_args et al.
- args=(tp, metadata),
- origin=self,
- )
- def __call__(self, *args, **kwargs):
- cons = self._get_cons()
- result = cons(*args, **kwargs)
- try:
- result.__orig_class__ = self
- except AttributeError:
- pass
- return result
- def __getattr__(self, attr):
- # For simplicity we just don't relay all dunder names
- if self.__origin__ is not None and not _is_dunder(attr):
- return getattr(self._get_cons(), attr)
- raise AttributeError(attr)
- def __setattr__(self, attr, value):
- if _is_dunder(attr) or attr.startswith('_abc_'):
- super(AnnotatedMeta, self).__setattr__(attr, value)
- elif self.__origin__ is None:
- raise AttributeError(attr)
- else:
- setattr(self._get_cons(), attr, value)
- class Annotated(object):
- """Add context specific metadata to a type.
- Example: Annotated[int, runtime_check.Unsigned] indicates to the
- hypothetical runtime_check module that this type is an unsigned int.
- Every other consumer of this type can ignore this metadata and treat
- this type as int.
- The first argument to Annotated must be a valid type, the remaining
- arguments are kept as a tuple in the __metadata__ field.
- Details:
- - It's an error to call `Annotated` with less than two arguments.
- - Nested Annotated are flattened::
- Annotated[Annotated[int, Ann1, Ann2], Ann3] == Annotated[int, Ann1, Ann2, Ann3]
- - Instantiating an annotated type is equivalent to instantiating the
- underlying type::
- Annotated[C, Ann1](5) == C(5)
- - Annotated can be used as a generic type alias::
- Optimized = Annotated[T, runtime.Optimize()]
- Optimized[int] == Annotated[int, runtime.Optimize()]
- OptimizedList = Annotated[List[T], runtime.Optimize()]
- OptimizedList[int] == Annotated[List[int], runtime.Optimize()]
- """
- __metaclass__ = AnnotatedMeta
- __slots__ = ()
- class _TypeAliasMeta(typing.TypingMeta):
- """Metaclass for TypeAlias"""
- def __new__(cls, name, bases, namespace):
- cls.assert_no_subclassing(bases)
- self = super(_TypeAliasMeta, cls).__new__(cls, name, bases, namespace)
- return self
- def __repr__(self):
- return 'typing_extensions.TypeAlias'
- class _TypeAliasBase(typing._FinalTypingBase):
- """Special marker indicating that an assignment should
- be recognized as a proper type alias definition by type
- checkers.
- For example::
- Predicate = Callable[..., bool] # type: TypeAlias
- It's invalid when used anywhere except as in the example above.
- """
- __metaclass__ = _TypeAliasMeta
- __slots__ = ()
- def __instancecheck__(self, obj):
- raise TypeError("TypeAlias cannot be used with isinstance().")
- def __subclasscheck__(self, cls):
- raise TypeError("TypeAlias cannot be used with issubclass().")
- def __repr__(self):
- return 'typing_extensions.TypeAlias'
- TypeAlias = _TypeAliasBase(_root=True)
- # This alias exists for backwards compatibility.
- runtime = runtime_checkable
|