codekingpro/portable-devtools
114k
1import abc2import collections3import collections.abc4import operator5import sys6import typing7 8# After PEP 560, internal typing API was substantially reworked.9# This is especially important for Protocol class which uses internal APIs10# quite extensively.11PEP_560 = sys.version_info[:3] >= (3, 7, 0)12 13if PEP_560:14 GenericMeta = type15else:16 # 3.617 from typing import GenericMeta, _type_vars # noqa18 19# The two functions below are copies of typing internal helpers.20# They are needed by _ProtocolMeta21 22 23def _no_slots_copy(dct):24 dict_copy = dict(dct)25 if '__slots__' in dict_copy:26 for slot in dict_copy['__slots__']:27 dict_copy.pop(slot, None)28 return dict_copy29 30 31def _check_generic(cls, parameters):32 if not cls.__parameters__:33 raise TypeError(f"{cls} is not a generic class")34 alen = len(parameters)35 elen = len(cls.__parameters__)36 if alen != elen:37 raise TypeError(f"Too {'many' if alen > elen else 'few'} arguments for {cls};"38 f" actual {alen}, expected {elen}")39 40 41# Please keep __all__ alphabetized within each category.42__all__ = [43 # Super-special typing primitives.44 'ClassVar',45 'Concatenate',46 'Final',47 'ParamSpec',48 'Self',49 'Type',50 51 # ABCs (from collections.abc).52 'Awaitable',53 'AsyncIterator',54 'AsyncIterable',55 'Coroutine',56 'AsyncGenerator',57 'AsyncContextManager',58 'ChainMap',59 60 # Concrete collection types.61 'ContextManager',62 'Counter',63 'Deque',64 'DefaultDict',65 'OrderedDict',66 'TypedDict',67 68 # Structural checks, a.k.a. protocols.69 'SupportsIndex',70 71 # One-off things.72 'Annotated',73 'final',74 'IntVar',75 'Literal',76 'NewType',77 'overload',78 'Protocol',79 'runtime',80 'runtime_checkable',81 'Text',82 'TypeAlias',83 'TypeGuard',84 'TYPE_CHECKING',85]86 87if PEP_560:88 __all__.extend(["get_args", "get_origin", "get_type_hints"])89 90# 3.6.2+91if hasattr(typing, 'NoReturn'):92 NoReturn = typing.NoReturn93# 3.6.0-3.6.194else:95 class _NoReturn(typing._FinalTypingBase, _root=True):96 """Special type indicating functions that never return.97 Example::98 99 from typing import NoReturn100 101 def stop() -> NoReturn:102 raise Exception('no way')103 104 This type is invalid in other positions, e.g., ``List[NoReturn]``105 will fail in static type checkers.106 """107 __slots__ = ()108 109 def __instancecheck__(self, obj):110 raise TypeError("NoReturn cannot be used with isinstance().")111 112 def __subclasscheck__(self, cls):113 raise TypeError("NoReturn cannot be used with issubclass().")114 115 NoReturn = _NoReturn(_root=True)116 117# Some unconstrained type variables. These are used by the container types.118# (These are not for export.)119T = typing.TypeVar('T') # Any type.120KT = typing.TypeVar('KT') # Key type.121VT = typing.TypeVar('VT') # Value type.122T_co = typing.TypeVar('T_co', covariant=True) # Any type covariant containers.123T_contra = typing.TypeVar('T_contra', contravariant=True) # Ditto contravariant.124 125ClassVar = typing.ClassVar126 127# On older versions of typing there is an internal class named "Final".128# 3.8+129if hasattr(typing, 'Final') and sys.version_info[:2] >= (3, 7):130 Final = typing.Final131# 3.7132elif sys.version_info[:2] >= (3, 7):133 class _FinalForm(typing._SpecialForm, _root=True):134 135 def __repr__(self):136 return 'typing_extensions.' + self._name137 138 def __getitem__(self, parameters):139 item = typing._type_check(parameters,140 f'{self._name} accepts only single type')141 return typing._GenericAlias(self, (item,))142 143 Final = _FinalForm('Final',144 doc="""A special typing construct to indicate that a name145 cannot be re-assigned or overridden in a subclass.146 For example:147 148 MAX_SIZE: Final = 9000149 MAX_SIZE += 1 # Error reported by type checker150 151 class Connection:152 TIMEOUT: Final[int] = 10153 class FastConnector(Connection):154 TIMEOUT = 1 # Error reported by type checker155 156 There is no runtime checking of these properties.""")157# 3.6158else:159 class _Final(typing._FinalTypingBase, _root=True):160 """A special typing construct to indicate that a name161 cannot be re-assigned or overridden in a subclass.162 For example:163 164 MAX_SIZE: Final = 9000165 MAX_SIZE += 1 # Error reported by type checker166 167 class Connection:168 TIMEOUT: Final[int] = 10169 class FastConnector(Connection):170 TIMEOUT = 1 # Error reported by type checker171 172 There is no runtime checking of these properties.173 """174 175 __slots__ = ('__type__',)176 177 def __init__(self, tp=None, **kwds):178 self.__type__ = tp179 180 def __getitem__(self, item):181 cls = type(self)182 if self.__type__ is None:183 return cls(typing._type_check(item,184 f'{cls.__name__[1:]} accepts only single type.'),185 _root=True)186 raise TypeError(f'{cls.__name__[1:]} cannot be further subscripted')187 188 def _eval_type(self, globalns, localns):189 new_tp = typing._eval_type(self.__type__, globalns, localns)190 if new_tp == self.__type__:191 return self192 return type(self)(new_tp, _root=True)193 194 def __repr__(self):195 r = super().__repr__()196 if self.__type__ is not None:197 r += f'[{typing._type_repr(self.__type__)}]'198 return r199 200 def __hash__(self):201 return hash((type(self).__name__, self.__type__))202 203 def __eq__(self, other):204 if not isinstance(other, _Final):205 return NotImplemented206 if self.__type__ is not None:207 return self.__type__ == other.__type__208 return self is other209 210 Final = _Final(_root=True)211 212 213# 3.8+214if hasattr(typing, 'final'):215 final = typing.final216# 3.6-3.7217else:218 def final(f):219 """This decorator can be used to indicate to type checkers that220 the decorated method cannot be overridden, and decorated class221 cannot be subclassed. For example:222 223 class Base:224 @final225 def done(self) -> None:226 ...227 class Sub(Base):228 def done(self) -> None: # Error reported by type checker229 ...230 @final231 class Leaf:232 ...233 class Other(Leaf): # Error reported by type checker234 ...235 236 There is no runtime checking of these properties.237 """238 return f239 240 241def IntVar(name):242 return typing.TypeVar(name)243 244 245# 3.8+:246if hasattr(typing, 'Literal'):247 Literal = typing.Literal248# 3.7:249elif sys.version_info[:2] >= (3, 7):250 class _LiteralForm(typing._SpecialForm, _root=True):251 252 def __repr__(self):253 return 'typing_extensions.' + self._name254 255 def __getitem__(self, parameters):256 return typing._GenericAlias(self, parameters)257 258 Literal = _LiteralForm('Literal',259 doc="""A type that can be used to indicate to type checkers260 that the corresponding value has a value literally equivalent261 to the provided parameter. For example:262 263 var: Literal[4] = 4264 265 The type checker understands that 'var' is literally equal to266 the value 4 and no other value.267 268 Literal[...] cannot be subclassed. There is no runtime269 checking verifying that the parameter is actually a value270 instead of a type.""")271# 3.6:272else:273 class _Literal(typing._FinalTypingBase, _root=True):274 """A type that can be used to indicate to type checkers that the275 corresponding value has a value literally equivalent to the276 provided parameter. For example:277 278 var: Literal[4] = 4279 280 The type checker understands that 'var' is literally equal to the281 value 4 and no other value.282 283 Literal[...] cannot be subclassed. There is no runtime checking284 verifying that the parameter is actually a value instead of a type.285 """286 287 __slots__ = ('__values__',)288 289 def __init__(self, values=None, **kwds):290 self.__values__ = values291 292 def __getitem__(self, values):293 cls = type(self)294 if self.__values__ is None:295 if not isinstance(values, tuple):296 values = (values,)297 return cls(values, _root=True)298 raise TypeError(f'{cls.__name__[1:]} cannot be further subscripted')299 300 def _eval_type(self, globalns, localns):301 return self302 303 def __repr__(self):304 r = super().__repr__()305 if self.__values__ is not None:306 r += f'[{", ".join(map(typing._type_repr, self.__values__))}]'307 return r308 309 def __hash__(self):310 return hash((type(self).__name__, self.__values__))311 312 def __eq__(self, other):313 if not isinstance(other, _Literal):314 return NotImplemented315 if self.__values__ is not None:316 return self.__values__ == other.__values__317 return self is other318 319 Literal = _Literal(_root=True)320 321 322_overload_dummy = typing._overload_dummy # noqa323overload = typing.overload324 325 326# This is not a real generic class. Don't use outside annotations.327Type = typing.Type328 329# Various ABCs mimicking those in collections.abc.330# A few are simply re-exported for completeness.331 332 333class _ExtensionsGenericMeta(GenericMeta):334 def __subclasscheck__(self, subclass):335 """This mimics a more modern GenericMeta.__subclasscheck__() logic336 (that does not have problems with recursion) to work around interactions337 between collections, typing, and typing_extensions on older338 versions of Python, see https://github.com/python/typing/issues/501.339 """340 if self.__origin__ is not None:341 if sys._getframe(1).f_globals['__name__'] not in ['abc', 'functools']:342 raise TypeError("Parameterized generics cannot be used with class "343 "or instance checks")344 return False345 if not self.__extra__:346 return super().__subclasscheck__(subclass)347 res = self.__extra__.__subclasshook__(subclass)348 if res is not NotImplemented:349 return res350 if self.__extra__ in subclass.__mro__:351 return True352 for scls in self.__extra__.__subclasses__():353 if isinstance(scls, GenericMeta):354 continue355 if issubclass(subclass, scls):356 return True357 return False358 359 360Awaitable = typing.Awaitable361Coroutine = typing.Coroutine362AsyncIterable = typing.AsyncIterable363AsyncIterator = typing.AsyncIterator364 365# 3.6.1+366if hasattr(typing, 'Deque'):367 Deque = typing.Deque368# 3.6.0369else:370 class Deque(collections.deque, typing.MutableSequence[T],371 metaclass=_ExtensionsGenericMeta,372 extra=collections.deque):373 __slots__ = ()374 375 def __new__(cls, *args, **kwds):376 if cls._gorg is Deque:377 return collections.deque(*args, **kwds)378 return typing._generic_new(collections.deque, cls, *args, **kwds)379 380ContextManager = typing.ContextManager381# 3.6.2+382if hasattr(typing, 'AsyncContextManager'):383 AsyncContextManager = typing.AsyncContextManager384# 3.6.0-3.6.1385else:386 from _collections_abc import _check_methods as _check_methods_in_mro # noqa387 388 class AsyncContextManager(typing.Generic[T_co]):389 __slots__ = ()390 391 async def __aenter__(self):392 return self393 394 @abc.abstractmethod395 async def __aexit__(self, exc_type, exc_value, traceback):396 return None397 398 @classmethod399 def __subclasshook__(cls, C):400 if cls is AsyncContextManager:401 return _check_methods_in_mro(C, "__aenter__", "__aexit__")402 return NotImplemented403 404DefaultDict = typing.DefaultDict405 406# 3.7.2+407if hasattr(typing, 'OrderedDict'):408 OrderedDict = typing.OrderedDict409# 3.7.0-3.7.2410elif (3, 7, 0) <= sys.version_info[:3] < (3, 7, 2):411 OrderedDict = typing._alias(collections.OrderedDict, (KT, VT))412# 3.6413else:414 class OrderedDict(collections.OrderedDict, typing.MutableMapping[KT, VT],415 metaclass=_ExtensionsGenericMeta,416 extra=collections.OrderedDict):417 418 __slots__ = ()419 420 def __new__(cls, *args, **kwds):421 if cls._gorg is OrderedDict:422 return collections.OrderedDict(*args, **kwds)423 return typing._generic_new(collections.OrderedDict, cls, *args, **kwds)424 425# 3.6.2+426if hasattr(typing, 'Counter'):427 Counter = typing.Counter428# 3.6.0-3.6.1429else:430 class Counter(collections.Counter,431 typing.Dict[T, int],432 metaclass=_ExtensionsGenericMeta, extra=collections.Counter):433 434 __slots__ = ()435 436 def __new__(cls, *args, **kwds):437 if cls._gorg is Counter:438 return collections.Counter(*args, **kwds)439 return typing._generic_new(collections.Counter, cls, *args, **kwds)440 441# 3.6.1+442if hasattr(typing, 'ChainMap'):443 ChainMap = typing.ChainMap444elif hasattr(collections, 'ChainMap'):445 class ChainMap(collections.ChainMap, typing.MutableMapping[KT, VT],446 metaclass=_ExtensionsGenericMeta,447 extra=collections.ChainMap):448 449 __slots__ = ()450 451 def __new__(cls, *args, **kwds):452 if cls._gorg is ChainMap:453 return collections.ChainMap(*args, **kwds)454 return typing._generic_new(collections.ChainMap, cls, *args, **kwds)455 456# 3.6.1+457if hasattr(typing, 'AsyncGenerator'):458 AsyncGenerator = typing.AsyncGenerator459# 3.6.0460else:461 class AsyncGenerator(AsyncIterator[T_co], typing.Generic[T_co, T_contra],462 metaclass=_ExtensionsGenericMeta,463 extra=collections.abc.AsyncGenerator):464 __slots__ = ()465 466NewType = typing.NewType467Text = typing.Text468TYPE_CHECKING = typing.TYPE_CHECKING469 470 471def _gorg(cls):472 """This function exists for compatibility with old typing versions."""473 assert isinstance(cls, GenericMeta)474 if hasattr(cls, '_gorg'):475 return cls._gorg476 while cls.__origin__ is not None:477 cls = cls.__origin__478 return cls479 480 481_PROTO_WHITELIST = ['Callable', 'Awaitable',482 'Iterable', 'Iterator', 'AsyncIterable', 'AsyncIterator',483 'Hashable', 'Sized', 'Container', 'Collection', 'Reversible',484 'ContextManager', 'AsyncContextManager']485 486 487def _get_protocol_attrs(cls):488 attrs = set()489 for base in cls.__mro__[:-1]: # without object490 if base.__name__ in ('Protocol', 'Generic'):491 continue492 annotations = getattr(base, '__annotations__', {})493 for attr in list(base.__dict__.keys()) + list(annotations.keys()):494 if (not attr.startswith('_abc_') and attr not in (495 '__abstractmethods__', '__annotations__', '__weakref__',496 '_is_protocol', '_is_runtime_protocol', '__dict__',497 '__args__', '__slots__',498 '__next_in_mro__', '__parameters__', '__origin__',499 '__orig_bases__', '__extra__', '__tree_hash__',500 '__doc__', '__subclasshook__', '__init__', '__new__',501 '__module__', '_MutableMapping__marker', '_gorg')):502 attrs.add(attr)503 return attrs504 505 506def _is_callable_members_only(cls):507 return all(callable(getattr(cls, attr, None)) for attr in _get_protocol_attrs(cls))508 509 510# 3.8+511if hasattr(typing, 'Protocol'):512 Protocol = typing.Protocol513# 3.7514elif PEP_560:515 from typing import _collect_type_vars # noqa516 517 def _no_init(self, *args, **kwargs):518 if type(self)._is_protocol:519 raise TypeError('Protocols cannot be instantiated')520 521 class _ProtocolMeta(abc.ABCMeta):522 # This metaclass is a bit unfortunate and exists only because of the lack523 # of __instancehook__.524 def __instancecheck__(cls, instance):525 # We need this method for situations where attributes are526 # assigned in __init__.527 if ((not getattr(cls, '_is_protocol', False) or528 _is_callable_members_only(cls)) and529 issubclass(instance.__class__, cls)):530 return True531 if cls._is_protocol:532 if all(hasattr(instance, attr) and533 (not callable(getattr(cls, attr, None)) or534 getattr(instance, attr) is not None)535 for attr in _get_protocol_attrs(cls)):536 return True537 return super().__instancecheck__(instance)538 539 class Protocol(metaclass=_ProtocolMeta):540 # There is quite a lot of overlapping code with typing.Generic.541 # Unfortunately it is hard to avoid this while these live in two different542 # modules. The duplicated code will be removed when Protocol is moved to typing.543 """Base class for protocol classes. Protocol classes are defined as::544 545 class Proto(Protocol):546 def meth(self) -> int:547 ...548 549 Such classes are primarily used with static type checkers that recognize550 structural subtyping (static duck-typing), for example::551 552 class C:553 def meth(self) -> int:554 return 0555 556 def func(x: Proto) -> int:557 return x.meth()558 559 func(C()) # Passes static type check560 561 See PEP 544 for details. Protocol classes decorated with562 @typing_extensions.runtime act as simple-minded runtime protocol that checks563 only the presence of given attributes, ignoring their type signatures.564 565 Protocol classes can be generic, they are defined as::566 567 class GenProto(Protocol[T]):568 def meth(self) -> T:569 ...570 """571 __slots__ = ()572 _is_protocol = True573 574 def __new__(cls, *args, **kwds):575 if cls is Protocol:576 raise TypeError("Type Protocol cannot be instantiated; "577 "it can only be used as a base class")578 return super().__new__(cls)579 580 @typing._tp_cache581 def __class_getitem__(cls, params):582 if not isinstance(params, tuple):583 params = (params,)584 if not params and cls is not typing.Tuple:585 raise TypeError(586 f"Parameter list to {cls.__qualname__}[...] cannot be empty")587 msg = "Parameters to generic types must be types."588 params = tuple(typing._type_check(p, msg) for p in params) # noqa589 if cls is Protocol:590 # Generic can only be subscripted with unique type variables.591 if not all(isinstance(p, typing.TypeVar) for p in params):592 i = 0593 while isinstance(params[i], typing.TypeVar):594 i += 1595 raise TypeError(596 "Parameters to Protocol[...] must all be type variables."597 f" Parameter {i + 1} is {params[i]}")598 if len(set(params)) != len(params):599 raise TypeError(600 "Parameters to Protocol[...] must all be unique")601 else:602 # Subscripting a regular Generic subclass.603 _check_generic(cls, params)604 return typing._GenericAlias(cls, params)605 606 def __init_subclass__(cls, *args, **kwargs):607 tvars = []608 if '__orig_bases__' in cls.__dict__:609 error = typing.Generic in cls.__orig_bases__610 else:611 error = typing.Generic in cls.__bases__612 if error:613 raise TypeError("Cannot inherit from plain Generic")614 if '__orig_bases__' in cls.__dict__:615 tvars = _collect_type_vars(cls.__orig_bases__)616 # Look for Generic[T1, ..., Tn] or Protocol[T1, ..., Tn].617 # If found, tvars must be a subset of it.618 # If not found, tvars is it.619 # Also check for and reject plain Generic,620 # and reject multiple Generic[...] and/or Protocol[...].621 gvars = None622 for base in cls.__orig_bases__:623 if (isinstance(base, typing._GenericAlias) and624 base.__origin__ in (typing.Generic, Protocol)):625 # for error messages626 the_base = base.__origin__.__name__627 if gvars is not None:628 raise TypeError(629 "Cannot inherit from Generic[...]"630 " and/or Protocol[...] multiple types.")631 gvars = base.__parameters__632 if gvars is None:633 gvars = tvars634 else:635 tvarset = set(tvars)636 gvarset = set(gvars)637 if not tvarset <= gvarset:638 s_vars = ', '.join(str(t) for t in tvars if t not in gvarset)639 s_args = ', '.join(str(g) for g in gvars)640 raise TypeError(f"Some type variables ({s_vars}) are"641 f" not listed in {the_base}[{s_args}]")642 tvars = gvars643 cls.__parameters__ = tuple(tvars)644 645 # Determine if this is a protocol or a concrete subclass.646 if not cls.__dict__.get('_is_protocol', None):647 cls._is_protocol = any(b is Protocol for b in cls.__bases__)648 649 # Set (or override) the protocol subclass hook.650 def _proto_hook(other):651 if not cls.__dict__.get('_is_protocol', None):652 return NotImplemented653 if not getattr(cls, '_is_runtime_protocol', False):654 if sys._getframe(2).f_globals['__name__'] in ['abc', 'functools']:655 return NotImplemented656 raise TypeError("Instance and class checks can only be used with"657 " @runtime protocols")658 if not _is_callable_members_only(cls):659 if sys._getframe(2).f_globals['__name__'] in ['abc', 'functools']:660 return NotImplemented661 raise TypeError("Protocols with non-method members"662 " don't support issubclass()")663 if not isinstance(other, type):664 # Same error as for issubclass(1, int)665 raise TypeError('issubclass() arg 1 must be a class')666 for attr in _get_protocol_attrs(cls):667 for base in other.__mro__:668 if attr in base.__dict__:669 if base.__dict__[attr] is None:670 return NotImplemented671 break672 annotations = getattr(base, '__annotations__', {})673 if (isinstance(annotations, typing.Mapping) and674 attr in annotations and675 isinstance(other, _ProtocolMeta) and676 other._is_protocol):677 break678 else:679 return NotImplemented680 return True681 if '__subclasshook__' not in cls.__dict__:682 cls.__subclasshook__ = _proto_hook683 684 # We have nothing more to do for non-protocols.685 if not cls._is_protocol:686 return687 688 # Check consistency of bases.689 for base in cls.__bases__:690 if not (base in (object, typing.Generic) or691 base.__module__ == 'collections.abc' and692 base.__name__ in _PROTO_WHITELIST or693 isinstance(base, _ProtocolMeta) and base._is_protocol):694 raise TypeError('Protocols can only inherit from other'695 f' protocols, got {repr(base)}')696 cls.__init__ = _no_init697# 3.6698else:699 from typing import _next_in_mro, _type_check # noqa700 701 def _no_init(self, *args, **kwargs):702 if type(self)._is_protocol:703 raise TypeError('Protocols cannot be instantiated')704 705 class _ProtocolMeta(GenericMeta):706 """Internal metaclass for Protocol.707 708 This exists so Protocol classes can be generic without deriving709 from Generic.710 """711 def __new__(cls, name, bases, namespace,712 tvars=None, args=None, origin=None, extra=None, orig_bases=None):713 # This is just a version copied from GenericMeta.__new__ that714 # includes "Protocol" special treatment. (Comments removed for brevity.)715 assert extra is None # Protocols should not have extra716 if tvars is not None:717 assert origin is not None718 assert all(isinstance(t, typing.TypeVar) for t in tvars), tvars719 else:720 tvars = _type_vars(bases)721 gvars = None722 for base in bases:723 if base is typing.Generic:724 raise TypeError("Cannot inherit from plain Generic")725 if (isinstance(base, GenericMeta) and726 base.__origin__ in (typing.Generic, Protocol)):727 if gvars is not None:728 raise TypeError(729 "Cannot inherit from Generic[...] or"730 " Protocol[...] multiple times.")731 gvars = base.__parameters__732 if gvars is None:733 gvars = tvars734 else:735 tvarset = set(tvars)736 gvarset = set(gvars)737 if not tvarset <= gvarset:738 s_vars = ", ".join(str(t) for t in tvars if t not in gvarset)739 s_args = ", ".join(str(g) for g in gvars)740 cls_name = "Generic" if any(b.__origin__ is typing.Generic741 for b in bases) else "Protocol"742 raise TypeError(f"Some type variables ({s_vars}) are"743 f" not listed in {cls_name}[{s_args}]")744 tvars = gvars745 746 initial_bases = bases747 if (extra is not None and type(extra) is abc.ABCMeta and748 extra not in bases):749 bases = (extra,) + bases750 bases = tuple(_gorg(b) if isinstance(b, GenericMeta) else b751 for b in bases)752 if any(isinstance(b, GenericMeta) and b is not typing.Generic for b in bases):753 bases = tuple(b for b in bases if b is not typing.Generic)754 namespace.update({'__origin__': origin, '__extra__': extra})755 self = super(GenericMeta, cls).__new__(cls, name, bases, namespace,756 _root=True)757 super(GenericMeta, self).__setattr__('_gorg',758 self if not origin else759 _gorg(origin))760 self.__parameters__ = tvars761 self.__args__ = tuple(... if a is typing._TypingEllipsis else762 () if a is typing._TypingEmpty else763 a for a in args) if args else None764 self.__next_in_mro__ = _next_in_mro(self)765 if orig_bases is None:766 self.__orig_bases__ = initial_bases767 elif origin is not None:768 self._abc_registry = origin._abc_registry769 self._abc_cache = origin._abc_cache770 if hasattr(self, '_subs_tree'):771 self.__tree_hash__ = (hash(self._subs_tree()) if origin else772 super(GenericMeta, self).__hash__())773 return self774 775 def __init__(cls, *args, **kwargs):776 super().__init__(*args, **kwargs)777 if not cls.__dict__.get('_is_protocol', None):778 cls._is_protocol = any(b is Protocol or779 isinstance(b, _ProtocolMeta) and780 b.__origin__ is Protocol781 for b in cls.__bases__)782 if cls._is_protocol:783 for base in cls.__mro__[1:]:784 if not (base in (object, typing.Generic) or785 base.__module__ == 'collections.abc' and786 base.__name__ in _PROTO_WHITELIST or787 isinstance(base, typing.TypingMeta) and base._is_protocol or788 isinstance(base, GenericMeta) and789 base.__origin__ is typing.Generic):790 raise TypeError(f'Protocols can only inherit from other'791 f' protocols, got {repr(base)}')792 793 cls.__init__ = _no_init794 795 def _proto_hook(other):796 if not cls.__dict__.get('_is_protocol', None):797 return NotImplemented798 if not isinstance(other, type):799 # Same error as for issubclass(1, int)800 raise TypeError('issubclass() arg 1 must be a class')801 for attr in _get_protocol_attrs(cls):802 for base in other.__mro__:803 if attr in base.__dict__:804 if base.__dict__[attr] is None:805 return NotImplemented806 break807 annotations = getattr(base, '__annotations__', {})808 if (isinstance(annotations, typing.Mapping) and809 attr in annotations and810 isinstance(other, _ProtocolMeta) and811 other._is_protocol):812 break813 else:814 return NotImplemented815 return True816 if '__subclasshook__' not in cls.__dict__:817 cls.__subclasshook__ = _proto_hook818 819 def __instancecheck__(self, instance):820 # We need this method for situations where attributes are821 # assigned in __init__.822 if ((not getattr(self, '_is_protocol', False) or823 _is_callable_members_only(self)) and824 issubclass(instance.__class__, self)):825 return True826 if self._is_protocol:827 if all(hasattr(instance, attr) and828 (not callable(getattr(self, attr, None)) or829 getattr(instance, attr) is not None)830 for attr in _get_protocol_attrs(self)):831 return True832 return super(GenericMeta, self).__instancecheck__(instance)833 834 def __subclasscheck__(self, cls):835 if self.__origin__ is not None:836 if sys._getframe(1).f_globals['__name__'] not in ['abc', 'functools']:837 raise TypeError("Parameterized generics cannot be used with class "838 "or instance checks")839 return False840 if (self.__dict__.get('_is_protocol', None) and841 not self.__dict__.get('_is_runtime_protocol', None)):842 if sys._getframe(1).f_globals['__name__'] in ['abc',843 'functools',844 'typing']:845 return False846 raise TypeError("Instance and class checks can only be used with"847 " @runtime protocols")848 if (self.__dict__.get('_is_runtime_protocol', None) and849 not _is_callable_members_only(self)):850 if sys._getframe(1).f_globals['__name__'] in ['abc',851 'functools',852 'typing']:853 return super(GenericMeta, self).__subclasscheck__(cls)854 raise TypeError("Protocols with non-method members"855 " don't support issubclass()")856 return super(GenericMeta, self).__subclasscheck__(cls)857 858 @typing._tp_cache859 def __getitem__(self, params):860 # We also need to copy this from GenericMeta.__getitem__ to get861 # special treatment of "Protocol". (Comments removed for brevity.)862 if not isinstance(params, tuple):863 params = (params,)864 if not params and _gorg(self) is not typing.Tuple:865 raise TypeError(866 f"Parameter list to {self.__qualname__}[...] cannot be empty")867 msg = "Parameters to generic types must be types."868 params = tuple(_type_check(p, msg) for p in params)869 if self in (typing.Generic, Protocol):870 if not all(isinstance(p, typing.TypeVar) for p in params):871 raise TypeError(872 f"Parameters to {repr(self)}[...] must all be type variables")873 if len(set(params)) != len(params):874 raise TypeError(875 f"Parameters to {repr(self)}[...] must all be unique")876 tvars = params877 args = params878 elif self in (typing.Tuple, typing.Callable):879 tvars = _type_vars(params)880 args = params881 elif self.__origin__ in (typing.Generic, Protocol):882 raise TypeError(f"Cannot subscript already-subscripted {repr(self)}")883 else:884 _check_generic(self, params)885 tvars = _type_vars(params)886 args = params887 888 prepend = (self,) if self.__origin__ is None else ()889 return self.__class__(self.__name__,890 prepend + self.__bases__,891 _no_slots_copy(self.__dict__),892 tvars=tvars,893 args=args,894 origin=self,895 extra=self.__extra__,896 orig_bases=self.__orig_bases__)897 898 class Protocol(metaclass=_ProtocolMeta):899 """Base class for protocol classes. Protocol classes are defined as::900 901 class Proto(Protocol):902 def meth(self) -> int:903 ...904 905 Such classes are primarily used with static type checkers that recognize906 structural subtyping (static duck-typing), for example::907 908 class C:909 def meth(self) -> int:910 return 0911 912 def func(x: Proto) -> int:913 return x.meth()914 915 func(C()) # Passes static type check916 917 See PEP 544 for details. Protocol classes decorated with918 @typing_extensions.runtime act as simple-minded runtime protocol that checks919 only the presence of given attributes, ignoring their type signatures.920 921 Protocol classes can be generic, they are defined as::922 923 class GenProto(Protocol[T]):924 def meth(self) -> T:925 ...926 """927 __slots__ = ()928 _is_protocol = True929 930 def __new__(cls, *args, **kwds):931 if _gorg(cls) is Protocol:932 raise TypeError("Type Protocol cannot be instantiated; "933 "it can be used only as a base class")934 return typing._generic_new(cls.__next_in_mro__, cls, *args, **kwds)935 936 937# 3.8+938if hasattr(typing, 'runtime_checkable'):939 runtime_checkable = typing.runtime_checkable940# 3.6-3.7941else:942 def runtime_checkable(cls):943 """Mark a protocol class as a runtime protocol, so that it944 can be used with isinstance() and issubclass(). Raise TypeError945 if applied to a non-protocol class.946 947 This allows a simple-minded structural check very similar to the948 one-offs in collections.abc such as Hashable.949 """950 if not isinstance(cls, _ProtocolMeta) or not cls._is_protocol:951 raise TypeError('@runtime_checkable can be only applied to protocol classes,'952 f' got {cls!r}')953 cls._is_runtime_protocol = True954 return cls955 956 957# Exists for backwards compatibility.958runtime = runtime_checkable959 960 961# 3.8+962if hasattr(typing, 'SupportsIndex'):963 SupportsIndex = typing.SupportsIndex964# 3.6-3.7965else:966 @runtime_checkable967 class SupportsIndex(Protocol):968 __slots__ = ()969 970 @abc.abstractmethod971 def __index__(self) -> int:972 pass973 974 975if sys.version_info >= (3, 9, 2):976 # The standard library TypedDict in Python 3.8 does not store runtime information977 # about which (if any) keys are optional. See https://bugs.python.org/issue38834978 # The standard library TypedDict in Python 3.9.0/1 does not honour the "total"979 # keyword with old-style TypedDict(). See https://bugs.python.org/issue42059980 TypedDict = typing.TypedDict981else:982 def _check_fails(cls, other):983 try:984 if sys._getframe(1).f_globals['__name__'] not in ['abc',985 'functools',986 'typing']:987 # Typed dicts are only for static structural subtyping.988 raise TypeError('TypedDict does not support instance and class checks')989 except (AttributeError, ValueError):990 pass991 return False992 993 def _dict_new(*args, **kwargs):994 if not args:995 raise TypeError('TypedDict.__new__(): not enough arguments')996 _, args = args[0], args[1:] # allow the "cls" keyword be passed997 return dict(*args, **kwargs)998 999 _dict_new.__text_signature__ = '($cls, _typename, _fields=None, /, **kwargs)'1000 1001 def _typeddict_new(*args, total=True, **kwargs):1002 if not args:1003 raise TypeError('TypedDict.__new__(): not enough arguments')1004 _, args = args[0], args[1:] # allow the "cls" keyword be passed1005 if args:1006 typename, args = args[0], args[1:] # allow the "_typename" keyword be passed1007 elif '_typename' in kwargs:1008 typename = kwargs.pop('_typename')1009 import warnings1010 warnings.warn("Passing '_typename' as keyword argument is deprecated",1011 DeprecationWarning, stacklevel=2)1012 else:1013 raise TypeError("TypedDict.__new__() missing 1 required positional "1014 "argument: '_typename'")1015 if args:1016 try:1017 fields, = args # allow the "_fields" keyword be passed1018 except ValueError:1019 raise TypeError('TypedDict.__new__() takes from 2 to 3 '1020 f'positional arguments but {len(args) + 2} '1021 'were given')1022 elif '_fields' in kwargs and len(kwargs) == 1:1023 fields = kwargs.pop('_fields')1024 import warnings1025 warnings.warn("Passing '_fields' as keyword argument is deprecated",1026 DeprecationWarning, stacklevel=2)1027 else:1028 fields = None1029 1030 if fields is None:1031 fields = kwargs1032 elif kwargs:1033 raise TypeError("TypedDict takes either a dict or keyword arguments,"1034 " but not both")1035 1036 ns = {'__annotations__': dict(fields)}1037 try:1038 # Setting correct module is necessary to make typed dict classes pickleable.1039 ns['__module__'] = sys._getframe(1).f_globals.get('__name__', '__main__')1040 except (AttributeError, ValueError):1041 pass1042 1043 return _TypedDictMeta(typename, (), ns, total=total)1044 1045 _typeddict_new.__text_signature__ = ('($cls, _typename, _fields=None,'1046 ' /, *, total=True, **kwargs)')1047 1048 class _TypedDictMeta(type):1049 def __init__(cls, name, bases, ns, total=True):1050 super().__init__(name, bases, ns)1051 1052 def __new__(cls, name, bases, ns, total=True):1053 # Create new typed dict class object.1054 # This method is called directly when TypedDict is subclassed,1055 # or via _typeddict_new when TypedDict is instantiated. This way1056 # TypedDict supports all three syntaxes described in its docstring.1057 # Subclasses and instances of TypedDict return actual dictionaries1058 # via _dict_new.1059 ns['__new__'] = _typeddict_new if name == 'TypedDict' else _dict_new1060 tp_dict = super().__new__(cls, name, (dict,), ns)1061 1062 annotations = {}1063 own_annotations = ns.get('__annotations__', {})1064 own_annotation_keys = set(own_annotations.keys())1065 msg = "TypedDict('Name', {f0: t0, f1: t1, ...}); each t must be a type"1066 own_annotations = {1067 n: typing._type_check(tp, msg) for n, tp in own_annotations.items()1068 }1069 required_keys = set()1070 optional_keys = set()1071 1072 for base in bases:1073 annotations.update(base.__dict__.get('__annotations__', {}))1074 required_keys.update(base.__dict__.get('__required_keys__', ()))1075 optional_keys.update(base.__dict__.get('__optional_keys__', ()))1076 1077 annotations.update(own_annotations)1078 if total:1079 required_keys.update(own_annotation_keys)1080 else:1081 optional_keys.update(own_annotation_keys)1082 1083 tp_dict.__annotations__ = annotations1084 tp_dict.__required_keys__ = frozenset(required_keys)1085 tp_dict.__optional_keys__ = frozenset(optional_keys)1086 if not hasattr(tp_dict, '__total__'):1087 tp_dict.__total__ = total1088 return tp_dict1089 1090 __instancecheck__ = __subclasscheck__ = _check_fails1091 1092 TypedDict = _TypedDictMeta('TypedDict', (dict,), {})1093 TypedDict.__module__ = __name__1094 TypedDict.__doc__ = \1095 """A simple typed name space. At runtime it is equivalent to a plain dict.1096 1097 TypedDict creates a dictionary type that expects all of its1098 instances to have a certain set of keys, with each key1099 associated with a value of a consistent type. This expectation1100 is not checked at runtime but is only enforced by type checkers.1101 Usage::1102 1103 class Point2D(TypedDict):1104 x: int1105 y: int1106 label: str1107 1108 a: Point2D = {'x': 1, 'y': 2, 'label': 'good'} # OK1109 b: Point2D = {'z': 3, 'label': 'bad'} # Fails type check1110 1111 assert Point2D(x=1, y=2, label='first') == dict(x=1, y=2, label='first')1112 1113 The type info can be accessed via the Point2D.__annotations__ dict, and1114 the Point2D.__required_keys__ and Point2D.__optional_keys__ frozensets.1115 TypedDict supports two additional equivalent forms::1116 1117 Point2D = TypedDict('Point2D', x=int, y=int, label=str)1118 Point2D = TypedDict('Point2D', {'x': int, 'y': int, 'label': str})1119 1120 The class syntax is only supported in Python 3.6+, while two other1121 syntax forms work for Python 2.7 and 3.2+1122 """1123 1124 1125# Python 3.9+ has PEP 593 (Annotated and modified get_type_hints)1126if hasattr(typing, 'Annotated'):1127 Annotated = typing.Annotated1128 get_type_hints = typing.get_type_hints1129 # Not exported and not a public API, but needed for get_origin() and get_args()1130 # to work.1131 _AnnotatedAlias = typing._AnnotatedAlias1132# 3.7-3.81133elif PEP_560:1134 class _AnnotatedAlias(typing._GenericAlias, _root=True):1135 """Runtime representation of an annotated type.1136 1137 At its core 'Annotated[t, dec1, dec2, ...]' is an alias for the type 't'1138 with extra annotations. The alias behaves like a normal typing alias,1139 instantiating is the same as instantiating the underlying type, binding1140 it to types is also the same.1141 """1142 def __init__(self, origin, metadata):1143 if isinstance(origin, _AnnotatedAlias):1144 metadata = origin.__metadata__ + metadata1145 origin = origin.__origin__1146 super().__init__(origin, origin)1147 self.__metadata__ = metadata1148 1149 def copy_with(self, params):1150 assert len(params) == 11151 new_type = params[0]1152 return _AnnotatedAlias(new_type, self.__metadata__)1153 1154 def __repr__(self):1155 return (f"typing_extensions.Annotated[{typing._type_repr(self.__origin__)}, "1156 f"{', '.join(repr(a) for a in self.__metadata__)}]")1157 1158 def __reduce__(self):1159 return operator.getitem, (1160 Annotated, (self.__origin__,) + self.__metadata__1161 )1162 1163 def __eq__(self, other):1164 if not isinstance(other, _AnnotatedAlias):1165 return NotImplemented1166 if self.__origin__ != other.__origin__:1167 return False1168 return self.__metadata__ == other.__metadata__1169 1170 def __hash__(self):1171 return hash((self.__origin__, self.__metadata__))1172 1173 class Annotated:1174 """Add context specific metadata to a type.1175 1176 Example: Annotated[int, runtime_check.Unsigned] indicates to the1177 hypothetical runtime_check module that this type is an unsigned int.1178 Every other consumer of this type can ignore this metadata and treat1179 this type as int.1180 1181 The first argument to Annotated must be a valid type (and will be in1182 the __origin__ field), the remaining arguments are kept as a tuple in1183 the __extra__ field.1184 1185 Details:1186 1187 - It's an error to call `Annotated` with less than two arguments.1188 - Nested Annotated are flattened::1189 1190 Annotated[Annotated[T, Ann1, Ann2], Ann3] == Annotated[T, Ann1, Ann2, Ann3]1191 1192 - Instantiating an annotated type is equivalent to instantiating the1193 underlying type::1194 1195 Annotated[C, Ann1](5) == C(5)1196 1197 - Annotated can be used as a generic type alias::1198 1199 Optimized = Annotated[T, runtime.Optimize()]1200 Optimized[int] == Annotated[int, runtime.Optimize()]