codekingpro/portable-devtools
114k
1import abc2import collections3import collections.abc4import functools5import inspect6import operator7import sys8import types as _types9import typing10import warnings11 12__all__ = [13 # Super-special typing primitives.14 'Any',15 'ClassVar',16 'Concatenate',17 'Final',18 'LiteralString',19 'ParamSpec',20 'ParamSpecArgs',21 'ParamSpecKwargs',22 'Self',23 'Type',24 'TypeVar',25 'TypeVarTuple',26 'Unpack',27 28 # ABCs (from collections.abc).29 'Awaitable',30 'AsyncIterator',31 'AsyncIterable',32 'Coroutine',33 'AsyncGenerator',34 'AsyncContextManager',35 'Buffer',36 'ChainMap',37 38 # Concrete collection types.39 'ContextManager',40 'Counter',41 'Deque',42 'DefaultDict',43 'NamedTuple',44 'OrderedDict',45 'TypedDict',46 47 # Structural checks, a.k.a. protocols.48 'SupportsAbs',49 'SupportsBytes',50 'SupportsComplex',51 'SupportsFloat',52 'SupportsIndex',53 'SupportsInt',54 'SupportsRound',55 56 # One-off things.57 'Annotated',58 'assert_never',59 'assert_type',60 'clear_overloads',61 'dataclass_transform',62 'deprecated',63 'Doc',64 'get_overloads',65 'final',66 'get_args',67 'get_origin',68 'get_original_bases',69 'get_protocol_members',70 'get_type_hints',71 'IntVar',72 'is_protocol',73 'is_typeddict',74 'Literal',75 'NewType',76 'overload',77 'override',78 'Protocol',79 'reveal_type',80 'runtime',81 'runtime_checkable',82 'Text',83 'TypeAlias',84 'TypeAliasType',85 'TypeGuard',86 'TypeIs',87 'TYPE_CHECKING',88 'Never',89 'NoReturn',90 'ReadOnly',91 'Required',92 'NotRequired',93 94 # Pure aliases, have always been in typing95 'AbstractSet',96 'AnyStr',97 'BinaryIO',98 'Callable',99 'Collection',100 'Container',101 'Dict',102 'ForwardRef',103 'FrozenSet',104 'Generator',105 'Generic',106 'Hashable',107 'IO',108 'ItemsView',109 'Iterable',110 'Iterator',111 'KeysView',112 'List',113 'Mapping',114 'MappingView',115 'Match',116 'MutableMapping',117 'MutableSequence',118 'MutableSet',119 'Optional',120 'Pattern',121 'Reversible',122 'Sequence',123 'Set',124 'Sized',125 'TextIO',126 'Tuple',127 'Union',128 'ValuesView',129 'cast',130 'no_type_check',131 'no_type_check_decorator',132]133 134# for backward compatibility135PEP_560 = True136GenericMeta = type137 138# The functions below are modified copies of typing internal helpers.139# They are needed by _ProtocolMeta and they provide support for PEP 646.140 141 142class _Sentinel:143 def __repr__(self):144 return "<sentinel>"145 146 147_marker = _Sentinel()148 149 150if sys.version_info >= (3, 10):151 def _should_collect_from_parameters(t):152 return isinstance(153 t, (typing._GenericAlias, _types.GenericAlias, _types.UnionType)154 )155elif sys.version_info >= (3, 9):156 def _should_collect_from_parameters(t):157 return isinstance(t, (typing._GenericAlias, _types.GenericAlias))158else:159 def _should_collect_from_parameters(t):160 return isinstance(t, typing._GenericAlias) and not t._special161 162 163NoReturn = typing.NoReturn164 165# Some unconstrained type variables. These are used by the container types.166# (These are not for export.)167T = typing.TypeVar('T') # Any type.168KT = typing.TypeVar('KT') # Key type.169VT = typing.TypeVar('VT') # Value type.170T_co = typing.TypeVar('T_co', covariant=True) # Any type covariant containers.171T_contra = typing.TypeVar('T_contra', contravariant=True) # Ditto contravariant.172 173 174if sys.version_info >= (3, 11):175 from typing import Any176else:177 178 class _AnyMeta(type):179 def __instancecheck__(self, obj):180 if self is Any:181 raise TypeError("typing_extensions.Any cannot be used with isinstance()")182 return super().__instancecheck__(obj)183 184 def __repr__(self):185 if self is Any:186 return "typing_extensions.Any"187 return super().__repr__()188 189 class Any(metaclass=_AnyMeta):190 """Special type indicating an unconstrained type.191 - Any is compatible with every type.192 - Any assumed to have all methods.193 - All values assumed to be instances of Any.194 Note that all the above statements are true from the point of view of195 static type checkers. At runtime, Any should not be used with instance196 checks.197 """198 def __new__(cls, *args, **kwargs):199 if cls is Any:200 raise TypeError("Any cannot be instantiated")201 return super().__new__(cls, *args, **kwargs)202 203 204ClassVar = typing.ClassVar205 206 207class _ExtensionsSpecialForm(typing._SpecialForm, _root=True):208 def __repr__(self):209 return 'typing_extensions.' + self._name210 211 212Final = typing.Final213 214if sys.version_info >= (3, 11):215 final = typing.final216else:217 # @final exists in 3.8+, but we backport it for all versions218 # before 3.11 to keep support for the __final__ attribute.219 # See https://bugs.python.org/issue46342220 def final(f):221 """This decorator can be used to indicate to type checkers that222 the decorated method cannot be overridden, and decorated class223 cannot be subclassed. For example:224 225 class Base:226 @final227 def done(self) -> None:228 ...229 class Sub(Base):230 def done(self) -> None: # Error reported by type checker231 ...232 @final233 class Leaf:234 ...235 class Other(Leaf): # Error reported by type checker236 ...237 238 There is no runtime checking of these properties. The decorator239 sets the ``__final__`` attribute to ``True`` on the decorated object240 to allow runtime introspection.241 """242 try:243 f.__final__ = True244 except (AttributeError, TypeError):245 # Skip the attribute silently if it is not writable.246 # AttributeError happens if the object has __slots__ or a247 # read-only property, TypeError if it's a builtin class.248 pass249 return f250 251 252def IntVar(name):253 return typing.TypeVar(name)254 255 256# A Literal bug was fixed in 3.11.0, 3.10.1 and 3.9.8257if sys.version_info >= (3, 10, 1):258 Literal = typing.Literal259else:260 def _flatten_literal_params(parameters):261 """An internal helper for Literal creation: flatten Literals among parameters"""262 params = []263 for p in parameters:264 if isinstance(p, _LiteralGenericAlias):265 params.extend(p.__args__)266 else:267 params.append(p)268 return tuple(params)269 270 def _value_and_type_iter(params):271 for p in params:272 yield p, type(p)273 274 class _LiteralGenericAlias(typing._GenericAlias, _root=True):275 def __eq__(self, other):276 if not isinstance(other, _LiteralGenericAlias):277 return NotImplemented278 these_args_deduped = set(_value_and_type_iter(self.__args__))279 other_args_deduped = set(_value_and_type_iter(other.__args__))280 return these_args_deduped == other_args_deduped281 282 def __hash__(self):283 return hash(frozenset(_value_and_type_iter(self.__args__)))284 285 class _LiteralForm(_ExtensionsSpecialForm, _root=True):286 def __init__(self, doc: str):287 self._name = 'Literal'288 self._doc = self.__doc__ = doc289 290 def __getitem__(self, parameters):291 if not isinstance(parameters, tuple):292 parameters = (parameters,)293 294 parameters = _flatten_literal_params(parameters)295 296 val_type_pairs = list(_value_and_type_iter(parameters))297 try:298 deduped_pairs = set(val_type_pairs)299 except TypeError:300 # unhashable parameters301 pass302 else:303 # similar logic to typing._deduplicate on Python 3.9+304 if len(deduped_pairs) < len(val_type_pairs):305 new_parameters = []306 for pair in val_type_pairs:307 if pair in deduped_pairs:308 new_parameters.append(pair[0])309 deduped_pairs.remove(pair)310 assert not deduped_pairs, deduped_pairs311 parameters = tuple(new_parameters)312 313 return _LiteralGenericAlias(self, parameters)314 315 Literal = _LiteralForm(doc="""\316 A type that can be used to indicate to type checkers317 that the corresponding value has a value literally equivalent318 to the provided parameter. For example:319 320 var: Literal[4] = 4321 322 The type checker understands that 'var' is literally equal to323 the value 4 and no other value.324 325 Literal[...] cannot be subclassed. There is no runtime326 checking verifying that the parameter is actually a value327 instead of a type.""")328 329 330_overload_dummy = typing._overload_dummy331 332 333if hasattr(typing, "get_overloads"): # 3.11+334 overload = typing.overload335 get_overloads = typing.get_overloads336 clear_overloads = typing.clear_overloads337else:338 # {module: {qualname: {firstlineno: func}}}339 _overload_registry = collections.defaultdict(340 functools.partial(collections.defaultdict, dict)341 )342 343 def overload(func):344 """Decorator for overloaded functions/methods.345 346 In a stub file, place two or more stub definitions for the same347 function in a row, each decorated with @overload. For example:348 349 @overload350 def utf8(value: None) -> None: ...351 @overload352 def utf8(value: bytes) -> bytes: ...353 @overload354 def utf8(value: str) -> bytes: ...355 356 In a non-stub file (i.e. a regular .py file), do the same but357 follow it with an implementation. The implementation should *not*358 be decorated with @overload. For example:359 360 @overload361 def utf8(value: None) -> None: ...362 @overload363 def utf8(value: bytes) -> bytes: ...364 @overload365 def utf8(value: str) -> bytes: ...366 def utf8(value):367 # implementation goes here368 369 The overloads for a function can be retrieved at runtime using the370 get_overloads() function.371 """372 # classmethod and staticmethod373 f = getattr(func, "__func__", func)374 try:375 _overload_registry[f.__module__][f.__qualname__][376 f.__code__.co_firstlineno377 ] = func378 except AttributeError:379 # Not a normal function; ignore.380 pass381 return _overload_dummy382 383 def get_overloads(func):384 """Return all defined overloads for *func* as a sequence."""385 # classmethod and staticmethod386 f = getattr(func, "__func__", func)387 if f.__module__ not in _overload_registry:388 return []389 mod_dict = _overload_registry[f.__module__]390 if f.__qualname__ not in mod_dict:391 return []392 return list(mod_dict[f.__qualname__].values())393 394 def clear_overloads():395 """Clear all overloads in the registry."""396 _overload_registry.clear()397 398 399# This is not a real generic class. Don't use outside annotations.400Type = typing.Type401 402# Various ABCs mimicking those in collections.abc.403# A few are simply re-exported for completeness.404Awaitable = typing.Awaitable405Coroutine = typing.Coroutine406AsyncIterable = typing.AsyncIterable407AsyncIterator = typing.AsyncIterator408Deque = typing.Deque409ContextManager = typing.ContextManager410AsyncContextManager = typing.AsyncContextManager411DefaultDict = typing.DefaultDict412OrderedDict = typing.OrderedDict413Counter = typing.Counter414ChainMap = typing.ChainMap415AsyncGenerator = typing.AsyncGenerator416Text = typing.Text417TYPE_CHECKING = typing.TYPE_CHECKING418 419 420_PROTO_ALLOWLIST = {421 'collections.abc': [422 'Callable', 'Awaitable', 'Iterable', 'Iterator', 'AsyncIterable',423 'Hashable', 'Sized', 'Container', 'Collection', 'Reversible', 'Buffer',424 ],425 'contextlib': ['AbstractContextManager', 'AbstractAsyncContextManager'],426 'typing_extensions': ['Buffer'],427}428 429 430_EXCLUDED_ATTRS = {431 "__abstractmethods__", "__annotations__", "__weakref__", "_is_protocol",432 "_is_runtime_protocol", "__dict__", "__slots__", "__parameters__",433 "__orig_bases__", "__module__", "_MutableMapping__marker", "__doc__",434 "__subclasshook__", "__orig_class__", "__init__", "__new__",435 "__protocol_attrs__", "__non_callable_proto_members__",436 "__match_args__",437}438 439if sys.version_info >= (3, 9):440 _EXCLUDED_ATTRS.add("__class_getitem__")441 442if sys.version_info >= (3, 12):443 _EXCLUDED_ATTRS.add("__type_params__")444 445_EXCLUDED_ATTRS = frozenset(_EXCLUDED_ATTRS)446 447 448def _get_protocol_attrs(cls):449 attrs = set()450 for base in cls.__mro__[:-1]: # without object451 if base.__name__ in {'Protocol', 'Generic'}:452 continue453 annotations = getattr(base, '__annotations__', {})454 for attr in (*base.__dict__, *annotations):455 if (not attr.startswith('_abc_') and attr not in _EXCLUDED_ATTRS):456 attrs.add(attr)457 return attrs458 459 460def _caller(depth=2):461 try:462 return sys._getframe(depth).f_globals.get('__name__', '__main__')463 except (AttributeError, ValueError): # For platforms without _getframe()464 return None465 466 467# `__match_args__` attribute was removed from protocol members in 3.13,468# we want to backport this change to older Python versions.469if sys.version_info >= (3, 13):470 Protocol = typing.Protocol471else:472 def _allow_reckless_class_checks(depth=3):473 """Allow instance and class checks for special stdlib modules.474 The abc and functools modules indiscriminately call isinstance() and475 issubclass() on the whole MRO of a user class, which may contain protocols.476 """477 return _caller(depth) in {'abc', 'functools', None}478 479 def _no_init(self, *args, **kwargs):480 if type(self)._is_protocol:481 raise TypeError('Protocols cannot be instantiated')482 483 def _type_check_issubclass_arg_1(arg):484 """Raise TypeError if `arg` is not an instance of `type`485 in `issubclass(arg, <protocol>)`.486 487 In most cases, this is verified by type.__subclasscheck__.488 Checking it again unnecessarily would slow down issubclass() checks,489 so, we don't perform this check unless we absolutely have to.490 491 For various error paths, however,492 we want to ensure that *this* error message is shown to the user493 where relevant, rather than a typing.py-specific error message.494 """495 if not isinstance(arg, type):496 # Same error message as for issubclass(1, int).497 raise TypeError('issubclass() arg 1 must be a class')498 499 # Inheriting from typing._ProtocolMeta isn't actually desirable,500 # but is necessary to allow typing.Protocol and typing_extensions.Protocol501 # to mix without getting TypeErrors about "metaclass conflict"502 class _ProtocolMeta(type(typing.Protocol)):503 # This metaclass is somewhat unfortunate,504 # but is necessary for several reasons...505 #506 # NOTE: DO NOT call super() in any methods in this class507 # That would call the methods on typing._ProtocolMeta on Python 3.8-3.11508 # and those are slow509 def __new__(mcls, name, bases, namespace, **kwargs):510 if name == "Protocol" and len(bases) < 2:511 pass512 elif {Protocol, typing.Protocol} & set(bases):513 for base in bases:514 if not (515 base in {object, typing.Generic, Protocol, typing.Protocol}516 or base.__name__ in _PROTO_ALLOWLIST.get(base.__module__, [])517 or is_protocol(base)518 ):519 raise TypeError(520 f"Protocols can only inherit from other protocols, "521 f"got {base!r}"522 )523 return abc.ABCMeta.__new__(mcls, name, bases, namespace, **kwargs)524 525 def __init__(cls, *args, **kwargs):526 abc.ABCMeta.__init__(cls, *args, **kwargs)527 if getattr(cls, "_is_protocol", False):528 cls.__protocol_attrs__ = _get_protocol_attrs(cls)529 530 def __subclasscheck__(cls, other):531 if cls is Protocol:532 return type.__subclasscheck__(cls, other)533 if (534 getattr(cls, '_is_protocol', False)535 and not _allow_reckless_class_checks()536 ):537 if not getattr(cls, '_is_runtime_protocol', False):538 _type_check_issubclass_arg_1(other)539 raise TypeError(540 "Instance and class checks can only be used with "541 "@runtime_checkable protocols"542 )543 if (544 # this attribute is set by @runtime_checkable:545 cls.__non_callable_proto_members__546 and cls.__dict__.get("__subclasshook__") is _proto_hook547 ):548 _type_check_issubclass_arg_1(other)549 non_method_attrs = sorted(cls.__non_callable_proto_members__)550 raise TypeError(551 "Protocols with non-method members don't support issubclass()."552 f" Non-method members: {str(non_method_attrs)[1:-1]}."553 )554 return abc.ABCMeta.__subclasscheck__(cls, other)555 556 def __instancecheck__(cls, instance):557 # We need this method for situations where attributes are558 # assigned in __init__.559 if cls is Protocol:560 return type.__instancecheck__(cls, instance)561 if not getattr(cls, "_is_protocol", False):562 # i.e., it's a concrete subclass of a protocol563 return abc.ABCMeta.__instancecheck__(cls, instance)564 565 if (566 not getattr(cls, '_is_runtime_protocol', False) and567 not _allow_reckless_class_checks()568 ):569 raise TypeError("Instance and class checks can only be used with"570 " @runtime_checkable protocols")571 572 if abc.ABCMeta.__instancecheck__(cls, instance):573 return True574 575 for attr in cls.__protocol_attrs__:576 try:577 val = inspect.getattr_static(instance, attr)578 except AttributeError:579 break580 # this attribute is set by @runtime_checkable:581 if val is None and attr not in cls.__non_callable_proto_members__:582 break583 else:584 return True585 586 return False587 588 def __eq__(cls, other):589 # Hack so that typing.Generic.__class_getitem__590 # treats typing_extensions.Protocol591 # as equivalent to typing.Protocol592 if abc.ABCMeta.__eq__(cls, other) is True:593 return True594 return cls is Protocol and other is typing.Protocol595 596 # This has to be defined, or the abc-module cache597 # complains about classes with this metaclass being unhashable,598 # if we define only __eq__!599 def __hash__(cls) -> int:600 return type.__hash__(cls)601 602 @classmethod603 def _proto_hook(cls, other):604 if not cls.__dict__.get('_is_protocol', False):605 return NotImplemented606 607 for attr in cls.__protocol_attrs__:608 for base in other.__mro__:609 # Check if the members appears in the class dictionary...610 if attr in base.__dict__:611 if base.__dict__[attr] is None:612 return NotImplemented613 break614 615 # ...or in annotations, if it is a sub-protocol.616 annotations = getattr(base, '__annotations__', {})617 if (618 isinstance(annotations, collections.abc.Mapping)619 and attr in annotations620 and is_protocol(other)621 ):622 break623 else:624 return NotImplemented625 return True626 627 class Protocol(typing.Generic, metaclass=_ProtocolMeta):628 __doc__ = typing.Protocol.__doc__629 __slots__ = ()630 _is_protocol = True631 _is_runtime_protocol = False632 633 def __init_subclass__(cls, *args, **kwargs):634 super().__init_subclass__(*args, **kwargs)635 636 # Determine if this is a protocol or a concrete subclass.637 if not cls.__dict__.get('_is_protocol', False):638 cls._is_protocol = any(b is Protocol for b in cls.__bases__)639 640 # Set (or override) the protocol subclass hook.641 if '__subclasshook__' not in cls.__dict__:642 cls.__subclasshook__ = _proto_hook643 644 # Prohibit instantiation for protocol classes645 if cls._is_protocol and cls.__init__ is Protocol.__init__:646 cls.__init__ = _no_init647 648 649if sys.version_info >= (3, 13):650 runtime_checkable = typing.runtime_checkable651else:652 def runtime_checkable(cls):653 """Mark a protocol class as a runtime protocol.654 655 Such protocol can be used with isinstance() and issubclass().656 Raise TypeError if applied to a non-protocol class.657 This allows a simple-minded structural check very similar to658 one trick ponies in collections.abc such as Iterable.659 660 For example::661 662 @runtime_checkable663 class Closable(Protocol):664 def close(self): ...665 666 assert isinstance(open('/some/file'), Closable)667 668 Warning: this will check only the presence of the required methods,669 not their type signatures!670 """671 if not issubclass(cls, typing.Generic) or not getattr(cls, '_is_protocol', False):672 raise TypeError('@runtime_checkable can be only applied to protocol classes,'673 ' got %r' % cls)674 cls._is_runtime_protocol = True675 676 # Only execute the following block if it's a typing_extensions.Protocol class.677 # typing.Protocol classes don't need it.678 if isinstance(cls, _ProtocolMeta):679 # PEP 544 prohibits using issubclass()680 # with protocols that have non-method members.681 # See gh-113320 for why we compute this attribute here,682 # rather than in `_ProtocolMeta.__init__`683 cls.__non_callable_proto_members__ = set()684 for attr in cls.__protocol_attrs__:685 try:686 is_callable = callable(getattr(cls, attr, None))687 except Exception as e:688 raise TypeError(689 f"Failed to determine whether protocol member {attr!r} "690 "is a method member"691 ) from e692 else:693 if not is_callable:694 cls.__non_callable_proto_members__.add(attr)695 696 return cls697 698 699# The "runtime" alias exists for backwards compatibility.700runtime = runtime_checkable701 702 703# Our version of runtime-checkable protocols is faster on Python 3.8-3.11704if sys.version_info >= (3, 12):705 SupportsInt = typing.SupportsInt706 SupportsFloat = typing.SupportsFloat707 SupportsComplex = typing.SupportsComplex708 SupportsBytes = typing.SupportsBytes709 SupportsIndex = typing.SupportsIndex710 SupportsAbs = typing.SupportsAbs711 SupportsRound = typing.SupportsRound712else:713 @runtime_checkable714 class SupportsInt(Protocol):715 """An ABC with one abstract method __int__."""716 __slots__ = ()717 718 @abc.abstractmethod719 def __int__(self) -> int:720 pass721 722 @runtime_checkable723 class SupportsFloat(Protocol):724 """An ABC with one abstract method __float__."""725 __slots__ = ()726 727 @abc.abstractmethod728 def __float__(self) -> float:729 pass730 731 @runtime_checkable732 class SupportsComplex(Protocol):733 """An ABC with one abstract method __complex__."""734 __slots__ = ()735 736 @abc.abstractmethod737 def __complex__(self) -> complex:738 pass739 740 @runtime_checkable741 class SupportsBytes(Protocol):742 """An ABC with one abstract method __bytes__."""743 __slots__ = ()744 745 @abc.abstractmethod746 def __bytes__(self) -> bytes:747 pass748 749 @runtime_checkable750 class SupportsIndex(Protocol):751 __slots__ = ()752 753 @abc.abstractmethod754 def __index__(self) -> int:755 pass756 757 @runtime_checkable758 class SupportsAbs(Protocol[T_co]):759 """760 An ABC with one abstract method __abs__ that is covariant in its return type.761 """762 __slots__ = ()763 764 @abc.abstractmethod765 def __abs__(self) -> T_co:766 pass767 768 @runtime_checkable769 class SupportsRound(Protocol[T_co]):770 """771 An ABC with one abstract method __round__ that is covariant in its return type.772 """773 __slots__ = ()774 775 @abc.abstractmethod776 def __round__(self, ndigits: int = 0) -> T_co:777 pass778 779 780def _ensure_subclassable(mro_entries):781 def inner(func):782 if sys.implementation.name == "pypy" and sys.version_info < (3, 9):783 cls_dict = {784 "__call__": staticmethod(func),785 "__mro_entries__": staticmethod(mro_entries)786 }787 t = type(func.__name__, (), cls_dict)788 return functools.update_wrapper(t(), func)789 else:790 func.__mro_entries__ = mro_entries791 return func792 return inner793 794 795# Update this to something like >=3.13.0b1 if and when796# PEP 728 is implemented in CPython797_PEP_728_IMPLEMENTED = False798 799if _PEP_728_IMPLEMENTED:800 # The standard library TypedDict in Python 3.8 does not store runtime information801 # about which (if any) keys are optional. See https://bugs.python.org/issue38834802 # The standard library TypedDict in Python 3.9.0/1 does not honour the "total"803 # keyword with old-style TypedDict(). See https://bugs.python.org/issue42059804 # The standard library TypedDict below Python 3.11 does not store runtime805 # information about optional and required keys when using Required or NotRequired.806 # Generic TypedDicts are also impossible using typing.TypedDict on Python <3.11.807 # Aaaand on 3.12 we add __orig_bases__ to TypedDict808 # to enable better runtime introspection.809 # On 3.13 we deprecate some odd ways of creating TypedDicts.810 # Also on 3.13, PEP 705 adds the ReadOnly[] qualifier.811 # PEP 728 (still pending) makes more changes.812 TypedDict = typing.TypedDict813 _TypedDictMeta = typing._TypedDictMeta814 is_typeddict = typing.is_typeddict815else:816 # 3.10.0 and later817 _TAKES_MODULE = "module" in inspect.signature(typing._type_check).parameters818 819 def _get_typeddict_qualifiers(annotation_type):820 while True:821 annotation_origin = get_origin(annotation_type)822 if annotation_origin is Annotated:823 annotation_args = get_args(annotation_type)824 if annotation_args:825 annotation_type = annotation_args[0]826 else:827 break828 elif annotation_origin is Required:829 yield Required830 annotation_type, = get_args(annotation_type)831 elif annotation_origin is NotRequired:832 yield NotRequired833 annotation_type, = get_args(annotation_type)834 elif annotation_origin is ReadOnly:835 yield ReadOnly836 annotation_type, = get_args(annotation_type)837 else:838 break839 840 class _TypedDictMeta(type):841 def __new__(cls, name, bases, ns, *, total=True, closed=False):842 """Create new typed dict class object.843 844 This method is called when TypedDict is subclassed,845 or when TypedDict is instantiated. This way846 TypedDict supports all three syntax forms described in its docstring.847 Subclasses and instances of TypedDict return actual dictionaries.848 """849 for base in bases:850 if type(base) is not _TypedDictMeta and base is not typing.Generic:851 raise TypeError('cannot inherit from both a TypedDict type '852 'and a non-TypedDict base class')853 854 if any(issubclass(b, typing.Generic) for b in bases):855 generic_base = (typing.Generic,)856 else:857 generic_base = ()858 859 # typing.py generally doesn't let you inherit from plain Generic, unless860 # the name of the class happens to be "Protocol"861 tp_dict = type.__new__(_TypedDictMeta, "Protocol", (*generic_base, dict), ns)862 tp_dict.__name__ = name863 if tp_dict.__qualname__ == "Protocol":864 tp_dict.__qualname__ = name865 866 if not hasattr(tp_dict, '__orig_bases__'):867 tp_dict.__orig_bases__ = bases868 869 annotations = {}870 own_annotations = ns.get('__annotations__', {})871 msg = "TypedDict('Name', {f0: t0, f1: t1, ...}); each t must be a type"872 if _TAKES_MODULE:873 own_annotations = {874 n: typing._type_check(tp, msg, module=tp_dict.__module__)875 for n, tp in own_annotations.items()876 }877 else:878 own_annotations = {879 n: typing._type_check(tp, msg)880 for n, tp in own_annotations.items()881 }882 required_keys = set()883 optional_keys = set()884 readonly_keys = set()885 mutable_keys = set()886 extra_items_type = None887 888 for base in bases:889 base_dict = base.__dict__890 891 annotations.update(base_dict.get('__annotations__', {}))892 required_keys.update(base_dict.get('__required_keys__', ()))893 optional_keys.update(base_dict.get('__optional_keys__', ()))894 readonly_keys.update(base_dict.get('__readonly_keys__', ()))895 mutable_keys.update(base_dict.get('__mutable_keys__', ()))896 base_extra_items_type = base_dict.get('__extra_items__', None)897 if base_extra_items_type is not None:898 extra_items_type = base_extra_items_type899 900 if closed and extra_items_type is None:901 extra_items_type = Never902 if closed and "__extra_items__" in own_annotations:903 annotation_type = own_annotations.pop("__extra_items__")904 qualifiers = set(_get_typeddict_qualifiers(annotation_type))905 if Required in qualifiers:906 raise TypeError(907 "Special key __extra_items__ does not support "908 "Required"909 )910 if NotRequired in qualifiers:911 raise TypeError(912 "Special key __extra_items__ does not support "913 "NotRequired"914 )915 extra_items_type = annotation_type916 917 annotations.update(own_annotations)918 for annotation_key, annotation_type in own_annotations.items():919 qualifiers = set(_get_typeddict_qualifiers(annotation_type))920 921 if Required in qualifiers:922 required_keys.add(annotation_key)923 elif NotRequired in qualifiers:924 optional_keys.add(annotation_key)925 elif total:926 required_keys.add(annotation_key)927 else:928 optional_keys.add(annotation_key)929 if ReadOnly in qualifiers:930 mutable_keys.discard(annotation_key)931 readonly_keys.add(annotation_key)932 else:933 mutable_keys.add(annotation_key)934 readonly_keys.discard(annotation_key)935 936 tp_dict.__annotations__ = annotations937 tp_dict.__required_keys__ = frozenset(required_keys)938 tp_dict.__optional_keys__ = frozenset(optional_keys)939 tp_dict.__readonly_keys__ = frozenset(readonly_keys)940 tp_dict.__mutable_keys__ = frozenset(mutable_keys)941 if not hasattr(tp_dict, '__total__'):942 tp_dict.__total__ = total943 tp_dict.__closed__ = closed944 tp_dict.__extra_items__ = extra_items_type945 return tp_dict946 947 __call__ = dict # static method948 949 def __subclasscheck__(cls, other):950 # Typed dicts are only for static structural subtyping.951 raise TypeError('TypedDict does not support instance and class checks')952 953 __instancecheck__ = __subclasscheck__954 955 _TypedDict = type.__new__(_TypedDictMeta, 'TypedDict', (), {})956 957 @_ensure_subclassable(lambda bases: (_TypedDict,))958 def TypedDict(typename, fields=_marker, /, *, total=True, closed=False, **kwargs):959 """A simple typed namespace. At runtime it is equivalent to a plain dict.960 961 TypedDict creates a dictionary type such that a type checker will expect all962 instances to have a certain set of keys, where each key is963 associated with a value of a consistent type. This expectation964 is not checked at runtime.965 966 Usage::967 968 class Point2D(TypedDict):969 x: int970 y: int971 label: str972 973 a: Point2D = {'x': 1, 'y': 2, 'label': 'good'} # OK974 b: Point2D = {'z': 3, 'label': 'bad'} # Fails type check975 976 assert Point2D(x=1, y=2, label='first') == dict(x=1, y=2, label='first')977 978 The type info can be accessed via the Point2D.__annotations__ dict, and979 the Point2D.__required_keys__ and Point2D.__optional_keys__ frozensets.980 TypedDict supports an additional equivalent form::981 982 Point2D = TypedDict('Point2D', {'x': int, 'y': int, 'label': str})983 984 By default, all keys must be present in a TypedDict. It is possible985 to override this by specifying totality::986 987 class Point2D(TypedDict, total=False):988 x: int989 y: int990 991 This means that a Point2D TypedDict can have any of the keys omitted. A type992 checker is only expected to support a literal False or True as the value of993 the total argument. True is the default, and makes all items defined in the994 class body be required.995 996 The Required and NotRequired special forms can also be used to mark997 individual keys as being required or not required::998 999 class Point2D(TypedDict):1000 x: int # the "x" key must always be present (Required is the default)1001 y: NotRequired[int] # the "y" key can be omitted1002 1003 See PEP 655 for more details on Required and NotRequired.1004 """1005 if fields is _marker or fields is None:1006 if fields is _marker:1007 deprecated_thing = "Failing to pass a value for the 'fields' parameter"1008 else:1009 deprecated_thing = "Passing `None` as the 'fields' parameter"1010 1011 example = f"`{typename} = TypedDict({typename!r}, {{}})`"1012 deprecation_msg = (1013 f"{deprecated_thing} is deprecated and will be disallowed in "1014 "Python 3.15. To create a TypedDict class with 0 fields "1015 "using the functional syntax, pass an empty dictionary, e.g. "1016 ) + example + "."1017 warnings.warn(deprecation_msg, DeprecationWarning, stacklevel=2)1018 if closed is not False and closed is not True:1019 kwargs["closed"] = closed1020 closed = False1021 fields = kwargs1022 elif kwargs:1023 raise TypeError("TypedDict takes either a dict or keyword arguments,"1024 " but not both")1025 if kwargs:1026 if sys.version_info >= (3, 13):1027 raise TypeError("TypedDict takes no keyword arguments")1028 warnings.warn(1029 "The kwargs-based syntax for TypedDict definitions is deprecated "1030 "in Python 3.11, will be removed in Python 3.13, and may not be "1031 "understood by third-party type checkers.",1032 DeprecationWarning,1033 stacklevel=2,1034 )1035 1036 ns = {'__annotations__': dict(fields)}1037 module = _caller()1038 if module is not None:1039 # Setting correct module is necessary to make typed dict classes pickleable.1040 ns['__module__'] = module1041 1042 td = _TypedDictMeta(typename, (), ns, total=total, closed=closed)1043 td.__orig_bases__ = (TypedDict,)1044 return td1045 1046 if hasattr(typing, "_TypedDictMeta"):1047 _TYPEDDICT_TYPES = (typing._TypedDictMeta, _TypedDictMeta)1048 else:1049 _TYPEDDICT_TYPES = (_TypedDictMeta,)1050 1051 def is_typeddict(tp):1052 """Check if an annotation is a TypedDict class1053 1054 For example::1055 class Film(TypedDict):1056 title: str1057 year: int1058 1059 is_typeddict(Film) # => True1060 is_typeddict(Union[list, str]) # => False1061 """1062 # On 3.8, this would otherwise return True1063 if hasattr(typing, "TypedDict") and tp is typing.TypedDict:1064 return False1065 return isinstance(tp, _TYPEDDICT_TYPES)1066 1067 1068if hasattr(typing, "assert_type"):1069 assert_type = typing.assert_type1070 1071else:1072 def assert_type(val, typ, /):1073 """Assert (to the type checker) that the value is of the given type.1074 1075 When the type checker encounters a call to assert_type(), it1076 emits an error if the value is not of the specified type::1077 1078 def greet(name: str) -> None:1079 assert_type(name, str) # ok1080 assert_type(name, int) # type checker error1081 1082 At runtime this returns the first argument unchanged and otherwise1083 does nothing.1084 """1085 return val1086 1087 1088if hasattr(typing, "ReadOnly"): # 3.13+1089 get_type_hints = typing.get_type_hints1090else: # <=3.131091 # replaces _strip_annotations()1092 def _strip_extras(t):1093 """Strips Annotated, Required and NotRequired from a given type."""1094 if isinstance(t, _AnnotatedAlias):1095 return _strip_extras(t.__origin__)1096 if hasattr(t, "__origin__") and t.__origin__ in (Required, NotRequired, ReadOnly):1097 return _strip_extras(t.__args__[0])1098 if isinstance(t, typing._GenericAlias):1099 stripped_args = tuple(_strip_extras(a) for a in t.__args__)1100 if stripped_args == t.__args__:1101 return t1102 return t.copy_with(stripped_args)1103 if hasattr(_types, "GenericAlias") and isinstance(t, _types.GenericAlias):1104 stripped_args = tuple(_strip_extras(a) for a in t.__args__)1105 if stripped_args == t.__args__:1106 return t1107 return _types.GenericAlias(t.__origin__, stripped_args)1108 if hasattr(_types, "UnionType") and isinstance(t, _types.UnionType):1109 stripped_args = tuple(_strip_extras(a) for a in t.__args__)1110 if stripped_args == t.__args__:1111 return t1112 return functools.reduce(operator.or_, stripped_args)1113 1114 return t1115 1116 def get_type_hints(obj, globalns=None, localns=None, include_extras=False):1117 """Return type hints for an object.1118 1119 This is often the same as obj.__annotations__, but it handles1120 forward references encoded as string literals, adds Optional[t] if a1121 default value equal to None is set and recursively replaces all1122 'Annotated[T, ...]', 'Required[T]' or 'NotRequired[T]' with 'T'1123 (unless 'include_extras=True').1124 1125 The argument may be a module, class, method, or function. The annotations1126 are returned as a dictionary. For classes, annotations include also1127 inherited members.1128 1129 TypeError is raised if the argument is not of a type that can contain1130 annotations, and an empty dictionary is returned if no annotations are1131 present.1132 1133 BEWARE -- the behavior of globalns and localns is counterintuitive1134 (unless you are familiar with how eval() and exec() work). The1135 search order is locals first, then globals.1136 1137 - If no dict arguments are passed, an attempt is made to use the1138 globals from obj (or the respective module's globals for classes),1139 and these are also used as the locals. If the object does not appear1140 to have globals, an empty dictionary is used.1141 1142 - If one dict argument is passed, it is used for both globals and1143 locals.1144 1145 - If two dict arguments are passed, they specify globals and1146 locals, respectively.1147 """1148 if hasattr(typing, "Annotated"): # 3.9+1149 hint = typing.get_type_hints(1150 obj, globalns=globalns, localns=localns, include_extras=True1151 )1152 else: # 3.81153 hint = typing.get_type_hints(obj, globalns=globalns, localns=localns)1154 if include_extras:1155 return hint1156 return {k: _strip_extras(t) for k, t in hint.items()}1157 1158 1159# Python 3.9+ has PEP 593 (Annotated)1160if hasattr(typing, 'Annotated'):1161 Annotated = typing.Annotated1162 # Not exported and not a public API, but needed for get_origin() and get_args()1163 # to work.1164 _AnnotatedAlias = typing._AnnotatedAlias1165# 3.81166else:1167 class _AnnotatedAlias(typing._GenericAlias, _root=True):1168 """Runtime representation of an annotated type.1169 1170 At its core 'Annotated[t, dec1, dec2, ...]' is an alias for the type 't'1171 with extra annotations. The alias behaves like a normal typing alias,1172 instantiating is the same as instantiating the underlying type, binding1173 it to types is also the same.1174 """1175 def __init__(self, origin, metadata):1176 if isinstance(origin, _AnnotatedAlias):1177 metadata = origin.__metadata__ + metadata1178 origin = origin.__origin__1179 super().__init__(origin, origin)1180 self.__metadata__ = metadata1181 1182 def copy_with(self, params):1183 assert len(params) == 11184 new_type = params[0]1185 return _AnnotatedAlias(new_type, self.__metadata__)1186 1187 def __repr__(self):1188 return (f"typing_extensions.Annotated[{typing._type_repr(self.__origin__)}, "1189 f"{', '.join(repr(a) for a in self.__metadata__)}]")1190 1191 def __reduce__(self):1192 return operator.getitem, (1193 Annotated, (self.__origin__,) + self.__metadata__1194 )1195 1196 def __eq__(self, other):1197 if not isinstance(other, _AnnotatedAlias):1198 return NotImplemented1199 if self.__origin__ != other.__origin__:1200 return False