| 
									
										
										
										
											2018-01-20 11:23:59 +00:00
										 |  |  | """
 | 
					
						
							| 
									
										
										
										
											2023-06-05 15:16:09 +01:00
										 |  |  | The typing module: Support for gradual typing as defined by PEP 484 and subsequent PEPs. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Among other things, the module includes the following: | 
					
						
							|  |  |  | * Generic, Protocol, and internal machinery to support generic aliases. | 
					
						
							|  |  |  |   All subscripted types like X[int], Union[int, str] are generic aliases. | 
					
						
							|  |  |  | * Various "special forms" that have unique meanings in type annotations: | 
					
						
							|  |  |  |   NoReturn, Never, ClassVar, Self, Concatenate, Unpack, and others. | 
					
						
							|  |  |  | * Classes whose instances can be type arguments to generic classes and functions: | 
					
						
							|  |  |  |   TypeVar, ParamSpec, TypeVarTuple. | 
					
						
							|  |  |  | * Public helper functions: get_type_hints, overload, cast, final, and others. | 
					
						
							|  |  |  | * Several protocols to support duck-typing: | 
					
						
							|  |  |  |   SupportsFloat, SupportsIndex, SupportsAbs, and others. | 
					
						
							| 
									
										
										
										
											2020-02-19 10:03:05 +05:30
										 |  |  | * Special types: NewType, NamedTuple, TypedDict. | 
					
						
							| 
									
										
										
										
											2023-06-05 15:16:09 +01:00
										 |  |  | * Deprecated aliases for builtin types and collections.abc ABCs. | 
					
						
							| 
									
										
										
										
											2023-06-07 01:21:16 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | Any name not present in __all__ is an implementation detail | 
					
						
							|  |  |  | that may be changed without notice. Use at your own risk! | 
					
						
							| 
									
										
										
										
											2018-01-20 11:23:59 +00:00
										 |  |  | """
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-09-27 15:54:26 +08:00
										 |  |  | from abc import abstractmethod, ABCMeta | 
					
						
							| 
									
										
										
										
											2024-07-23 14:16:50 -07:00
										 |  |  | import annotationlib | 
					
						
							|  |  |  | from annotationlib import ForwardRef | 
					
						
							| 
									
										
										
										
											2015-05-22 10:14:11 -07:00
										 |  |  | import collections | 
					
						
							| 
									
										
										
										
											2022-04-16 09:01:43 -07:00
										 |  |  | from collections import defaultdict | 
					
						
							| 
									
										
										
										
											2018-01-20 11:23:59 +00:00
										 |  |  | import collections.abc | 
					
						
							| 
									
										
										
										
											2023-05-15 20:36:23 -07:00
										 |  |  | import copyreg | 
					
						
							| 
									
										
										
										
											2015-05-22 10:14:11 -07:00
										 |  |  | import functools | 
					
						
							| 
									
										
										
										
											2018-05-26 21:19:26 +03:00
										 |  |  | import operator | 
					
						
							| 
									
										
										
										
											2015-05-22 10:14:11 -07:00
										 |  |  | import sys | 
					
						
							|  |  |  | import types | 
					
						
							| 
									
										
										
										
											2025-03-04 11:44:19 -08:00
										 |  |  | from types import ( | 
					
						
							|  |  |  |     WrapperDescriptorType, | 
					
						
							|  |  |  |     MethodWrapperType, | 
					
						
							|  |  |  |     MethodDescriptorType, | 
					
						
							|  |  |  |     GenericAlias, | 
					
						
							|  |  |  | ) | 
					
						
							|  |  |  | import warnings | 
					
						
							| 
									
										
										
										
											2015-05-22 10:14:11 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-05-15 20:36:23 -07:00
										 |  |  | from _typing import ( | 
					
						
							|  |  |  |     _idfunc, | 
					
						
							|  |  |  |     TypeVar, | 
					
						
							|  |  |  |     ParamSpec, | 
					
						
							|  |  |  |     TypeVarTuple, | 
					
						
							|  |  |  |     ParamSpecArgs, | 
					
						
							|  |  |  |     ParamSpecKwargs, | 
					
						
							|  |  |  |     TypeAliasType, | 
					
						
							|  |  |  |     Generic, | 
					
						
							| 
									
										
										
										
											2025-03-04 11:44:19 -08:00
										 |  |  |     Union, | 
					
						
							| 
									
										
										
										
											2024-05-03 06:17:32 -07:00
										 |  |  |     NoDefault, | 
					
						
							| 
									
										
										
										
											2023-05-15 20:36:23 -07:00
										 |  |  | ) | 
					
						
							| 
									
										
										
										
											2021-07-23 00:06:54 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-05-22 10:14:11 -07:00
										 |  |  | # Please keep __all__ alphabetized within each category. | 
					
						
							|  |  |  | __all__ = [ | 
					
						
							|  |  |  |     # Super-special typing primitives. | 
					
						
							| 
									
										
										
										
											2020-02-05 02:10:19 +01:00
										 |  |  |     'Annotated', | 
					
						
							| 
									
										
										
										
											2015-05-22 10:14:11 -07:00
										 |  |  |     'Any', | 
					
						
							|  |  |  |     'Callable', | 
					
						
							| 
									
										
										
										
											2016-09-11 15:34:56 -07:00
										 |  |  |     'ClassVar', | 
					
						
							| 
									
										
										
										
											2020-12-24 12:33:48 +08:00
										 |  |  |     'Concatenate', | 
					
						
							| 
									
										
										
										
											2019-05-26 09:37:07 +01:00
										 |  |  |     'Final', | 
					
						
							| 
									
										
										
										
											2019-05-29 11:19:38 -07:00
										 |  |  |     'ForwardRef', | 
					
						
							| 
									
										
										
										
											2015-05-22 10:14:11 -07:00
										 |  |  |     'Generic', | 
					
						
							| 
									
										
										
										
											2019-05-26 09:37:48 +01:00
										 |  |  |     'Literal', | 
					
						
							| 
									
										
										
										
											2015-05-22 10:14:11 -07:00
										 |  |  |     'Optional', | 
					
						
							| 
									
										
										
										
											2020-12-24 12:33:48 +08:00
										 |  |  |     'ParamSpec', | 
					
						
							| 
									
										
										
										
											2019-05-28 08:40:15 +01:00
										 |  |  |     'Protocol', | 
					
						
							| 
									
										
										
										
											2016-05-24 16:38:22 -07:00
										 |  |  |     'Tuple', | 
					
						
							|  |  |  |     'Type', | 
					
						
							| 
									
										
										
										
											2015-05-22 10:14:11 -07:00
										 |  |  |     'TypeVar', | 
					
						
							| 
									
										
										
										
											2022-03-08 04:02:55 +00:00
										 |  |  |     'TypeVarTuple', | 
					
						
							| 
									
										
										
										
											2015-05-22 10:14:11 -07:00
										 |  |  |     'Union', | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     # ABCs (from collections.abc). | 
					
						
							|  |  |  |     'AbstractSet',  # collections.abc.Set. | 
					
						
							|  |  |  |     'Container', | 
					
						
							| 
									
										
										
										
											2017-06-10 21:57:56 +02:00
										 |  |  |     'ContextManager', | 
					
						
							| 
									
										
										
										
											2015-05-22 10:14:11 -07:00
										 |  |  |     'Hashable', | 
					
						
							|  |  |  |     'ItemsView', | 
					
						
							|  |  |  |     'Iterable', | 
					
						
							|  |  |  |     'Iterator', | 
					
						
							|  |  |  |     'KeysView', | 
					
						
							|  |  |  |     'Mapping', | 
					
						
							|  |  |  |     'MappingView', | 
					
						
							|  |  |  |     'MutableMapping', | 
					
						
							|  |  |  |     'MutableSequence', | 
					
						
							|  |  |  |     'MutableSet', | 
					
						
							|  |  |  |     'Sequence', | 
					
						
							|  |  |  |     'Sized', | 
					
						
							|  |  |  |     'ValuesView', | 
					
						
							| 
									
										
										
										
											2018-01-20 11:23:59 +00:00
										 |  |  |     'Awaitable', | 
					
						
							|  |  |  |     'AsyncIterator', | 
					
						
							|  |  |  |     'AsyncIterable', | 
					
						
							|  |  |  |     'Coroutine', | 
					
						
							|  |  |  |     'Collection', | 
					
						
							|  |  |  |     'AsyncGenerator', | 
					
						
							|  |  |  |     'AsyncContextManager', | 
					
						
							| 
									
										
										
										
											2015-05-22 10:14:11 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |     # Structural checks, a.k.a. protocols. | 
					
						
							|  |  |  |     'Reversible', | 
					
						
							|  |  |  |     'SupportsAbs', | 
					
						
							| 
									
										
										
										
											2017-05-02 19:14:07 +02:00
										 |  |  |     'SupportsBytes', | 
					
						
							|  |  |  |     'SupportsComplex', | 
					
						
							| 
									
										
										
										
											2015-05-22 10:14:11 -07:00
										 |  |  |     'SupportsFloat', | 
					
						
							| 
									
										
										
										
											2019-05-22 07:23:01 -07:00
										 |  |  |     'SupportsIndex', | 
					
						
							| 
									
										
										
										
											2015-05-22 10:14:11 -07:00
										 |  |  |     'SupportsInt', | 
					
						
							|  |  |  |     'SupportsRound', | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     # Concrete collection types. | 
					
						
							| 
									
										
										
										
											2019-05-29 11:19:38 -07:00
										 |  |  |     'ChainMap', | 
					
						
							| 
									
										
										
										
											2017-02-13 22:50:14 +01:00
										 |  |  |     'Counter', | 
					
						
							| 
									
										
										
										
											2017-01-16 22:42:37 -08:00
										 |  |  |     'Deque', | 
					
						
							| 
									
										
										
										
											2015-05-22 10:14:11 -07:00
										 |  |  |     'Dict', | 
					
						
							| 
									
										
										
										
											2016-04-05 08:28:52 -07:00
										 |  |  |     'DefaultDict', | 
					
						
							| 
									
										
										
										
											2015-05-22 10:14:11 -07:00
										 |  |  |     'List', | 
					
						
							| 
									
										
										
										
											2019-05-29 11:19:38 -07:00
										 |  |  |     'OrderedDict', | 
					
						
							| 
									
										
										
										
											2015-05-22 10:14:11 -07:00
										 |  |  |     'Set', | 
					
						
							| 
									
										
										
										
											2016-08-23 11:01:50 -07:00
										 |  |  |     'FrozenSet', | 
					
						
							| 
									
										
										
										
											2015-05-22 10:14:11 -07:00
										 |  |  |     'NamedTuple',  # Not really a type. | 
					
						
							| 
									
										
										
										
											2019-05-26 09:39:24 +01:00
										 |  |  |     'TypedDict',  # Not really a type. | 
					
						
							| 
									
										
										
										
											2015-05-22 10:14:11 -07:00
										 |  |  |     'Generator', | 
					
						
							| 
									
										
										
										
											2021-05-06 02:08:20 +09:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-05-04 02:29:49 -07:00
										 |  |  |     # Other concrete types. | 
					
						
							|  |  |  |     'BinaryIO', | 
					
						
							|  |  |  |     'IO', | 
					
						
							|  |  |  |     'Match', | 
					
						
							|  |  |  |     'Pattern', | 
					
						
							|  |  |  |     'TextIO', | 
					
						
							| 
									
										
										
										
											2015-05-22 10:14:11 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |     # One-off things. | 
					
						
							|  |  |  |     'AnyStr', | 
					
						
							| 
									
										
										
										
											2022-03-16 20:02:26 -07:00
										 |  |  |     'assert_type', | 
					
						
							| 
									
										
										
										
											2022-02-08 10:50:26 -08:00
										 |  |  |     'assert_never', | 
					
						
							| 
									
										
										
										
											2015-05-22 10:14:11 -07:00
										 |  |  |     'cast', | 
					
						
							| 
									
										
										
										
											2022-04-16 09:01:43 -07:00
										 |  |  |     'clear_overloads', | 
					
						
							| 
									
										
										
										
											2022-04-25 20:30:25 -07:00
										 |  |  |     'dataclass_transform', | 
					
						
							| 
									
										
										
										
											2024-07-23 14:16:50 -07:00
										 |  |  |     'evaluate_forward_ref', | 
					
						
							| 
									
										
										
										
											2019-05-26 09:37:07 +01:00
										 |  |  |     'final', | 
					
						
							| 
									
										
										
										
											2019-05-31 00:10:07 +01:00
										 |  |  |     'get_args', | 
					
						
							|  |  |  |     'get_origin', | 
					
						
							| 
									
										
										
										
											2022-04-16 09:01:43 -07:00
										 |  |  |     'get_overloads', | 
					
						
							| 
									
										
										
										
											2023-06-14 05:35:06 -07:00
										 |  |  |     'get_protocol_members', | 
					
						
							| 
									
										
										
										
											2015-05-22 10:14:11 -07:00
										 |  |  |     'get_type_hints', | 
					
						
							| 
									
										
										
										
											2023-06-14 05:35:06 -07:00
										 |  |  |     'is_protocol', | 
					
						
							| 
									
										
										
										
											2020-09-16 05:58:32 +01:00
										 |  |  |     'is_typeddict', | 
					
						
							| 
									
										
										
										
											2022-04-05 07:21:03 -07:00
										 |  |  |     'LiteralString', | 
					
						
							| 
									
										
										
										
											2022-02-08 10:50:26 -08:00
										 |  |  |     'Never', | 
					
						
							| 
									
										
										
										
											2016-06-08 11:19:11 -07:00
										 |  |  |     'NewType', | 
					
						
							| 
									
										
										
										
											2015-05-22 10:14:11 -07:00
										 |  |  |     'no_type_check', | 
					
						
							|  |  |  |     'no_type_check_decorator', | 
					
						
							| 
									
										
										
										
											2024-05-03 06:17:32 -07:00
										 |  |  |     'NoDefault', | 
					
						
							| 
									
										
										
										
											2018-03-19 14:41:32 -04:00
										 |  |  |     'NoReturn', | 
					
						
							| 
									
										
										
										
											2022-04-12 12:31:02 -07:00
										 |  |  |     'NotRequired', | 
					
						
							| 
									
										
										
										
											2015-05-22 10:14:11 -07:00
										 |  |  |     'overload', | 
					
						
							| 
									
										
										
										
											2023-02-27 13:16:11 -08:00
										 |  |  |     'override', | 
					
						
							| 
									
										
										
										
											2021-04-10 19:57:05 -07:00
										 |  |  |     'ParamSpecArgs', | 
					
						
							|  |  |  |     'ParamSpecKwargs', | 
					
						
							| 
									
										
										
										
											2024-03-12 17:49:39 +03:00
										 |  |  |     'ReadOnly', | 
					
						
							| 
									
										
										
										
											2022-04-12 12:31:02 -07:00
										 |  |  |     'Required', | 
					
						
							| 
									
										
										
										
											2022-02-01 18:48:55 -08:00
										 |  |  |     'reveal_type', | 
					
						
							| 
									
										
										
										
											2019-05-28 08:40:15 +01:00
										 |  |  |     'runtime_checkable', | 
					
						
							| 
									
										
										
										
											2022-02-07 20:47:48 +00:00
										 |  |  |     'Self', | 
					
						
							| 
									
										
										
										
											2016-04-05 14:54:25 -07:00
										 |  |  |     'Text', | 
					
						
							| 
									
										
										
										
											2016-06-08 11:19:11 -07:00
										 |  |  |     'TYPE_CHECKING', | 
					
						
							| 
									
										
										
										
											2020-10-08 00:44:31 +03:00
										 |  |  |     'TypeAlias', | 
					
						
							| 
									
										
										
										
											2021-04-27 22:31:04 +08:00
										 |  |  |     'TypeGuard', | 
					
						
							| 
									
										
										
										
											2024-04-09 06:50:37 -04:00
										 |  |  |     'TypeIs', | 
					
						
							| 
									
										
										
										
											2023-05-15 20:36:23 -07:00
										 |  |  |     'TypeAliasType', | 
					
						
							| 
									
										
										
										
											2022-03-08 04:02:55 +00:00
										 |  |  |     'Unpack', | 
					
						
							| 
									
										
										
										
											2015-05-22 10:14:11 -07:00
										 |  |  | ] | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-12-14 02:38:24 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-01-26 19:11:51 -08:00
										 |  |  | def _type_convert(arg, module=None, *, allow_special_forms=False): | 
					
						
							| 
									
										
										
										
											2020-12-14 02:38:24 +08:00
										 |  |  |     """For converting None to type(None), and strings to ForwardRef.""" | 
					
						
							|  |  |  |     if arg is None: | 
					
						
							|  |  |  |         return type(None) | 
					
						
							|  |  |  |     if isinstance(arg, str): | 
					
						
							| 
									
										
										
										
											2024-07-23 14:16:50 -07:00
										 |  |  |         return _make_forward_ref(arg, module=module, is_class=allow_special_forms) | 
					
						
							| 
									
										
										
										
											2020-12-14 02:38:24 +08:00
										 |  |  |     return arg | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-01-24 22:37:15 -08:00
										 |  |  | def _type_check(arg, msg, is_argument=True, module=None, *, allow_special_forms=False): | 
					
						
							| 
									
										
										
										
											2018-01-20 11:23:59 +00:00
										 |  |  |     """Check that the argument is a type, and return it (internal helper).
 | 
					
						
							| 
									
										
										
										
											2015-05-22 10:14:11 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-01-20 11:23:59 +00:00
										 |  |  |     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. | 
					
						
							| 
									
										
										
										
											2023-06-05 15:16:09 +01:00
										 |  |  |     The msg argument is a human-readable error message, e.g.:: | 
					
						
							| 
									
										
										
										
											2015-05-22 10:14:11 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-01-20 11:23:59 +00:00
										 |  |  |         "Union[arg, ...]: arg should be a type." | 
					
						
							| 
									
										
										
										
											2016-09-27 15:20:12 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-01-20 11:23:59 +00:00
										 |  |  |     We append the repr() of the actual value (truncated to 100 chars). | 
					
						
							|  |  |  |     """
 | 
					
						
							| 
									
										
										
										
											2019-05-28 08:40:15 +01:00
										 |  |  |     invalid_generic_forms = (Generic, Protocol) | 
					
						
							| 
									
										
										
										
											2022-01-24 22:37:15 -08:00
										 |  |  |     if not allow_special_forms: | 
					
						
							| 
									
										
										
										
											2021-09-25 11:56:22 +03:00
										 |  |  |         invalid_generic_forms += (ClassVar,) | 
					
						
							|  |  |  |         if is_argument: | 
					
						
							|  |  |  |             invalid_generic_forms += (Final,) | 
					
						
							| 
									
										
										
										
											2018-05-16 12:27:03 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-01-26 19:11:51 -08:00
										 |  |  |     arg = _type_convert(arg, module=module, allow_special_forms=allow_special_forms) | 
					
						
							| 
									
										
										
										
											2018-01-20 11:23:59 +00:00
										 |  |  |     if (isinstance(arg, _GenericAlias) and | 
					
						
							| 
									
										
										
										
											2018-05-16 12:27:03 -04:00
										 |  |  |             arg.__origin__ in invalid_generic_forms): | 
					
						
							| 
									
										
										
										
											2018-01-20 11:23:59 +00:00
										 |  |  |         raise TypeError(f"{arg} is not valid as type argument") | 
					
						
							| 
									
										
										
										
											2022-04-05 07:21:03 -07:00
										 |  |  |     if arg in (Any, LiteralString, NoReturn, Never, Self, TypeAlias): | 
					
						
							| 
									
										
										
										
											2022-03-11 10:47:26 +02:00
										 |  |  |         return arg | 
					
						
							|  |  |  |     if allow_special_forms and arg in (ClassVar, Final): | 
					
						
							| 
									
										
										
										
											2020-04-23 21:26:48 +03:00
										 |  |  |         return arg | 
					
						
							|  |  |  |     if isinstance(arg, _SpecialForm) or arg in (Generic, Protocol): | 
					
						
							| 
									
										
										
										
											2018-01-20 11:23:59 +00:00
										 |  |  |         raise TypeError(f"Plain {arg} is not valid as type argument") | 
					
						
							| 
									
										
										
										
											2022-03-11 17:12:17 -08:00
										 |  |  |     if type(arg) is tuple: | 
					
						
							| 
									
										
										
										
											2018-01-20 11:23:59 +00:00
										 |  |  |         raise TypeError(f"{msg} Got {arg!r:.100}.") | 
					
						
							|  |  |  |     return arg | 
					
						
							| 
									
										
										
										
											2016-09-27 15:20:12 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-05-22 10:14:11 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-08-04 21:07:01 +03:00
										 |  |  | def _is_param_expr(arg): | 
					
						
							|  |  |  |     return arg is ... or isinstance(arg, | 
					
						
							|  |  |  |             (tuple, list, ParamSpec, _ConcatenateGenericAlias)) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-05-02 17:08:28 -06:00
										 |  |  | def _should_unflatten_callable_args(typ, args): | 
					
						
							|  |  |  |     """Internal helper for munging collections.abc.Callable's __args__.
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     The canonical representation for a Callable's __args__ flattens the | 
					
						
							| 
									
										
										
										
											2023-06-07 01:21:16 +01:00
										 |  |  |     argument types, see https://github.com/python/cpython/issues/86361. | 
					
						
							| 
									
										
										
										
											2022-05-02 17:08:28 -06:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-06-07 01:21:16 +01:00
										 |  |  |     For example:: | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-11-17 20:56:31 +03:00
										 |  |  |         >>> import collections.abc | 
					
						
							|  |  |  |         >>> P = ParamSpec('P') | 
					
						
							|  |  |  |         >>> collections.abc.Callable[[int, int], str].__args__ == (int, int, str) | 
					
						
							|  |  |  |         True | 
					
						
							|  |  |  |         >>> collections.abc.Callable[P, str].__args__ == (P, str) | 
					
						
							|  |  |  |         True | 
					
						
							| 
									
										
										
										
											2022-05-02 17:08:28 -06:00
										 |  |  | 
 | 
					
						
							|  |  |  |     As a result, if we need to reconstruct the Callable from its __args__, | 
					
						
							|  |  |  |     we need to unflatten it. | 
					
						
							|  |  |  |     """
 | 
					
						
							|  |  |  |     return ( | 
					
						
							|  |  |  |         typ.__origin__ is collections.abc.Callable | 
					
						
							|  |  |  |         and not (len(args) == 2 and _is_param_expr(args[0])) | 
					
						
							|  |  |  |     ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-01-20 11:23:59 +00:00
										 |  |  | def _type_repr(obj): | 
					
						
							|  |  |  |     """Return the repr() of an object, special-casing types (internal helper).
 | 
					
						
							| 
									
										
										
										
											2015-05-22 10:14:11 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-01-20 11:23:59 +00:00
										 |  |  |     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). | 
					
						
							| 
									
										
										
										
											2015-05-22 10:14:11 -07:00
										 |  |  |     """
 | 
					
						
							| 
									
										
										
										
											2023-03-15 12:33:41 +03:00
										 |  |  |     if isinstance(obj, tuple): | 
					
						
							|  |  |  |         # Special case for `repr` of types with `ParamSpec`: | 
					
						
							|  |  |  |         return '[' + ', '.join(_type_repr(t) for t in obj) + ']' | 
					
						
							| 
									
										
										
										
											2024-09-26 13:49:48 -07:00
										 |  |  |     return annotationlib.value_to_string(obj) | 
					
						
							| 
									
										
										
										
											2015-05-22 10:14:11 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-05-10 09:55:49 -07:00
										 |  |  | def _collect_type_parameters(args, *, enforce_default_ordering: bool = True): | 
					
						
							|  |  |  |     """Collect all type parameters in args
 | 
					
						
							| 
									
										
										
										
											2023-06-05 15:16:09 +01:00
										 |  |  |     in order of first appearance (lexicographic order). | 
					
						
							| 
									
										
										
										
											2015-05-22 10:14:11 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-06-05 15:16:09 +01:00
										 |  |  |     For example:: | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-11-17 20:56:31 +03:00
										 |  |  |         >>> P = ParamSpec('P') | 
					
						
							|  |  |  |         >>> T = TypeVar('T') | 
					
						
							| 
									
										
										
										
											2024-05-10 09:55:49 -07:00
										 |  |  |         >>> _collect_type_parameters((T, Callable[P, T])) | 
					
						
							| 
									
										
										
										
											2023-11-17 20:56:31 +03:00
										 |  |  |         (~T, ~P) | 
					
						
							| 
									
										
										
										
											2018-01-20 11:23:59 +00:00
										 |  |  |     """
 | 
					
						
							| 
									
										
										
										
											2024-05-03 06:17:32 -07:00
										 |  |  |     # required type parameter cannot appear after parameter with default | 
					
						
							|  |  |  |     default_encountered = False | 
					
						
							|  |  |  |     # or after TypeVarTuple | 
					
						
							|  |  |  |     type_var_tuple_encountered = False | 
					
						
							| 
									
										
										
										
											2022-03-11 10:47:26 +02:00
										 |  |  |     parameters = [] | 
					
						
							|  |  |  |     for t in args: | 
					
						
							| 
									
										
										
										
											2022-07-09 12:18:01 +08:00
										 |  |  |         if isinstance(t, type): | 
					
						
							| 
									
										
										
										
											2023-03-23 19:26:11 +03:00
										 |  |  |             # We don't want __parameters__ descriptor of a bare Python class. | 
					
						
							|  |  |  |             pass | 
					
						
							|  |  |  |         elif isinstance(t, tuple): | 
					
						
							|  |  |  |             # `t` might be a tuple, when `ParamSpec` is substituted with | 
					
						
							|  |  |  |             # `[T, int]`, or `[int, *Ts]`, etc. | 
					
						
							|  |  |  |             for x in t: | 
					
						
							| 
									
										
										
										
											2024-05-10 09:55:49 -07:00
										 |  |  |                 for collected in _collect_type_parameters([x]): | 
					
						
							| 
									
										
										
										
											2023-03-23 19:26:11 +03:00
										 |  |  |                     if collected not in parameters: | 
					
						
							|  |  |  |                         parameters.append(collected) | 
					
						
							|  |  |  |         elif hasattr(t, '__typing_subst__'): | 
					
						
							| 
									
										
										
										
											2022-03-11 10:47:26 +02:00
										 |  |  |             if t not in parameters: | 
					
						
							| 
									
										
										
										
											2024-05-08 09:54:51 -07:00
										 |  |  |                 if enforce_default_ordering: | 
					
						
							|  |  |  |                     if type_var_tuple_encountered and t.has_default(): | 
					
						
							|  |  |  |                         raise TypeError('Type parameter with a default' | 
					
						
							|  |  |  |                                         ' follows TypeVarTuple') | 
					
						
							| 
									
										
										
										
											2024-05-03 06:17:32 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-05-08 09:54:51 -07:00
										 |  |  |                     if t.has_default(): | 
					
						
							|  |  |  |                         default_encountered = True | 
					
						
							|  |  |  |                     elif default_encountered: | 
					
						
							|  |  |  |                         raise TypeError(f'Type parameter {t!r} without a default' | 
					
						
							|  |  |  |                                         ' follows type parameter with a default') | 
					
						
							| 
									
										
										
										
											2024-05-03 06:17:32 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-03-11 10:47:26 +02:00
										 |  |  |                 parameters.append(t) | 
					
						
							|  |  |  |         else: | 
					
						
							| 
									
										
										
										
											2024-05-03 06:17:32 -07:00
										 |  |  |             if _is_unpacked_typevartuple(t): | 
					
						
							|  |  |  |                 type_var_tuple_encountered = True | 
					
						
							| 
									
										
										
										
											2022-03-11 10:47:26 +02:00
										 |  |  |             for x in getattr(t, '__parameters__', ()): | 
					
						
							|  |  |  |                 if x not in parameters: | 
					
						
							|  |  |  |                     parameters.append(x) | 
					
						
							|  |  |  |     return tuple(parameters) | 
					
						
							| 
									
										
										
										
											2015-05-22 10:14:11 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-05-03 06:17:32 -07:00
										 |  |  | def _check_generic_specialization(cls, arguments): | 
					
						
							| 
									
										
										
										
											2018-01-20 11:23:59 +00:00
										 |  |  |     """Check correct count for parameters of a generic cls (internal helper).
 | 
					
						
							| 
									
										
										
										
											2023-06-05 15:16:09 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-01-20 11:23:59 +00:00
										 |  |  |     This gives a nice error message in case of count mismatch. | 
					
						
							|  |  |  |     """
 | 
					
						
							| 
									
										
										
										
											2024-05-03 06:17:32 -07:00
										 |  |  |     expected_len = len(cls.__parameters__) | 
					
						
							|  |  |  |     if not expected_len: | 
					
						
							| 
									
										
										
										
											2018-01-20 11:23:59 +00:00
										 |  |  |         raise TypeError(f"{cls} is not a generic class") | 
					
						
							| 
									
										
										
										
											2024-05-03 06:17:32 -07:00
										 |  |  |     actual_len = len(arguments) | 
					
						
							|  |  |  |     if actual_len != expected_len: | 
					
						
							|  |  |  |         # deal with defaults | 
					
						
							|  |  |  |         if actual_len < expected_len: | 
					
						
							|  |  |  |             # If the parameter at index `actual_len` in the parameters list | 
					
						
							|  |  |  |             # has a default, then all parameters after it must also have | 
					
						
							| 
									
										
										
										
											2024-05-10 09:55:49 -07:00
										 |  |  |             # one, because we validated as much in _collect_type_parameters(). | 
					
						
							| 
									
										
										
										
											2024-05-03 06:17:32 -07:00
										 |  |  |             # That means that no error needs to be raised here, despite | 
					
						
							|  |  |  |             # the number of arguments being passed not matching the number | 
					
						
							|  |  |  |             # of parameters: all parameters that aren't explicitly | 
					
						
							|  |  |  |             # specialized in this call are parameters with default values. | 
					
						
							|  |  |  |             if cls.__parameters__[actual_len].has_default(): | 
					
						
							|  |  |  |                 return | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             expected_len -= sum(p.has_default() for p in cls.__parameters__) | 
					
						
							|  |  |  |             expect_val = f"at least {expected_len}" | 
					
						
							|  |  |  |         else: | 
					
						
							|  |  |  |             expect_val = expected_len | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         raise TypeError(f"Too {'many' if actual_len > expected_len else 'few'} arguments" | 
					
						
							|  |  |  |                         f" for {cls}; actual {actual_len}, expected {expect_val}") | 
					
						
							| 
									
										
										
										
											2018-01-20 11:23:59 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-05-03 06:17:32 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | def _unpack_args(*args): | 
					
						
							| 
									
										
										
										
											2022-05-08 18:32:32 +03:00
										 |  |  |     newargs = [] | 
					
						
							|  |  |  |     for arg in args: | 
					
						
							|  |  |  |         subargs = getattr(arg, '__typing_unpacked_tuple_args__', None) | 
					
						
							|  |  |  |         if subargs is not None and not (subargs and subargs[-1] is ...): | 
					
						
							|  |  |  |             newargs.extend(subargs) | 
					
						
							|  |  |  |         else: | 
					
						
							|  |  |  |             newargs.append(arg) | 
					
						
							|  |  |  |     return newargs | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-03-01 19:19:24 +03:00
										 |  |  | def _deduplicate(params, *, unhashable_fallback=False): | 
					
						
							| 
									
										
										
										
											2020-11-17 04:23:19 +02:00
										 |  |  |     # Weed out strict duplicates, preserving the first of each occurrence. | 
					
						
							| 
									
										
										
										
											2024-03-01 19:19:24 +03:00
										 |  |  |     try: | 
					
						
							|  |  |  |         return dict.fromkeys(params) | 
					
						
							|  |  |  |     except TypeError: | 
					
						
							|  |  |  |         if not unhashable_fallback: | 
					
						
							|  |  |  |             raise | 
					
						
							|  |  |  |         # Happens for cases like `Annotated[dict, {'x': IntValidator()}]` | 
					
						
							|  |  |  |         return _deduplicate_unhashable(params) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | def _deduplicate_unhashable(unhashable_params): | 
					
						
							|  |  |  |     new_unhashable = [] | 
					
						
							|  |  |  |     for t in unhashable_params: | 
					
						
							|  |  |  |         if t not in new_unhashable: | 
					
						
							|  |  |  |             new_unhashable.append(t) | 
					
						
							|  |  |  |     return new_unhashable | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | def _compare_args_orderless(first_args, second_args): | 
					
						
							|  |  |  |     first_unhashable = _deduplicate_unhashable(first_args) | 
					
						
							|  |  |  |     second_unhashable = _deduplicate_unhashable(second_args) | 
					
						
							|  |  |  |     t = list(second_unhashable) | 
					
						
							|  |  |  |     try: | 
					
						
							|  |  |  |         for elem in first_unhashable: | 
					
						
							|  |  |  |             t.remove(elem) | 
					
						
							|  |  |  |     except ValueError: | 
					
						
							|  |  |  |         return False | 
					
						
							|  |  |  |     return not t | 
					
						
							| 
									
										
										
										
											2020-11-17 04:23:19 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | def _flatten_literal_params(parameters): | 
					
						
							| 
									
										
										
										
											2023-06-05 15:16:09 +01:00
										 |  |  |     """Internal helper for Literal creation: flatten Literals among parameters.""" | 
					
						
							| 
									
										
										
										
											2020-11-17 04:23:19 +02:00
										 |  |  |     params = [] | 
					
						
							|  |  |  |     for p in parameters: | 
					
						
							|  |  |  |         if isinstance(p, _LiteralGenericAlias): | 
					
						
							|  |  |  |             params.extend(p.__args__) | 
					
						
							|  |  |  |         else: | 
					
						
							|  |  |  |             params.append(p) | 
					
						
							| 
									
										
										
										
											2018-05-18 16:00:38 -07:00
										 |  |  |     return tuple(params) | 
					
						
							| 
									
										
										
										
											2018-01-20 11:23:59 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | _cleanups = [] | 
					
						
							| 
									
										
										
										
											2022-11-30 09:33:32 +01:00
										 |  |  | _caches = {} | 
					
						
							| 
									
										
										
										
											2018-01-20 11:23:59 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-17 04:23:19 +02:00
										 |  |  | def _tp_cache(func=None, /, *, typed=False): | 
					
						
							| 
									
										
										
										
											2023-06-07 01:21:16 +01:00
										 |  |  |     """Internal wrapper caching __getitem__ of generic types.
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     For non-hashable arguments, the original function is used as a fallback. | 
					
						
							| 
									
										
										
										
											2018-01-20 11:23:59 +00:00
										 |  |  |     """
 | 
					
						
							| 
									
										
										
										
											2020-11-17 04:23:19 +02:00
										 |  |  |     def decorator(func): | 
					
						
							| 
									
										
										
										
											2022-11-30 09:33:32 +01:00
										 |  |  |         # The callback 'inner' references the newly created lru_cache | 
					
						
							|  |  |  |         # indirectly by performing a lookup in the global '_caches' dictionary. | 
					
						
							|  |  |  |         # This breaks a reference that can be problematic when combined with | 
					
						
							|  |  |  |         # C API extensions that leak references to types. See GH-98253. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         cache = functools.lru_cache(typed=typed)(func) | 
					
						
							|  |  |  |         _caches[func] = cache | 
					
						
							|  |  |  |         _cleanups.append(cache.cache_clear) | 
					
						
							|  |  |  |         del cache | 
					
						
							| 
									
										
										
										
											2018-01-20 11:23:59 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-17 04:23:19 +02:00
										 |  |  |         @functools.wraps(func) | 
					
						
							|  |  |  |         def inner(*args, **kwds): | 
					
						
							|  |  |  |             try: | 
					
						
							| 
									
										
										
										
											2022-11-30 09:33:32 +01:00
										 |  |  |                 return _caches[func](*args, **kwds) | 
					
						
							| 
									
										
										
										
											2020-11-17 04:23:19 +02:00
										 |  |  |             except TypeError: | 
					
						
							|  |  |  |                 pass  # All real errors (not unhashable args) are raised below. | 
					
						
							|  |  |  |             return func(*args, **kwds) | 
					
						
							|  |  |  |         return inner | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if func is not None: | 
					
						
							|  |  |  |         return decorator(func) | 
					
						
							| 
									
										
										
										
											2018-01-20 11:23:59 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-17 04:23:19 +02:00
										 |  |  |     return decorator | 
					
						
							| 
									
										
										
										
											2018-01-20 11:23:59 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-04-19 14:03:44 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-05-07 12:12:28 +01:00
										 |  |  | def _deprecation_warning_for_no_type_params_passed(funcname: str) -> None: | 
					
						
							|  |  |  |     import warnings | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     depr_message = ( | 
					
						
							|  |  |  |         f"Failing to pass a value to the 'type_params' parameter " | 
					
						
							|  |  |  |         f"of {funcname!r} is deprecated, as it leads to incorrect behaviour " | 
					
						
							|  |  |  |         f"when calling {funcname} on a stringified annotation " | 
					
						
							|  |  |  |         f"that references a PEP 695 type parameter. " | 
					
						
							|  |  |  |         f"It will be disallowed in Python 3.15." | 
					
						
							|  |  |  |     ) | 
					
						
							|  |  |  |     warnings.warn(depr_message, category=DeprecationWarning, stacklevel=3) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | class _Sentinel: | 
					
						
							|  |  |  |     __slots__ = () | 
					
						
							|  |  |  |     def __repr__(self): | 
					
						
							|  |  |  |         return '<sentinel>' | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | _sentinel = _Sentinel() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-07-23 14:16:50 -07:00
										 |  |  | def _eval_type(t, globalns, localns, type_params=_sentinel, *, recursive_guard=frozenset(), | 
					
						
							|  |  |  |                format=annotationlib.Format.VALUE, owner=None): | 
					
						
							| 
									
										
										
										
											2020-09-08 18:41:10 -04:00
										 |  |  |     """Evaluate all forward references in the given type t.
 | 
					
						
							| 
									
										
										
										
											2023-06-05 15:16:09 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-01-20 11:23:59 +00:00
										 |  |  |     For use of globalns and localns see the docstring for get_type_hints(). | 
					
						
							| 
									
										
										
										
											2022-03-04 20:51:55 -06:00
										 |  |  |     recursive_guard is used to prevent infinite recursion with a recursive | 
					
						
							|  |  |  |     ForwardRef. | 
					
						
							| 
									
										
										
										
											2018-01-20 11:23:59 +00:00
										 |  |  |     """
 | 
					
						
							| 
									
										
										
										
											2024-05-07 12:12:28 +01:00
										 |  |  |     if type_params is _sentinel: | 
					
						
							|  |  |  |         _deprecation_warning_for_no_type_params_passed("typing._eval_type") | 
					
						
							|  |  |  |         type_params = () | 
					
						
							| 
									
										
										
										
											2018-01-20 11:23:59 +00:00
										 |  |  |     if isinstance(t, ForwardRef): | 
					
						
							| 
									
										
										
										
											2024-08-11 16:42:57 -07:00
										 |  |  |         # If the forward_ref has __forward_module__ set, evaluate() infers the globals | 
					
						
							|  |  |  |         # from the module, and it will probably pick better than the globals we have here. | 
					
						
							|  |  |  |         if t.__forward_module__ is not None: | 
					
						
							|  |  |  |             globalns = None | 
					
						
							| 
									
										
										
										
											2024-07-23 14:16:50 -07:00
										 |  |  |         return evaluate_forward_ref(t, globals=globalns, locals=localns, | 
					
						
							|  |  |  |                                     type_params=type_params, owner=owner, | 
					
						
							|  |  |  |                                     _recursive_guard=recursive_guard, format=format) | 
					
						
							| 
									
										
										
										
											2025-03-04 11:44:19 -08:00
										 |  |  |     if isinstance(t, (_GenericAlias, GenericAlias, Union)): | 
					
						
							| 
									
										
										
										
											2022-03-07 19:02:59 +01:00
										 |  |  |         if isinstance(t, GenericAlias): | 
					
						
							|  |  |  |             args = tuple( | 
					
						
							| 
									
										
										
										
											2024-07-23 14:16:50 -07:00
										 |  |  |                 _make_forward_ref(arg) if isinstance(arg, str) else arg | 
					
						
							| 
									
										
										
										
											2022-03-07 19:02:59 +01:00
										 |  |  |                 for arg in t.__args__ | 
					
						
							|  |  |  |             ) | 
					
						
							| 
									
										
										
										
											2023-01-23 10:52:58 +03:00
										 |  |  |             is_unpacked = t.__unpacked__ | 
					
						
							| 
									
										
										
										
											2022-05-02 17:08:28 -06:00
										 |  |  |             if _should_unflatten_callable_args(t, args): | 
					
						
							|  |  |  |                 t = t.__origin__[(args[:-1], args[-1])] | 
					
						
							|  |  |  |             else: | 
					
						
							|  |  |  |                 t = t.__origin__[args] | 
					
						
							| 
									
										
										
										
											2023-01-23 10:52:58 +03:00
										 |  |  |             if is_unpacked: | 
					
						
							|  |  |  |                 t = Unpack[t] | 
					
						
							| 
									
										
										
										
											2024-04-19 14:03:44 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |         ev_args = tuple( | 
					
						
							|  |  |  |             _eval_type( | 
					
						
							| 
									
										
										
										
											2024-07-23 14:16:50 -07:00
										 |  |  |                 a, globalns, localns, type_params, recursive_guard=recursive_guard, | 
					
						
							|  |  |  |                 format=format, owner=owner, | 
					
						
							| 
									
										
										
										
											2024-04-19 14:03:44 +01:00
										 |  |  |             ) | 
					
						
							|  |  |  |             for a in t.__args__ | 
					
						
							|  |  |  |         ) | 
					
						
							| 
									
										
										
										
											2018-01-20 11:23:59 +00:00
										 |  |  |         if ev_args == t.__args__: | 
					
						
							|  |  |  |             return t | 
					
						
							| 
									
										
										
										
											2020-05-07 04:09:33 +03:00
										 |  |  |         if isinstance(t, GenericAlias): | 
					
						
							|  |  |  |             return GenericAlias(t.__origin__, ev_args) | 
					
						
							| 
									
										
										
										
											2025-03-04 11:44:19 -08:00
										 |  |  |         if isinstance(t, Union): | 
					
						
							| 
									
										
										
										
											2021-07-24 21:26:02 +03:00
										 |  |  |             return functools.reduce(operator.or_, ev_args) | 
					
						
							| 
									
										
										
										
											2020-05-07 04:09:33 +03:00
										 |  |  |         else: | 
					
						
							|  |  |  |             return t.copy_with(ev_args) | 
					
						
							| 
									
										
										
										
											2018-01-20 11:23:59 +00:00
										 |  |  |     return t | 
					
						
							| 
									
										
										
										
											2016-09-27 15:20:12 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-01-20 11:23:59 +00:00
										 |  |  | class _Final: | 
					
						
							| 
									
										
										
										
											2023-06-05 15:16:09 +01:00
										 |  |  |     """Mixin to prohibit subclassing.""" | 
					
						
							| 
									
										
										
										
											2016-09-27 15:20:12 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-01-17 20:43:28 -08:00
										 |  |  |     __slots__ = ('__weakref__',) | 
					
						
							| 
									
										
										
										
											2016-09-27 15:20:12 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-02-05 07:50:00 -08:00
										 |  |  |     def __init_subclass__(cls, /, *args, **kwds): | 
					
						
							| 
									
										
										
										
											2018-01-20 11:23:59 +00:00
										 |  |  |         if '_root' not in kwds: | 
					
						
							|  |  |  |             raise TypeError("Cannot subclass special typing classes") | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-03-26 23:01:12 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-05-08 14:21:28 +01:00
										 |  |  | class _NotIterable: | 
					
						
							|  |  |  |     """Mixin to prevent iteration, without being compatible with Iterable.
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-06-05 15:16:09 +01:00
										 |  |  |     That is, we could do:: | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-05-08 14:21:28 +01:00
										 |  |  |         def __iter__(self): raise TypeError() | 
					
						
							| 
									
										
										
										
											2023-06-05 15:16:09 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-05-08 14:21:28 +01:00
										 |  |  |     But this would make users of this mixin duck type-compatible with | 
					
						
							|  |  |  |     collections.abc.Iterable - isinstance(foo, Iterable) would be True. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     Luckily, we can instead prevent iteration by setting __iter__ to None, which | 
					
						
							|  |  |  |     is treated specially. | 
					
						
							|  |  |  |     """
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-05-10 10:17:54 +01:00
										 |  |  |     __slots__ = () | 
					
						
							| 
									
										
										
										
											2022-05-08 14:21:28 +01:00
										 |  |  |     __iter__ = None | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-23 21:26:48 +03:00
										 |  |  | # Internal indicator of special typing constructs. | 
					
						
							|  |  |  | # See __doc__ instance attribute for specific docs. | 
					
						
							| 
									
										
										
										
											2022-05-08 14:21:28 +01:00
										 |  |  | class _SpecialForm(_Final, _NotIterable, _root=True): | 
					
						
							| 
									
										
										
										
											2020-04-23 21:26:48 +03:00
										 |  |  |     __slots__ = ('_name', '__doc__', '_getitem') | 
					
						
							| 
									
										
										
										
											2016-09-27 15:20:12 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-23 21:26:48 +03:00
										 |  |  |     def __init__(self, getitem): | 
					
						
							|  |  |  |         self._getitem = getitem | 
					
						
							|  |  |  |         self._name = getitem.__name__ | 
					
						
							|  |  |  |         self.__doc__ = getitem.__doc__ | 
					
						
							| 
									
										
										
										
											2016-09-27 15:20:12 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-07-19 20:22:12 +03:00
										 |  |  |     def __getattr__(self, item): | 
					
						
							|  |  |  |         if item in {'__name__', '__qualname__'}: | 
					
						
							|  |  |  |             return self._name | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         raise AttributeError(item) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-23 21:26:48 +03:00
										 |  |  |     def __mro_entries__(self, bases): | 
					
						
							|  |  |  |         raise TypeError(f"Cannot subclass {self!r}") | 
					
						
							| 
									
										
										
										
											2016-09-27 15:20:12 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |     def __repr__(self): | 
					
						
							| 
									
										
										
										
											2018-01-20 11:23:59 +00:00
										 |  |  |         return 'typing.' + self._name | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-03-26 23:01:12 +01:00
										 |  |  |     def __reduce__(self): | 
					
						
							|  |  |  |         return self._name | 
					
						
							| 
									
										
										
										
											2015-05-22 10:14:11 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-09-27 15:20:12 -07:00
										 |  |  |     def __call__(self, *args, **kwds): | 
					
						
							| 
									
										
										
										
											2018-01-20 11:23:59 +00:00
										 |  |  |         raise TypeError(f"Cannot instantiate {self!r}") | 
					
						
							| 
									
										
										
										
											2015-05-22 10:14:11 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-07-24 16:34:48 +03:00
										 |  |  |     def __or__(self, other): | 
					
						
							|  |  |  |         return Union[self, other] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def __ror__(self, other): | 
					
						
							|  |  |  |         return Union[other, self] | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-01-20 11:23:59 +00:00
										 |  |  |     def __instancecheck__(self, obj): | 
					
						
							|  |  |  |         raise TypeError(f"{self} cannot be used with isinstance()") | 
					
						
							| 
									
										
										
										
											2016-09-27 15:20:12 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-01-20 11:23:59 +00:00
										 |  |  |     def __subclasscheck__(self, cls): | 
					
						
							|  |  |  |         raise TypeError(f"{self} cannot be used with issubclass()") | 
					
						
							| 
									
										
										
										
											2016-10-03 08:40:50 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-01-20 11:23:59 +00:00
										 |  |  |     @_tp_cache | 
					
						
							|  |  |  |     def __getitem__(self, parameters): | 
					
						
							| 
									
										
										
										
											2020-04-23 21:26:48 +03:00
										 |  |  |         return self._getitem(self, parameters) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-17 04:23:19 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-12-02 19:10:19 +03:00
										 |  |  | class _TypedCacheSpecialForm(_SpecialForm, _root=True): | 
					
						
							| 
									
										
										
										
											2020-11-17 04:23:19 +02:00
										 |  |  |     def __getitem__(self, parameters): | 
					
						
							| 
									
										
										
										
											2021-10-31 10:22:16 +02:00
										 |  |  |         if not isinstance(parameters, tuple): | 
					
						
							|  |  |  |             parameters = (parameters,) | 
					
						
							|  |  |  |         return self._getitem(self, *parameters) | 
					
						
							| 
									
										
										
										
											2020-11-17 04:23:19 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-04-04 19:35:29 -07:00
										 |  |  | class _AnyMeta(type): | 
					
						
							|  |  |  |     def __instancecheck__(self, obj): | 
					
						
							|  |  |  |         if self is Any: | 
					
						
							|  |  |  |             raise TypeError("typing.Any cannot be used with isinstance()") | 
					
						
							|  |  |  |         return super().__instancecheck__(obj) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def __repr__(self): | 
					
						
							| 
									
										
										
										
											2022-08-30 20:36:16 +03:00
										 |  |  |         if self is Any: | 
					
						
							|  |  |  |             return "typing.Any" | 
					
						
							|  |  |  |         return super().__repr__()  # respect to subclasses | 
					
						
							| 
									
										
										
										
											2022-04-04 19:35:29 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | class Any(metaclass=_AnyMeta): | 
					
						
							| 
									
										
										
										
											2018-01-20 11:23:59 +00:00
										 |  |  |     """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 | 
					
						
							| 
									
										
										
										
											2022-04-04 19:35:29 -07:00
										 |  |  |     checks. | 
					
						
							| 
									
										
										
										
											2020-04-23 21:26:48 +03:00
										 |  |  |     """
 | 
					
						
							| 
									
										
										
										
											2023-06-05 15:16:09 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-04-04 19:35:29 -07:00
										 |  |  |     def __new__(cls, *args, **kwargs): | 
					
						
							|  |  |  |         if cls is Any: | 
					
						
							|  |  |  |             raise TypeError("Any cannot be instantiated") | 
					
						
							| 
									
										
										
										
											2024-03-29 08:19:20 +08:00
										 |  |  |         return super().__new__(cls) | 
					
						
							| 
									
										
										
										
											2022-04-04 19:35:29 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-01-20 11:23:59 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-23 21:26:48 +03:00
										 |  |  | @_SpecialForm | 
					
						
							|  |  |  | def NoReturn(self, parameters): | 
					
						
							| 
									
										
										
										
											2018-01-20 11:23:59 +00:00
										 |  |  |     """Special type indicating functions that never return.
 | 
					
						
							| 
									
										
										
										
											2023-06-05 15:16:09 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-01-20 11:23:59 +00:00
										 |  |  |     Example:: | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-06-05 15:16:09 +01:00
										 |  |  |         from typing import NoReturn | 
					
						
							| 
									
										
										
										
											2018-01-20 11:23:59 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-06-05 15:16:09 +01:00
										 |  |  |         def stop() -> NoReturn: | 
					
						
							|  |  |  |             raise Exception('no way') | 
					
						
							| 
									
										
										
										
											2018-01-20 11:23:59 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-02-08 10:50:26 -08:00
										 |  |  |     NoReturn can also be used as a bottom type, a type that | 
					
						
							|  |  |  |     has no values. Starting in Python 3.11, the Never type should | 
					
						
							|  |  |  |     be used for this concept instead. Type checkers should treat the two | 
					
						
							|  |  |  |     equivalently. | 
					
						
							|  |  |  |     """
 | 
					
						
							|  |  |  |     raise TypeError(f"{self} is not subscriptable") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | # This is semantically identical to NoReturn, but it is implemented | 
					
						
							|  |  |  | # separately so that type checkers can distinguish between the two | 
					
						
							|  |  |  | # if they want. | 
					
						
							|  |  |  | @_SpecialForm | 
					
						
							|  |  |  | def Never(self, parameters): | 
					
						
							|  |  |  |     """The bottom type, a type that has no members.
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     This can be used to define a function that should never be | 
					
						
							|  |  |  |     called, or a function that never returns:: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         from typing import Never | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         def never_call_me(arg: Never) -> None: | 
					
						
							|  |  |  |             pass | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         def int_or_str(arg: int | str) -> None: | 
					
						
							|  |  |  |             never_call_me(arg)  # type checker error | 
					
						
							|  |  |  |             match arg: | 
					
						
							|  |  |  |                 case int(): | 
					
						
							|  |  |  |                     print("It's an int") | 
					
						
							|  |  |  |                 case str(): | 
					
						
							|  |  |  |                     print("It's a str") | 
					
						
							|  |  |  |                 case _: | 
					
						
							| 
									
										
										
										
											2023-06-09 16:08:57 +01:00
										 |  |  |                     never_call_me(arg)  # OK, arg is of type Never | 
					
						
							| 
									
										
										
										
											2020-04-23 21:26:48 +03:00
										 |  |  |     """
 | 
					
						
							|  |  |  |     raise TypeError(f"{self} is not subscriptable") | 
					
						
							| 
									
										
										
										
											2018-01-20 11:23:59 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-02-07 20:47:48 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | @_SpecialForm | 
					
						
							|  |  |  | def Self(self, parameters): | 
					
						
							|  |  |  |     """Used to spell the type of "self" in classes.
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     Example:: | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-06-05 15:16:09 +01:00
										 |  |  |         from typing import Self | 
					
						
							| 
									
										
										
										
											2022-02-07 20:47:48 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-06-05 15:16:09 +01:00
										 |  |  |         class Foo: | 
					
						
							|  |  |  |             def return_self(self) -> Self: | 
					
						
							|  |  |  |                 ... | 
					
						
							|  |  |  |                 return self | 
					
						
							| 
									
										
										
										
											2022-02-07 20:47:48 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     This is especially useful for: | 
					
						
							|  |  |  |         - classmethods that are used as alternative constructors | 
					
						
							|  |  |  |         - annotating an `__enter__` method which returns self | 
					
						
							|  |  |  |     """
 | 
					
						
							|  |  |  |     raise TypeError(f"{self} is not subscriptable") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-04-05 07:21:03 -07:00
										 |  |  | @_SpecialForm | 
					
						
							|  |  |  | def LiteralString(self, parameters): | 
					
						
							|  |  |  |     """Represents an arbitrary literal string.
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     Example:: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         from typing import LiteralString | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-06-09 16:08:57 +01:00
										 |  |  |         def run_query(sql: LiteralString) -> None: | 
					
						
							| 
									
										
										
										
											2022-04-05 07:21:03 -07:00
										 |  |  |             ... | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         def caller(arbitrary_string: str, literal_string: LiteralString) -> None: | 
					
						
							| 
									
										
										
										
											2023-06-09 16:08:57 +01:00
										 |  |  |             run_query("SELECT * FROM students")  # OK | 
					
						
							|  |  |  |             run_query(literal_string)  # OK | 
					
						
							|  |  |  |             run_query("SELECT * FROM " + literal_string)  # OK | 
					
						
							| 
									
										
										
										
											2022-04-05 07:21:03 -07:00
										 |  |  |             run_query(arbitrary_string)  # type checker error | 
					
						
							|  |  |  |             run_query(  # type checker error | 
					
						
							|  |  |  |                 f"SELECT * FROM students WHERE name = {arbitrary_string}" | 
					
						
							|  |  |  |             ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     Only string literals and other LiteralStrings are compatible | 
					
						
							|  |  |  |     with LiteralString. This provides a tool to help prevent | 
					
						
							|  |  |  |     security issues such as SQL injection. | 
					
						
							|  |  |  |     """
 | 
					
						
							|  |  |  |     raise TypeError(f"{self} is not subscriptable") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-23 21:26:48 +03:00
										 |  |  | @_SpecialForm | 
					
						
							|  |  |  | def ClassVar(self, parameters): | 
					
						
							| 
									
										
										
										
											2018-01-20 11:23:59 +00:00
										 |  |  |     """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 | 
					
						
							| 
									
										
										
										
											2023-06-07 01:21:16 +01:00
										 |  |  |     should not be set on instances of that class. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     Usage:: | 
					
						
							| 
									
										
										
										
											2018-01-20 11:23:59 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-06-05 15:16:09 +01:00
										 |  |  |         class Starship: | 
					
						
							| 
									
										
										
										
											2023-06-07 01:21:16 +01:00
										 |  |  |             stats: ClassVar[dict[str, int]] = {} # class variable | 
					
						
							| 
									
										
										
										
											2023-06-05 15:16:09 +01:00
										 |  |  |             damage: int = 10                     # instance variable | 
					
						
							| 
									
										
										
										
											2018-01-20 11:23:59 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     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(). | 
					
						
							| 
									
										
										
										
											2020-04-23 21:26:48 +03:00
										 |  |  |     """
 | 
					
						
							| 
									
										
										
										
											2024-03-11 23:11:56 -07:00
										 |  |  |     item = _type_check(parameters, f'{self} accepts only single type.', allow_special_forms=True) | 
					
						
							| 
									
										
										
										
											2021-08-21 09:47:59 +03:00
										 |  |  |     return _GenericAlias(self, (item,)) | 
					
						
							| 
									
										
										
										
											2018-01-20 11:23:59 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-23 21:26:48 +03:00
										 |  |  | @_SpecialForm | 
					
						
							|  |  |  | def Final(self, parameters): | 
					
						
							| 
									
										
										
										
											2019-05-26 09:37:07 +01:00
										 |  |  |     """Special typing construct to indicate final names to type checkers.
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     A final name cannot be re-assigned or overridden in a subclass. | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-06-05 15:16:09 +01:00
										 |  |  |     For example:: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         MAX_SIZE: Final = 9000 | 
					
						
							|  |  |  |         MAX_SIZE += 1  # Error reported by type checker | 
					
						
							| 
									
										
										
										
											2019-05-26 09:37:07 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-06-05 15:16:09 +01:00
										 |  |  |         class Connection: | 
					
						
							|  |  |  |             TIMEOUT: Final[int] = 10 | 
					
						
							| 
									
										
										
										
											2019-05-26 09:37:07 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-06-05 15:16:09 +01:00
										 |  |  |         class FastConnector(Connection): | 
					
						
							|  |  |  |             TIMEOUT = 1  # Error reported by type checker | 
					
						
							| 
									
										
										
										
											2019-05-26 09:37:07 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |     There is no runtime checking of these properties. | 
					
						
							| 
									
										
										
										
											2020-04-23 21:26:48 +03:00
										 |  |  |     """
 | 
					
						
							| 
									
										
										
										
											2024-03-11 23:11:56 -07:00
										 |  |  |     item = _type_check(parameters, f'{self} accepts only single type.', allow_special_forms=True) | 
					
						
							| 
									
										
										
										
											2021-08-21 09:47:59 +03:00
										 |  |  |     return _GenericAlias(self, (item,)) | 
					
						
							| 
									
										
										
										
											2019-05-26 09:37:07 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-23 21:26:48 +03:00
										 |  |  | @_SpecialForm | 
					
						
							|  |  |  | def Optional(self, parameters): | 
					
						
							| 
									
										
										
										
											2023-06-05 15:16:09 +01:00
										 |  |  |     """Optional[X] is equivalent to Union[X, None].""" | 
					
						
							| 
									
										
										
										
											2020-04-23 21:26:48 +03:00
										 |  |  |     arg = _type_check(parameters, f"{self} requires a single type.") | 
					
						
							|  |  |  |     return Union[arg, type(None)] | 
					
						
							| 
									
										
										
										
											2016-10-29 12:44:29 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-12-02 19:10:19 +03:00
										 |  |  | @_TypedCacheSpecialForm | 
					
						
							| 
									
										
										
										
											2021-10-31 10:22:16 +02:00
										 |  |  | @_tp_cache(typed=True) | 
					
						
							|  |  |  | def Literal(self, *parameters): | 
					
						
							| 
									
										
										
										
											2019-05-26 09:37:48 +01:00
										 |  |  |     """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 | 
					
						
							| 
									
										
										
										
											2023-06-05 15:16:09 +01:00
										 |  |  |     literal (or one of several literals):: | 
					
						
							| 
									
										
										
										
											2019-05-26 09:37:48 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-06-05 15:16:09 +01:00
										 |  |  |         def validate_simple(data: Any) -> Literal[True]:  # always returns True | 
					
						
							|  |  |  |             ... | 
					
						
							| 
									
										
										
										
											2019-05-26 09:37:48 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-06-05 15:16:09 +01:00
										 |  |  |         MODE = Literal['r', 'rb', 'w', 'wb'] | 
					
						
							|  |  |  |         def open_helper(file: str, mode: MODE) -> str: | 
					
						
							|  |  |  |             ... | 
					
						
							| 
									
										
										
										
											2019-05-26 09:37:48 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-06-05 15:16:09 +01:00
										 |  |  |         open_helper('/some/path', 'r')  # Passes type check | 
					
						
							|  |  |  |         open_helper('/other/path', 'typo')  # Error in type checker | 
					
						
							| 
									
										
										
										
											2019-05-26 09:37:48 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-23 21:26:48 +03:00
										 |  |  |     Literal[...] cannot be subclassed. At runtime, an arbitrary value | 
					
						
							|  |  |  |     is allowed as type argument to Literal[...], but type checkers may | 
					
						
							|  |  |  |     impose restrictions. | 
					
						
							|  |  |  |     """
 | 
					
						
							|  |  |  |     # There is no '_type_check' call because arguments to Literal[...] are | 
					
						
							|  |  |  |     # values, not types. | 
					
						
							| 
									
										
										
										
											2020-11-17 04:23:19 +02:00
										 |  |  |     parameters = _flatten_literal_params(parameters) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     try: | 
					
						
							|  |  |  |         parameters = tuple(p for p, _ in _deduplicate(list(_value_and_type_iter(parameters)))) | 
					
						
							|  |  |  |     except TypeError:  # unhashable parameters | 
					
						
							|  |  |  |         pass | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-08-21 09:47:59 +03:00
										 |  |  |     return _LiteralGenericAlias(self, parameters) | 
					
						
							| 
									
										
										
										
											2019-05-26 09:37:48 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-05-22 10:14:11 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-10-08 00:44:31 +03:00
										 |  |  | @_SpecialForm | 
					
						
							|  |  |  | def TypeAlias(self, parameters): | 
					
						
							| 
									
										
										
										
											2023-06-05 15:16:09 +01:00
										 |  |  |     """Special form for marking type aliases.
 | 
					
						
							| 
									
										
										
										
											2020-10-08 00:44:31 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-06-05 15:16:09 +01:00
										 |  |  |     Use TypeAlias to indicate that an assignment should | 
					
						
							|  |  |  |     be recognized as a proper type alias definition by type | 
					
						
							| 
									
										
										
										
											2023-06-07 01:21:16 +01:00
										 |  |  |     checkers. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     For example:: | 
					
						
							| 
									
										
										
										
											2020-10-08 00:44:31 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  |         Predicate: TypeAlias = Callable[..., bool] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     It's invalid when used anywhere except as in the example above. | 
					
						
							|  |  |  |     """
 | 
					
						
							|  |  |  |     raise TypeError(f"{self} is not subscriptable") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-12-24 12:33:48 +08:00
										 |  |  | @_SpecialForm | 
					
						
							|  |  |  | def Concatenate(self, parameters): | 
					
						
							| 
									
										
										
										
											2023-06-05 15:16:09 +01:00
										 |  |  |     """Special form for annotating higher-order functions.
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-06-07 01:21:16 +01:00
										 |  |  |     ``Concatenate`` can be used in conjunction with ``ParamSpec`` and | 
					
						
							|  |  |  |     ``Callable`` to represent a higher-order function which adds, removes or | 
					
						
							| 
									
										
										
										
											2023-06-05 15:16:09 +01:00
										 |  |  |     transforms the parameters of a callable. | 
					
						
							| 
									
										
										
										
											2020-12-24 12:33:48 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |     For example:: | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-06-05 15:16:09 +01:00
										 |  |  |         Callable[Concatenate[int, P], int] | 
					
						
							| 
									
										
										
										
											2020-12-24 12:33:48 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |     See PEP 612 for detailed information. | 
					
						
							|  |  |  |     """
 | 
					
						
							|  |  |  |     if parameters == (): | 
					
						
							|  |  |  |         raise TypeError("Cannot take a Concatenate of no types.") | 
					
						
							|  |  |  |     if not isinstance(parameters, tuple): | 
					
						
							|  |  |  |         parameters = (parameters,) | 
					
						
							| 
									
										
										
										
											2022-04-30 00:01:40 +03:00
										 |  |  |     if not (parameters[-1] is ... or isinstance(parameters[-1], ParamSpec)): | 
					
						
							| 
									
										
										
										
											2020-12-24 12:33:48 +08:00
										 |  |  |         raise TypeError("The last parameter to Concatenate should be a " | 
					
						
							| 
									
										
										
										
											2022-04-30 00:01:40 +03:00
										 |  |  |                         "ParamSpec variable or ellipsis.") | 
					
						
							| 
									
										
										
										
											2020-12-24 12:33:48 +08:00
										 |  |  |     msg = "Concatenate[arg, ...]: each arg must be a type." | 
					
						
							| 
									
										
										
										
											2022-01-27 14:34:55 +02:00
										 |  |  |     parameters = (*(_type_check(p, msg) for p in parameters[:-1]), parameters[-1]) | 
					
						
							| 
									
										
										
										
											2023-05-11 16:41:26 -07:00
										 |  |  |     return _ConcatenateGenericAlias(self, parameters) | 
					
						
							| 
									
										
										
										
											2020-12-24 12:33:48 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-04-27 22:31:04 +08:00
										 |  |  | @_SpecialForm | 
					
						
							|  |  |  | def TypeGuard(self, parameters): | 
					
						
							| 
									
										
										
										
											2024-04-09 06:50:37 -04:00
										 |  |  |     """Special typing construct for marking user-defined type predicate functions.
 | 
					
						
							| 
									
										
										
										
											2023-06-05 15:16:09 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |     ``TypeGuard`` can be used to annotate the return type of a user-defined | 
					
						
							| 
									
										
										
										
											2024-04-09 06:50:37 -04:00
										 |  |  |     type predicate function.  ``TypeGuard`` only accepts a single type argument. | 
					
						
							| 
									
										
										
										
											2021-04-27 22:31:04 +08:00
										 |  |  |     At runtime, functions marked this way should return a boolean. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     ``TypeGuard`` aims to benefit *type narrowing* -- a technique used by static | 
					
						
							|  |  |  |     type checkers to determine a more precise type of an expression within a | 
					
						
							|  |  |  |     program's code flow.  Usually type narrowing is done by analyzing | 
					
						
							|  |  |  |     conditional code flow and applying the narrowing to a block of code.  The | 
					
						
							| 
									
										
										
										
											2024-04-09 06:50:37 -04:00
										 |  |  |     conditional expression here is sometimes referred to as a "type predicate". | 
					
						
							| 
									
										
										
										
											2021-04-27 22:31:04 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |     Sometimes it would be convenient to use a user-defined boolean function | 
					
						
							| 
									
										
										
										
											2024-04-09 06:50:37 -04:00
										 |  |  |     as a type predicate.  Such a function should use ``TypeGuard[...]`` or | 
					
						
							|  |  |  |     ``TypeIs[...]`` as its return type to alert static type checkers to | 
					
						
							|  |  |  |     this intention. ``TypeGuard`` should be used over ``TypeIs`` when narrowing | 
					
						
							|  |  |  |     from an incompatible type (e.g., ``list[object]`` to ``list[int]``) or when | 
					
						
							|  |  |  |     the function does not return ``True`` for all instances of the narrowed type. | 
					
						
							| 
									
										
										
										
											2021-04-27 22:31:04 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-04-09 06:50:37 -04:00
										 |  |  |     Using  ``-> TypeGuard[NarrowedType]`` tells the static type checker that | 
					
						
							|  |  |  |     for a given function: | 
					
						
							| 
									
										
										
										
											2021-04-27 22:31:04 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |     1. The return value is a boolean. | 
					
						
							|  |  |  |     2. If the return value is ``True``, the type of its argument | 
					
						
							| 
									
										
										
										
											2024-04-09 06:50:37 -04:00
										 |  |  |        is ``NarrowedType``. | 
					
						
							| 
									
										
										
										
											2021-04-27 22:31:04 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-04-04 06:39:16 -04:00
										 |  |  |     For example:: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |          def is_str_list(val: list[object]) -> TypeGuard[list[str]]: | 
					
						
							|  |  |  |              '''Determines whether all objects in the list are strings''' | 
					
						
							|  |  |  |              return all(isinstance(x, str) for x in val) | 
					
						
							| 
									
										
										
										
											2021-04-27 22:31:04 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-04-04 06:39:16 -04:00
										 |  |  |          def func1(val: list[object]): | 
					
						
							|  |  |  |              if is_str_list(val): | 
					
						
							|  |  |  |                  # Type of ``val`` is narrowed to ``list[str]``. | 
					
						
							|  |  |  |                  print(" ".join(val)) | 
					
						
							|  |  |  |              else: | 
					
						
							|  |  |  |                  # Type of ``val`` remains as ``list[object]``. | 
					
						
							|  |  |  |                  print("Not a list of strings!") | 
					
						
							| 
									
										
										
										
											2021-04-27 22:31:04 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |     Strict type narrowing is not enforced -- ``TypeB`` need not be a narrower | 
					
						
							|  |  |  |     form of ``TypeA`` (it can even be a wider form) and this may lead to | 
					
						
							|  |  |  |     type-unsafe results.  The main reason is to allow for things like | 
					
						
							| 
									
										
										
										
											2024-04-04 06:39:16 -04:00
										 |  |  |     narrowing ``list[object]`` to ``list[str]`` even though the latter is not | 
					
						
							|  |  |  |     a subtype of the former, since ``list`` is invariant.  The responsibility of | 
					
						
							| 
									
										
										
										
											2024-04-09 06:50:37 -04:00
										 |  |  |     writing type-safe type predicates is left to the user. | 
					
						
							| 
									
										
										
										
											2021-04-27 22:31:04 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |     ``TypeGuard`` also works with type variables.  For more information, see | 
					
						
							|  |  |  |     PEP 647 (User-Defined Type Guards). | 
					
						
							|  |  |  |     """
 | 
					
						
							|  |  |  |     item = _type_check(parameters, f'{self} accepts only single type.') | 
					
						
							| 
									
										
										
										
											2021-08-21 09:47:59 +03:00
										 |  |  |     return _GenericAlias(self, (item,)) | 
					
						
							| 
									
										
										
										
											2021-04-27 22:31:04 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-04-09 06:50:37 -04:00
										 |  |  | @_SpecialForm | 
					
						
							|  |  |  | def TypeIs(self, parameters): | 
					
						
							|  |  |  |     """Special typing construct for marking user-defined type predicate functions.
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     ``TypeIs`` can be used to annotate the return type of a user-defined | 
					
						
							|  |  |  |     type predicate function.  ``TypeIs`` only accepts a single type argument. | 
					
						
							|  |  |  |     At runtime, functions marked this way should return a boolean and accept | 
					
						
							|  |  |  |     at least one argument. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     ``TypeIs`` aims to benefit *type narrowing* -- a technique used by static | 
					
						
							|  |  |  |     type checkers to determine a more precise type of an expression within a | 
					
						
							|  |  |  |     program's code flow.  Usually type narrowing is done by analyzing | 
					
						
							|  |  |  |     conditional code flow and applying the narrowing to a block of code.  The | 
					
						
							|  |  |  |     conditional expression here is sometimes referred to as a "type predicate". | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     Sometimes it would be convenient to use a user-defined boolean function | 
					
						
							|  |  |  |     as a type predicate.  Such a function should use ``TypeIs[...]`` or | 
					
						
							|  |  |  |     ``TypeGuard[...]`` as its return type to alert static type checkers to | 
					
						
							|  |  |  |     this intention.  ``TypeIs`` usually has more intuitive behavior than | 
					
						
							|  |  |  |     ``TypeGuard``, but it cannot be used when the input and output types | 
					
						
							|  |  |  |     are incompatible (e.g., ``list[object]`` to ``list[int]``) or when the | 
					
						
							|  |  |  |     function does not return ``True`` for all instances of the narrowed type. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     Using  ``-> TypeIs[NarrowedType]`` tells the static type checker that for | 
					
						
							|  |  |  |     a given function: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     1. The return value is a boolean. | 
					
						
							|  |  |  |     2. If the return value is ``True``, the type of its argument | 
					
						
							|  |  |  |        is the intersection of the argument's original type and | 
					
						
							|  |  |  |        ``NarrowedType``. | 
					
						
							|  |  |  |     3. If the return value is ``False``, the type of its argument | 
					
						
							|  |  |  |        is narrowed to exclude ``NarrowedType``. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     For example:: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         from typing import assert_type, final, TypeIs | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         class Parent: pass | 
					
						
							|  |  |  |         class Child(Parent): pass | 
					
						
							|  |  |  |         @final | 
					
						
							|  |  |  |         class Unrelated: pass | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         def is_parent(val: object) -> TypeIs[Parent]: | 
					
						
							|  |  |  |             return isinstance(val, Parent) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         def run(arg: Child | Unrelated): | 
					
						
							|  |  |  |             if is_parent(arg): | 
					
						
							|  |  |  |                 # Type of ``arg`` is narrowed to the intersection | 
					
						
							|  |  |  |                 # of ``Parent`` and ``Child``, which is equivalent to | 
					
						
							|  |  |  |                 # ``Child``. | 
					
						
							|  |  |  |                 assert_type(arg, Child) | 
					
						
							|  |  |  |             else: | 
					
						
							|  |  |  |                 # Type of ``arg`` is narrowed to exclude ``Parent``, | 
					
						
							|  |  |  |                 # so only ``Unrelated`` is left. | 
					
						
							|  |  |  |                 assert_type(arg, Unrelated) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     The type inside ``TypeIs`` must be consistent with the type of the | 
					
						
							|  |  |  |     function's argument; if it is not, static type checkers will raise | 
					
						
							|  |  |  |     an error.  An incorrectly written ``TypeIs`` function can lead to | 
					
						
							|  |  |  |     unsound behavior in the type system; it is the user's responsibility | 
					
						
							|  |  |  |     to write such functions in a type-safe manner. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     ``TypeIs`` also works with type variables.  For more information, see | 
					
						
							|  |  |  |     PEP 742 (Narrowing types with ``TypeIs``). | 
					
						
							|  |  |  |     """
 | 
					
						
							|  |  |  |     item = _type_check(parameters, f'{self} accepts only single type.') | 
					
						
							|  |  |  |     return _GenericAlias(self, (item,)) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-07-23 14:16:50 -07:00
										 |  |  | def _make_forward_ref(code, **kwargs): | 
					
						
							|  |  |  |     forward_ref = ForwardRef(code, **kwargs) | 
					
						
							|  |  |  |     # For compatibility, eagerly compile the forwardref's code. | 
					
						
							|  |  |  |     forward_ref.__forward_code__ | 
					
						
							|  |  |  |     return forward_ref | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | def evaluate_forward_ref( | 
					
						
							|  |  |  |     forward_ref, | 
					
						
							|  |  |  |     *, | 
					
						
							|  |  |  |     owner=None, | 
					
						
							|  |  |  |     globals=None, | 
					
						
							|  |  |  |     locals=None, | 
					
						
							| 
									
										
										
										
											2025-01-09 18:15:13 +03:00
										 |  |  |     type_params=_sentinel, | 
					
						
							| 
									
										
										
										
											2024-07-23 14:16:50 -07:00
										 |  |  |     format=annotationlib.Format.VALUE, | 
					
						
							|  |  |  |     _recursive_guard=frozenset(), | 
					
						
							|  |  |  | ): | 
					
						
							|  |  |  |     """Evaluate a forward reference as a type hint.
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     This is similar to calling the ForwardRef.evaluate() method, | 
					
						
							|  |  |  |     but unlike that method, evaluate_forward_ref() also: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     * Recursively evaluates forward references nested within the type hint. | 
					
						
							|  |  |  |     * Rejects certain objects that are not valid type hints. | 
					
						
							|  |  |  |     * Replaces type hints that evaluate to None with types.NoneType. | 
					
						
							| 
									
										
										
										
											2024-09-26 13:49:48 -07:00
										 |  |  |     * Supports the *FORWARDREF* and *STRING* formats. | 
					
						
							| 
									
										
										
										
											2024-07-23 14:16:50 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |     *forward_ref* must be an instance of ForwardRef. *owner*, if given, | 
					
						
							|  |  |  |     should be the object that holds the annotations that the forward reference | 
					
						
							|  |  |  |     derived from, such as a module, class object, or function. It is used to | 
					
						
							|  |  |  |     infer the namespaces to use for looking up names. *globals* and *locals* | 
					
						
							|  |  |  |     can also be explicitly given to provide the global and local namespaces. | 
					
						
							|  |  |  |     *type_params* is a tuple of type parameters that are in scope when | 
					
						
							|  |  |  |     evaluating the forward reference. This parameter must be provided (though | 
					
						
							|  |  |  |     it may be an empty tuple) if *owner* is not given and the forward reference | 
					
						
							|  |  |  |     does not already have an owner set. *format* specifies the format of the | 
					
						
							| 
									
										
										
										
											2024-08-07 14:39:16 +08:00
										 |  |  |     annotation and is a member of the annotationlib.Format enum. | 
					
						
							| 
									
										
										
										
											2015-05-22 10:14:11 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-07-23 14:16:50 -07:00
										 |  |  |     """
 | 
					
						
							|  |  |  |     if type_params is _sentinel: | 
					
						
							|  |  |  |         _deprecation_warning_for_no_type_params_passed("typing.evaluate_forward_ref") | 
					
						
							|  |  |  |         type_params = () | 
					
						
							| 
									
										
										
										
											2024-09-26 13:49:48 -07:00
										 |  |  |     if format == annotationlib.Format.STRING: | 
					
						
							| 
									
										
										
										
											2024-07-23 14:16:50 -07:00
										 |  |  |         return forward_ref.__forward_arg__ | 
					
						
							|  |  |  |     if forward_ref.__forward_arg__ in _recursive_guard: | 
					
						
							|  |  |  |         return forward_ref | 
					
						
							| 
									
										
										
										
											2022-03-26 16:55:35 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-07-23 14:16:50 -07:00
										 |  |  |     try: | 
					
						
							|  |  |  |         value = forward_ref.evaluate(globals=globals, locals=locals, | 
					
						
							|  |  |  |                                      type_params=type_params, owner=owner) | 
					
						
							|  |  |  |     except NameError: | 
					
						
							|  |  |  |         if format == annotationlib.Format.FORWARDREF: | 
					
						
							|  |  |  |             return forward_ref | 
					
						
							| 
									
										
										
										
											2022-03-26 16:55:35 +00:00
										 |  |  |         else: | 
					
						
							| 
									
										
										
										
											2024-07-23 14:16:50 -07:00
										 |  |  |             raise | 
					
						
							| 
									
										
										
										
											2021-10-17 00:12:58 +09:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-07-23 14:16:50 -07:00
										 |  |  |     type_ = _type_check( | 
					
						
							|  |  |  |         value, | 
					
						
							|  |  |  |         "Forward references must evaluate to types.", | 
					
						
							|  |  |  |         is_argument=forward_ref.__forward_is_argument__, | 
					
						
							|  |  |  |         allow_special_forms=forward_ref.__forward_is_class__, | 
					
						
							|  |  |  |     ) | 
					
						
							|  |  |  |     return _eval_type( | 
					
						
							|  |  |  |         type_, | 
					
						
							|  |  |  |         globals, | 
					
						
							|  |  |  |         locals, | 
					
						
							|  |  |  |         type_params, | 
					
						
							|  |  |  |         recursive_guard=_recursive_guard | {forward_ref.__forward_arg__}, | 
					
						
							|  |  |  |         format=format, | 
					
						
							|  |  |  |         owner=owner, | 
					
						
							|  |  |  |     ) | 
					
						
							| 
									
										
										
										
											2015-08-05 12:11:06 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-03-08 04:02:55 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | def _is_unpacked_typevartuple(x: Any) -> bool: | 
					
						
							| 
									
										
										
										
											2022-05-08 18:32:32 +03:00
										 |  |  |     return ((not isinstance(x, type)) and | 
					
						
							|  |  |  |             getattr(x, '__typing_is_unpacked_typevartuple__', False)) | 
					
						
							| 
									
										
										
										
											2022-03-08 04:02:55 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | def _is_typevar_like(x: Any) -> bool: | 
					
						
							|  |  |  |     return isinstance(x, (TypeVar, ParamSpec)) or _is_unpacked_typevartuple(x) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-05-15 20:36:23 -07:00
										 |  |  | def _typevar_subst(self, arg): | 
					
						
							|  |  |  |     msg = "Parameters to generic types must be types." | 
					
						
							|  |  |  |     arg = _type_check(arg, msg, is_argument=True) | 
					
						
							|  |  |  |     if ((isinstance(arg, _GenericAlias) and arg.__origin__ is Unpack) or | 
					
						
							|  |  |  |         (isinstance(arg, GenericAlias) and getattr(arg, '__unpacked__', False))): | 
					
						
							|  |  |  |         raise TypeError(f"{arg} is not valid as type argument") | 
					
						
							|  |  |  |     return arg | 
					
						
							| 
									
										
										
										
											2018-03-26 23:01:12 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-05-22 10:14:11 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-05-15 20:36:23 -07:00
										 |  |  | def _typevartuple_prepare_subst(self, alias, args): | 
					
						
							|  |  |  |     params = alias.__parameters__ | 
					
						
							|  |  |  |     typevartuple_index = params.index(self) | 
					
						
							|  |  |  |     for param in params[typevartuple_index + 1:]: | 
					
						
							|  |  |  |         if isinstance(param, TypeVarTuple): | 
					
						
							|  |  |  |             raise TypeError(f"More than one TypeVarTuple parameter in {alias}") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     alen = len(args) | 
					
						
							|  |  |  |     plen = len(params) | 
					
						
							|  |  |  |     left = typevartuple_index | 
					
						
							|  |  |  |     right = plen - typevartuple_index - 1 | 
					
						
							|  |  |  |     var_tuple_index = None | 
					
						
							|  |  |  |     fillarg = None | 
					
						
							|  |  |  |     for k, arg in enumerate(args): | 
					
						
							|  |  |  |         if not isinstance(arg, type): | 
					
						
							|  |  |  |             subargs = getattr(arg, '__typing_unpacked_tuple_args__', None) | 
					
						
							|  |  |  |             if subargs and len(subargs) == 2 and subargs[-1] is ...: | 
					
						
							|  |  |  |                 if var_tuple_index is not None: | 
					
						
							|  |  |  |                     raise TypeError("More than one unpacked arbitrary-length tuple argument") | 
					
						
							|  |  |  |                 var_tuple_index = k | 
					
						
							|  |  |  |                 fillarg = subargs[0] | 
					
						
							|  |  |  |     if var_tuple_index is not None: | 
					
						
							|  |  |  |         left = min(left, var_tuple_index) | 
					
						
							|  |  |  |         right = min(right, alen - var_tuple_index - 1) | 
					
						
							|  |  |  |     elif left + right > alen: | 
					
						
							|  |  |  |         raise TypeError(f"Too few arguments for {alias};" | 
					
						
							|  |  |  |                         f" actual {alen}, expected at least {plen-1}") | 
					
						
							| 
									
										
										
										
											2024-05-03 06:17:32 -07:00
										 |  |  |     if left == alen - right and self.has_default(): | 
					
						
							|  |  |  |         replacement = _unpack_args(self.__default__) | 
					
						
							|  |  |  |     else: | 
					
						
							|  |  |  |         replacement = args[left: alen - right] | 
					
						
							| 
									
										
										
										
											2022-03-11 10:47:26 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-05-15 20:36:23 -07:00
										 |  |  |     return ( | 
					
						
							|  |  |  |         *args[:left], | 
					
						
							|  |  |  |         *([fillarg]*(typevartuple_index - left)), | 
					
						
							| 
									
										
										
										
											2024-05-03 06:17:32 -07:00
										 |  |  |         replacement, | 
					
						
							| 
									
										
										
										
											2023-05-15 20:36:23 -07:00
										 |  |  |         *([fillarg]*(plen - right - left - typevartuple_index - 1)), | 
					
						
							|  |  |  |         *args[alen - right:], | 
					
						
							|  |  |  |     ) | 
					
						
							| 
									
										
										
										
											2020-09-09 13:23:24 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-03-08 04:02:55 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-05-15 20:36:23 -07:00
										 |  |  | def _paramspec_subst(self, arg): | 
					
						
							|  |  |  |     if isinstance(arg, (list, tuple)): | 
					
						
							|  |  |  |         arg = tuple(_type_check(a, "Expected a type.") for a in arg) | 
					
						
							|  |  |  |     elif not _is_param_expr(arg): | 
					
						
							|  |  |  |         raise TypeError(f"Expected a list of types, an ellipsis, " | 
					
						
							|  |  |  |                         f"ParamSpec, or Concatenate. Got {arg}") | 
					
						
							|  |  |  |     return arg | 
					
						
							| 
									
										
										
										
											2022-03-08 04:02:55 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-05-15 20:36:23 -07:00
										 |  |  | def _paramspec_prepare_subst(self, alias, args): | 
					
						
							|  |  |  |     params = alias.__parameters__ | 
					
						
							|  |  |  |     i = params.index(self) | 
					
						
							| 
									
										
										
										
											2024-05-03 06:17:32 -07:00
										 |  |  |     if i == len(args) and self.has_default(): | 
					
						
							|  |  |  |         args = [*args, self.__default__] | 
					
						
							| 
									
										
										
										
											2023-05-15 20:36:23 -07:00
										 |  |  |     if i >= len(args): | 
					
						
							|  |  |  |         raise TypeError(f"Too few arguments for {alias}") | 
					
						
							|  |  |  |     # Special case where Z[[int, str, bool]] == Z[int, str, bool] in PEP 612. | 
					
						
							|  |  |  |     if len(params) == 1 and not _is_param_expr(args[0]): | 
					
						
							|  |  |  |         assert i == 0 | 
					
						
							|  |  |  |         args = (args,) | 
					
						
							|  |  |  |     # Convert lists to tuples to help other libraries cache the results. | 
					
						
							|  |  |  |     elif isinstance(args[i], list): | 
					
						
							|  |  |  |         args = (*args[:i], tuple(args[i]), *args[i+1:]) | 
					
						
							|  |  |  |     return args | 
					
						
							| 
									
										
										
										
											2022-03-08 04:02:55 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-05-15 20:36:23 -07:00
										 |  |  | @_tp_cache | 
					
						
							| 
									
										
										
										
											2024-05-03 06:17:32 -07:00
										 |  |  | def _generic_class_getitem(cls, args): | 
					
						
							| 
									
										
										
										
											2023-05-15 20:36:23 -07:00
										 |  |  |     """Parameterizes a generic class.
 | 
					
						
							| 
									
										
										
										
											2022-03-08 04:02:55 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-05-15 20:36:23 -07:00
										 |  |  |     At least, parameterizing a generic class is the *main* thing this method | 
					
						
							|  |  |  |     does. For example, for some generic class `Foo`, this is called when we | 
					
						
							| 
									
										
										
										
											2024-05-03 06:17:32 -07:00
										 |  |  |     do `Foo[int]` - there, with `cls=Foo` and `args=int`. | 
					
						
							| 
									
										
										
										
											2022-04-22 05:22:53 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-05-15 20:36:23 -07:00
										 |  |  |     However, note that this method is also called when defining generic | 
					
						
							|  |  |  |     classes in the first place with `class Foo(Generic[T]): ...`. | 
					
						
							| 
									
										
										
										
											2022-03-08 04:02:55 +00:00
										 |  |  |     """
 | 
					
						
							| 
									
										
										
										
											2024-05-03 06:17:32 -07:00
										 |  |  |     if not isinstance(args, tuple): | 
					
						
							|  |  |  |         args = (args,) | 
					
						
							| 
									
										
										
										
											2022-03-08 04:02:55 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-05-03 06:17:32 -07:00
										 |  |  |     args = tuple(_type_convert(p) for p in args) | 
					
						
							| 
									
										
										
										
											2023-05-15 20:36:23 -07:00
										 |  |  |     is_generic_or_protocol = cls in (Generic, Protocol) | 
					
						
							| 
									
										
										
										
											2022-03-08 04:02:55 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-05-15 20:36:23 -07:00
										 |  |  |     if is_generic_or_protocol: | 
					
						
							|  |  |  |         # Generic and Protocol can only be subscripted with unique type variables. | 
					
						
							| 
									
										
										
										
											2024-05-03 06:17:32 -07:00
										 |  |  |         if not args: | 
					
						
							| 
									
										
										
										
											2023-05-15 20:36:23 -07:00
										 |  |  |             raise TypeError( | 
					
						
							|  |  |  |                 f"Parameter list to {cls.__qualname__}[...] cannot be empty" | 
					
						
							|  |  |  |             ) | 
					
						
							| 
									
										
										
										
											2024-05-03 06:17:32 -07:00
										 |  |  |         if not all(_is_typevar_like(p) for p in args): | 
					
						
							| 
									
										
										
										
											2023-05-15 20:36:23 -07:00
										 |  |  |             raise TypeError( | 
					
						
							|  |  |  |                 f"Parameters to {cls.__name__}[...] must all be type variables " | 
					
						
							|  |  |  |                 f"or parameter specification variables.") | 
					
						
							| 
									
										
										
										
											2024-05-03 06:17:32 -07:00
										 |  |  |         if len(set(args)) != len(args): | 
					
						
							| 
									
										
										
										
											2023-05-15 20:36:23 -07:00
										 |  |  |             raise TypeError( | 
					
						
							|  |  |  |                 f"Parameters to {cls.__name__}[...] must all be unique") | 
					
						
							|  |  |  |     else: | 
					
						
							|  |  |  |         # Subscripting a regular Generic subclass. | 
					
						
							|  |  |  |         for param in cls.__parameters__: | 
					
						
							|  |  |  |             prepare = getattr(param, '__typing_prepare_subst__', None) | 
					
						
							|  |  |  |             if prepare is not None: | 
					
						
							| 
									
										
										
										
											2024-05-03 06:17:32 -07:00
										 |  |  |                 args = prepare(cls, args) | 
					
						
							|  |  |  |         _check_generic_specialization(cls, args) | 
					
						
							| 
									
										
										
										
											2022-03-11 10:47:26 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-05-15 20:36:23 -07:00
										 |  |  |         new_args = [] | 
					
						
							| 
									
										
										
										
											2024-05-03 06:17:32 -07:00
										 |  |  |         for param, new_arg in zip(cls.__parameters__, args): | 
					
						
							| 
									
										
										
										
											2022-06-12 16:22:01 +03:00
										 |  |  |             if isinstance(param, TypeVarTuple): | 
					
						
							| 
									
										
										
										
											2023-05-15 20:36:23 -07:00
										 |  |  |                 new_args.extend(new_arg) | 
					
						
							|  |  |  |             else: | 
					
						
							|  |  |  |                 new_args.append(new_arg) | 
					
						
							| 
									
										
										
										
											2024-05-03 06:17:32 -07:00
										 |  |  |         args = tuple(new_args) | 
					
						
							| 
									
										
										
										
											2020-12-24 12:33:48 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-05-03 06:17:32 -07:00
										 |  |  |     return _GenericAlias(cls, args) | 
					
						
							| 
									
										
										
										
											2020-12-24 12:33:48 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-04-10 19:57:05 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-05-15 20:36:23 -07:00
										 |  |  | def _generic_init_subclass(cls, *args, **kwargs): | 
					
						
							|  |  |  |     super(Generic, cls).__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' and | 
					
						
							|  |  |  |                     type(cls) != _TypedDictMeta) | 
					
						
							|  |  |  |     if error: | 
					
						
							|  |  |  |         raise TypeError("Cannot inherit from plain Generic") | 
					
						
							|  |  |  |     if '__orig_bases__' in cls.__dict__: | 
					
						
							| 
									
										
										
										
											2024-05-10 09:55:49 -07:00
										 |  |  |         tvars = _collect_type_parameters(cls.__orig_bases__) | 
					
						
							| 
									
										
										
										
											2023-05-15 20:36:23 -07:00
										 |  |  |         # 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 times.") | 
					
						
							|  |  |  |                 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) | 
					
						
							| 
									
										
										
										
											2022-03-11 10:47:26 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-10-29 08:54:56 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-01-20 11:23:59 +00:00
										 |  |  | def _is_dunder(attr): | 
					
						
							|  |  |  |     return attr.startswith('__') and attr.endswith('__') | 
					
						
							| 
									
										
										
										
											2017-01-17 20:43:28 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-07 04:09:33 +03:00
										 |  |  | class _BaseGenericAlias(_Final, _root=True): | 
					
						
							| 
									
										
										
										
											2023-06-05 15:16:09 +01:00
										 |  |  |     """The central part of the internal API.
 | 
					
						
							| 
									
										
										
										
											2016-10-29 08:54:56 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-01-20 11:23:59 +00:00
										 |  |  |     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 | 
					
						
							| 
									
										
										
										
											2023-06-05 15:16:09 +01:00
										 |  |  |     have 'name' always set. If 'inst' is False, then the alias can't be instantiated; | 
					
						
							| 
									
										
										
										
											2018-01-20 11:23:59 +00:00
										 |  |  |     this is used by e.g. typing.List and typing.Dict. | 
					
						
							| 
									
										
										
										
											2016-10-29 08:54:56 -07:00
										 |  |  |     """
 | 
					
						
							| 
									
										
										
										
											2023-06-05 15:16:09 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-10 11:53:16 +03:00
										 |  |  |     def __init__(self, origin, *, inst=True, name=None): | 
					
						
							| 
									
										
										
										
											2018-01-20 11:23:59 +00:00
										 |  |  |         self._inst = inst | 
					
						
							|  |  |  |         self._name = name | 
					
						
							| 
									
										
										
										
											2016-10-29 08:54:56 -07:00
										 |  |  |         self.__origin__ = origin | 
					
						
							| 
									
										
										
										
											2018-01-20 11:23:59 +00:00
										 |  |  |         self.__slots__ = None  # This is not documented. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def __call__(self, *args, **kwargs): | 
					
						
							|  |  |  |         if not self._inst: | 
					
						
							|  |  |  |             raise TypeError(f"Type {self._name} cannot be instantiated; " | 
					
						
							| 
									
										
										
										
											2020-05-07 04:09:33 +03:00
										 |  |  |                             f"use {self.__origin__.__name__}() instead") | 
					
						
							| 
									
										
										
										
											2018-01-20 11:23:59 +00:00
										 |  |  |         result = self.__origin__(*args, **kwargs) | 
					
						
							| 
									
										
										
										
											2016-10-29 08:54:56 -07:00
										 |  |  |         try: | 
					
						
							| 
									
										
										
										
											2018-01-20 11:23:59 +00:00
										 |  |  |             result.__orig_class__ = self | 
					
						
							| 
									
										
										
										
											2024-02-09 17:11:37 -05:00
										 |  |  |         # Some objects raise TypeError (or something even more exotic) | 
					
						
							|  |  |  |         # if you try to set attributes on them; we guard against that here | 
					
						
							|  |  |  |         except Exception: | 
					
						
							| 
									
										
										
										
											2016-10-29 08:54:56 -07:00
										 |  |  |             pass | 
					
						
							| 
									
										
										
										
											2018-01-20 11:23:59 +00:00
										 |  |  |         return result | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def __mro_entries__(self, bases): | 
					
						
							| 
									
										
										
										
											2020-05-07 04:09:33 +03:00
										 |  |  |         res = [] | 
					
						
							|  |  |  |         if self.__origin__ not in bases: | 
					
						
							|  |  |  |             res.append(self.__origin__) | 
					
						
							| 
									
										
										
										
											2024-02-09 12:19:09 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |         # Check if any base that occurs after us in `bases` is either itself a | 
					
						
							|  |  |  |         # subclass of Generic, or something which will add a subclass of Generic | 
					
						
							|  |  |  |         # to `__bases__` via its `__mro_entries__`. If not, add Generic | 
					
						
							|  |  |  |         # ourselves. The goal is to ensure that Generic (or a subclass) will | 
					
						
							|  |  |  |         # appear exactly once in the final bases tuple. If we let it appear | 
					
						
							|  |  |  |         # multiple times, we risk "can't form a consistent MRO" errors. | 
					
						
							| 
									
										
										
										
											2020-05-07 04:09:33 +03:00
										 |  |  |         i = bases.index(self) | 
					
						
							|  |  |  |         for b in bases[i+1:]: | 
					
						
							| 
									
										
										
										
											2024-02-09 12:19:09 -07:00
										 |  |  |             if isinstance(b, _BaseGenericAlias): | 
					
						
							|  |  |  |                 break | 
					
						
							|  |  |  |             if not isinstance(b, type): | 
					
						
							|  |  |  |                 meth = getattr(b, "__mro_entries__", None) | 
					
						
							|  |  |  |                 new_bases = meth(bases) if meth else None | 
					
						
							|  |  |  |                 if ( | 
					
						
							|  |  |  |                     isinstance(new_bases, tuple) and | 
					
						
							|  |  |  |                     any( | 
					
						
							|  |  |  |                         isinstance(b2, type) and issubclass(b2, Generic) | 
					
						
							|  |  |  |                         for b2 in new_bases | 
					
						
							|  |  |  |                     ) | 
					
						
							|  |  |  |                 ): | 
					
						
							|  |  |  |                     break | 
					
						
							|  |  |  |             elif issubclass(b, Generic): | 
					
						
							| 
									
										
										
										
											2020-05-07 04:09:33 +03:00
										 |  |  |                 break | 
					
						
							|  |  |  |         else: | 
					
						
							|  |  |  |             res.append(Generic) | 
					
						
							|  |  |  |         return tuple(res) | 
					
						
							| 
									
										
										
										
											2018-01-20 11:23:59 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     def __getattr__(self, attr): | 
					
						
							| 
									
										
										
										
											2021-07-19 20:22:12 +03:00
										 |  |  |         if attr in {'__name__', '__qualname__'}: | 
					
						
							| 
									
										
										
										
											2021-08-21 09:47:59 +03:00
										 |  |  |             return self._name or self.__origin__.__name__ | 
					
						
							| 
									
										
										
										
											2021-07-19 20:22:12 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-04-20 23:08:45 +03:00
										 |  |  |         # We are careful for copy and pickle. | 
					
						
							| 
									
										
										
										
											2022-03-04 20:51:55 -06:00
										 |  |  |         # Also for simplicity we don't relay any dunder names | 
					
						
							| 
									
										
										
										
											2018-01-20 11:23:59 +00:00
										 |  |  |         if '__origin__' in self.__dict__ and not _is_dunder(attr): | 
					
						
							|  |  |  |             return getattr(self.__origin__, attr) | 
					
						
							|  |  |  |         raise AttributeError(attr) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def __setattr__(self, attr, val): | 
					
						
							| 
									
										
										
										
											2024-05-06 15:35:06 -07:00
										 |  |  |         if _is_dunder(attr) or attr in {'_name', '_inst', '_nparams', '_defaults'}: | 
					
						
							| 
									
										
										
										
											2018-01-20 11:23:59 +00:00
										 |  |  |             super().__setattr__(attr, val) | 
					
						
							|  |  |  |         else: | 
					
						
							|  |  |  |             setattr(self.__origin__, attr, val) | 
					
						
							| 
									
										
										
										
											2016-10-29 08:54:56 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |     def __instancecheck__(self, obj): | 
					
						
							| 
									
										
										
										
											2018-01-20 11:23:59 +00:00
										 |  |  |         return self.__subclasscheck__(type(obj)) | 
					
						
							| 
									
										
										
										
											2016-10-29 08:54:56 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |     def __subclasscheck__(self, cls): | 
					
						
							| 
									
										
										
										
											2018-01-20 11:23:59 +00:00
										 |  |  |         raise TypeError("Subscripted generics cannot be used with" | 
					
						
							|  |  |  |                         " class and instance checks") | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-16 22:29:59 +08:00
										 |  |  |     def __dir__(self): | 
					
						
							|  |  |  |         return list(set(super().__dir__() | 
					
						
							|  |  |  |                 + [attr for attr in dir(self.__origin__) if not _is_dunder(attr)])) | 
					
						
							| 
									
										
										
										
											2018-05-26 21:19:26 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-03-08 04:02:55 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-10 11:53:16 +03:00
										 |  |  | # Special typing constructs Union, Optional, Generic, Callable and Tuple | 
					
						
							|  |  |  | # use three special attributes for internal bookkeeping of generic types: | 
					
						
							|  |  |  | # * __parameters__ is a tuple of unique free type parameters of a generic | 
					
						
							|  |  |  | #   type, for example, Dict[T, T].__parameters__ == (T,); | 
					
						
							|  |  |  | # * __origin__ keeps a reference to a type that was subscripted, | 
					
						
							|  |  |  | #   e.g., Union[T, int].__origin__ == Union, or the non-generic version of | 
					
						
							|  |  |  | #   the type. | 
					
						
							|  |  |  | # * __args__ is a tuple of all arguments used in subscripting, | 
					
						
							|  |  |  | #   e.g., Dict[T, int].__args__ == (T, int). | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-07 04:09:33 +03:00
										 |  |  | class _GenericAlias(_BaseGenericAlias, _root=True): | 
					
						
							| 
									
										
										
										
											2022-02-07 01:59:22 +00:00
										 |  |  |     # The type of parameterized generics. | 
					
						
							|  |  |  |     # | 
					
						
							|  |  |  |     # That is, for example, `type(List[int])` is `_GenericAlias`. | 
					
						
							|  |  |  |     # | 
					
						
							|  |  |  |     # Objects which are instances of this class include: | 
					
						
							|  |  |  |     # * Parameterized container types, e.g. `Tuple[int]`, `List[int]`. | 
					
						
							|  |  |  |     #  * Note that native container types, e.g. `tuple`, `list`, use | 
					
						
							|  |  |  |     #    `types.GenericAlias` instead. | 
					
						
							|  |  |  |     # * Parameterized classes: | 
					
						
							| 
									
										
										
										
											2023-06-05 15:16:09 +01:00
										 |  |  |     #     class C[T]: pass | 
					
						
							| 
									
										
										
										
											2022-02-07 01:59:22 +00:00
										 |  |  |     #     # C[int] is a _GenericAlias | 
					
						
							|  |  |  |     # * `Callable` aliases, generic `Callable` aliases, and | 
					
						
							|  |  |  |     #   parameterized `Callable` aliases: | 
					
						
							|  |  |  |     #     T = TypeVar('T') | 
					
						
							|  |  |  |     #     # _CallableGenericAlias inherits from _GenericAlias. | 
					
						
							|  |  |  |     #     A = Callable[[], None]  # _CallableGenericAlias | 
					
						
							|  |  |  |     #     B = Callable[[T], None]  # _CallableGenericAlias | 
					
						
							|  |  |  |     #     C = B[int]  # _CallableGenericAlias | 
					
						
							| 
									
										
										
										
											2024-04-09 06:50:37 -04:00
										 |  |  |     # * Parameterized `Final`, `ClassVar`, `TypeGuard`, and `TypeIs`: | 
					
						
							| 
									
										
										
										
											2022-02-07 01:59:22 +00:00
										 |  |  |     #     # All _GenericAlias | 
					
						
							|  |  |  |     #     Final[int] | 
					
						
							|  |  |  |     #     ClassVar[float] | 
					
						
							| 
									
										
										
										
											2024-04-09 06:50:37 -04:00
										 |  |  |     #     TypeGuard[bool] | 
					
						
							|  |  |  |     #     TypeIs[range] | 
					
						
							| 
									
										
										
										
											2022-02-07 01:59:22 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-05-11 16:41:26 -07:00
										 |  |  |     def __init__(self, origin, args, *, inst=True, name=None): | 
					
						
							| 
									
										
										
										
											2020-05-10 11:53:16 +03:00
										 |  |  |         super().__init__(origin, inst=inst, name=name) | 
					
						
							| 
									
										
										
										
											2022-02-07 01:59:22 +00:00
										 |  |  |         if not isinstance(args, tuple): | 
					
						
							|  |  |  |             args = (args,) | 
					
						
							| 
									
										
										
										
											2020-05-10 11:53:16 +03:00
										 |  |  |         self.__args__ = tuple(... if a is _TypingEllipsis else | 
					
						
							| 
									
										
										
										
											2022-02-07 01:59:22 +00:00
										 |  |  |                               a for a in args) | 
					
						
							| 
									
										
										
										
											2024-05-08 09:54:51 -07:00
										 |  |  |         enforce_default_ordering = origin in (Generic, Protocol) | 
					
						
							| 
									
										
										
										
											2024-05-10 09:55:49 -07:00
										 |  |  |         self.__parameters__ = _collect_type_parameters( | 
					
						
							| 
									
										
										
										
											2024-05-08 09:54:51 -07:00
										 |  |  |             args, | 
					
						
							|  |  |  |             enforce_default_ordering=enforce_default_ordering, | 
					
						
							|  |  |  |         ) | 
					
						
							| 
									
										
										
										
											2020-05-10 11:53:16 +03:00
										 |  |  |         if not name: | 
					
						
							|  |  |  |             self.__module__ = origin.__module__ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def __eq__(self, other): | 
					
						
							|  |  |  |         if not isinstance(other, _GenericAlias): | 
					
						
							|  |  |  |             return NotImplemented | 
					
						
							|  |  |  |         return (self.__origin__ == other.__origin__ | 
					
						
							|  |  |  |                 and self.__args__ == other.__args__) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def __hash__(self): | 
					
						
							|  |  |  |         return hash((self.__origin__, self.__args__)) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-09-09 13:23:24 -07:00
										 |  |  |     def __or__(self, right): | 
					
						
							|  |  |  |         return Union[self, right] | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-07-16 16:11:30 +03:00
										 |  |  |     def __ror__(self, left): | 
					
						
							|  |  |  |         return Union[left, self] | 
					
						
							| 
									
										
										
										
											2020-09-09 13:23:24 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-07 04:09:33 +03:00
										 |  |  |     @_tp_cache | 
					
						
							| 
									
										
										
										
											2022-02-07 01:59:22 +00:00
										 |  |  |     def __getitem__(self, args): | 
					
						
							|  |  |  |         # Parameterizes an already-parameterized object. | 
					
						
							|  |  |  |         # | 
					
						
							|  |  |  |         # For example, we arrive here doing something like: | 
					
						
							|  |  |  |         #   T1 = TypeVar('T1') | 
					
						
							|  |  |  |         #   T2 = TypeVar('T2') | 
					
						
							|  |  |  |         #   T3 = TypeVar('T3') | 
					
						
							|  |  |  |         #   class A(Generic[T1]): pass | 
					
						
							|  |  |  |         #   B = A[T2]  # B is a _GenericAlias | 
					
						
							|  |  |  |         #   C = B[T3]  # Invokes _GenericAlias.__getitem__ | 
					
						
							|  |  |  |         # | 
					
						
							|  |  |  |         # We also arrive here when parameterizing a generic `Callable` alias: | 
					
						
							|  |  |  |         #   T = TypeVar('T') | 
					
						
							|  |  |  |         #   C = Callable[[T], None] | 
					
						
							|  |  |  |         #   C[int]  # Invokes _GenericAlias.__getitem__ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-07 04:09:33 +03:00
										 |  |  |         if self.__origin__ in (Generic, Protocol): | 
					
						
							|  |  |  |             # Can't subscript Generic[...] or Protocol[...]. | 
					
						
							|  |  |  |             raise TypeError(f"Cannot subscript already-subscripted {self}") | 
					
						
							| 
									
										
										
										
											2022-05-08 18:32:32 +03:00
										 |  |  |         if not self.__parameters__: | 
					
						
							|  |  |  |             raise TypeError(f"{self} is not a generic class") | 
					
						
							| 
									
										
										
										
											2022-02-07 01:59:22 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |         # Preprocess `args`. | 
					
						
							|  |  |  |         if not isinstance(args, tuple): | 
					
						
							|  |  |  |             args = (args,) | 
					
						
							| 
									
										
										
										
											2024-05-03 06:17:32 -07:00
										 |  |  |         args = _unpack_args(*(_type_convert(p) for p in args)) | 
					
						
							| 
									
										
										
										
											2022-02-07 01:59:22 +00:00
										 |  |  |         new_args = self._determine_new_args(args) | 
					
						
							|  |  |  |         r = self.copy_with(new_args) | 
					
						
							|  |  |  |         return r | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def _determine_new_args(self, args): | 
					
						
							|  |  |  |         # Determines new __args__ for __getitem__. | 
					
						
							|  |  |  |         # | 
					
						
							|  |  |  |         # For example, suppose we had: | 
					
						
							|  |  |  |         #   T1 = TypeVar('T1') | 
					
						
							|  |  |  |         #   T2 = TypeVar('T2') | 
					
						
							|  |  |  |         #   class A(Generic[T1, T2]): pass | 
					
						
							|  |  |  |         #   T3 = TypeVar('T3') | 
					
						
							|  |  |  |         #   B = A[int, T3] | 
					
						
							|  |  |  |         #   C = B[str] | 
					
						
							|  |  |  |         # `B.__args__` is `(int, T3)`, so `C.__args__` should be `(int, str)`. | 
					
						
							|  |  |  |         # Unfortunately, this is harder than it looks, because if `T3` is | 
					
						
							|  |  |  |         # anything more exotic than a plain `TypeVar`, we need to consider | 
					
						
							|  |  |  |         # edge cases. | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-03-11 21:43:58 +02:00
										 |  |  |         params = self.__parameters__ | 
					
						
							| 
									
										
										
										
											2022-02-07 01:59:22 +00:00
										 |  |  |         # In the example above, this would be {T3: str} | 
					
						
							| 
									
										
										
										
											2022-06-12 16:22:01 +03:00
										 |  |  |         for param in params: | 
					
						
							|  |  |  |             prepare = getattr(param, '__typing_prepare_subst__', None) | 
					
						
							|  |  |  |             if prepare is not None: | 
					
						
							|  |  |  |                 args = prepare(self, args) | 
					
						
							| 
									
										
										
										
											2022-05-08 18:32:32 +03:00
										 |  |  |         alen = len(args) | 
					
						
							|  |  |  |         plen = len(params) | 
					
						
							| 
									
										
										
										
											2022-06-12 16:22:01 +03:00
										 |  |  |         if alen != plen: | 
					
						
							|  |  |  |             raise TypeError(f"Too {'many' if alen > plen else 'few'} arguments for {self};" | 
					
						
							|  |  |  |                             f" actual {alen}, expected {plen}") | 
					
						
							|  |  |  |         new_arg_by_param = dict(zip(params, args)) | 
					
						
							| 
									
										
										
										
											2023-03-23 19:26:11 +03:00
										 |  |  |         return tuple(self._make_substitution(self.__args__, new_arg_by_param)) | 
					
						
							| 
									
										
										
										
											2020-05-07 04:09:33 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-03-23 19:26:11 +03:00
										 |  |  |     def _make_substitution(self, args, new_arg_by_param): | 
					
						
							|  |  |  |         """Create a list of new type arguments.""" | 
					
						
							| 
									
										
										
										
											2020-05-07 04:09:33 +03:00
										 |  |  |         new_args = [] | 
					
						
							| 
									
										
										
										
											2023-03-23 19:26:11 +03:00
										 |  |  |         for old_arg in args: | 
					
						
							| 
									
										
										
										
											2022-11-01 09:33:09 +02:00
										 |  |  |             if isinstance(old_arg, type): | 
					
						
							|  |  |  |                 new_args.append(old_arg) | 
					
						
							|  |  |  |                 continue | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-03-11 21:43:58 +02:00
										 |  |  |             substfunc = getattr(old_arg, '__typing_subst__', None) | 
					
						
							|  |  |  |             if substfunc: | 
					
						
							|  |  |  |                 new_arg = substfunc(new_arg_by_param[old_arg]) | 
					
						
							| 
									
										
										
										
											2020-12-24 12:33:48 +08:00
										 |  |  |             else: | 
					
						
							| 
									
										
										
										
											2022-03-11 21:43:58 +02:00
										 |  |  |                 subparams = getattr(old_arg, '__parameters__', ()) | 
					
						
							|  |  |  |                 if not subparams: | 
					
						
							|  |  |  |                     new_arg = old_arg | 
					
						
							| 
									
										
										
										
											2022-03-11 10:47:26 +02:00
										 |  |  |                 else: | 
					
						
							| 
									
										
										
										
											2022-03-11 21:43:58 +02:00
										 |  |  |                     subargs = [] | 
					
						
							|  |  |  |                     for x in subparams: | 
					
						
							|  |  |  |                         if isinstance(x, TypeVarTuple): | 
					
						
							|  |  |  |                             subargs.extend(new_arg_by_param[x]) | 
					
						
							|  |  |  |                         else: | 
					
						
							|  |  |  |                             subargs.append(new_arg_by_param[x]) | 
					
						
							|  |  |  |                     new_arg = old_arg[tuple(subargs)] | 
					
						
							| 
									
										
										
										
											2022-02-07 01:59:22 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |             if self.__origin__ == collections.abc.Callable and isinstance(new_arg, tuple): | 
					
						
							|  |  |  |                 # Consider the following `Callable`. | 
					
						
							|  |  |  |                 #   C = Callable[[int], str] | 
					
						
							|  |  |  |                 # Here, `C.__args__` should be (int, str) - NOT ([int], str). | 
					
						
							|  |  |  |                 # That means that if we had something like... | 
					
						
							|  |  |  |                 #   P = ParamSpec('P') | 
					
						
							|  |  |  |                 #   T = TypeVar('T') | 
					
						
							|  |  |  |                 #   C = Callable[P, T] | 
					
						
							|  |  |  |                 #   D = C[[int, str], float] | 
					
						
							|  |  |  |                 # ...we need to be careful; `new_args` should end up as | 
					
						
							|  |  |  |                 # `(int, str, float)` rather than `([int, str], float)`. | 
					
						
							|  |  |  |                 new_args.extend(new_arg) | 
					
						
							| 
									
										
										
										
											2022-03-08 04:02:55 +00:00
										 |  |  |             elif _is_unpacked_typevartuple(old_arg): | 
					
						
							|  |  |  |                 # Consider the following `_GenericAlias`, `B`: | 
					
						
							|  |  |  |                 #   class A(Generic[*Ts]): ... | 
					
						
							|  |  |  |                 #   B = A[T, *Ts] | 
					
						
							|  |  |  |                 # If we then do: | 
					
						
							|  |  |  |                 #   B[float, int, str] | 
					
						
							|  |  |  |                 # The `new_arg` corresponding to `T` will be `float`, and the | 
					
						
							|  |  |  |                 # `new_arg` corresponding to `*Ts` will be `(int, str)`. We | 
					
						
							|  |  |  |                 # should join all these types together in a flat list | 
					
						
							|  |  |  |                 # `(float, int, str)` - so again, we should `extend`. | 
					
						
							|  |  |  |                 new_args.extend(new_arg) | 
					
						
							| 
									
										
										
										
											2023-03-23 19:26:11 +03:00
										 |  |  |             elif isinstance(old_arg, tuple): | 
					
						
							|  |  |  |                 # Corner case: | 
					
						
							|  |  |  |                 #    P = ParamSpec('P') | 
					
						
							|  |  |  |                 #    T = TypeVar('T') | 
					
						
							|  |  |  |                 #    class Base(Generic[P]): ... | 
					
						
							|  |  |  |                 # Can be substituted like this: | 
					
						
							|  |  |  |                 #    X = Base[[int, T]] | 
					
						
							|  |  |  |                 # In this case, `old_arg` will be a tuple: | 
					
						
							|  |  |  |                 new_args.append( | 
					
						
							|  |  |  |                     tuple(self._make_substitution(old_arg, new_arg_by_param)), | 
					
						
							|  |  |  |                 ) | 
					
						
							| 
									
										
										
										
											2022-02-07 01:59:22 +00:00
										 |  |  |             else: | 
					
						
							|  |  |  |                 new_args.append(new_arg) | 
					
						
							| 
									
										
										
										
											2023-03-23 19:26:11 +03:00
										 |  |  |         return new_args | 
					
						
							| 
									
										
										
										
											2020-05-07 04:09:33 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-02-07 01:59:22 +00:00
										 |  |  |     def copy_with(self, args): | 
					
						
							| 
									
										
										
										
											2023-05-11 16:41:26 -07:00
										 |  |  |         return self.__class__(self.__origin__, args, name=self._name, inst=self._inst) | 
					
						
							| 
									
										
										
										
											2020-05-07 04:09:33 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  |     def __repr__(self): | 
					
						
							|  |  |  |         if self._name: | 
					
						
							|  |  |  |             name = 'typing.' + self._name | 
					
						
							|  |  |  |         else: | 
					
						
							|  |  |  |             name = _type_repr(self.__origin__) | 
					
						
							| 
									
										
										
										
											2022-03-08 04:02:55 +00:00
										 |  |  |         if self.__args__: | 
					
						
							|  |  |  |             args = ", ".join([_type_repr(a) for a in self.__args__]) | 
					
						
							|  |  |  |         else: | 
					
						
							|  |  |  |             # To ensure the repr is eval-able. | 
					
						
							|  |  |  |             args = "()" | 
					
						
							| 
									
										
										
										
											2020-05-07 04:09:33 +03:00
										 |  |  |         return f'{name}[{args}]' | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def __reduce__(self): | 
					
						
							| 
									
										
										
										
											2018-05-26 21:19:26 +03:00
										 |  |  |         if self._name: | 
					
						
							|  |  |  |             origin = globals()[self._name] | 
					
						
							|  |  |  |         else: | 
					
						
							|  |  |  |             origin = self.__origin__ | 
					
						
							| 
									
										
										
										
											2020-05-07 04:09:33 +03:00
										 |  |  |         args = tuple(self.__args__) | 
					
						
							|  |  |  |         if len(args) == 1 and not isinstance(args[0], tuple): | 
					
						
							|  |  |  |             args, = args | 
					
						
							| 
									
										
										
										
											2018-05-26 21:19:26 +03:00
										 |  |  |         return operator.getitem, (origin, args) | 
					
						
							| 
									
										
										
										
											2018-03-26 23:01:12 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-07 04:09:33 +03:00
										 |  |  |     def __mro_entries__(self, bases): | 
					
						
							| 
									
										
										
										
											2021-08-18 22:08:32 +03:00
										 |  |  |         if isinstance(self.__origin__, _SpecialForm): | 
					
						
							|  |  |  |             raise TypeError(f"Cannot subclass {self!r}") | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-07 04:09:33 +03:00
										 |  |  |         if self._name:  # generic version of an ABC or built-in class | 
					
						
							|  |  |  |             return super().__mro_entries__(bases) | 
					
						
							|  |  |  |         if self.__origin__ is Generic: | 
					
						
							|  |  |  |             if Protocol in bases: | 
					
						
							|  |  |  |                 return () | 
					
						
							|  |  |  |             i = bases.index(self) | 
					
						
							|  |  |  |             for b in bases[i+1:]: | 
					
						
							|  |  |  |                 if isinstance(b, _BaseGenericAlias) and b is not self: | 
					
						
							|  |  |  |                     return () | 
					
						
							|  |  |  |         return (self.__origin__,) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-03-08 04:02:55 +00:00
										 |  |  |     def __iter__(self): | 
					
						
							|  |  |  |         yield Unpack[self] | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-07 04:09:33 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-10 11:53:16 +03:00
										 |  |  | # _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__). | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-05-08 14:21:28 +01:00
										 |  |  | class _SpecialGenericAlias(_NotIterable, _BaseGenericAlias, _root=True): | 
					
						
							| 
									
										
										
										
											2024-05-06 15:35:06 -07:00
										 |  |  |     def __init__(self, origin, nparams, *, inst=True, name=None, defaults=()): | 
					
						
							| 
									
										
										
										
											2020-05-07 04:09:33 +03:00
										 |  |  |         if name is None: | 
					
						
							|  |  |  |             name = origin.__name__ | 
					
						
							| 
									
										
										
										
											2020-05-10 11:53:16 +03:00
										 |  |  |         super().__init__(origin, inst=inst, name=name) | 
					
						
							|  |  |  |         self._nparams = nparams | 
					
						
							| 
									
										
										
										
											2024-05-06 15:35:06 -07:00
										 |  |  |         self._defaults = defaults | 
					
						
							| 
									
										
										
										
											2020-05-10 15:14:27 +03:00
										 |  |  |         if origin.__module__ == 'builtins': | 
					
						
							|  |  |  |             self.__doc__ = f'A generic version of {origin.__qualname__}.' | 
					
						
							|  |  |  |         else: | 
					
						
							|  |  |  |             self.__doc__ = f'A generic version of {origin.__module__}.{origin.__qualname__}.' | 
					
						
							| 
									
										
										
										
											2020-05-07 04:09:33 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  |     @_tp_cache | 
					
						
							|  |  |  |     def __getitem__(self, params): | 
					
						
							|  |  |  |         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) | 
					
						
							| 
									
										
										
										
											2024-05-06 15:35:06 -07:00
										 |  |  |         if (self._defaults | 
					
						
							|  |  |  |             and len(params) < self._nparams | 
					
						
							|  |  |  |             and len(params) + len(self._defaults) >= self._nparams | 
					
						
							|  |  |  |         ): | 
					
						
							|  |  |  |             params = (*params, *self._defaults[len(params) - self._nparams:]) | 
					
						
							| 
									
										
										
										
											2024-05-03 06:17:32 -07:00
										 |  |  |         actual_len = len(params) | 
					
						
							| 
									
										
										
										
											2024-05-06 15:35:06 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-05-03 06:17:32 -07:00
										 |  |  |         if actual_len != self._nparams: | 
					
						
							| 
									
										
										
										
											2024-05-06 15:35:06 -07:00
										 |  |  |             if self._defaults: | 
					
						
							|  |  |  |                 expected = f"at least {self._nparams - len(self._defaults)}" | 
					
						
							|  |  |  |             else: | 
					
						
							|  |  |  |                 expected = str(self._nparams) | 
					
						
							| 
									
										
										
										
											2024-05-03 06:17:32 -07:00
										 |  |  |             if not self._nparams: | 
					
						
							|  |  |  |                 raise TypeError(f"{self} is not a generic class") | 
					
						
							|  |  |  |             raise TypeError(f"Too {'many' if actual_len > self._nparams else 'few'} arguments for {self};" | 
					
						
							| 
									
										
										
										
											2024-05-06 15:35:06 -07:00
										 |  |  |                             f" actual {actual_len}, expected {expected}") | 
					
						
							| 
									
										
										
										
											2020-05-07 04:09:33 +03:00
										 |  |  |         return self.copy_with(params) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def copy_with(self, params): | 
					
						
							|  |  |  |         return _GenericAlias(self.__origin__, params, | 
					
						
							|  |  |  |                              name=self._name, inst=self._inst) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def __repr__(self): | 
					
						
							|  |  |  |         return 'typing.' + self._name | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     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): | 
					
						
							|  |  |  |         return self._name | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-09-09 13:23:24 -07:00
										 |  |  |     def __or__(self, right): | 
					
						
							|  |  |  |         return Union[self, right] | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-07-16 16:11:30 +03:00
										 |  |  |     def __ror__(self, left): | 
					
						
							|  |  |  |         return Union[left, self] | 
					
						
							| 
									
										
										
										
											2020-05-07 04:09:33 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-05-12 07:01:31 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-05-08 14:21:28 +01:00
										 |  |  | class _CallableGenericAlias(_NotIterable, _GenericAlias, _root=True): | 
					
						
							| 
									
										
										
										
											2020-05-07 04:09:33 +03:00
										 |  |  |     def __repr__(self): | 
					
						
							|  |  |  |         assert self._name == 'Callable' | 
					
						
							| 
									
										
										
										
											2020-12-24 12:33:48 +08:00
										 |  |  |         args = self.__args__ | 
					
						
							| 
									
										
										
										
											2021-08-04 21:07:01 +03:00
										 |  |  |         if len(args) == 2 and _is_param_expr(args[0]): | 
					
						
							| 
									
										
										
										
											2020-05-07 04:09:33 +03:00
										 |  |  |             return super().__repr__() | 
					
						
							|  |  |  |         return (f'typing.Callable' | 
					
						
							| 
									
										
										
										
											2020-12-24 12:33:48 +08:00
										 |  |  |                 f'[[{", ".join([_type_repr(a) for a in args[:-1]])}], ' | 
					
						
							|  |  |  |                 f'{_type_repr(args[-1])}]') | 
					
						
							| 
									
										
										
										
											2020-05-07 04:09:33 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  |     def __reduce__(self): | 
					
						
							|  |  |  |         args = self.__args__ | 
					
						
							| 
									
										
										
										
											2021-08-04 21:07:01 +03:00
										 |  |  |         if not (len(args) == 2 and _is_param_expr(args[0])): | 
					
						
							| 
									
										
										
										
											2020-05-07 04:09:33 +03:00
										 |  |  |             args = list(args[:-1]), args[-1] | 
					
						
							|  |  |  |         return operator.getitem, (Callable, args) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | class _CallableType(_SpecialGenericAlias, _root=True): | 
					
						
							|  |  |  |     def copy_with(self, params): | 
					
						
							|  |  |  |         return _CallableGenericAlias(self.__origin__, params, | 
					
						
							| 
									
										
										
										
											2023-05-11 16:41:26 -07:00
										 |  |  |                                      name=self._name, inst=self._inst) | 
					
						
							| 
									
										
										
										
											2018-01-20 11:23:59 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     def __getitem__(self, params): | 
					
						
							|  |  |  |         if not isinstance(params, tuple) or len(params) != 2: | 
					
						
							| 
									
										
										
										
											2016-10-29 08:54:56 -07:00
										 |  |  |             raise TypeError("Callable must be used as " | 
					
						
							|  |  |  |                             "Callable[[arg, ...], result].") | 
					
						
							| 
									
										
										
										
											2018-01-20 11:23:59 +00:00
										 |  |  |         args, result = params | 
					
						
							| 
									
										
										
										
											2020-12-14 02:38:24 +08:00
										 |  |  |         # 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): | 
					
						
							| 
									
										
										
										
											2018-01-20 11:23:59 +00:00
										 |  |  |             params = (tuple(args), result) | 
					
						
							| 
									
										
										
										
											2020-12-14 02:38:24 +08:00
										 |  |  |         else: | 
					
						
							|  |  |  |             params = (args, result) | 
					
						
							| 
									
										
										
										
											2018-01-20 11:23:59 +00:00
										 |  |  |         return self.__getitem_inner__(params) | 
					
						
							| 
									
										
										
										
											2016-10-29 08:54:56 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |     @_tp_cache | 
					
						
							| 
									
										
										
										
											2018-01-20 11:23:59 +00:00
										 |  |  |     def __getitem_inner__(self, params): | 
					
						
							| 
									
										
										
										
											2020-05-07 04:09:33 +03:00
										 |  |  |         args, result = params | 
					
						
							|  |  |  |         msg = "Callable[args, result]: result must be a type." | 
					
						
							|  |  |  |         result = _type_check(result, msg) | 
					
						
							|  |  |  |         if args is Ellipsis: | 
					
						
							|  |  |  |             return self.copy_with((_TypingEllipsis, result)) | 
					
						
							| 
									
										
										
										
											2020-12-14 02:38:24 +08:00
										 |  |  |         if not isinstance(args, tuple): | 
					
						
							|  |  |  |             args = (args,) | 
					
						
							|  |  |  |         args = tuple(_type_convert(arg) for arg in args) | 
					
						
							| 
									
										
										
										
											2020-05-07 04:09:33 +03:00
										 |  |  |         params = args + (result,) | 
					
						
							|  |  |  |         return self.copy_with(params) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | class _TupleType(_SpecialGenericAlias, _root=True): | 
					
						
							|  |  |  |     @_tp_cache | 
					
						
							|  |  |  |     def __getitem__(self, params): | 
					
						
							|  |  |  |         if not isinstance(params, tuple): | 
					
						
							|  |  |  |             params = (params,) | 
					
						
							| 
									
										
										
										
											2022-03-08 04:02:55 +00:00
										 |  |  |         if len(params) >= 2 and params[-1] is ...: | 
					
						
							| 
									
										
										
										
											2020-05-07 04:09:33 +03:00
										 |  |  |             msg = "Tuple[t, ...]: t must be a type." | 
					
						
							| 
									
										
										
										
											2022-03-08 04:02:55 +00:00
										 |  |  |             params = tuple(_type_check(p, msg) for p in params[:-1]) | 
					
						
							|  |  |  |             return self.copy_with((*params, _TypingEllipsis)) | 
					
						
							| 
									
										
										
										
											2020-05-07 04:09:33 +03:00
										 |  |  |         msg = "Tuple[t0, t1, ...]: each t must be a type." | 
					
						
							|  |  |  |         params = tuple(_type_check(p, msg) for p in params) | 
					
						
							|  |  |  |         return self.copy_with(params) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-03-04 11:44:19 -08:00
										 |  |  | class _UnionGenericAliasMeta(type): | 
					
						
							|  |  |  |     def __instancecheck__(self, inst: object) -> bool: | 
					
						
							|  |  |  |         warnings._deprecated("_UnionGenericAlias", remove=(3, 17)) | 
					
						
							|  |  |  |         return isinstance(inst, Union) | 
					
						
							| 
									
										
										
										
											2020-05-07 04:09:33 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-03-04 11:44:19 -08:00
										 |  |  |     def __subclasscheck__(self, inst: type) -> bool: | 
					
						
							|  |  |  |         warnings._deprecated("_UnionGenericAlias", remove=(3, 17)) | 
					
						
							|  |  |  |         return issubclass(inst, Union) | 
					
						
							| 
									
										
										
										
											2020-05-07 04:09:33 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-03-04 11:44:19 -08:00
										 |  |  |     def __eq__(self, other): | 
					
						
							|  |  |  |         warnings._deprecated("_UnionGenericAlias", remove=(3, 17)) | 
					
						
							|  |  |  |         if other is _UnionGenericAlias or other is Union: | 
					
						
							|  |  |  |             return True | 
					
						
							|  |  |  |         return NotImplemented | 
					
						
							| 
									
										
										
										
											2020-05-07 04:09:33 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-01-20 11:23:59 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-03-04 11:44:19 -08:00
										 |  |  | class _UnionGenericAlias(metaclass=_UnionGenericAliasMeta): | 
					
						
							|  |  |  |     """Compatibility hack.
 | 
					
						
							| 
									
										
										
										
											2020-09-09 13:23:24 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-03-04 11:44:19 -08:00
										 |  |  |     A class named _UnionGenericAlias used to be used to implement | 
					
						
							|  |  |  |     typing.Union. This class exists to serve as a shim to preserve | 
					
						
							|  |  |  |     the meaning of some code that used to use _UnionGenericAlias | 
					
						
							|  |  |  |     directly. | 
					
						
							| 
									
										
										
										
											2020-09-09 13:23:24 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-03-04 11:44:19 -08:00
										 |  |  |     """
 | 
					
						
							|  |  |  |     def __new__(cls, self_cls, parameters, /, *, name=None): | 
					
						
							|  |  |  |         warnings._deprecated("_UnionGenericAlias", remove=(3, 17)) | 
					
						
							|  |  |  |         return Union[parameters] | 
					
						
							| 
									
										
										
										
											2021-08-06 15:36:35 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-09-09 13:23:24 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-17 04:23:19 +02:00
										 |  |  | def _value_and_type_iter(parameters): | 
					
						
							|  |  |  |     return ((p, type(p)) for p in parameters) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | class _LiteralGenericAlias(_GenericAlias, _root=True): | 
					
						
							|  |  |  |     def __eq__(self, other): | 
					
						
							|  |  |  |         if not isinstance(other, _LiteralGenericAlias): | 
					
						
							|  |  |  |             return NotImplemented | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         return set(_value_and_type_iter(self.__args__)) == set(_value_and_type_iter(other.__args__)) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def __hash__(self): | 
					
						
							| 
									
										
										
										
											2020-11-19 18:17:38 +02:00
										 |  |  |         return hash(frozenset(_value_and_type_iter(self.__args__))) | 
					
						
							| 
									
										
										
										
											2020-11-17 04:23:19 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-01-20 11:23:59 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-12-24 12:33:48 +08:00
										 |  |  | class _ConcatenateGenericAlias(_GenericAlias, _root=True): | 
					
						
							| 
									
										
										
										
											2022-01-27 14:34:55 +02:00
										 |  |  |     def copy_with(self, params): | 
					
						
							|  |  |  |         if isinstance(params[-1], (list, tuple)): | 
					
						
							|  |  |  |             return (*params[:-1], *params[-1]) | 
					
						
							|  |  |  |         if isinstance(params[-1], _ConcatenateGenericAlias): | 
					
						
							|  |  |  |             params = (*params[:-1], *params[-1].__args__) | 
					
						
							|  |  |  |         return super().copy_with(params) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-12-24 12:33:48 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-03-08 04:02:55 +00:00
										 |  |  | @_SpecialForm | 
					
						
							|  |  |  | def Unpack(self, parameters): | 
					
						
							|  |  |  |     """Type unpack operator.
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     The type unpack operator takes the child types from some container type, | 
					
						
							| 
									
										
										
										
											2023-06-07 01:21:16 +01:00
										 |  |  |     such as `tuple[int, str]` or a `TypeVarTuple`, and 'pulls them out'. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     For example:: | 
					
						
							| 
									
										
										
										
											2022-03-08 04:02:55 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-06-05 15:16:09 +01:00
										 |  |  |         # For some generic class `Foo`: | 
					
						
							|  |  |  |         Foo[Unpack[tuple[int, str]]]  # Equivalent to Foo[int, str] | 
					
						
							| 
									
										
										
										
											2022-03-08 04:02:55 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-06-05 15:16:09 +01:00
										 |  |  |         Ts = TypeVarTuple('Ts') | 
					
						
							|  |  |  |         # Specifies that `Bar` is generic in an arbitrary number of types. | 
					
						
							|  |  |  |         # (Think of `Ts` as a tuple of an arbitrary number of individual | 
					
						
							|  |  |  |         #  `TypeVar`s, which the `Unpack` is 'pulling out' directly into the | 
					
						
							|  |  |  |         #  `Generic[]`.) | 
					
						
							|  |  |  |         class Bar(Generic[Unpack[Ts]]): ... | 
					
						
							|  |  |  |         Bar[int]  # Valid | 
					
						
							|  |  |  |         Bar[int, str]  # Also valid | 
					
						
							| 
									
										
										
										
											2022-03-08 04:02:55 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-06-05 15:16:09 +01:00
										 |  |  |     From Python 3.11, this can also be done using the `*` operator:: | 
					
						
							| 
									
										
										
										
											2022-03-08 04:02:55 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |         Foo[*tuple[int, str]] | 
					
						
							|  |  |  |         class Bar(Generic[*Ts]): ... | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-06-05 15:16:09 +01:00
										 |  |  |     And from Python 3.12, it can be done using built-in syntax for generics:: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         Foo[*tuple[int, str]] | 
					
						
							|  |  |  |         class Bar[*Ts]: ... | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-05-01 19:58:50 +02:00
										 |  |  |     The operator can also be used along with a `TypedDict` to annotate | 
					
						
							| 
									
										
										
										
											2023-06-07 01:21:16 +01:00
										 |  |  |     `**kwargs` in a function signature:: | 
					
						
							| 
									
										
										
										
											2023-05-01 19:58:50 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-06-05 15:16:09 +01:00
										 |  |  |         class Movie(TypedDict): | 
					
						
							|  |  |  |             name: str | 
					
						
							|  |  |  |             year: int | 
					
						
							| 
									
										
										
										
											2023-05-01 19:58:50 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-06-05 15:16:09 +01:00
										 |  |  |         # This function expects two keyword arguments - *name* of type `str` and | 
					
						
							|  |  |  |         # *year* of type `int`. | 
					
						
							|  |  |  |         def foo(**kwargs: Unpack[Movie]): ... | 
					
						
							| 
									
										
										
										
											2023-05-01 19:58:50 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-03-08 04:02:55 +00:00
										 |  |  |     Note that there is only some runtime checking of this operator. Not | 
					
						
							|  |  |  |     everything the runtime allows may be accepted by static type checkers. | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-06-07 01:21:16 +01:00
										 |  |  |     For more information, see PEPs 646 and 692. | 
					
						
							| 
									
										
										
										
											2022-03-08 04:02:55 +00:00
										 |  |  |     """
 | 
					
						
							|  |  |  |     item = _type_check(parameters, f'{self} accepts only single type.') | 
					
						
							|  |  |  |     return _UnpackGenericAlias(origin=self, args=(item,)) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | class _UnpackGenericAlias(_GenericAlias, _root=True): | 
					
						
							|  |  |  |     def __repr__(self): | 
					
						
							|  |  |  |         # `Unpack` only takes one argument, so __args__ should contain only | 
					
						
							|  |  |  |         # a single item. | 
					
						
							| 
									
										
										
										
											2023-05-01 19:58:50 +02:00
										 |  |  |         return f'typing.Unpack[{_type_repr(self.__args__[0])}]' | 
					
						
							| 
									
										
										
										
											2022-03-08 04:02:55 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-03-11 21:43:58 +02:00
										 |  |  |     def __getitem__(self, args): | 
					
						
							| 
									
										
										
										
											2022-05-08 18:32:32 +03:00
										 |  |  |         if self.__typing_is_unpacked_typevartuple__: | 
					
						
							| 
									
										
										
										
											2022-03-11 21:43:58 +02:00
										 |  |  |             return args | 
					
						
							|  |  |  |         return super().__getitem__(args) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-05-08 18:32:32 +03:00
										 |  |  |     @property | 
					
						
							|  |  |  |     def __typing_unpacked_tuple_args__(self): | 
					
						
							|  |  |  |         assert self.__origin__ is Unpack | 
					
						
							|  |  |  |         assert len(self.__args__) == 1 | 
					
						
							|  |  |  |         arg, = self.__args__ | 
					
						
							| 
									
										
										
										
											2024-04-23 06:40:26 -07:00
										 |  |  |         if isinstance(arg, (_GenericAlias, types.GenericAlias)): | 
					
						
							|  |  |  |             if arg.__origin__ is not tuple: | 
					
						
							|  |  |  |                 raise TypeError("Unpack[...] must be used with a tuple type") | 
					
						
							| 
									
										
										
										
											2022-05-08 18:32:32 +03:00
										 |  |  |             return arg.__args__ | 
					
						
							|  |  |  |         return None | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     @property | 
					
						
							|  |  |  |     def __typing_is_unpacked_typevartuple__(self): | 
					
						
							|  |  |  |         assert self.__origin__ is Unpack | 
					
						
							|  |  |  |         assert len(self.__args__) == 1 | 
					
						
							|  |  |  |         return isinstance(self.__args__[0], TypeVarTuple) | 
					
						
							| 
									
										
										
										
											2022-04-30 08:22:46 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-03-08 04:02:55 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-01-20 11:23:59 +00:00
										 |  |  | class _TypingEllipsis: | 
					
						
							|  |  |  |     """Internal placeholder for ... (ellipsis).""" | 
					
						
							| 
									
										
										
										
											2016-09-11 15:34:56 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-03-31 21:54:50 +01:00
										 |  |  | _TYPING_INTERNALS = frozenset({ | 
					
						
							|  |  |  |     '__parameters__', '__orig_bases__',  '__orig_class__', | 
					
						
							| 
									
										
										
										
											2023-04-05 12:19:03 +01:00
										 |  |  |     '_is_protocol', '_is_runtime_protocol', '__protocol_attrs__', | 
					
						
							| 
									
										
										
										
											2024-01-05 01:01:48 +00:00
										 |  |  |     '__non_callable_proto_members__', '__type_params__', | 
					
						
							| 
									
										
										
										
											2023-03-31 21:54:50 +01:00
										 |  |  | }) | 
					
						
							| 
									
										
										
										
											2019-05-28 08:40:15 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-03-31 21:54:50 +01:00
										 |  |  | _SPECIAL_NAMES = frozenset({ | 
					
						
							|  |  |  |     '__abstractmethods__', '__annotations__', '__dict__', '__doc__', | 
					
						
							|  |  |  |     '__init__', '__module__', '__new__', '__slots__', | 
					
						
							| 
									
										
										
										
											2023-10-12 05:20:20 +03:00
										 |  |  |     '__subclasshook__', '__weakref__', '__class_getitem__', | 
					
						
							| 
									
										
										
										
											2024-05-06 12:02:37 +03:00
										 |  |  |     '__match_args__', '__static_attributes__', '__firstlineno__', | 
					
						
							| 
									
										
										
										
											2024-05-21 22:38:12 -04:00
										 |  |  |     '__annotate__', | 
					
						
							| 
									
										
										
										
											2023-03-31 21:54:50 +01:00
										 |  |  | }) | 
					
						
							| 
									
										
										
										
											2019-05-28 08:40:15 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | # These special attributes will be not collected as protocol members. | 
					
						
							| 
									
										
										
										
											2023-03-31 21:54:50 +01:00
										 |  |  | EXCLUDED_ATTRIBUTES = _TYPING_INTERNALS | _SPECIAL_NAMES | {'_MutableMapping__marker'} | 
					
						
							| 
									
										
										
										
											2019-05-28 08:40:15 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | def _get_protocol_attrs(cls): | 
					
						
							|  |  |  |     """Collect protocol members from a protocol class objects.
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     This includes names actually defined in the class dictionary, as well | 
					
						
							|  |  |  |     as names that appear in annotations. Special names (above) are skipped. | 
					
						
							|  |  |  |     """
 | 
					
						
							|  |  |  |     attrs = set() | 
					
						
							|  |  |  |     for base in cls.__mro__[:-1]:  # without object | 
					
						
							| 
									
										
										
										
											2023-03-31 21:54:50 +01:00
										 |  |  |         if base.__name__ in {'Protocol', 'Generic'}: | 
					
						
							| 
									
										
										
										
											2019-05-28 08:40:15 +01:00
										 |  |  |             continue | 
					
						
							|  |  |  |         annotations = getattr(base, '__annotations__', {}) | 
					
						
							| 
									
										
										
										
											2023-03-31 21:54:50 +01:00
										 |  |  |         for attr in (*base.__dict__, *annotations): | 
					
						
							| 
									
										
										
										
											2019-05-28 08:40:15 +01:00
										 |  |  |             if not attr.startswith('_abc_') and attr not in EXCLUDED_ATTRIBUTES: | 
					
						
							|  |  |  |                 attrs.add(attr) | 
					
						
							|  |  |  |     return attrs | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-09-02 19:17:13 +03:00
										 |  |  | def _no_init_or_replace_init(self, *args, **kwargs): | 
					
						
							|  |  |  |     cls = type(self) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if cls._is_protocol: | 
					
						
							|  |  |  |         raise TypeError('Protocols cannot be instantiated') | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-09-08 13:25:09 +03:00
										 |  |  |     # Already using a custom `__init__`. No need to calculate correct | 
					
						
							|  |  |  |     # `__init__` to call. This can lead to RecursionError. See bpo-45121. | 
					
						
							|  |  |  |     if cls.__init__ is not _no_init_or_replace_init: | 
					
						
							|  |  |  |         return | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-09-02 19:17:13 +03:00
										 |  |  |     # Initially, `__init__` of a protocol subclass is set to `_no_init_or_replace_init`. | 
					
						
							|  |  |  |     # The first instantiation of the subclass will call `_no_init_or_replace_init` which | 
					
						
							|  |  |  |     # searches for a proper new `__init__` in the MRO. The new `__init__` | 
					
						
							|  |  |  |     # replaces the subclass' old `__init__` (ie `_no_init_or_replace_init`). Subsequent | 
					
						
							|  |  |  |     # instantiation of the protocol subclass will thus use the new | 
					
						
							|  |  |  |     # `__init__` and no longer call `_no_init_or_replace_init`. | 
					
						
							|  |  |  |     for base in cls.__mro__: | 
					
						
							|  |  |  |         init = base.__dict__.get('__init__', _no_init_or_replace_init) | 
					
						
							|  |  |  |         if init is not _no_init_or_replace_init: | 
					
						
							|  |  |  |             cls.__init__ = init | 
					
						
							|  |  |  |             break | 
					
						
							|  |  |  |     else: | 
					
						
							|  |  |  |         # should not happen | 
					
						
							|  |  |  |         cls.__init__ = object.__init__ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     cls.__init__(self, *args, **kwargs) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-05-28 08:40:15 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-07-30 15:56:12 +03:00
										 |  |  | def _caller(depth=1, default='__main__'): | 
					
						
							| 
									
										
										
										
											2023-01-13 11:31:06 +00:00
										 |  |  |     try: | 
					
						
							|  |  |  |         return sys._getframemodulename(depth + 1) or default | 
					
						
							|  |  |  |     except AttributeError:  # For platforms without _getframemodulename() | 
					
						
							|  |  |  |         pass | 
					
						
							| 
									
										
										
										
											2021-07-20 16:20:38 +03:00
										 |  |  |     try: | 
					
						
							| 
									
										
										
										
											2021-07-30 15:56:12 +03:00
										 |  |  |         return sys._getframe(depth + 1).f_globals.get('__name__', default) | 
					
						
							| 
									
										
										
										
											2021-07-20 16:20:38 +03:00
										 |  |  |     except (AttributeError, ValueError):  # For platforms without _getframe() | 
					
						
							| 
									
										
										
										
											2023-01-13 11:31:06 +00:00
										 |  |  |         pass | 
					
						
							|  |  |  |     return None | 
					
						
							| 
									
										
										
										
											2019-05-28 08:40:15 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-05-31 18:02:25 +01:00
										 |  |  | def _allow_reckless_class_checks(depth=2): | 
					
						
							| 
									
										
										
										
											2020-04-26 12:49:11 -05:00
										 |  |  |     """Allow instance and class checks for special stdlib modules.
 | 
					
						
							| 
									
										
										
										
											2019-05-28 08:40:15 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |     The abc and functools modules indiscriminately call isinstance() and | 
					
						
							|  |  |  |     issubclass() on the whole MRO of a user class, which may contain protocols. | 
					
						
							|  |  |  |     """
 | 
					
						
							| 
									
										
										
										
											2021-07-30 16:49:24 +03:00
										 |  |  |     return _caller(depth) in {'abc', 'functools', None} | 
					
						
							| 
									
										
										
										
											2019-05-28 08:40:15 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-12 10:53:12 +02:00
										 |  |  | _PROTO_ALLOWLIST = { | 
					
						
							| 
									
										
										
										
											2019-09-12 11:13:51 +01:00
										 |  |  |     'collections.abc': [ | 
					
						
							|  |  |  |         'Callable', 'Awaitable', 'Iterable', 'Iterator', 'AsyncIterable', | 
					
						
							| 
									
										
										
										
											2024-11-12 01:17:07 -08:00
										 |  |  |         'AsyncIterator', 'Hashable', 'Sized', 'Container', 'Collection', | 
					
						
							|  |  |  |         'Reversible', 'Buffer', | 
					
						
							| 
									
										
										
										
											2019-09-12 11:13:51 +01:00
										 |  |  |     ], | 
					
						
							|  |  |  |     'contextlib': ['AbstractContextManager', 'AbstractAsyncContextManager'], | 
					
						
							| 
									
										
										
										
											2025-03-06 16:36:19 +01:00
										 |  |  |     'io': ['Reader', 'Writer'], | 
					
						
							| 
									
										
										
										
											2024-11-12 09:54:13 -08:00
										 |  |  |     'os': ['PathLike'], | 
					
						
							| 
									
										
										
										
											2019-09-12 11:13:51 +01:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2019-05-28 08:40:15 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-04-02 14:22:19 +01:00
										 |  |  | @functools.cache | 
					
						
							|  |  |  | def _lazy_load_getattr_static(): | 
					
						
							|  |  |  |     # Import getattr_static lazily so as not to slow down the import of typing.py | 
					
						
							|  |  |  |     # Cache the result so we don't slow down _ProtocolMeta.__instancecheck__ unnecessarily | 
					
						
							|  |  |  |     from inspect import getattr_static | 
					
						
							|  |  |  |     return getattr_static | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | _cleanups.append(_lazy_load_getattr_static.cache_clear) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-05-15 20:36:23 -07:00
										 |  |  | def _pickle_psargs(psargs): | 
					
						
							|  |  |  |     return ParamSpecArgs, (psargs.__origin__,) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | copyreg.pickle(ParamSpecArgs, _pickle_psargs) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | def _pickle_pskwargs(pskwargs): | 
					
						
							|  |  |  |     return ParamSpecKwargs, (pskwargs.__origin__,) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | copyreg.pickle(ParamSpecKwargs, _pickle_pskwargs) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | del _pickle_psargs, _pickle_pskwargs | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-04-02 14:22:19 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-12-04 15:41:41 +00:00
										 |  |  | # Preload these once, as globals, as a micro-optimisation. | 
					
						
							|  |  |  | # This makes a significant difference to the time it takes | 
					
						
							|  |  |  | # to do `isinstance()`/`issubclass()` checks | 
					
						
							|  |  |  | # against runtime-checkable protocols with only one callable member. | 
					
						
							|  |  |  | _abc_instancecheck = ABCMeta.__instancecheck__ | 
					
						
							|  |  |  | _abc_subclasscheck = ABCMeta.__subclasscheck__ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-12-04 19:35:46 +00:00
										 |  |  | def _type_check_issubclass_arg_1(arg): | 
					
						
							|  |  |  |     """Raise TypeError if `arg` is not an instance of `type`
 | 
					
						
							|  |  |  |     in `issubclass(arg, <protocol>)`. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     In most cases, this is verified by type.__subclasscheck__. | 
					
						
							|  |  |  |     Checking it again unnecessarily would slow down issubclass() checks, | 
					
						
							|  |  |  |     so, we don't perform this check unless we absolutely have to. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     For various error paths, however, | 
					
						
							|  |  |  |     we want to ensure that *this* error message is shown to the user | 
					
						
							|  |  |  |     where relevant, rather than a typing.py-specific error message. | 
					
						
							|  |  |  |     """
 | 
					
						
							|  |  |  |     if not isinstance(arg, type): | 
					
						
							|  |  |  |         # Same error message as for issubclass(1, int). | 
					
						
							|  |  |  |         raise TypeError('issubclass() arg 1 must be a class') | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-05-28 08:40:15 +01:00
										 |  |  | class _ProtocolMeta(ABCMeta): | 
					
						
							| 
									
										
										
										
											2023-05-18 00:43:12 +01:00
										 |  |  |     # This metaclass is somewhat unfortunate, | 
					
						
							|  |  |  |     # but is necessary for several reasons... | 
					
						
							| 
									
										
										
										
											2023-06-05 15:10:49 +01:00
										 |  |  |     def __new__(mcls, name, bases, namespace, /, **kwargs): | 
					
						
							|  |  |  |         if name == "Protocol" and bases == (Generic,): | 
					
						
							|  |  |  |             pass | 
					
						
							|  |  |  |         elif Protocol in bases: | 
					
						
							|  |  |  |             for base in bases: | 
					
						
							|  |  |  |                 if not ( | 
					
						
							|  |  |  |                     base in {object, Generic} | 
					
						
							|  |  |  |                     or base.__name__ in _PROTO_ALLOWLIST.get(base.__module__, []) | 
					
						
							|  |  |  |                     or ( | 
					
						
							|  |  |  |                         issubclass(base, Generic) | 
					
						
							|  |  |  |                         and getattr(base, "_is_protocol", False) | 
					
						
							|  |  |  |                     ) | 
					
						
							|  |  |  |                 ): | 
					
						
							|  |  |  |                     raise TypeError( | 
					
						
							|  |  |  |                         f"Protocols can only inherit from other protocols, " | 
					
						
							|  |  |  |                         f"got {base!r}" | 
					
						
							|  |  |  |                     ) | 
					
						
							|  |  |  |         return super().__new__(mcls, name, bases, namespace, **kwargs) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-04-05 12:19:03 +01:00
										 |  |  |     def __init__(cls, *args, **kwargs): | 
					
						
							|  |  |  |         super().__init__(*args, **kwargs) | 
					
						
							| 
									
										
										
										
											2023-05-19 00:34:40 +01:00
										 |  |  |         if getattr(cls, "_is_protocol", False): | 
					
						
							|  |  |  |             cls.__protocol_attrs__ = _get_protocol_attrs(cls) | 
					
						
							| 
									
										
										
										
											2023-04-05 12:19:03 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-05-18 00:43:12 +01:00
										 |  |  |     def __subclasscheck__(cls, other): | 
					
						
							| 
									
										
										
										
											2023-06-05 14:36:51 +01:00
										 |  |  |         if cls is Protocol: | 
					
						
							|  |  |  |             return type.__subclasscheck__(cls, other) | 
					
						
							| 
									
										
										
										
											2023-05-18 00:43:12 +01:00
										 |  |  |         if ( | 
					
						
							|  |  |  |             getattr(cls, '_is_protocol', False) | 
					
						
							| 
									
										
										
										
											2023-05-31 18:02:25 +01:00
										 |  |  |             and not _allow_reckless_class_checks() | 
					
						
							| 
									
										
										
										
											2023-05-18 00:43:12 +01:00
										 |  |  |         ): | 
					
						
							| 
									
										
										
										
											2024-01-05 01:01:48 +00:00
										 |  |  |             if not getattr(cls, '_is_runtime_protocol', False): | 
					
						
							|  |  |  |                 _type_check_issubclass_arg_1(other) | 
					
						
							|  |  |  |                 raise TypeError( | 
					
						
							|  |  |  |                     "Instance and class checks can only be used with " | 
					
						
							|  |  |  |                     "@runtime_checkable protocols" | 
					
						
							|  |  |  |                 ) | 
					
						
							| 
									
										
										
										
											2023-06-23 15:59:25 +01:00
										 |  |  |             if ( | 
					
						
							| 
									
										
										
										
											2024-01-05 01:01:48 +00:00
										 |  |  |                 # this attribute is set by @runtime_checkable: | 
					
						
							|  |  |  |                 cls.__non_callable_proto_members__ | 
					
						
							| 
									
										
										
										
											2023-06-23 15:59:25 +01:00
										 |  |  |                 and cls.__dict__.get("__subclasshook__") is _proto_hook | 
					
						
							|  |  |  |             ): | 
					
						
							| 
									
										
										
										
											2023-12-04 19:35:46 +00:00
										 |  |  |                 _type_check_issubclass_arg_1(other) | 
					
						
							| 
									
										
										
										
											2024-01-05 01:01:48 +00:00
										 |  |  |                 non_method_attrs = sorted(cls.__non_callable_proto_members__) | 
					
						
							| 
									
										
										
										
											2023-05-31 18:02:25 +01:00
										 |  |  |                 raise TypeError( | 
					
						
							| 
									
										
										
										
											2023-11-24 10:46:08 +01:00
										 |  |  |                     "Protocols with non-method members don't support issubclass()." | 
					
						
							|  |  |  |                     f" Non-method members: {str(non_method_attrs)[1:-1]}." | 
					
						
							| 
									
										
										
										
											2023-05-31 18:02:25 +01:00
										 |  |  |                 ) | 
					
						
							| 
									
										
										
										
											2023-12-04 15:41:41 +00:00
										 |  |  |         return _abc_subclasscheck(cls, other) | 
					
						
							| 
									
										
										
										
											2023-05-18 00:43:12 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-05-28 08:40:15 +01:00
										 |  |  |     def __instancecheck__(cls, instance): | 
					
						
							|  |  |  |         # We need this method for situations where attributes are | 
					
						
							|  |  |  |         # assigned in __init__. | 
					
						
							| 
									
										
										
										
											2023-06-05 14:36:51 +01:00
										 |  |  |         if cls is Protocol: | 
					
						
							|  |  |  |             return type.__instancecheck__(cls, instance) | 
					
						
							| 
									
										
										
										
											2023-05-19 14:30:02 +01:00
										 |  |  |         if not getattr(cls, "_is_protocol", False): | 
					
						
							|  |  |  |             # i.e., it's a concrete subclass of a protocol | 
					
						
							| 
									
										
										
										
											2023-12-04 15:41:41 +00:00
										 |  |  |             return _abc_instancecheck(cls, instance) | 
					
						
							| 
									
										
										
										
											2023-05-19 14:30:02 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-05-12 18:47:49 +03:00
										 |  |  |         if ( | 
					
						
							|  |  |  |             not getattr(cls, '_is_runtime_protocol', False) and | 
					
						
							| 
									
										
										
										
											2023-05-31 18:02:25 +01:00
										 |  |  |             not _allow_reckless_class_checks() | 
					
						
							| 
									
										
										
										
											2021-05-12 18:47:49 +03:00
										 |  |  |         ): | 
					
						
							|  |  |  |             raise TypeError("Instance and class checks can only be used with" | 
					
						
							|  |  |  |                             " @runtime_checkable protocols") | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-12-04 15:41:41 +00:00
										 |  |  |         if _abc_instancecheck(cls, instance): | 
					
						
							| 
									
										
										
										
											2023-03-31 18:37:24 +01:00
										 |  |  |             return True | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-05-19 14:30:02 +01:00
										 |  |  |         getattr_static = _lazy_load_getattr_static() | 
					
						
							|  |  |  |         for attr in cls.__protocol_attrs__: | 
					
						
							|  |  |  |             try: | 
					
						
							|  |  |  |                 val = getattr_static(instance, attr) | 
					
						
							|  |  |  |             except AttributeError: | 
					
						
							|  |  |  |                 break | 
					
						
							| 
									
										
										
										
											2024-01-05 01:01:48 +00:00
										 |  |  |             # this attribute is set by @runtime_checkable: | 
					
						
							|  |  |  |             if val is None and attr not in cls.__non_callable_proto_members__: | 
					
						
							| 
									
										
										
										
											2023-05-19 14:30:02 +01:00
										 |  |  |                 break | 
					
						
							|  |  |  |         else: | 
					
						
							|  |  |  |             return True | 
					
						
							| 
									
										
										
										
											2023-04-02 14:22:19 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-04-05 10:07:30 +01:00
										 |  |  |         return False | 
					
						
							| 
									
										
										
										
											2019-05-28 08:40:15 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-06-23 15:59:25 +01:00
										 |  |  | @classmethod | 
					
						
							|  |  |  | def _proto_hook(cls, other): | 
					
						
							|  |  |  |     if not cls.__dict__.get('_is_protocol', False): | 
					
						
							|  |  |  |         return NotImplemented | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     for attr in cls.__protocol_attrs__: | 
					
						
							|  |  |  |         for base in other.__mro__: | 
					
						
							|  |  |  |             # Check if the members appears in the class dictionary... | 
					
						
							|  |  |  |             if attr in base.__dict__: | 
					
						
							|  |  |  |                 if base.__dict__[attr] is None: | 
					
						
							|  |  |  |                     return NotImplemented | 
					
						
							|  |  |  |                 break | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             # ...or in annotations, if it is a sub-protocol. | 
					
						
							|  |  |  |             annotations = getattr(base, '__annotations__', {}) | 
					
						
							|  |  |  |             if (isinstance(annotations, collections.abc.Mapping) and | 
					
						
							|  |  |  |                     attr in annotations and | 
					
						
							|  |  |  |                     issubclass(other, Generic) and getattr(other, '_is_protocol', False)): | 
					
						
							|  |  |  |                 break | 
					
						
							|  |  |  |         else: | 
					
						
							|  |  |  |             return NotImplemented | 
					
						
							|  |  |  |     return True | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-05-28 08:40:15 +01:00
										 |  |  | class Protocol(Generic, metaclass=_ProtocolMeta): | 
					
						
							|  |  |  |     """Base class for protocol classes.
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     Protocol classes are defined as:: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         class Proto(Protocol): | 
					
						
							|  |  |  |             def meth(self) -> int: | 
					
						
							|  |  |  |                 ... | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     Such classes are primarily used with static type checkers that recognize | 
					
						
							| 
									
										
										
										
											2023-06-07 01:21:16 +01:00
										 |  |  |     structural subtyping (static duck-typing). | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     For example:: | 
					
						
							| 
									
										
										
										
											2019-05-28 08:40:15 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |         class C: | 
					
						
							|  |  |  |             def meth(self) -> int: | 
					
						
							|  |  |  |                 return 0 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         def func(x: Proto) -> int: | 
					
						
							|  |  |  |             return x.meth() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         func(C())  # Passes static type check | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     See PEP 544 for details. Protocol classes decorated with | 
					
						
							|  |  |  |     @typing.runtime_checkable act as simple-minded runtime protocols that check | 
					
						
							|  |  |  |     only the presence of given attributes, ignoring their type signatures. | 
					
						
							|  |  |  |     Protocol classes can be generic, they are defined as:: | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-06-05 15:16:09 +01:00
										 |  |  |         class GenProto[T](Protocol): | 
					
						
							| 
									
										
										
										
											2019-05-28 08:40:15 +01:00
										 |  |  |             def meth(self) -> T: | 
					
						
							|  |  |  |                 ... | 
					
						
							|  |  |  |     """
 | 
					
						
							| 
									
										
										
										
											2023-06-05 15:16:09 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-05-28 08:40:15 +01:00
										 |  |  |     __slots__ = () | 
					
						
							|  |  |  |     _is_protocol = True | 
					
						
							|  |  |  |     _is_runtime_protocol = False | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def __init_subclass__(cls, *args, **kwargs): | 
					
						
							|  |  |  |         super().__init_subclass__(*args, **kwargs) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         # Determine if this is a protocol or a concrete subclass. | 
					
						
							|  |  |  |         if not cls.__dict__.get('_is_protocol', False): | 
					
						
							|  |  |  |             cls._is_protocol = any(b is Protocol for b in cls.__bases__) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         # Set (or override) the protocol subclass hook. | 
					
						
							|  |  |  |         if '__subclasshook__' not in cls.__dict__: | 
					
						
							|  |  |  |             cls.__subclasshook__ = _proto_hook | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-06-23 15:59:25 +01:00
										 |  |  |         # Prohibit instantiation for protocol classes | 
					
						
							|  |  |  |         if cls._is_protocol and cls.__init__ is Protocol.__init__: | 
					
						
							| 
									
										
										
										
											2022-04-11 09:51:25 -05:00
										 |  |  |             cls.__init__ = _no_init_or_replace_init | 
					
						
							| 
									
										
										
										
											2019-05-28 08:40:15 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-05-08 14:21:28 +01:00
										 |  |  | class _AnnotatedAlias(_NotIterable, _GenericAlias, _root=True): | 
					
						
							| 
									
										
										
										
											2020-02-05 02:10:19 +01:00
										 |  |  |     """Runtime representation of an annotated type.
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     At its core 'Annotated[t, dec1, dec2, ...]' is an alias for the type 't' | 
					
						
							| 
									
										
										
										
											2024-07-23 14:16:50 -07:00
										 |  |  |     with extra metadata. The alias behaves like a normal typing alias. | 
					
						
							| 
									
										
										
										
											2023-06-05 15:16:09 +01:00
										 |  |  |     Instantiating is the same as instantiating the underlying type; binding | 
					
						
							| 
									
										
										
										
											2020-02-05 02:10:19 +01:00
										 |  |  |     it to types is also the same. | 
					
						
							| 
									
										
										
										
											2023-04-10 17:57:17 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  |     The metadata itself is stored in a '__metadata__' attribute as a tuple. | 
					
						
							| 
									
										
										
										
											2020-02-05 02:10:19 +01:00
										 |  |  |     """
 | 
					
						
							| 
									
										
										
										
											2023-06-05 15:16:09 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-02-05 02:10:19 +01:00
										 |  |  |     def __init__(self, origin, metadata): | 
					
						
							|  |  |  |         if isinstance(origin, _AnnotatedAlias): | 
					
						
							|  |  |  |             metadata = origin.__metadata__ + metadata | 
					
						
							|  |  |  |             origin = origin.__origin__ | 
					
						
							| 
									
										
										
										
											2022-09-01 07:02:24 +08:00
										 |  |  |         super().__init__(origin, origin, name='Annotated') | 
					
						
							| 
									
										
										
										
											2020-02-05 02:10:19 +01:00
										 |  |  |         self.__metadata__ = metadata | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def copy_with(self, params): | 
					
						
							|  |  |  |         assert len(params) == 1 | 
					
						
							|  |  |  |         new_type = params[0] | 
					
						
							|  |  |  |         return _AnnotatedAlias(new_type, self.__metadata__) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def __repr__(self): | 
					
						
							|  |  |  |         return "typing.Annotated[{}, {}]".format( | 
					
						
							|  |  |  |             _type_repr(self.__origin__), | 
					
						
							|  |  |  |             ", ".join(repr(a) for a in self.__metadata__) | 
					
						
							|  |  |  |         ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def __reduce__(self): | 
					
						
							|  |  |  |         return operator.getitem, ( | 
					
						
							|  |  |  |             Annotated, (self.__origin__,) + self.__metadata__ | 
					
						
							|  |  |  |         ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def __eq__(self, other): | 
					
						
							|  |  |  |         if not isinstance(other, _AnnotatedAlias): | 
					
						
							|  |  |  |             return NotImplemented | 
					
						
							| 
									
										
										
										
											2020-05-07 04:09:33 +03:00
										 |  |  |         return (self.__origin__ == other.__origin__ | 
					
						
							|  |  |  |                 and self.__metadata__ == other.__metadata__) | 
					
						
							| 
									
										
										
										
											2020-02-05 02:10:19 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |     def __hash__(self): | 
					
						
							|  |  |  |         return hash((self.__origin__, self.__metadata__)) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-08-26 02:13:59 +08:00
										 |  |  |     def __getattr__(self, attr): | 
					
						
							|  |  |  |         if attr in {'__name__', '__qualname__'}: | 
					
						
							|  |  |  |             return 'Annotated' | 
					
						
							|  |  |  |         return super().__getattr__(attr) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-09-01 07:02:24 +08:00
										 |  |  |     def __mro_entries__(self, bases): | 
					
						
							|  |  |  |         return (self.__origin__,) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-02-05 02:10:19 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-12-02 19:10:19 +03:00
										 |  |  | @_TypedCacheSpecialForm | 
					
						
							|  |  |  | @_tp_cache(typed=True) | 
					
						
							|  |  |  | def Annotated(self, *params): | 
					
						
							| 
									
										
										
										
											2023-06-05 15:16:09 +01:00
										 |  |  |     """Add context-specific metadata to a type.
 | 
					
						
							| 
									
										
										
										
											2020-02-05 02:10:19 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |     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. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     Details: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     - It's an error to call `Annotated` with less than two arguments. | 
					
						
							| 
									
										
										
										
											2023-04-10 17:57:17 +03:00
										 |  |  |     - Access the metadata via the ``__metadata__`` attribute:: | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-06-05 15:16:09 +01:00
										 |  |  |         assert Annotated[int, '$'].__metadata__ == ('$',) | 
					
						
							| 
									
										
										
										
											2023-04-10 17:57:17 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-06-08 15:36:30 +01:00
										 |  |  |     - Nested Annotated types are flattened:: | 
					
						
							| 
									
										
										
										
											2020-02-05 02:10:19 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-06-05 15:16:09 +01:00
										 |  |  |         assert Annotated[Annotated[T, Ann1, Ann2], Ann3] == Annotated[T, Ann1, Ann2, Ann3] | 
					
						
							| 
									
										
										
										
											2020-02-05 02:10:19 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |     - Instantiating an annotated type is equivalent to instantiating the | 
					
						
							|  |  |  |     underlying type:: | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-06-05 15:16:09 +01:00
										 |  |  |         assert Annotated[C, Ann1](5) == C(5) | 
					
						
							| 
									
										
										
										
											2020-02-05 02:10:19 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |     - Annotated can be used as a generic type alias:: | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-06-08 15:36:30 +01:00
										 |  |  |         type Optimized[T] = Annotated[T, runtime.Optimize()] | 
					
						
							|  |  |  |         # type checker will treat Optimized[int] | 
					
						
							|  |  |  |         # as equivalent to Annotated[int, runtime.Optimize()] | 
					
						
							| 
									
										
										
										
											2020-02-05 02:10:19 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-06-08 15:36:30 +01:00
										 |  |  |         type OptimizedList[T] = Annotated[list[T], runtime.Optimize()] | 
					
						
							|  |  |  |         # type checker will treat OptimizedList[int] | 
					
						
							|  |  |  |         # as equivalent to Annotated[list[int], runtime.Optimize()] | 
					
						
							| 
									
										
										
										
											2022-04-16 05:24:28 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |     - Annotated cannot be used with an unpacked TypeVarTuple:: | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-06-08 15:36:30 +01:00
										 |  |  |         type Variadic[*Ts] = Annotated[*Ts, Ann1]  # NOT valid | 
					
						
							| 
									
										
										
										
											2022-04-16 05:24:28 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-06-07 01:21:16 +01:00
										 |  |  |       This would be equivalent to:: | 
					
						
							| 
									
										
										
										
											2022-04-16 05:24:28 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |         Annotated[T1, T2, T3, ..., Ann1] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       where T1, T2 etc. are TypeVars, which would be invalid, because | 
					
						
							|  |  |  |       only one type should be passed to Annotated. | 
					
						
							| 
									
										
										
										
											2020-02-05 02:10:19 +01:00
										 |  |  |     """
 | 
					
						
							| 
									
										
										
										
											2023-12-02 19:10:19 +03:00
										 |  |  |     if len(params) < 2: | 
					
						
							| 
									
										
										
										
											2023-09-01 21:57:25 +01:00
										 |  |  |         raise TypeError("Annotated[...] should be used " | 
					
						
							|  |  |  |                         "with at least two arguments (a type and an " | 
					
						
							|  |  |  |                         "annotation).") | 
					
						
							|  |  |  |     if _is_unpacked_typevartuple(params[0]): | 
					
						
							|  |  |  |         raise TypeError("Annotated[...] should not be used with an " | 
					
						
							|  |  |  |                         "unpacked TypeVarTuple") | 
					
						
							|  |  |  |     msg = "Annotated[t, ...]: t must be a type." | 
					
						
							|  |  |  |     origin = _type_check(params[0], msg, allow_special_forms=True) | 
					
						
							|  |  |  |     metadata = tuple(params[1:]) | 
					
						
							|  |  |  |     return _AnnotatedAlias(origin, metadata) | 
					
						
							| 
									
										
										
										
											2020-02-05 02:10:19 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-05-28 08:40:15 +01:00
										 |  |  | def runtime_checkable(cls): | 
					
						
							|  |  |  |     """Mark a protocol class as a runtime protocol.
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     Such protocol can be used with isinstance() and issubclass(). | 
					
						
							|  |  |  |     Raise TypeError if applied to a non-protocol class. | 
					
						
							|  |  |  |     This allows a simple-minded structural check very similar to | 
					
						
							|  |  |  |     one trick ponies in collections.abc such as Iterable. | 
					
						
							| 
									
										
										
										
											2023-06-05 15:16:09 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-05-28 08:40:15 +01:00
										 |  |  |     For example:: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         @runtime_checkable | 
					
						
							|  |  |  |         class Closable(Protocol): | 
					
						
							|  |  |  |             def close(self): ... | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         assert isinstance(open('/some/file'), Closable) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     Warning: this will check only the presence of the required methods, | 
					
						
							|  |  |  |     not their type signatures! | 
					
						
							|  |  |  |     """
 | 
					
						
							| 
									
										
										
										
											2023-05-25 09:43:40 -07:00
										 |  |  |     if not issubclass(cls, Generic) or not getattr(cls, '_is_protocol', False): | 
					
						
							| 
									
										
										
										
											2019-05-28 08:40:15 +01:00
										 |  |  |         raise TypeError('@runtime_checkable can be only applied to protocol classes,' | 
					
						
							|  |  |  |                         ' got %r' % cls) | 
					
						
							|  |  |  |     cls._is_runtime_protocol = True | 
					
						
							| 
									
										
										
										
											2024-01-05 01:01:48 +00:00
										 |  |  |     # PEP 544 prohibits using issubclass() | 
					
						
							|  |  |  |     # with protocols that have non-method members. | 
					
						
							|  |  |  |     # See gh-113320 for why we compute this attribute here, | 
					
						
							|  |  |  |     # rather than in `_ProtocolMeta.__init__` | 
					
						
							|  |  |  |     cls.__non_callable_proto_members__ = set() | 
					
						
							|  |  |  |     for attr in cls.__protocol_attrs__: | 
					
						
							|  |  |  |         try: | 
					
						
							|  |  |  |             is_callable = callable(getattr(cls, attr, None)) | 
					
						
							|  |  |  |         except Exception as e: | 
					
						
							|  |  |  |             raise TypeError( | 
					
						
							|  |  |  |                 f"Failed to determine whether protocol member {attr!r} " | 
					
						
							|  |  |  |                 "is a method member" | 
					
						
							|  |  |  |             ) from e | 
					
						
							|  |  |  |         else: | 
					
						
							|  |  |  |             if not is_callable: | 
					
						
							|  |  |  |                 cls.__non_callable_proto_members__.add(attr) | 
					
						
							| 
									
										
										
										
											2019-05-28 08:40:15 +01:00
										 |  |  |     return cls | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-05-22 10:14:11 -07:00
										 |  |  | 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 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-03-16 20:02:26 -07:00
										 |  |  | def assert_type(val, typ, /): | 
					
						
							| 
									
										
										
										
											2022-03-23 19:15:06 -07:00
										 |  |  |     """Ask a static type checker to confirm that the value is of the given type.
 | 
					
						
							| 
									
										
										
										
											2022-03-16 20:02:26 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-05-01 23:05:25 -07:00
										 |  |  |     At runtime this does nothing: it returns the first argument unchanged with no | 
					
						
							|  |  |  |     checks or side effects, no matter the actual type of the argument. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     When a static type checker encounters a call to assert_type(), it | 
					
						
							| 
									
										
										
										
											2022-03-16 20:02:26 -07:00
										 |  |  |     emits an error if the value is not of the specified type:: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         def greet(name: str) -> None: | 
					
						
							| 
									
										
										
										
											2023-06-09 16:08:57 +01:00
										 |  |  |             assert_type(name, str)  # OK | 
					
						
							| 
									
										
										
										
											2022-03-16 20:02:26 -07:00
										 |  |  |             assert_type(name, int)  # type checker error | 
					
						
							|  |  |  |     """
 | 
					
						
							|  |  |  |     return val | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-02-13 22:50:14 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-07-23 14:16:50 -07:00
										 |  |  | def get_type_hints(obj, globalns=None, localns=None, include_extras=False, | 
					
						
							|  |  |  |                    *, format=annotationlib.Format.VALUE): | 
					
						
							| 
									
										
										
										
											2016-11-09 13:12:51 -08:00
										 |  |  |     """Return type hints for an object.
 | 
					
						
							| 
									
										
										
										
											2015-05-22 10:14:11 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-11-09 13:12:51 -08:00
										 |  |  |     This is often the same as obj.__annotations__, but it handles | 
					
						
							| 
									
										
										
										
											2022-03-02 08:29:46 +03:00
										 |  |  |     forward references encoded as string literals and recursively replaces all | 
					
						
							| 
									
										
										
										
											2020-02-05 02:10:19 +01:00
										 |  |  |     'Annotated[T, ...]' with 'T' (unless 'include_extras=True'). | 
					
						
							| 
									
										
										
										
											2015-05-22 10:14:11 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-11-09 13:12:51 -08:00
										 |  |  |     The argument may be a module, class, method, or function. The annotations | 
					
						
							|  |  |  |     are returned as a dictionary. For classes, annotations include also | 
					
						
							|  |  |  |     inherited members. | 
					
						
							| 
									
										
										
										
											2015-05-22 10:14:11 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-11-09 13:12:51 -08:00
										 |  |  |     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. | 
					
						
							| 
									
										
										
										
											2015-05-22 10:14:11 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-11-09 13:12:51 -08:00
										 |  |  |     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. | 
					
						
							| 
									
										
										
										
											2015-05-22 10:14:11 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-11-09 13:12:51 -08:00
										 |  |  |     - If no dict arguments are passed, an attempt is made to use the | 
					
						
							| 
									
										
										
										
											2017-09-14 14:33:00 -04:00
										 |  |  |       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 | 
					
						
							| 
									
										
										
										
											2021-04-27 01:31:21 +08:00
										 |  |  |       to have globals, an empty dictionary is used.  For classes, the search | 
					
						
							|  |  |  |       order is globals first then locals. | 
					
						
							| 
									
										
										
										
											2016-09-11 15:34:56 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-11-09 13:12:51 -08:00
										 |  |  |     - If one dict argument is passed, it is used for both globals and | 
					
						
							|  |  |  |       locals. | 
					
						
							| 
									
										
										
										
											2016-09-11 15:34:56 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-11-09 13:12:51 -08:00
										 |  |  |     - 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__): | 
					
						
							| 
									
										
										
										
											2024-07-23 14:16:50 -07:00
										 |  |  |             ann = annotationlib.get_annotations(base, format=format) | 
					
						
							| 
									
										
										
										
											2024-09-26 13:49:48 -07:00
										 |  |  |             if format is annotationlib.Format.STRING: | 
					
						
							| 
									
										
										
										
											2024-07-23 14:16:50 -07:00
										 |  |  |                 hints.update(ann) | 
					
						
							|  |  |  |                 continue | 
					
						
							| 
									
										
										
										
											2017-09-14 14:33:00 -04:00
										 |  |  |             if globalns is None: | 
					
						
							| 
									
										
										
										
											2021-06-26 23:31:32 +00:00
										 |  |  |                 base_globals = getattr(sys.modules.get(base.__module__, None), '__dict__', {}) | 
					
						
							| 
									
										
										
										
											2017-09-14 14:33:00 -04:00
										 |  |  |             else: | 
					
						
							|  |  |  |                 base_globals = globalns | 
					
						
							| 
									
										
										
										
											2021-04-13 01:23:12 +08:00
										 |  |  |             base_locals = dict(vars(base)) if localns is None else localns | 
					
						
							| 
									
										
										
										
											2021-04-27 01:31:21 +08:00
										 |  |  |             if localns is None and globalns is None: | 
					
						
							|  |  |  |                 # This is surprising, but required.  Before Python 3.10, | 
					
						
							|  |  |  |                 # get_type_hints only evaluated the globalns of | 
					
						
							|  |  |  |                 # a class.  To maintain backwards compatibility, we reverse | 
					
						
							|  |  |  |                 # the globalns and localns order so that eval() looks into | 
					
						
							|  |  |  |                 # *base_globals* first rather than *base_locals*. | 
					
						
							|  |  |  |                 # This only affects ForwardRefs. | 
					
						
							|  |  |  |                 base_globals, base_locals = base_locals, base_globals | 
					
						
							| 
									
										
										
										
											2016-11-09 13:12:51 -08:00
										 |  |  |             for name, value in ann.items(): | 
					
						
							| 
									
										
										
										
											2016-09-11 15:34:56 -07:00
										 |  |  |                 if value is None: | 
					
						
							|  |  |  |                     value = type(None) | 
					
						
							|  |  |  |                 if isinstance(value, str): | 
					
						
							| 
									
										
										
										
											2024-07-23 14:16:50 -07:00
										 |  |  |                     value = _make_forward_ref(value, is_argument=False, is_class=True) | 
					
						
							|  |  |  |                 value = _eval_type(value, base_globals, base_locals, base.__type_params__, | 
					
						
							|  |  |  |                                    format=format, owner=obj) | 
					
						
							| 
									
										
										
										
											2016-09-11 15:34:56 -07:00
										 |  |  |                 hints[name] = value | 
					
						
							| 
									
										
										
										
											2024-09-26 13:49:48 -07:00
										 |  |  |         if include_extras or format is annotationlib.Format.STRING: | 
					
						
							| 
									
										
										
										
											2024-07-23 14:16:50 -07:00
										 |  |  |             return hints | 
					
						
							|  |  |  |         else: | 
					
						
							|  |  |  |             return {k: _strip_annotations(t) for k, t in hints.items()} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     hints = annotationlib.get_annotations(obj, format=format) | 
					
						
							|  |  |  |     if ( | 
					
						
							|  |  |  |         not hints | 
					
						
							|  |  |  |         and not isinstance(obj, types.ModuleType) | 
					
						
							|  |  |  |         and not callable(obj) | 
					
						
							|  |  |  |         and not hasattr(obj, '__annotations__') | 
					
						
							|  |  |  |         and not hasattr(obj, '__annotate__') | 
					
						
							|  |  |  |     ): | 
					
						
							|  |  |  |         raise TypeError(f"{obj!r} is not a module, class, or callable.") | 
					
						
							| 
									
										
										
										
											2024-09-26 13:49:48 -07:00
										 |  |  |     if format is annotationlib.Format.STRING: | 
					
						
							| 
									
										
										
										
											2024-07-23 14:16:50 -07:00
										 |  |  |         return hints | 
					
						
							| 
									
										
										
										
											2017-09-14 14:33:00 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  |     if globalns is None: | 
					
						
							|  |  |  |         if isinstance(obj, types.ModuleType): | 
					
						
							|  |  |  |             globalns = obj.__dict__ | 
					
						
							|  |  |  |         else: | 
					
						
							| 
									
										
										
										
											2019-11-21 17:24:58 +00:00
										 |  |  |             nsobj = obj | 
					
						
							|  |  |  |             # Find globalns for the unwrapped object. | 
					
						
							|  |  |  |             while hasattr(nsobj, '__wrapped__'): | 
					
						
							|  |  |  |                 nsobj = nsobj.__wrapped__ | 
					
						
							|  |  |  |             globalns = getattr(nsobj, '__globals__', {}) | 
					
						
							| 
									
										
										
										
											2017-09-14 14:33:00 -04:00
										 |  |  |         if localns is None: | 
					
						
							|  |  |  |             localns = globalns | 
					
						
							|  |  |  |     elif localns is None: | 
					
						
							|  |  |  |         localns = globalns | 
					
						
							| 
									
										
										
										
											2024-04-19 14:03:44 +01:00
										 |  |  |     type_params = getattr(obj, "__type_params__", ()) | 
					
						
							| 
									
										
										
										
											2016-11-09 13:12:51 -08:00
										 |  |  |     for name, value in hints.items(): | 
					
						
							|  |  |  |         if value is None: | 
					
						
							|  |  |  |             value = type(None) | 
					
						
							|  |  |  |         if isinstance(value, str): | 
					
						
							| 
									
										
										
										
											2021-09-25 11:56:22 +03:00
										 |  |  |             # class-level forward refs were handled above, this must be either | 
					
						
							|  |  |  |             # a module-level annotation or a function argument annotation | 
					
						
							| 
									
										
										
										
											2024-07-23 14:16:50 -07:00
										 |  |  |             value = _make_forward_ref( | 
					
						
							| 
									
										
										
										
											2021-09-25 11:56:22 +03:00
										 |  |  |                 value, | 
					
						
							|  |  |  |                 is_argument=not isinstance(obj, types.ModuleType), | 
					
						
							|  |  |  |                 is_class=False, | 
					
						
							|  |  |  |             ) | 
					
						
							| 
									
										
										
										
											2024-07-23 14:16:50 -07:00
										 |  |  |         hints[name] = _eval_type(value, globalns, localns, type_params, format=format, owner=obj) | 
					
						
							| 
									
										
										
										
											2020-02-05 02:10:19 +01:00
										 |  |  |     return hints if include_extras else {k: _strip_annotations(t) for k, t in hints.items()} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | def _strip_annotations(t): | 
					
						
							| 
									
										
										
										
											2023-06-05 15:16:09 +01:00
										 |  |  |     """Strip the annotations from a given type.""" | 
					
						
							| 
									
										
										
										
											2020-02-05 02:10:19 +01:00
										 |  |  |     if isinstance(t, _AnnotatedAlias): | 
					
						
							|  |  |  |         return _strip_annotations(t.__origin__) | 
					
						
							| 
									
										
										
										
											2024-03-12 17:49:39 +03:00
										 |  |  |     if hasattr(t, "__origin__") and t.__origin__ in (Required, NotRequired, ReadOnly): | 
					
						
							| 
									
										
										
										
											2022-04-12 12:31:02 -07:00
										 |  |  |         return _strip_annotations(t.__args__[0]) | 
					
						
							| 
									
										
										
										
											2020-02-05 02:10:19 +01:00
										 |  |  |     if isinstance(t, _GenericAlias): | 
					
						
							|  |  |  |         stripped_args = tuple(_strip_annotations(a) for a in t.__args__) | 
					
						
							|  |  |  |         if stripped_args == t.__args__: | 
					
						
							|  |  |  |             return t | 
					
						
							| 
									
										
										
										
											2020-05-07 04:09:33 +03:00
										 |  |  |         return t.copy_with(stripped_args) | 
					
						
							| 
									
										
										
										
											2020-04-26 21:21:08 +03:00
										 |  |  |     if isinstance(t, GenericAlias): | 
					
						
							|  |  |  |         stripped_args = tuple(_strip_annotations(a) for a in t.__args__) | 
					
						
							|  |  |  |         if stripped_args == t.__args__: | 
					
						
							|  |  |  |             return t | 
					
						
							|  |  |  |         return GenericAlias(t.__origin__, stripped_args) | 
					
						
							| 
									
										
										
										
											2025-03-04 11:44:19 -08:00
										 |  |  |     if isinstance(t, Union): | 
					
						
							| 
									
										
										
										
											2021-07-17 06:33:40 +03:00
										 |  |  |         stripped_args = tuple(_strip_annotations(a) for a in t.__args__) | 
					
						
							|  |  |  |         if stripped_args == t.__args__: | 
					
						
							|  |  |  |             return t | 
					
						
							| 
									
										
										
										
											2021-07-24 21:26:02 +03:00
										 |  |  |         return functools.reduce(operator.or_, stripped_args) | 
					
						
							| 
									
										
										
										
											2021-07-17 06:33:40 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-02-05 02:10:19 +01:00
										 |  |  |     return t | 
					
						
							| 
									
										
										
										
											2015-05-22 10:14:11 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-05-31 00:10:07 +01:00
										 |  |  | def get_origin(tp): | 
					
						
							|  |  |  |     """Get the unsubscripted version of a type.
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-06-07 01:21:16 +01:00
										 |  |  |     This supports generic types, Callable, Tuple, Union, Literal, Final, ClassVar, | 
					
						
							|  |  |  |     Annotated, and others. Return None for unsupported types. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     Examples:: | 
					
						
							| 
									
										
										
										
											2023-06-05 15:16:09 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-11-17 20:56:31 +03:00
										 |  |  |         >>> P = ParamSpec('P') | 
					
						
							|  |  |  |         >>> assert get_origin(Literal[42]) is Literal | 
					
						
							|  |  |  |         >>> assert get_origin(int) is None | 
					
						
							|  |  |  |         >>> assert get_origin(ClassVar[int]) is ClassVar | 
					
						
							|  |  |  |         >>> assert get_origin(Generic) is Generic | 
					
						
							|  |  |  |         >>> assert get_origin(Generic[T]) is Generic | 
					
						
							|  |  |  |         >>> assert get_origin(Union[T, int]) is Union | 
					
						
							|  |  |  |         >>> assert get_origin(List[Tuple[T, T]][int]) is list | 
					
						
							|  |  |  |         >>> assert get_origin(P.args) is P | 
					
						
							| 
									
										
										
										
											2019-05-31 00:10:07 +01:00
										 |  |  |     """
 | 
					
						
							| 
									
										
										
										
											2020-02-05 02:10:19 +01:00
										 |  |  |     if isinstance(tp, _AnnotatedAlias): | 
					
						
							|  |  |  |         return Annotated | 
					
						
							| 
									
										
										
										
											2021-04-10 19:57:05 -07:00
										 |  |  |     if isinstance(tp, (_BaseGenericAlias, GenericAlias, | 
					
						
							|  |  |  |                        ParamSpecArgs, ParamSpecKwargs)): | 
					
						
							| 
									
										
										
										
											2019-05-31 00:10:07 +01:00
										 |  |  |         return tp.__origin__ | 
					
						
							|  |  |  |     if tp is Generic: | 
					
						
							|  |  |  |         return Generic | 
					
						
							| 
									
										
										
										
											2025-03-04 11:44:19 -08:00
										 |  |  |     if isinstance(tp, Union): | 
					
						
							|  |  |  |         return Union | 
					
						
							| 
									
										
										
										
											2019-05-31 00:10:07 +01:00
										 |  |  |     return None | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | def get_args(tp): | 
					
						
							|  |  |  |     """Get type arguments with all substitutions performed.
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     For unions, basic simplifications used by Union constructor are performed. | 
					
						
							| 
									
										
										
										
											2023-06-05 15:16:09 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-05-31 00:10:07 +01:00
										 |  |  |     Examples:: | 
					
						
							| 
									
										
										
										
											2023-06-05 15:16:09 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-11-17 20:56:31 +03:00
										 |  |  |         >>> T = TypeVar('T') | 
					
						
							|  |  |  |         >>> assert get_args(Dict[str, int]) == (str, int) | 
					
						
							|  |  |  |         >>> assert get_args(int) == () | 
					
						
							|  |  |  |         >>> assert get_args(Union[int, Union[T, int], str][int]) == (int, str) | 
					
						
							|  |  |  |         >>> assert get_args(Union[int, Tuple[T, int]][str]) == (int, Tuple[str, int]) | 
					
						
							|  |  |  |         >>> assert get_args(Callable[[], T][int]) == ([], int) | 
					
						
							| 
									
										
										
										
											2019-05-31 00:10:07 +01:00
										 |  |  |     """
 | 
					
						
							| 
									
										
										
										
											2020-02-05 02:10:19 +01:00
										 |  |  |     if isinstance(tp, _AnnotatedAlias): | 
					
						
							|  |  |  |         return (tp.__origin__,) + tp.__metadata__ | 
					
						
							| 
									
										
										
										
											2020-12-29 04:06:19 +08:00
										 |  |  |     if isinstance(tp, (_GenericAlias, GenericAlias)): | 
					
						
							| 
									
										
										
										
											2019-05-31 00:10:07 +01:00
										 |  |  |         res = tp.__args__ | 
					
						
							| 
									
										
										
										
											2022-05-02 17:08:28 -06:00
										 |  |  |         if _should_unflatten_callable_args(tp, res): | 
					
						
							| 
									
										
										
										
											2019-05-31 00:10:07 +01:00
										 |  |  |             res = (list(res[:-1]), res[-1]) | 
					
						
							|  |  |  |         return res | 
					
						
							| 
									
										
										
										
											2025-03-04 11:44:19 -08:00
										 |  |  |     if isinstance(tp, Union): | 
					
						
							| 
									
										
										
										
											2020-12-29 10:26:19 +08:00
										 |  |  |         return tp.__args__ | 
					
						
							| 
									
										
										
										
											2019-05-31 00:10:07 +01:00
										 |  |  |     return () | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-09-16 05:58:32 +01:00
										 |  |  | def is_typeddict(tp): | 
					
						
							| 
									
										
										
										
											2023-06-05 15:16:09 +01:00
										 |  |  |     """Check if an annotation is a TypedDict class.
 | 
					
						
							| 
									
										
										
										
											2020-09-16 05:58:32 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |     For example:: | 
					
						
							| 
									
										
										
										
											2023-06-05 15:16:09 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-11-17 20:56:31 +03:00
										 |  |  |         >>> from typing import TypedDict | 
					
						
							|  |  |  |         >>> class Film(TypedDict): | 
					
						
							|  |  |  |         ...     title: str | 
					
						
							|  |  |  |         ...     year: int | 
					
						
							|  |  |  |         ... | 
					
						
							|  |  |  |         >>> is_typeddict(Film) | 
					
						
							|  |  |  |         True | 
					
						
							|  |  |  |         >>> is_typeddict(dict) | 
					
						
							|  |  |  |         False | 
					
						
							| 
									
										
										
										
											2020-09-16 05:58:32 +01:00
										 |  |  |     """
 | 
					
						
							|  |  |  |     return isinstance(tp, _TypedDictMeta) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-04-25 06:40:18 -07:00
										 |  |  | _ASSERT_NEVER_REPR_MAX_LENGTH = 100 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-02-08 10:50:26 -08:00
										 |  |  | def assert_never(arg: Never, /) -> Never: | 
					
						
							|  |  |  |     """Statically assert that a line of code is unreachable.
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     Example:: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         def int_or_str(arg: int | str) -> None: | 
					
						
							|  |  |  |             match arg: | 
					
						
							|  |  |  |                 case int(): | 
					
						
							|  |  |  |                     print("It's an int") | 
					
						
							|  |  |  |                 case str(): | 
					
						
							|  |  |  |                     print("It's a str") | 
					
						
							|  |  |  |                 case _: | 
					
						
							|  |  |  |                     assert_never(arg) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     If a type checker finds that a call to assert_never() is | 
					
						
							|  |  |  |     reachable, it will emit an error. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     At runtime, this throws an exception when called. | 
					
						
							|  |  |  |     """
 | 
					
						
							| 
									
										
										
										
											2022-04-25 06:40:18 -07:00
										 |  |  |     value = repr(arg) | 
					
						
							|  |  |  |     if len(value) > _ASSERT_NEVER_REPR_MAX_LENGTH: | 
					
						
							|  |  |  |         value = value[:_ASSERT_NEVER_REPR_MAX_LENGTH] + '...' | 
					
						
							|  |  |  |     raise AssertionError(f"Expected code to be unreachable, but got: {value}") | 
					
						
							| 
									
										
										
										
											2022-02-08 10:50:26 -08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-05-22 10:14:11 -07:00
										 |  |  | 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 | 
					
						
							| 
									
										
										
										
											2016-09-11 15:34:56 -07:00
										 |  |  |     applies recursively to all methods and classes defined in that class | 
					
						
							|  |  |  |     (but not to methods defined in its superclasses or subclasses). | 
					
						
							| 
									
										
										
										
											2015-05-22 10:14:11 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-09-11 15:34:56 -07:00
										 |  |  |     This mutates the function(s) or class(es) in place. | 
					
						
							| 
									
										
										
										
											2015-05-22 10:14:11 -07:00
										 |  |  |     """
 | 
					
						
							|  |  |  |     if isinstance(arg, type): | 
					
						
							| 
									
										
										
										
											2022-02-19 04:53:29 +03:00
										 |  |  |         for key in dir(arg): | 
					
						
							|  |  |  |             obj = getattr(arg, key) | 
					
						
							|  |  |  |             if ( | 
					
						
							|  |  |  |                 not hasattr(obj, '__qualname__') | 
					
						
							|  |  |  |                 or obj.__qualname__ != f'{arg.__qualname__}.{obj.__name__}' | 
					
						
							|  |  |  |                 or getattr(obj, '__module__', None) != arg.__module__ | 
					
						
							|  |  |  |             ): | 
					
						
							|  |  |  |                 # We only modify objects that are defined in this type directly. | 
					
						
							|  |  |  |                 # If classes / methods are nested in multiple layers, | 
					
						
							|  |  |  |                 # we will modify them when processing their direct holders. | 
					
						
							|  |  |  |                 continue | 
					
						
							|  |  |  |             # Instance, class, and static methods: | 
					
						
							| 
									
										
										
										
											2015-05-22 10:14:11 -07:00
										 |  |  |             if isinstance(obj, types.FunctionType): | 
					
						
							|  |  |  |                 obj.__no_type_check__ = True | 
					
						
							| 
									
										
										
										
											2022-02-19 04:53:29 +03:00
										 |  |  |             if isinstance(obj, types.MethodType): | 
					
						
							|  |  |  |                 obj.__func__.__no_type_check__ = True | 
					
						
							|  |  |  |             # Nested types: | 
					
						
							| 
									
										
										
										
											2016-09-11 15:34:56 -07:00
										 |  |  |             if isinstance(obj, type): | 
					
						
							|  |  |  |                 no_type_check(obj) | 
					
						
							|  |  |  |     try: | 
					
						
							| 
									
										
										
										
											2015-05-22 10:14:11 -07:00
										 |  |  |         arg.__no_type_check__ = True | 
					
						
							| 
									
										
										
										
											2017-01-22 17:43:53 -08:00
										 |  |  |     except TypeError:  # built-in classes | 
					
						
							| 
									
										
										
										
											2016-09-11 15:34:56 -07:00
										 |  |  |         pass | 
					
						
							| 
									
										
										
										
											2015-05-22 10:14:11 -07:00
										 |  |  |     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. | 
					
						
							|  |  |  |     """
 | 
					
						
							| 
									
										
										
										
											2023-07-13 14:30:35 +01:00
										 |  |  |     import warnings | 
					
						
							|  |  |  |     warnings._deprecated("typing.no_type_check_decorator", remove=(3, 15)) | 
					
						
							| 
									
										
										
										
											2015-05-22 10:14:11 -07:00
										 |  |  |     @functools.wraps(decorator) | 
					
						
							|  |  |  |     def wrapped_decorator(*args, **kwds): | 
					
						
							|  |  |  |         func = decorator(*args, **kwds) | 
					
						
							|  |  |  |         func = no_type_check(func) | 
					
						
							|  |  |  |         return func | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return wrapped_decorator | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-04-05 08:28:52 -07:00
										 |  |  | 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.") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-04-16 09:01:43 -07:00
										 |  |  | # {module: {qualname: {firstlineno: func}}} | 
					
						
							|  |  |  | _overload_registry = defaultdict(functools.partial(defaultdict, dict)) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-05-22 10:14:11 -07:00
										 |  |  | def overload(func): | 
					
						
							| 
									
										
										
										
											2016-04-05 08:28:52 -07:00
										 |  |  |     """Decorator for overloaded functions/methods.
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     In a stub file, place two or more stub definitions for the same | 
					
						
							| 
									
										
										
										
											2023-06-07 01:21:16 +01:00
										 |  |  |     function in a row, each decorated with @overload. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     For example:: | 
					
						
							| 
									
										
										
										
											2016-04-05 08:28:52 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-06-05 15:16:09 +01:00
										 |  |  |         @overload | 
					
						
							|  |  |  |         def utf8(value: None) -> None: ... | 
					
						
							|  |  |  |         @overload | 
					
						
							|  |  |  |         def utf8(value: bytes) -> bytes: ... | 
					
						
							|  |  |  |         @overload | 
					
						
							|  |  |  |         def utf8(value: str) -> bytes: ... | 
					
						
							| 
									
										
										
										
											2016-04-05 08:28:52 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |     In a non-stub file (i.e. a regular .py file), do the same but | 
					
						
							|  |  |  |     follow it with an implementation.  The implementation should *not* | 
					
						
							| 
									
										
										
										
											2023-06-07 01:21:16 +01:00
										 |  |  |     be decorated with @overload:: | 
					
						
							| 
									
										
										
										
											2016-04-05 08:28:52 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-06-05 15:16:09 +01:00
										 |  |  |         @overload | 
					
						
							|  |  |  |         def utf8(value: None) -> None: ... | 
					
						
							|  |  |  |         @overload | 
					
						
							|  |  |  |         def utf8(value: bytes) -> bytes: ... | 
					
						
							|  |  |  |         @overload | 
					
						
							|  |  |  |         def utf8(value: str) -> bytes: ... | 
					
						
							|  |  |  |         def utf8(value): | 
					
						
							|  |  |  |             ...  # implementation goes here | 
					
						
							| 
									
										
										
										
											2022-04-16 09:01:43 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |     The overloads for a function can be retrieved at runtime using the | 
					
						
							|  |  |  |     get_overloads() function. | 
					
						
							| 
									
										
										
										
											2016-04-05 08:28:52 -07:00
										 |  |  |     """
 | 
					
						
							| 
									
										
										
										
											2022-04-16 09:01:43 -07:00
										 |  |  |     # classmethod and staticmethod | 
					
						
							|  |  |  |     f = getattr(func, "__func__", func) | 
					
						
							|  |  |  |     try: | 
					
						
							|  |  |  |         _overload_registry[f.__module__][f.__qualname__][f.__code__.co_firstlineno] = func | 
					
						
							|  |  |  |     except AttributeError: | 
					
						
							|  |  |  |         # Not a normal function; ignore. | 
					
						
							|  |  |  |         pass | 
					
						
							| 
									
										
										
										
											2016-04-05 08:28:52 -07:00
										 |  |  |     return _overload_dummy | 
					
						
							| 
									
										
										
										
											2015-05-22 10:14:11 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-04-16 09:01:43 -07:00
										 |  |  | def get_overloads(func): | 
					
						
							|  |  |  |     """Return all defined overloads for *func* as a sequence.""" | 
					
						
							|  |  |  |     # classmethod and staticmethod | 
					
						
							|  |  |  |     f = getattr(func, "__func__", func) | 
					
						
							|  |  |  |     if f.__module__ not in _overload_registry: | 
					
						
							|  |  |  |         return [] | 
					
						
							|  |  |  |     mod_dict = _overload_registry[f.__module__] | 
					
						
							|  |  |  |     if f.__qualname__ not in mod_dict: | 
					
						
							|  |  |  |         return [] | 
					
						
							|  |  |  |     return list(mod_dict[f.__qualname__].values()) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | def clear_overloads(): | 
					
						
							|  |  |  |     """Clear all overloads in the registry.""" | 
					
						
							|  |  |  |     _overload_registry.clear() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-05-26 09:37:07 +01:00
										 |  |  | def final(f): | 
					
						
							| 
									
										
										
										
											2023-06-05 15:16:09 +01:00
										 |  |  |     """Decorator to indicate final methods and final classes.
 | 
					
						
							| 
									
										
										
										
											2019-05-26 09:37:07 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |     Use this decorator to indicate to type checkers that the decorated | 
					
						
							|  |  |  |     method cannot be overridden, and decorated class cannot be subclassed. | 
					
						
							| 
									
										
										
										
											2023-06-05 15:16:09 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |     For example:: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         class Base: | 
					
						
							|  |  |  |             @final | 
					
						
							|  |  |  |             def done(self) -> None: | 
					
						
							|  |  |  |                 ... | 
					
						
							|  |  |  |         class Sub(Base): | 
					
						
							|  |  |  |             def done(self) -> None:  # Error reported by type checker | 
					
						
							| 
									
										
										
										
											2019-05-26 09:37:07 +01:00
										 |  |  |                 ... | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-06-05 15:16:09 +01:00
										 |  |  |         @final | 
					
						
							|  |  |  |         class Leaf: | 
					
						
							|  |  |  |             ... | 
					
						
							|  |  |  |         class Other(Leaf):  # Error reported by type checker | 
					
						
							|  |  |  |             ... | 
					
						
							| 
									
										
										
										
											2019-05-26 09:37:07 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-01-12 11:38:25 -08:00
										 |  |  |     There is no runtime checking of these properties. The decorator | 
					
						
							| 
									
										
										
										
											2023-06-05 15:16:09 +01:00
										 |  |  |     attempts to set the ``__final__`` attribute to ``True`` on the decorated | 
					
						
							|  |  |  |     object to allow runtime introspection. | 
					
						
							| 
									
										
										
										
											2019-05-26 09:37:07 +01:00
										 |  |  |     """
 | 
					
						
							| 
									
										
										
										
											2022-01-12 11:38:25 -08:00
										 |  |  |     try: | 
					
						
							|  |  |  |         f.__final__ = True | 
					
						
							|  |  |  |     except (AttributeError, TypeError): | 
					
						
							|  |  |  |         # Skip the attribute silently if it is not writable. | 
					
						
							|  |  |  |         # AttributeError happens if the object has __slots__ or a | 
					
						
							|  |  |  |         # read-only property, TypeError if it's a builtin class. | 
					
						
							|  |  |  |         pass | 
					
						
							| 
									
										
										
										
											2019-05-26 09:37:07 +01:00
										 |  |  |     return f | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-05-17 06:03:58 -07:00
										 |  |  | # Some unconstrained type variables.  These were initially used by the container types. | 
					
						
							|  |  |  | # They were never meant for export and are now unused, but we keep them around to | 
					
						
							|  |  |  | # avoid breaking compatibility with users who import them. | 
					
						
							| 
									
										
										
										
											2018-01-20 11:23:59 +00:00
										 |  |  | 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) | 
					
						
							| 
									
										
										
										
											2015-05-22 10:14:11 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-02-27 13:16:11 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-01-20 11:23:59 +00:00
										 |  |  | # A useful type variable with constraints.  This represents string types. | 
					
						
							|  |  |  | # (This one *is* for export!) | 
					
						
							|  |  |  | AnyStr = TypeVar('AnyStr', bytes, str) | 
					
						
							| 
									
										
										
										
											2016-10-29 16:05:26 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-01-20 11:23:59 +00:00
										 |  |  | # Various ABCs mimicking those in collections.abc. | 
					
						
							| 
									
										
										
										
											2020-05-07 04:09:33 +03:00
										 |  |  | _alias = _SpecialGenericAlias | 
					
						
							| 
									
										
										
										
											2018-01-20 11:23:59 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-10 11:53:16 +03:00
										 |  |  | Hashable = _alias(collections.abc.Hashable, 0)  # Not generic. | 
					
						
							|  |  |  | Awaitable = _alias(collections.abc.Awaitable, 1) | 
					
						
							|  |  |  | Coroutine = _alias(collections.abc.Coroutine, 3) | 
					
						
							|  |  |  | AsyncIterable = _alias(collections.abc.AsyncIterable, 1) | 
					
						
							|  |  |  | AsyncIterator = _alias(collections.abc.AsyncIterator, 1) | 
					
						
							|  |  |  | Iterable = _alias(collections.abc.Iterable, 1) | 
					
						
							|  |  |  | Iterator = _alias(collections.abc.Iterator, 1) | 
					
						
							|  |  |  | Reversible = _alias(collections.abc.Reversible, 1) | 
					
						
							|  |  |  | 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) | 
					
						
							| 
									
										
										
										
											2018-01-20 11:23:59 +00:00
										 |  |  | Callable.__doc__ = \ | 
					
						
							| 
									
										
										
										
											2023-06-05 15:16:09 +01:00
										 |  |  |     """Deprecated alias to collections.abc.Callable.
 | 
					
						
							| 
									
										
										
										
											2016-10-29 16:05:26 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-06-07 15:02:40 +01:00
										 |  |  |     Callable[[int], str] signifies a function that takes a single | 
					
						
							|  |  |  |     parameter of type int and returns a str. | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-01-20 11:23:59 +00:00
										 |  |  |     The subscription syntax must always be used with exactly two | 
					
						
							| 
									
										
										
										
											2023-06-05 15:16:09 +01:00
										 |  |  |     values: the argument list and the return type. | 
					
						
							| 
									
										
										
										
											2023-06-07 15:02:40 +01:00
										 |  |  |     The argument list must be a list of types, a ParamSpec, | 
					
						
							|  |  |  |     Concatenate or ellipsis. The return type must be a single type. | 
					
						
							| 
									
										
										
										
											2015-12-03 17:31:24 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-06-05 15:16:09 +01:00
										 |  |  |     There is no syntax to indicate optional or keyword arguments; | 
					
						
							| 
									
										
										
										
											2018-01-20 11:23:59 +00:00
										 |  |  |     such function types are rarely used as callback types. | 
					
						
							|  |  |  |     """
 | 
					
						
							| 
									
										
										
										
											2020-05-10 11:53:16 +03:00
										 |  |  | AbstractSet = _alias(collections.abc.Set, 1, name='AbstractSet') | 
					
						
							|  |  |  | MutableSet = _alias(collections.abc.MutableSet, 1) | 
					
						
							| 
									
										
										
										
											2018-01-20 11:23:59 +00:00
										 |  |  | # NOTE: Mapping is only covariant in the value type. | 
					
						
							| 
									
										
										
										
											2020-05-10 11:53:16 +03:00
										 |  |  | Mapping = _alias(collections.abc.Mapping, 2) | 
					
						
							|  |  |  | MutableMapping = _alias(collections.abc.MutableMapping, 2) | 
					
						
							|  |  |  | Sequence = _alias(collections.abc.Sequence, 1) | 
					
						
							|  |  |  | MutableSequence = _alias(collections.abc.MutableSequence, 1) | 
					
						
							|  |  |  | # Tuple accepts variable number of parameters. | 
					
						
							|  |  |  | Tuple = _TupleType(tuple, -1, inst=False, name='Tuple') | 
					
						
							| 
									
										
										
										
											2018-01-20 11:23:59 +00:00
										 |  |  | Tuple.__doc__ = \ | 
					
						
							| 
									
										
										
										
											2023-06-05 15:16:09 +01:00
										 |  |  |     """Deprecated alias to builtins.tuple.
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     Tuple[X, Y] is the cross-product type of X and Y. | 
					
						
							| 
									
										
										
										
											2015-12-03 17:31:24 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-01-20 11:23:59 +00:00
										 |  |  |     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. | 
					
						
							| 
									
										
										
										
											2015-12-03 17:31:24 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-01-20 11:23:59 +00:00
										 |  |  |     To specify a variable-length tuple of homogeneous type, use Tuple[T, ...]. | 
					
						
							|  |  |  |     """
 | 
					
						
							| 
									
										
										
										
											2020-05-10 11:53:16 +03:00
										 |  |  | List = _alias(list, 1, inst=False, name='List') | 
					
						
							|  |  |  | Deque = _alias(collections.deque, 1, name='Deque') | 
					
						
							|  |  |  | Set = _alias(set, 1, inst=False, name='Set') | 
					
						
							|  |  |  | FrozenSet = _alias(frozenset, 1, inst=False, name='FrozenSet') | 
					
						
							|  |  |  | MappingView = _alias(collections.abc.MappingView, 1) | 
					
						
							|  |  |  | KeysView = _alias(collections.abc.KeysView, 1) | 
					
						
							|  |  |  | ItemsView = _alias(collections.abc.ItemsView, 2) | 
					
						
							|  |  |  | ValuesView = _alias(collections.abc.ValuesView, 1) | 
					
						
							|  |  |  | Dict = _alias(dict, 2, inst=False, name='Dict') | 
					
						
							|  |  |  | DefaultDict = _alias(collections.defaultdict, 2, name='DefaultDict') | 
					
						
							|  |  |  | OrderedDict = _alias(collections.OrderedDict, 2) | 
					
						
							|  |  |  | Counter = _alias(collections.Counter, 1) | 
					
						
							|  |  |  | ChainMap = _alias(collections.ChainMap, 2) | 
					
						
							| 
									
										
										
										
											2024-05-06 15:35:06 -07:00
										 |  |  | Generator = _alias(collections.abc.Generator, 3, defaults=(types.NoneType, types.NoneType)) | 
					
						
							|  |  |  | AsyncGenerator = _alias(collections.abc.AsyncGenerator, 2, defaults=(types.NoneType,)) | 
					
						
							| 
									
										
										
										
											2020-05-10 11:53:16 +03:00
										 |  |  | Type = _alias(type, 1, inst=False, name='Type') | 
					
						
							| 
									
										
										
										
											2018-01-20 11:23:59 +00:00
										 |  |  | Type.__doc__ = \ | 
					
						
							| 
									
										
										
										
											2023-06-05 15:16:09 +01:00
										 |  |  |     """Deprecated alias to builtins.type.
 | 
					
						
							| 
									
										
										
										
											2015-12-03 17:31:24 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-06-05 15:16:09 +01:00
										 |  |  |     builtins.type or typing.Type can be used to annotate class objects. | 
					
						
							| 
									
										
										
										
											2018-01-20 11:23:59 +00:00
										 |  |  |     For example, suppose we have the following classes:: | 
					
						
							| 
									
										
										
										
											2016-04-05 08:28:52 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-06-05 15:16:09 +01:00
										 |  |  |         class User: ...  # Abstract base for User classes | 
					
						
							|  |  |  |         class BasicUser(User): ... | 
					
						
							|  |  |  |         class ProUser(User): ... | 
					
						
							|  |  |  |         class TeamUser(User): ... | 
					
						
							| 
									
										
										
										
											2015-12-03 17:31:24 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-01-20 11:23:59 +00:00
										 |  |  |     And a function that takes a class argument that's a subclass of | 
					
						
							|  |  |  |     User and returns an instance of the corresponding class:: | 
					
						
							| 
									
										
										
										
											2015-12-03 17:31:24 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-06-05 15:16:09 +01:00
										 |  |  |         def new_user[U](user_class: Type[U]) -> U: | 
					
						
							|  |  |  |             user = user_class() | 
					
						
							|  |  |  |             # (Here we could write the user object to a database) | 
					
						
							|  |  |  |             return user | 
					
						
							| 
									
										
										
										
											2015-05-22 10:14:11 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-06-05 15:16:09 +01:00
										 |  |  |         joe = new_user(BasicUser) | 
					
						
							| 
									
										
										
										
											2015-05-22 10:14:11 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-01-20 11:23:59 +00:00
										 |  |  |     At this point the type checker knows that joe has type BasicUser. | 
					
						
							|  |  |  |     """
 | 
					
						
							| 
									
										
										
										
											2015-05-22 10:14:11 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-05-28 08:40:15 +01:00
										 |  |  | @runtime_checkable | 
					
						
							|  |  |  | class SupportsInt(Protocol): | 
					
						
							| 
									
										
										
										
											2019-10-08 16:30:17 +03:00
										 |  |  |     """An ABC with one abstract method __int__.""" | 
					
						
							| 
									
										
										
										
											2023-06-05 15:16:09 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-08-05 12:11:06 +02:00
										 |  |  |     __slots__ = () | 
					
						
							| 
									
										
										
										
											2015-05-22 10:14:11 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |     @abstractmethod | 
					
						
							|  |  |  |     def __int__(self) -> int: | 
					
						
							|  |  |  |         pass | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-05-28 08:40:15 +01:00
										 |  |  | @runtime_checkable | 
					
						
							|  |  |  | class SupportsFloat(Protocol): | 
					
						
							| 
									
										
										
										
											2019-10-08 16:30:17 +03:00
										 |  |  |     """An ABC with one abstract method __float__.""" | 
					
						
							| 
									
										
										
										
											2023-06-05 15:16:09 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-08-05 12:11:06 +02:00
										 |  |  |     __slots__ = () | 
					
						
							| 
									
										
										
										
											2015-05-22 10:14:11 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |     @abstractmethod | 
					
						
							|  |  |  |     def __float__(self) -> float: | 
					
						
							|  |  |  |         pass | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-05-28 08:40:15 +01:00
										 |  |  | @runtime_checkable | 
					
						
							|  |  |  | class SupportsComplex(Protocol): | 
					
						
							| 
									
										
										
										
											2019-10-08 16:30:17 +03:00
										 |  |  |     """An ABC with one abstract method __complex__.""" | 
					
						
							| 
									
										
										
										
											2023-06-05 15:16:09 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-08-05 12:11:06 +02:00
										 |  |  |     __slots__ = () | 
					
						
							| 
									
										
										
										
											2015-05-22 10:14:11 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |     @abstractmethod | 
					
						
							|  |  |  |     def __complex__(self) -> complex: | 
					
						
							|  |  |  |         pass | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-05-28 08:40:15 +01:00
										 |  |  | @runtime_checkable | 
					
						
							|  |  |  | class SupportsBytes(Protocol): | 
					
						
							| 
									
										
										
										
											2019-10-08 16:30:17 +03:00
										 |  |  |     """An ABC with one abstract method __bytes__.""" | 
					
						
							| 
									
										
										
										
											2023-06-05 15:16:09 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-08-05 12:11:06 +02:00
										 |  |  |     __slots__ = () | 
					
						
							| 
									
										
										
										
											2015-05-22 10:14:11 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |     @abstractmethod | 
					
						
							|  |  |  |     def __bytes__(self) -> bytes: | 
					
						
							|  |  |  |         pass | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-05-28 08:40:15 +01:00
										 |  |  | @runtime_checkable | 
					
						
							|  |  |  | class SupportsIndex(Protocol): | 
					
						
							| 
									
										
										
										
											2019-10-08 16:30:17 +03:00
										 |  |  |     """An ABC with one abstract method __index__.""" | 
					
						
							| 
									
										
										
										
											2023-06-05 15:16:09 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-05-22 07:23:01 -07:00
										 |  |  |     __slots__ = () | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     @abstractmethod | 
					
						
							|  |  |  |     def __index__(self) -> int: | 
					
						
							|  |  |  |         pass | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-05-28 08:40:15 +01:00
										 |  |  | @runtime_checkable | 
					
						
							| 
									
										
										
										
											2023-05-17 06:03:58 -07:00
										 |  |  | class SupportsAbs[T](Protocol): | 
					
						
							| 
									
										
										
										
											2019-10-08 16:30:17 +03:00
										 |  |  |     """An ABC with one abstract method __abs__ that is covariant in its return type.""" | 
					
						
							| 
									
										
										
										
											2023-06-05 15:16:09 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-08-05 12:11:06 +02:00
										 |  |  |     __slots__ = () | 
					
						
							| 
									
										
										
										
											2015-05-22 10:14:11 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |     @abstractmethod | 
					
						
							| 
									
										
										
										
											2023-05-17 06:03:58 -07:00
										 |  |  |     def __abs__(self) -> T: | 
					
						
							| 
									
										
										
										
											2015-05-22 10:14:11 -07:00
										 |  |  |         pass | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-05-28 08:40:15 +01:00
										 |  |  | @runtime_checkable | 
					
						
							| 
									
										
										
										
											2023-05-17 06:03:58 -07:00
										 |  |  | class SupportsRound[T](Protocol): | 
					
						
							| 
									
										
										
										
											2019-10-08 16:30:17 +03:00
										 |  |  |     """An ABC with one abstract method __round__ that is covariant in its return type.""" | 
					
						
							| 
									
										
										
										
											2023-06-05 15:16:09 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-08-05 12:11:06 +02:00
										 |  |  |     __slots__ = () | 
					
						
							| 
									
										
										
										
											2015-05-22 10:14:11 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |     @abstractmethod | 
					
						
							| 
									
										
										
										
											2023-05-17 06:03:58 -07:00
										 |  |  |     def __round__(self, ndigits: int = 0) -> T: | 
					
						
							| 
									
										
										
										
											2015-05-22 10:14:11 -07:00
										 |  |  |         pass | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-07-23 14:16:50 -07:00
										 |  |  | def _make_nmtuple(name, fields, annotate_func, module, defaults = ()): | 
					
						
							| 
									
										
										
										
											2020-04-08 10:59:04 +03:00
										 |  |  |     nm_tpl = collections.namedtuple(name, fields, | 
					
						
							|  |  |  |                                     defaults=defaults, module=module) | 
					
						
							| 
									
										
										
										
											2024-07-23 14:16:50 -07:00
										 |  |  |     nm_tpl.__annotate__ = nm_tpl.__new__.__annotate__ = annotate_func | 
					
						
							| 
									
										
										
										
											2016-09-11 15:34:56 -07:00
										 |  |  |     return nm_tpl | 
					
						
							| 
									
										
										
										
											2015-05-22 10:14:11 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-07-23 14:16:50 -07:00
										 |  |  | def _make_eager_annotate(types): | 
					
						
							|  |  |  |     checked_types = {key: _type_check(val, f"field {key} annotation must be a type") | 
					
						
							|  |  |  |                      for key, val in types.items()} | 
					
						
							|  |  |  |     def annotate(format): | 
					
						
							| 
									
										
										
										
											2024-11-26 07:40:13 -08:00
										 |  |  |         match format: | 
					
						
							|  |  |  |             case annotationlib.Format.VALUE | annotationlib.Format.FORWARDREF: | 
					
						
							|  |  |  |                 return checked_types | 
					
						
							|  |  |  |             case annotationlib.Format.STRING: | 
					
						
							|  |  |  |                 return annotationlib.annotations_to_string(types) | 
					
						
							|  |  |  |             case _: | 
					
						
							|  |  |  |                 raise NotImplementedError(format) | 
					
						
							| 
									
										
										
										
											2024-07-23 14:16:50 -07:00
										 |  |  |     return annotate | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-02-13 22:50:14 +01:00
										 |  |  | # attributes prohibited to set in NamedTuple class syntax | 
					
						
							| 
									
										
										
										
											2020-04-08 10:59:04 +03:00
										 |  |  | _prohibited = frozenset({'__new__', '__init__', '__slots__', '__getnewargs__', | 
					
						
							|  |  |  |                          '_fields', '_field_defaults', | 
					
						
							|  |  |  |                          '_make', '_replace', '_asdict', '_source'}) | 
					
						
							| 
									
										
										
										
											2017-02-13 22:50:14 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-07-23 14:16:50 -07:00
										 |  |  | _special = frozenset({'__module__', '__name__', '__annotations__', '__annotate__'}) | 
					
						
							| 
									
										
										
										
											2017-02-13 22:50:14 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-05-22 10:14:11 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-11-15 09:48:06 -08:00
										 |  |  | class NamedTupleMeta(type): | 
					
						
							|  |  |  |     def __new__(cls, typename, bases, ns): | 
					
						
							| 
									
										
										
										
											2022-05-03 01:41:23 +03:00
										 |  |  |         assert _NamedTuple in bases | 
					
						
							| 
									
										
										
										
											2025-03-06 05:45:47 +01:00
										 |  |  |         if "__classcell__" in ns: | 
					
						
							|  |  |  |             raise TypeError( | 
					
						
							|  |  |  |                 "uses of super() and __class__ are unsupported in methods of NamedTuple subclasses") | 
					
						
							| 
									
										
										
										
											2022-05-03 01:41:23 +03:00
										 |  |  |         for base in bases: | 
					
						
							|  |  |  |             if base is not _NamedTuple and base is not Generic: | 
					
						
							|  |  |  |                 raise TypeError( | 
					
						
							|  |  |  |                     'can only inherit from a NamedTuple type and Generic') | 
					
						
							|  |  |  |         bases = tuple(tuple if base is _NamedTuple else base for base in bases) | 
					
						
							| 
									
										
										
										
											2024-06-11 07:06:49 -06:00
										 |  |  |         if "__annotations__" in ns: | 
					
						
							|  |  |  |             types = ns["__annotations__"] | 
					
						
							| 
									
										
										
										
											2024-07-23 14:16:50 -07:00
										 |  |  |             field_names = list(types) | 
					
						
							|  |  |  |             annotate = _make_eager_annotate(types) | 
					
						
							| 
									
										
										
										
											2024-06-11 07:06:49 -06:00
										 |  |  |         elif "__annotate__" in ns: | 
					
						
							| 
									
										
										
										
											2024-07-23 14:16:50 -07:00
										 |  |  |             original_annotate = ns["__annotate__"] | 
					
						
							|  |  |  |             types = annotationlib.call_annotate_function(original_annotate, annotationlib.Format.FORWARDREF) | 
					
						
							|  |  |  |             field_names = list(types) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             # For backward compatibility, type-check all the types at creation time | 
					
						
							|  |  |  |             for typ in types.values(): | 
					
						
							|  |  |  |                 _type_check(typ, "field annotation must be a type") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             def annotate(format): | 
					
						
							|  |  |  |                 annos = annotationlib.call_annotate_function(original_annotate, format) | 
					
						
							| 
									
										
										
										
											2024-09-26 13:49:48 -07:00
										 |  |  |                 if format != annotationlib.Format.STRING: | 
					
						
							| 
									
										
										
										
											2024-07-23 14:16:50 -07:00
										 |  |  |                     return {key: _type_check(val, f"field {key} annotation must be a type") | 
					
						
							|  |  |  |                             for key, val in annos.items()} | 
					
						
							|  |  |  |                 return annos | 
					
						
							| 
									
										
										
										
											2024-06-11 07:06:49 -06:00
										 |  |  |         else: | 
					
						
							| 
									
										
										
										
											2024-07-23 14:16:50 -07:00
										 |  |  |             # Empty NamedTuple | 
					
						
							|  |  |  |             field_names = [] | 
					
						
							|  |  |  |             annotate = lambda format: {} | 
					
						
							| 
									
										
										
										
											2020-04-08 10:59:04 +03:00
										 |  |  |         default_names = [] | 
					
						
							| 
									
										
										
										
											2024-07-23 14:16:50 -07:00
										 |  |  |         for field_name in field_names: | 
					
						
							| 
									
										
										
										
											2017-01-18 08:03:50 -08:00
										 |  |  |             if field_name in ns: | 
					
						
							| 
									
										
										
										
											2020-04-08 10:59:04 +03:00
										 |  |  |                 default_names.append(field_name) | 
					
						
							|  |  |  |             elif default_names: | 
					
						
							|  |  |  |                 raise TypeError(f"Non-default namedtuple field {field_name} " | 
					
						
							|  |  |  |                                 f"cannot follow default field" | 
					
						
							|  |  |  |                                 f"{'s' if len(default_names) > 1 else ''} " | 
					
						
							|  |  |  |                                 f"{', '.join(default_names)}") | 
					
						
							| 
									
										
										
										
											2024-07-23 14:16:50 -07:00
										 |  |  |         nm_tpl = _make_nmtuple(typename, field_names, annotate, | 
					
						
							| 
									
										
										
										
											2020-04-08 10:59:04 +03:00
										 |  |  |                                defaults=[ns[n] for n in default_names], | 
					
						
							|  |  |  |                                module=ns['__module__']) | 
					
						
							| 
									
										
										
										
											2022-05-03 01:41:23 +03:00
										 |  |  |         nm_tpl.__bases__ = bases | 
					
						
							|  |  |  |         if Generic in bases: | 
					
						
							| 
									
										
										
										
											2023-05-15 20:36:23 -07:00
										 |  |  |             class_getitem = _generic_class_getitem | 
					
						
							| 
									
										
										
										
											2022-05-03 01:41:23 +03:00
										 |  |  |             nm_tpl.__class_getitem__ = classmethod(class_getitem) | 
					
						
							| 
									
										
										
										
											2017-01-22 17:47:20 -08:00
										 |  |  |         # update from user namespace without overriding special namedtuple attributes | 
					
						
							| 
									
										
										
										
											2023-11-27 16:34:44 +00:00
										 |  |  |         for key, val in ns.items(): | 
					
						
							| 
									
										
										
										
											2017-02-13 22:50:14 +01:00
										 |  |  |             if key in _prohibited: | 
					
						
							|  |  |  |                 raise AttributeError("Cannot overwrite NamedTuple attribute " + key) | 
					
						
							| 
									
										
										
										
											2023-11-27 16:34:44 +00:00
										 |  |  |             elif key not in _special: | 
					
						
							|  |  |  |                 if key not in nm_tpl._fields: | 
					
						
							|  |  |  |                     setattr(nm_tpl, key, val) | 
					
						
							|  |  |  |                 try: | 
					
						
							|  |  |  |                     set_name = type(val).__set_name__ | 
					
						
							|  |  |  |                 except AttributeError: | 
					
						
							|  |  |  |                     pass | 
					
						
							|  |  |  |                 else: | 
					
						
							|  |  |  |                     try: | 
					
						
							|  |  |  |                         set_name(val, nm_tpl, key) | 
					
						
							|  |  |  |                     except BaseException as e: | 
					
						
							|  |  |  |                         e.add_note( | 
					
						
							|  |  |  |                             f"Error calling __set_name__ on {type(val).__name__!r} " | 
					
						
							|  |  |  |                             f"instance {key!r} in {typename!r}" | 
					
						
							|  |  |  |                         ) | 
					
						
							|  |  |  |                         raise | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-05-03 01:41:23 +03:00
										 |  |  |         if Generic in bases: | 
					
						
							|  |  |  |             nm_tpl.__init_subclass__() | 
					
						
							| 
									
										
										
										
											2017-01-18 08:03:50 -08:00
										 |  |  |         return nm_tpl | 
					
						
							| 
									
										
										
										
											2016-09-11 15:34:56 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-01-22 17:43:53 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-06-14 13:38:49 +01:00
										 |  |  | def NamedTuple(typename, fields=_sentinel, /, **kwargs): | 
					
						
							| 
									
										
										
										
											2016-11-15 09:48:06 -08:00
										 |  |  |     """Typed version of namedtuple.
 | 
					
						
							| 
									
										
										
										
											2016-09-11 15:34:56 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-05-26 08:34:17 +02:00
										 |  |  |     Usage:: | 
					
						
							| 
									
										
										
										
											2016-09-11 15:34:56 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-11-15 09:48:06 -08:00
										 |  |  |         class Employee(NamedTuple): | 
					
						
							|  |  |  |             name: str | 
					
						
							|  |  |  |             id: int | 
					
						
							| 
									
										
										
										
											2016-09-11 15:34:56 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-11-15 09:48:06 -08:00
										 |  |  |     This is equivalent to:: | 
					
						
							| 
									
										
										
										
											2016-09-11 15:34:56 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-11-15 09:48:06 -08:00
										 |  |  |         Employee = collections.namedtuple('Employee', ['name', 'id']) | 
					
						
							| 
									
										
										
										
											2016-09-11 15:34:56 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-03-18 09:53:56 -07:00
										 |  |  |     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.) | 
					
						
							| 
									
										
										
										
											2023-06-05 15:16:09 +01:00
										 |  |  |     An alternative equivalent functional syntax is also accepted:: | 
					
						
							| 
									
										
										
										
											2016-09-11 15:34:56 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-06-05 15:16:09 +01:00
										 |  |  |         Employee = NamedTuple('Employee', [('name', str), ('id', int)]) | 
					
						
							| 
									
										
										
										
											2016-11-15 09:48:06 -08:00
										 |  |  |     """
 | 
					
						
							| 
									
										
										
										
											2023-06-14 13:38:49 +01:00
										 |  |  |     if fields is _sentinel: | 
					
						
							|  |  |  |         if kwargs: | 
					
						
							|  |  |  |             deprecated_thing = "Creating NamedTuple classes using keyword arguments" | 
					
						
							|  |  |  |             deprecation_msg = ( | 
					
						
							|  |  |  |                 "{name} is deprecated and will be disallowed in Python {remove}. " | 
					
						
							|  |  |  |                 "Use the class-based or functional syntax instead." | 
					
						
							|  |  |  |             ) | 
					
						
							|  |  |  |         else: | 
					
						
							|  |  |  |             deprecated_thing = "Failing to pass a value for the 'fields' parameter" | 
					
						
							|  |  |  |             example = f"`{typename} = NamedTuple({typename!r}, [])`" | 
					
						
							|  |  |  |             deprecation_msg = ( | 
					
						
							|  |  |  |                 "{name} is deprecated and will be disallowed in Python {remove}. " | 
					
						
							|  |  |  |                 "To create a NamedTuple class with 0 fields " | 
					
						
							|  |  |  |                 "using the functional syntax, " | 
					
						
							|  |  |  |                 "pass an empty list, e.g. " | 
					
						
							|  |  |  |             ) + example + "." | 
					
						
							|  |  |  |     elif fields is None: | 
					
						
							|  |  |  |         if kwargs: | 
					
						
							|  |  |  |             raise TypeError( | 
					
						
							|  |  |  |                 "Cannot pass `None` as the 'fields' parameter " | 
					
						
							|  |  |  |                 "and also specify fields using keyword arguments" | 
					
						
							|  |  |  |             ) | 
					
						
							|  |  |  |         else: | 
					
						
							|  |  |  |             deprecated_thing = "Passing `None` as the 'fields' parameter" | 
					
						
							|  |  |  |             example = f"`{typename} = NamedTuple({typename!r}, [])`" | 
					
						
							|  |  |  |             deprecation_msg = ( | 
					
						
							|  |  |  |                 "{name} is deprecated and will be disallowed in Python {remove}. " | 
					
						
							|  |  |  |                 "To create a NamedTuple class with 0 fields " | 
					
						
							|  |  |  |                 "using the functional syntax, " | 
					
						
							|  |  |  |                 "pass an empty list, e.g. " | 
					
						
							|  |  |  |             ) + example + "." | 
					
						
							| 
									
										
										
										
											2020-04-08 10:59:04 +03:00
										 |  |  |     elif kwargs: | 
					
						
							|  |  |  |         raise TypeError("Either list of fields or keywords" | 
					
						
							|  |  |  |                         " can be provided to NamedTuple, not both") | 
					
						
							| 
									
										
										
										
											2023-06-14 13:38:49 +01:00
										 |  |  |     if fields is _sentinel or fields is None: | 
					
						
							|  |  |  |         import warnings | 
					
						
							|  |  |  |         warnings._deprecated(deprecated_thing, message=deprecation_msg, remove=(3, 15)) | 
					
						
							|  |  |  |         fields = kwargs.items() | 
					
						
							| 
									
										
										
										
											2024-07-23 14:16:50 -07:00
										 |  |  |     types = {n: _type_check(t, f"field {n} annotation must be a type") | 
					
						
							|  |  |  |              for n, t in fields} | 
					
						
							|  |  |  |     field_names = [n for n, _ in fields] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     nt = _make_nmtuple(typename, field_names, _make_eager_annotate(types), module=_caller()) | 
					
						
							| 
									
										
										
										
											2023-04-23 08:33:39 -06:00
										 |  |  |     nt.__orig_bases__ = (NamedTuple,) | 
					
						
							|  |  |  |     return nt | 
					
						
							| 
									
										
										
										
											2020-04-08 10:59:04 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | _NamedTuple = type.__new__(NamedTupleMeta, 'NamedTuple', (), {}) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | def _namedtuple_mro_entries(bases): | 
					
						
							| 
									
										
										
										
											2022-05-03 01:41:23 +03:00
										 |  |  |     assert NamedTuple in bases | 
					
						
							| 
									
										
										
										
											2020-04-08 10:59:04 +03:00
										 |  |  |     return (_NamedTuple,) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | NamedTuple.__mro_entries__ = _namedtuple_mro_entries | 
					
						
							| 
									
										
										
										
											2015-05-22 10:14:11 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-03-12 17:49:39 +03:00
										 |  |  | def _get_typeddict_qualifiers(annotation_type): | 
					
						
							|  |  |  |     while True: | 
					
						
							|  |  |  |         annotation_origin = get_origin(annotation_type) | 
					
						
							|  |  |  |         if annotation_origin is Annotated: | 
					
						
							|  |  |  |             annotation_args = get_args(annotation_type) | 
					
						
							|  |  |  |             if annotation_args: | 
					
						
							|  |  |  |                 annotation_type = annotation_args[0] | 
					
						
							|  |  |  |             else: | 
					
						
							|  |  |  |                 break | 
					
						
							|  |  |  |         elif annotation_origin is Required: | 
					
						
							|  |  |  |             yield Required | 
					
						
							|  |  |  |             (annotation_type,) = get_args(annotation_type) | 
					
						
							|  |  |  |         elif annotation_origin is NotRequired: | 
					
						
							|  |  |  |             yield NotRequired | 
					
						
							|  |  |  |             (annotation_type,) = get_args(annotation_type) | 
					
						
							|  |  |  |         elif annotation_origin is ReadOnly: | 
					
						
							|  |  |  |             yield ReadOnly | 
					
						
							|  |  |  |             (annotation_type,) = get_args(annotation_type) | 
					
						
							|  |  |  |         else: | 
					
						
							|  |  |  |             break | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-05-26 09:39:24 +01:00
										 |  |  | class _TypedDictMeta(type): | 
					
						
							|  |  |  |     def __new__(cls, name, bases, ns, total=True): | 
					
						
							| 
									
										
										
										
											2023-06-05 15:16:09 +01:00
										 |  |  |         """Create a new typed dict class object.
 | 
					
						
							| 
									
										
										
										
											2019-05-26 09:39:24 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-08 11:03:27 +03:00
										 |  |  |         This method is called when TypedDict is subclassed, | 
					
						
							|  |  |  |         or when TypedDict is instantiated. This way | 
					
						
							| 
									
										
										
										
											2019-05-26 09:39:24 +01:00
										 |  |  |         TypedDict supports all three syntax forms described in its docstring. | 
					
						
							| 
									
										
										
										
											2020-04-08 11:03:27 +03:00
										 |  |  |         Subclasses and instances of TypedDict return actual dictionaries. | 
					
						
							| 
									
										
										
										
											2019-05-26 09:39:24 +01:00
										 |  |  |         """
 | 
					
						
							| 
									
										
										
										
											2020-04-08 11:03:27 +03:00
										 |  |  |         for base in bases: | 
					
						
							| 
									
										
										
										
											2022-05-03 18:51:42 +05:30
										 |  |  |             if type(base) is not _TypedDictMeta and base is not Generic: | 
					
						
							| 
									
										
										
										
											2020-04-08 11:03:27 +03:00
										 |  |  |                 raise TypeError('cannot inherit from both a TypedDict type ' | 
					
						
							|  |  |  |                                 'and a non-TypedDict base class') | 
					
						
							| 
									
										
										
										
											2022-05-03 18:51:42 +05:30
										 |  |  | 
 | 
					
						
							|  |  |  |         if any(issubclass(b, Generic) for b in bases): | 
					
						
							|  |  |  |             generic_base = (Generic,) | 
					
						
							|  |  |  |         else: | 
					
						
							|  |  |  |             generic_base = () | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         tp_dict = type.__new__(_TypedDictMeta, name, (*generic_base, dict), ns) | 
					
						
							| 
									
										
										
										
											2019-05-26 09:39:24 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-04-23 08:33:39 -06:00
										 |  |  |         if not hasattr(tp_dict, '__orig_bases__'): | 
					
						
							|  |  |  |             tp_dict.__orig_bases__ = bases | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-06-11 07:06:49 -06:00
										 |  |  |         if "__annotations__" in ns: | 
					
						
							| 
									
										
										
										
											2024-07-23 14:16:50 -07:00
										 |  |  |             own_annotate = None | 
					
						
							| 
									
										
										
										
											2024-06-11 07:06:49 -06:00
										 |  |  |             own_annotations = ns["__annotations__"] | 
					
						
							|  |  |  |         elif "__annotate__" in ns: | 
					
						
							| 
									
										
										
										
											2024-07-23 14:16:50 -07:00
										 |  |  |             own_annotate = ns["__annotate__"] | 
					
						
							|  |  |  |             own_annotations = annotationlib.call_annotate_function( | 
					
						
							|  |  |  |                 own_annotate, annotationlib.Format.FORWARDREF, owner=tp_dict | 
					
						
							|  |  |  |             ) | 
					
						
							| 
									
										
										
										
											2024-06-11 07:06:49 -06:00
										 |  |  |         else: | 
					
						
							| 
									
										
										
										
											2024-07-23 14:16:50 -07:00
										 |  |  |             own_annotate = None | 
					
						
							| 
									
										
										
										
											2024-06-11 07:06:49 -06:00
										 |  |  |             own_annotations = {} | 
					
						
							| 
									
										
										
										
											2019-05-26 09:39:24 +01:00
										 |  |  |         msg = "TypedDict('Name', {f0: t0, f1: t1, ...}); each t must be a type" | 
					
						
							| 
									
										
										
										
											2024-07-23 14:16:50 -07:00
										 |  |  |         own_checked_annotations = { | 
					
						
							| 
									
										
										
										
											2021-07-16 20:49:30 -07:00
										 |  |  |             n: _type_check(tp, msg, module=tp_dict.__module__) | 
					
						
							|  |  |  |             for n, tp in own_annotations.items() | 
					
						
							| 
									
										
										
										
											2020-02-13 20:53:29 +01:00
										 |  |  |         } | 
					
						
							|  |  |  |         required_keys = set() | 
					
						
							|  |  |  |         optional_keys = set() | 
					
						
							| 
									
										
										
										
											2024-03-12 17:49:39 +03:00
										 |  |  |         readonly_keys = set() | 
					
						
							|  |  |  |         mutable_keys = set() | 
					
						
							| 
									
										
										
										
											2019-11-24 21:48:48 +11:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-05-26 09:39:24 +01:00
										 |  |  |         for base in bases: | 
					
						
							| 
									
										
										
										
											2023-11-29 09:36:48 -08:00
										 |  |  |             base_required = base.__dict__.get('__required_keys__', set()) | 
					
						
							|  |  |  |             required_keys |= base_required | 
					
						
							|  |  |  |             optional_keys -= base_required | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             base_optional = base.__dict__.get('__optional_keys__', set()) | 
					
						
							|  |  |  |             required_keys -= base_optional | 
					
						
							|  |  |  |             optional_keys |= base_optional | 
					
						
							| 
									
										
										
										
											2020-02-13 20:53:29 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-03-12 17:49:39 +03:00
										 |  |  |             readonly_keys.update(base.__dict__.get('__readonly_keys__', ())) | 
					
						
							|  |  |  |             mutable_keys.update(base.__dict__.get('__mutable_keys__', ())) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-07-23 14:16:50 -07:00
										 |  |  |         for annotation_key, annotation_type in own_checked_annotations.items(): | 
					
						
							| 
									
										
										
										
											2024-03-12 17:49:39 +03:00
										 |  |  |             qualifiers = set(_get_typeddict_qualifiers(annotation_type)) | 
					
						
							|  |  |  |             if Required in qualifiers: | 
					
						
							| 
									
										
										
										
											2023-11-29 09:36:48 -08:00
										 |  |  |                 is_required = True | 
					
						
							| 
									
										
										
										
											2024-03-12 17:49:39 +03:00
										 |  |  |             elif NotRequired in qualifiers: | 
					
						
							| 
									
										
										
										
											2023-11-29 09:36:48 -08:00
										 |  |  |                 is_required = False | 
					
						
							|  |  |  |             else: | 
					
						
							|  |  |  |                 is_required = total | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             if is_required: | 
					
						
							| 
									
										
										
										
											2022-04-12 12:31:02 -07:00
										 |  |  |                 required_keys.add(annotation_key) | 
					
						
							| 
									
										
										
										
											2023-11-29 09:36:48 -08:00
										 |  |  |                 optional_keys.discard(annotation_key) | 
					
						
							| 
									
										
										
										
											2022-04-12 12:31:02 -07:00
										 |  |  |             else: | 
					
						
							|  |  |  |                 optional_keys.add(annotation_key) | 
					
						
							| 
									
										
										
										
											2023-11-29 09:36:48 -08:00
										 |  |  |                 required_keys.discard(annotation_key) | 
					
						
							| 
									
										
										
										
											2019-11-24 21:48:48 +11:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-03-12 17:49:39 +03:00
										 |  |  |             if ReadOnly in qualifiers: | 
					
						
							|  |  |  |                 if annotation_key in mutable_keys: | 
					
						
							|  |  |  |                     raise TypeError( | 
					
						
							|  |  |  |                         f"Cannot override mutable key {annotation_key!r}" | 
					
						
							|  |  |  |                         " with read-only key" | 
					
						
							|  |  |  |                     ) | 
					
						
							|  |  |  |                 readonly_keys.add(annotation_key) | 
					
						
							|  |  |  |             else: | 
					
						
							|  |  |  |                 mutable_keys.add(annotation_key) | 
					
						
							|  |  |  |                 readonly_keys.discard(annotation_key) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-11-29 09:36:48 -08:00
										 |  |  |         assert required_keys.isdisjoint(optional_keys), ( | 
					
						
							|  |  |  |             f"Required keys overlap with optional keys in {name}:" | 
					
						
							|  |  |  |             f" {required_keys=}, {optional_keys=}" | 
					
						
							|  |  |  |         ) | 
					
						
							| 
									
										
										
										
											2024-07-23 14:16:50 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |         def __annotate__(format): | 
					
						
							|  |  |  |             annos = {} | 
					
						
							|  |  |  |             for base in bases: | 
					
						
							|  |  |  |                 if base is Generic: | 
					
						
							|  |  |  |                     continue | 
					
						
							|  |  |  |                 base_annotate = base.__annotate__ | 
					
						
							|  |  |  |                 if base_annotate is None: | 
					
						
							|  |  |  |                     continue | 
					
						
							|  |  |  |                 base_annos = annotationlib.call_annotate_function(base.__annotate__, format, owner=base) | 
					
						
							|  |  |  |                 annos.update(base_annos) | 
					
						
							|  |  |  |             if own_annotate is not None: | 
					
						
							|  |  |  |                 own = annotationlib.call_annotate_function(own_annotate, format, owner=tp_dict) | 
					
						
							| 
									
										
										
										
											2024-09-26 13:49:48 -07:00
										 |  |  |                 if format != annotationlib.Format.STRING: | 
					
						
							| 
									
										
										
										
											2024-07-23 14:16:50 -07:00
										 |  |  |                     own = { | 
					
						
							|  |  |  |                         n: _type_check(tp, msg, module=tp_dict.__module__) | 
					
						
							|  |  |  |                         for n, tp in own.items() | 
					
						
							|  |  |  |                     } | 
					
						
							| 
									
										
										
										
											2024-09-26 13:49:48 -07:00
										 |  |  |             elif format == annotationlib.Format.STRING: | 
					
						
							|  |  |  |                 own = annotationlib.annotations_to_string(own_annotations) | 
					
						
							| 
									
										
										
										
											2024-11-26 07:40:13 -08:00
										 |  |  |             elif format in (annotationlib.Format.FORWARDREF, annotationlib.Format.VALUE): | 
					
						
							| 
									
										
										
										
											2024-07-23 14:16:50 -07:00
										 |  |  |                 own = own_checked_annotations | 
					
						
							| 
									
										
										
										
											2024-11-26 07:40:13 -08:00
										 |  |  |             else: | 
					
						
							|  |  |  |                 raise NotImplementedError(format) | 
					
						
							| 
									
										
										
										
											2024-07-23 14:16:50 -07:00
										 |  |  |             annos.update(own) | 
					
						
							|  |  |  |             return annos | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         tp_dict.__annotate__ = __annotate__ | 
					
						
							| 
									
										
										
										
											2020-02-13 20:53:29 +01:00
										 |  |  |         tp_dict.__required_keys__ = frozenset(required_keys) | 
					
						
							|  |  |  |         tp_dict.__optional_keys__ = frozenset(optional_keys) | 
					
						
							| 
									
										
										
										
											2024-03-12 17:49:39 +03:00
										 |  |  |         tp_dict.__readonly_keys__ = frozenset(readonly_keys) | 
					
						
							|  |  |  |         tp_dict.__mutable_keys__ = frozenset(mutable_keys) | 
					
						
							| 
									
										
										
										
											2023-09-19 20:15:52 -07:00
										 |  |  |         tp_dict.__total__ = total | 
					
						
							| 
									
										
										
										
											2019-05-26 09:39:24 +01:00
										 |  |  |         return tp_dict | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-08 11:03:27 +03:00
										 |  |  |     __call__ = dict  # static method | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def __subclasscheck__(cls, other): | 
					
						
							|  |  |  |         # Typed dicts are only for static structural subtyping. | 
					
						
							|  |  |  |         raise TypeError('TypedDict does not support instance and class checks') | 
					
						
							| 
									
										
										
										
											2019-05-26 09:39:24 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-08 11:03:27 +03:00
										 |  |  |     __instancecheck__ = __subclasscheck__ | 
					
						
							| 
									
										
										
										
											2019-05-26 09:39:24 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-08 11:03:27 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-06-14 15:58:41 +01:00
										 |  |  | def TypedDict(typename, fields=_sentinel, /, *, total=True): | 
					
						
							| 
									
										
										
										
											2019-05-26 09:39:24 +01:00
										 |  |  |     """A simple typed namespace. At runtime it is equivalent to a plain dict.
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-06-05 15:16:09 +01:00
										 |  |  |     TypedDict creates a dictionary type such that a type checker will expect all | 
					
						
							| 
									
										
										
										
											2019-05-26 09:39:24 +01:00
										 |  |  |     instances to have a certain set of keys, where each key is | 
					
						
							|  |  |  |     associated with a value of a consistent type. This expectation | 
					
						
							| 
									
										
										
										
											2023-06-05 15:16:09 +01:00
										 |  |  |     is not checked at runtime. | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-05-26 09:39:24 +01:00
										 |  |  |     Usage:: | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-11-17 20:56:31 +03:00
										 |  |  |         >>> class Point2D(TypedDict): | 
					
						
							|  |  |  |         ...     x: int | 
					
						
							|  |  |  |         ...     y: int | 
					
						
							|  |  |  |         ...     label: str | 
					
						
							|  |  |  |         ... | 
					
						
							|  |  |  |         >>> a: Point2D = {'x': 1, 'y': 2, 'label': 'good'}  # OK | 
					
						
							|  |  |  |         >>> b: Point2D = {'z': 3, 'label': 'bad'}           # Fails type check | 
					
						
							|  |  |  |         >>> Point2D(x=1, y=2, label='first') == dict(x=1, y=2, label='first') | 
					
						
							|  |  |  |         True | 
					
						
							| 
									
										
										
										
											2019-05-26 09:39:24 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-11-24 21:48:48 +11:00
										 |  |  |     The type info can be accessed via the Point2D.__annotations__ dict, and | 
					
						
							|  |  |  |     the Point2D.__required_keys__ and Point2D.__optional_keys__ frozensets. | 
					
						
							| 
									
										
										
										
											2022-02-17 11:26:07 +08:00
										 |  |  |     TypedDict supports an additional equivalent form:: | 
					
						
							| 
									
										
										
										
											2019-05-26 09:39:24 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |         Point2D = TypedDict('Point2D', {'x': int, 'y': int, 'label': str}) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-02-19 10:03:05 +05:30
										 |  |  |     By default, all keys must be present in a TypedDict. It is possible | 
					
						
							| 
									
										
										
										
											2023-06-05 15:16:09 +01:00
										 |  |  |     to override this by specifying totality:: | 
					
						
							| 
									
										
										
										
											2020-02-19 10:03:05 +05:30
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-06-05 15:16:09 +01:00
										 |  |  |         class Point2D(TypedDict, total=False): | 
					
						
							| 
									
										
										
										
											2020-02-19 10:03:05 +05:30
										 |  |  |             x: int | 
					
						
							|  |  |  |             y: int | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-06-05 15:16:09 +01:00
										 |  |  |     This means that a Point2D TypedDict can have any of the keys omitted. A type | 
					
						
							| 
									
										
										
										
											2020-02-19 10:03:05 +05:30
										 |  |  |     checker is only expected to support a literal False or True as the value of | 
					
						
							|  |  |  |     the total argument. True is the default, and makes all items defined in the | 
					
						
							|  |  |  |     class body be required. | 
					
						
							| 
									
										
										
										
											2023-06-05 15:16:09 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |     The Required and NotRequired special forms can also be used to mark | 
					
						
							|  |  |  |     individual keys as being required or not required:: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         class Point2D(TypedDict): | 
					
						
							|  |  |  |             x: int               # the "x" key must always be present (Required is the default) | 
					
						
							|  |  |  |             y: NotRequired[int]  # the "y" key can be omitted | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     See PEP 655 for more details on Required and NotRequired. | 
					
						
							| 
									
										
										
										
											2024-03-12 17:49:39 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  |     The ReadOnly special form can be used | 
					
						
							|  |  |  |     to mark individual keys as immutable for type checkers:: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         class DatabaseUser(TypedDict): | 
					
						
							|  |  |  |             id: ReadOnly[int]  # the "id" key must not be modified | 
					
						
							|  |  |  |             username: str      # the "username" key can be changed | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-05-26 09:39:24 +01:00
										 |  |  |     """
 | 
					
						
							| 
									
										
										
										
											2023-06-14 15:58:41 +01:00
										 |  |  |     if fields is _sentinel or fields is None: | 
					
						
							|  |  |  |         import warnings | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if fields is _sentinel: | 
					
						
							|  |  |  |             deprecated_thing = "Failing to pass a value for the 'fields' parameter" | 
					
						
							|  |  |  |         else: | 
					
						
							|  |  |  |             deprecated_thing = "Passing `None` as the 'fields' parameter" | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         example = f"`{typename} = TypedDict({typename!r}, {{{{}}}})`" | 
					
						
							|  |  |  |         deprecation_msg = ( | 
					
						
							|  |  |  |             "{name} is deprecated and will be disallowed in Python {remove}. " | 
					
						
							|  |  |  |             "To create a TypedDict class with 0 fields " | 
					
						
							|  |  |  |             "using the functional syntax, " | 
					
						
							|  |  |  |             "pass an empty dictionary, e.g. " | 
					
						
							|  |  |  |         ) + example + "." | 
					
						
							|  |  |  |         warnings._deprecated(deprecated_thing, message=deprecation_msg, remove=(3, 15)) | 
					
						
							| 
									
										
										
										
											2023-05-25 22:14:58 +02:00
										 |  |  |         fields = {} | 
					
						
							| 
									
										
										
										
											2020-04-08 11:03:27 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-12-10 23:49:05 +02:00
										 |  |  |     ns = {'__annotations__': dict(fields)} | 
					
						
							| 
									
										
										
										
											2021-07-30 16:49:24 +03:00
										 |  |  |     module = _caller() | 
					
						
							|  |  |  |     if module is not None: | 
					
						
							| 
									
										
										
										
											2020-04-08 11:03:27 +03:00
										 |  |  |         # Setting correct module is necessary to make typed dict classes pickleable. | 
					
						
							| 
									
										
										
										
											2021-07-30 16:49:24 +03:00
										 |  |  |         ns['__module__'] = module | 
					
						
							| 
									
										
										
										
											2020-04-08 11:03:27 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-04-23 08:33:39 -06:00
										 |  |  |     td = _TypedDictMeta(typename, (), ns, total=total) | 
					
						
							|  |  |  |     td.__orig_bases__ = (TypedDict,) | 
					
						
							|  |  |  |     return td | 
					
						
							| 
									
										
										
										
											2020-04-08 11:03:27 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | _TypedDict = type.__new__(_TypedDictMeta, 'TypedDict', (), {}) | 
					
						
							|  |  |  | TypedDict.__mro_entries__ = lambda bases: (_TypedDict,) | 
					
						
							| 
									
										
										
										
											2019-05-26 09:39:24 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-04-12 12:31:02 -07:00
										 |  |  | @_SpecialForm | 
					
						
							|  |  |  | def Required(self, parameters): | 
					
						
							| 
									
										
										
										
											2023-06-05 15:16:09 +01:00
										 |  |  |     """Special typing construct to mark a TypedDict key as required.
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-06-07 01:21:16 +01:00
										 |  |  |     This is mainly useful for total=False TypedDicts. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     For example:: | 
					
						
							| 
									
										
										
										
											2022-04-12 12:31:02 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |         class Movie(TypedDict, total=False): | 
					
						
							|  |  |  |             title: Required[str] | 
					
						
							|  |  |  |             year: int | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         m = Movie( | 
					
						
							|  |  |  |             title='The Matrix',  # typechecker error if key is omitted | 
					
						
							|  |  |  |             year=1999, | 
					
						
							|  |  |  |         ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     There is no runtime checking that a required key is actually provided | 
					
						
							|  |  |  |     when instantiating a related TypedDict. | 
					
						
							|  |  |  |     """
 | 
					
						
							|  |  |  |     item = _type_check(parameters, f'{self._name} accepts only a single type.') | 
					
						
							|  |  |  |     return _GenericAlias(self, (item,)) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | @_SpecialForm | 
					
						
							|  |  |  | def NotRequired(self, parameters): | 
					
						
							| 
									
										
										
										
											2023-06-05 15:16:09 +01:00
										 |  |  |     """Special typing construct to mark a TypedDict key as potentially missing.
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     For example:: | 
					
						
							| 
									
										
										
										
											2022-04-12 12:31:02 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |         class Movie(TypedDict): | 
					
						
							|  |  |  |             title: str | 
					
						
							|  |  |  |             year: NotRequired[int] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         m = Movie( | 
					
						
							|  |  |  |             title='The Matrix',  # typechecker error if key is omitted | 
					
						
							|  |  |  |             year=1999, | 
					
						
							|  |  |  |         ) | 
					
						
							|  |  |  |     """
 | 
					
						
							|  |  |  |     item = _type_check(parameters, f'{self._name} accepts only a single type.') | 
					
						
							| 
									
										
										
										
											2024-03-12 17:49:39 +03:00
										 |  |  |     return _GenericAlias(self, (item,)) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | @_SpecialForm | 
					
						
							|  |  |  | def ReadOnly(self, parameters): | 
					
						
							|  |  |  |     """A special typing construct to mark an item of a TypedDict as read-only.
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     For example:: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         class Movie(TypedDict): | 
					
						
							|  |  |  |             title: ReadOnly[str] | 
					
						
							|  |  |  |             year: int | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         def mutate_movie(m: Movie) -> None: | 
					
						
							|  |  |  |             m["year"] = 1992  # allowed | 
					
						
							|  |  |  |             m["title"] = "The Matrix"  # typechecker error | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     There is no runtime checking for this property. | 
					
						
							|  |  |  |     """
 | 
					
						
							|  |  |  |     item = _type_check(parameters, f'{self._name} accepts only a single type.') | 
					
						
							| 
									
										
										
										
											2022-04-12 12:31:02 -07:00
										 |  |  |     return _GenericAlias(self, (item,)) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-07-20 16:20:38 +03:00
										 |  |  | class NewType: | 
					
						
							| 
									
										
										
										
											2023-06-05 15:16:09 +01:00
										 |  |  |     """NewType creates simple unique types with almost zero runtime overhead.
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     NewType(name, tp) is considered a subtype of tp | 
					
						
							| 
									
										
										
										
											2016-06-08 11:19:11 -07:00
										 |  |  |     by static type checkers. At runtime, NewType(name, tp) returns | 
					
						
							| 
									
										
										
										
											2023-06-07 01:21:16 +01:00
										 |  |  |     a dummy callable that simply returns its argument. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     Usage:: | 
					
						
							| 
									
										
										
										
											2016-06-08 11:19:11 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |         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 | 
					
						
							|  |  |  |     """
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-07-23 00:06:54 +03:00
										 |  |  |     __call__ = _idfunc | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-07-20 16:20:38 +03:00
										 |  |  |     def __init__(self, name, tp): | 
					
						
							|  |  |  |         self.__qualname__ = name | 
					
						
							| 
									
										
										
										
											2021-07-24 10:40:08 +03:00
										 |  |  |         if '.' in name: | 
					
						
							|  |  |  |             name = name.rpartition('.')[-1] | 
					
						
							|  |  |  |         self.__name__ = name | 
					
						
							| 
									
										
										
										
											2021-07-20 16:20:38 +03:00
										 |  |  |         self.__supertype__ = tp | 
					
						
							| 
									
										
										
										
											2021-07-30 15:56:12 +03:00
										 |  |  |         def_mod = _caller() | 
					
						
							|  |  |  |         if def_mod != 'typing': | 
					
						
							|  |  |  |             self.__module__ = def_mod | 
					
						
							| 
									
										
										
										
											2021-07-20 16:20:38 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-03-08 03:50:46 +00:00
										 |  |  |     def __mro_entries__(self, bases): | 
					
						
							|  |  |  |         # We defined __mro_entries__ to get a better error message | 
					
						
							|  |  |  |         # if a user attempts to subclass a NewType instance. bpo-46170 | 
					
						
							|  |  |  |         superclass_name = self.__name__ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         class Dummy: | 
					
						
							|  |  |  |             def __init_subclass__(cls): | 
					
						
							|  |  |  |                 subclass_name = cls.__name__ | 
					
						
							|  |  |  |                 raise TypeError( | 
					
						
							|  |  |  |                     f"Cannot subclass an instance of NewType. Perhaps you were looking for: " | 
					
						
							|  |  |  |                     f"`{subclass_name} = NewType({subclass_name!r}, {superclass_name})`" | 
					
						
							|  |  |  |                 ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         return (Dummy,) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-07-20 16:20:38 +03:00
										 |  |  |     def __repr__(self): | 
					
						
							|  |  |  |         return f'{self.__module__}.{self.__qualname__}' | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-07-24 10:40:08 +03:00
										 |  |  |     def __reduce__(self): | 
					
						
							|  |  |  |         return self.__qualname__ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-07-20 16:20:38 +03:00
										 |  |  |     def __or__(self, other): | 
					
						
							|  |  |  |         return Union[self, other] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def __ror__(self, other): | 
					
						
							|  |  |  |         return Union[other, self] | 
					
						
							| 
									
										
										
										
											2016-06-08 11:19:11 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-04-05 14:54:25 -07:00
										 |  |  | # Python-version-specific alias (Python 2: unicode; Python 3: str) | 
					
						
							|  |  |  | Text = str | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-06-08 11:19:11 -07:00
										 |  |  | # Constant that's True when type checking, but False here. | 
					
						
							|  |  |  | TYPE_CHECKING = False | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-05-22 10:14:11 -07:00
										 |  |  | 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. | 
					
						
							|  |  |  |     """
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-08-05 12:11:06 +02:00
										 |  |  |     __slots__ = () | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-09-27 15:54:26 +08:00
										 |  |  |     @property | 
					
						
							|  |  |  |     @abstractmethod | 
					
						
							| 
									
										
										
										
											2015-05-22 10:14:11 -07:00
										 |  |  |     def mode(self) -> str: | 
					
						
							|  |  |  |         pass | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-09-27 15:54:26 +08:00
										 |  |  |     @property | 
					
						
							|  |  |  |     @abstractmethod | 
					
						
							| 
									
										
										
										
											2015-05-22 10:14:11 -07:00
										 |  |  |     def name(self) -> str: | 
					
						
							|  |  |  |         pass | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     @abstractmethod | 
					
						
							|  |  |  |     def close(self) -> None: | 
					
						
							|  |  |  |         pass | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-01-29 18:52:36 -08:00
										 |  |  |     @property | 
					
						
							| 
									
										
										
										
											2015-05-22 10:14:11 -07:00
										 |  |  |     @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.""" | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-08-05 12:11:06 +02:00
										 |  |  |     __slots__ = () | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-05-22 10:14:11 -07:00
										 |  |  |     @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.""" | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-08-05 12:11:06 +02:00
										 |  |  |     __slots__ = () | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-09-27 15:54:26 +08:00
										 |  |  |     @property | 
					
						
							|  |  |  |     @abstractmethod | 
					
						
							| 
									
										
										
										
											2015-05-22 10:14:11 -07:00
										 |  |  |     def buffer(self) -> BinaryIO: | 
					
						
							|  |  |  |         pass | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-09-27 15:54:26 +08:00
										 |  |  |     @property | 
					
						
							|  |  |  |     @abstractmethod | 
					
						
							| 
									
										
										
										
											2015-05-22 10:14:11 -07:00
										 |  |  |     def encoding(self) -> str: | 
					
						
							|  |  |  |         pass | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-09-27 15:54:26 +08:00
										 |  |  |     @property | 
					
						
							|  |  |  |     @abstractmethod | 
					
						
							| 
									
										
										
										
											2016-11-09 13:12:51 -08:00
										 |  |  |     def errors(self) -> Optional[str]: | 
					
						
							| 
									
										
										
										
											2015-05-22 10:14:11 -07:00
										 |  |  |         pass | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-09-27 15:54:26 +08:00
										 |  |  |     @property | 
					
						
							|  |  |  |     @abstractmethod | 
					
						
							| 
									
										
										
										
											2015-05-22 10:14:11 -07:00
										 |  |  |     def line_buffering(self) -> bool: | 
					
						
							|  |  |  |         pass | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-09-27 15:54:26 +08:00
										 |  |  |     @property | 
					
						
							|  |  |  |     @abstractmethod | 
					
						
							| 
									
										
										
										
											2015-05-22 10:14:11 -07:00
										 |  |  |     def newlines(self) -> Any: | 
					
						
							|  |  |  |         pass | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     @abstractmethod | 
					
						
							|  |  |  |     def __enter__(self) -> 'TextIO': | 
					
						
							|  |  |  |         pass | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-05-17 06:03:58 -07:00
										 |  |  | def reveal_type[T](obj: T, /) -> T: | 
					
						
							| 
									
										
										
										
											2023-12-21 02:21:23 +09:00
										 |  |  |     """Ask a static type checker to reveal the inferred type of an expression.
 | 
					
						
							| 
									
										
										
										
											2022-02-01 18:48:55 -08:00
										 |  |  | 
 | 
					
						
							|  |  |  |     When a static type checker encounters a call to ``reveal_type()``, | 
					
						
							|  |  |  |     it will emit the inferred type of the argument:: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         x: int = 1 | 
					
						
							|  |  |  |         reveal_type(x) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-06-05 15:16:09 +01:00
										 |  |  |     Running a static type checker (e.g., mypy) on this example | 
					
						
							| 
									
										
										
										
											2022-02-01 18:48:55 -08:00
										 |  |  |     will produce output similar to 'Revealed type is "builtins.int"'. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     At runtime, the function prints the runtime type of the | 
					
						
							| 
									
										
										
										
											2023-12-21 02:21:23 +09:00
										 |  |  |     argument and returns the argument unchanged. | 
					
						
							| 
									
										
										
										
											2022-02-01 18:48:55 -08:00
										 |  |  |     """
 | 
					
						
							|  |  |  |     print(f"Runtime type is {type(obj).__name__!r}", file=sys.stderr) | 
					
						
							|  |  |  |     return obj | 
					
						
							| 
									
										
										
										
											2022-04-25 20:30:25 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-05-17 06:03:58 -07:00
										 |  |  | class _IdentityCallable(Protocol): | 
					
						
							|  |  |  |     def __call__[T](self, arg: T, /) -> T: | 
					
						
							|  |  |  |         ... | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-04-25 20:30:25 -07:00
										 |  |  | def dataclass_transform( | 
					
						
							|  |  |  |     *, | 
					
						
							|  |  |  |     eq_default: bool = True, | 
					
						
							|  |  |  |     order_default: bool = False, | 
					
						
							|  |  |  |     kw_only_default: bool = False, | 
					
						
							| 
									
										
										
										
											2022-12-05 19:35:43 -08:00
										 |  |  |     frozen_default: bool = False, | 
					
						
							| 
									
										
										
										
											2022-04-25 20:30:25 -07:00
										 |  |  |     field_specifiers: tuple[type[Any] | Callable[..., Any], ...] = (), | 
					
						
							|  |  |  |     **kwargs: Any, | 
					
						
							| 
									
										
										
										
											2023-05-17 06:03:58 -07:00
										 |  |  | ) -> _IdentityCallable: | 
					
						
							| 
									
										
										
										
											2023-06-05 15:16:09 +01:00
										 |  |  |     """Decorator to mark an object as providing dataclass-like behaviour.
 | 
					
						
							| 
									
										
										
										
											2022-04-25 20:30:25 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-06-05 15:16:09 +01:00
										 |  |  |     The decorator can be applied to a function, class, or metaclass. | 
					
						
							| 
									
										
										
										
											2022-04-25 20:30:25 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-06-05 15:16:09 +01:00
										 |  |  |     Example usage with a decorator function:: | 
					
						
							| 
									
										
										
										
											2022-04-25 20:30:25 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |         @dataclass_transform() | 
					
						
							| 
									
										
										
										
											2023-06-05 15:16:09 +01:00
										 |  |  |         def create_model[T](cls: type[T]) -> type[T]: | 
					
						
							| 
									
										
										
										
											2022-04-25 20:30:25 -07:00
										 |  |  |             ... | 
					
						
							|  |  |  |             return cls | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         @create_model | 
					
						
							|  |  |  |         class CustomerModel: | 
					
						
							|  |  |  |             id: int | 
					
						
							|  |  |  |             name: str | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-06-05 15:16:09 +01:00
										 |  |  |     On a base class:: | 
					
						
							| 
									
										
										
										
											2022-04-25 20:30:25 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |         @dataclass_transform() | 
					
						
							|  |  |  |         class ModelBase: ... | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         class CustomerModel(ModelBase): | 
					
						
							|  |  |  |             id: int | 
					
						
							|  |  |  |             name: str | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-06-05 15:16:09 +01:00
										 |  |  |     On a metaclass:: | 
					
						
							| 
									
										
										
										
											2022-04-25 20:30:25 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |         @dataclass_transform() | 
					
						
							|  |  |  |         class ModelMeta(type): ... | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         class ModelBase(metaclass=ModelMeta): ... | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         class CustomerModel(ModelBase): | 
					
						
							|  |  |  |             id: int | 
					
						
							|  |  |  |             name: str | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-05-20 07:32:29 -07:00
										 |  |  |     The ``CustomerModel`` classes defined above will | 
					
						
							|  |  |  |     be treated by type checkers similarly to classes created with | 
					
						
							|  |  |  |     ``@dataclasses.dataclass``. | 
					
						
							|  |  |  |     For example, type checkers will assume these classes have | 
					
						
							|  |  |  |     ``__init__`` methods that accept ``id`` and ``name``. | 
					
						
							| 
									
										
										
										
											2022-04-25 20:30:25 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |     The arguments to this decorator can be used to customize this behavior: | 
					
						
							|  |  |  |     - ``eq_default`` indicates whether the ``eq`` parameter is assumed to be | 
					
						
							| 
									
										
										
										
											2022-05-20 07:32:29 -07:00
										 |  |  |         ``True`` or ``False`` if it is omitted by the caller. | 
					
						
							| 
									
										
										
										
											2022-04-25 20:30:25 -07:00
										 |  |  |     - ``order_default`` indicates whether the ``order`` parameter is | 
					
						
							|  |  |  |         assumed to be True or False if it is omitted by the caller. | 
					
						
							|  |  |  |     - ``kw_only_default`` indicates whether the ``kw_only`` parameter is | 
					
						
							|  |  |  |         assumed to be True or False if it is omitted by the caller. | 
					
						
							| 
									
										
										
										
											2022-12-05 19:35:43 -08:00
										 |  |  |     - ``frozen_default`` indicates whether the ``frozen`` parameter is | 
					
						
							|  |  |  |         assumed to be True or False if it is omitted by the caller. | 
					
						
							| 
									
										
										
										
											2022-04-25 20:30:25 -07:00
										 |  |  |     - ``field_specifiers`` specifies a static list of supported classes | 
					
						
							|  |  |  |         or functions that describe fields, similar to ``dataclasses.field()``. | 
					
						
							| 
									
										
										
										
											2022-05-20 07:32:29 -07:00
										 |  |  |     - Arbitrary other keyword arguments are accepted in order to allow for | 
					
						
							|  |  |  |         possible future extensions. | 
					
						
							| 
									
										
										
										
											2022-04-25 20:30:25 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |     At runtime, this decorator records its arguments in the | 
					
						
							|  |  |  |     ``__dataclass_transform__`` attribute on the decorated object. | 
					
						
							|  |  |  |     It has no other runtime effect. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     See PEP 681 for more details. | 
					
						
							|  |  |  |     """
 | 
					
						
							|  |  |  |     def decorator(cls_or_fn): | 
					
						
							|  |  |  |         cls_or_fn.__dataclass_transform__ = { | 
					
						
							|  |  |  |             "eq_default": eq_default, | 
					
						
							|  |  |  |             "order_default": order_default, | 
					
						
							|  |  |  |             "kw_only_default": kw_only_default, | 
					
						
							| 
									
										
										
										
											2022-12-05 19:35:43 -08:00
										 |  |  |             "frozen_default": frozen_default, | 
					
						
							| 
									
										
										
										
											2022-04-25 20:30:25 -07:00
										 |  |  |             "field_specifiers": field_specifiers, | 
					
						
							|  |  |  |             "kwargs": kwargs, | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         return cls_or_fn | 
					
						
							|  |  |  |     return decorator | 
					
						
							| 
									
										
										
										
											2023-02-27 13:16:11 -08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-05-17 06:03:58 -07:00
										 |  |  | type _Func = Callable[..., Any] | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-02-27 13:16:11 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-05-17 06:03:58 -07:00
										 |  |  | def override[F: _Func](method: F, /) -> F: | 
					
						
							| 
									
										
										
										
											2023-02-27 13:16:11 -08:00
										 |  |  |     """Indicate that a method is intended to override a method in a base class.
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-06-05 15:16:09 +01:00
										 |  |  |     Usage:: | 
					
						
							| 
									
										
										
										
											2023-02-27 13:16:11 -08:00
										 |  |  | 
 | 
					
						
							|  |  |  |         class Base: | 
					
						
							| 
									
										
										
										
											2023-11-16 18:16:04 +03:00
										 |  |  |             def method(self) -> None: | 
					
						
							| 
									
										
										
										
											2023-02-27 13:16:11 -08:00
										 |  |  |                 pass | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         class Child(Base): | 
					
						
							|  |  |  |             @override | 
					
						
							|  |  |  |             def method(self) -> None: | 
					
						
							|  |  |  |                 super().method() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     When this decorator is applied to a method, the type checker will | 
					
						
							|  |  |  |     validate that it overrides a method or attribute with the same name on a | 
					
						
							|  |  |  |     base class.  This helps prevent bugs that may occur when a base class is | 
					
						
							|  |  |  |     changed without an equivalent change to a child class. | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-06-05 15:16:09 +01:00
										 |  |  |     There is no runtime checking of this property. The decorator attempts to | 
					
						
							|  |  |  |     set the ``__override__`` attribute to ``True`` on the decorated object to | 
					
						
							|  |  |  |     allow runtime introspection. | 
					
						
							| 
									
										
										
										
											2023-02-27 13:16:11 -08:00
										 |  |  | 
 | 
					
						
							|  |  |  |     See PEP 698 for details. | 
					
						
							|  |  |  |     """
 | 
					
						
							|  |  |  |     try: | 
					
						
							|  |  |  |         method.__override__ = True | 
					
						
							|  |  |  |     except (AttributeError, TypeError): | 
					
						
							|  |  |  |         # Skip the attribute silently if it is not writable. | 
					
						
							|  |  |  |         # AttributeError happens if the object has __slots__ or a | 
					
						
							|  |  |  |         # read-only property, TypeError if it's a builtin class. | 
					
						
							|  |  |  |         pass | 
					
						
							|  |  |  |     return method | 
					
						
							| 
									
										
										
										
											2023-06-14 05:35:06 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | def is_protocol(tp: type, /) -> bool: | 
					
						
							|  |  |  |     """Return True if the given type is a Protocol.
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     Example:: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         >>> from typing import Protocol, is_protocol | 
					
						
							|  |  |  |         >>> class P(Protocol): | 
					
						
							|  |  |  |         ...     def a(self) -> str: ... | 
					
						
							|  |  |  |         ...     b: int | 
					
						
							|  |  |  |         >>> is_protocol(P) | 
					
						
							|  |  |  |         True | 
					
						
							|  |  |  |         >>> is_protocol(int) | 
					
						
							|  |  |  |         False | 
					
						
							|  |  |  |     """
 | 
					
						
							|  |  |  |     return ( | 
					
						
							|  |  |  |         isinstance(tp, type) | 
					
						
							|  |  |  |         and getattr(tp, '_is_protocol', False) | 
					
						
							|  |  |  |         and tp != Protocol | 
					
						
							|  |  |  |     ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | def get_protocol_members(tp: type, /) -> frozenset[str]: | 
					
						
							|  |  |  |     """Return the set of members defined in a Protocol.
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     Example:: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         >>> from typing import Protocol, get_protocol_members | 
					
						
							|  |  |  |         >>> class P(Protocol): | 
					
						
							|  |  |  |         ...     def a(self) -> str: ... | 
					
						
							|  |  |  |         ...     b: int | 
					
						
							| 
									
										
										
										
											2023-11-16 18:40:09 +03:00
										 |  |  |         >>> get_protocol_members(P) == frozenset({'a', 'b'}) | 
					
						
							|  |  |  |         True | 
					
						
							| 
									
										
										
										
											2023-06-14 05:35:06 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |     Raise a TypeError for arguments that are not Protocols. | 
					
						
							|  |  |  |     """
 | 
					
						
							|  |  |  |     if not is_protocol(tp): | 
					
						
							|  |  |  |         raise TypeError(f'{tp!r} is not a Protocol') | 
					
						
							|  |  |  |     return frozenset(tp.__protocol_attrs__) | 
					
						
							| 
									
										
										
										
											2023-09-23 08:46:35 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | def __getattr__(attr): | 
					
						
							|  |  |  |     """Improve the import time of the typing module.
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     Soft-deprecated objects which are costly to create | 
					
						
							|  |  |  |     are only created on-demand here. | 
					
						
							|  |  |  |     """
 | 
					
						
							|  |  |  |     if attr in {"Pattern", "Match"}: | 
					
						
							|  |  |  |         import re | 
					
						
							|  |  |  |         obj = _alias(getattr(re, attr), 1) | 
					
						
							|  |  |  |     elif attr in {"ContextManager", "AsyncContextManager"}: | 
					
						
							|  |  |  |         import contextlib | 
					
						
							| 
									
										
										
										
											2024-05-07 07:16:05 -07:00
										 |  |  |         obj = _alias(getattr(contextlib, f"Abstract{attr}"), 2, name=attr, defaults=(bool | None,)) | 
					
						
							| 
									
										
										
										
											2024-05-10 09:55:49 -07:00
										 |  |  |     elif attr == "_collect_parameters": | 
					
						
							|  |  |  |         import warnings | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         depr_message = ( | 
					
						
							|  |  |  |             "The private _collect_parameters function is deprecated and will be" | 
					
						
							|  |  |  |             " removed in a future version of Python. Any use of private functions" | 
					
						
							|  |  |  |             " is discouraged and may break in the future." | 
					
						
							|  |  |  |         ) | 
					
						
							|  |  |  |         warnings.warn(depr_message, category=DeprecationWarning, stacklevel=2) | 
					
						
							|  |  |  |         obj = _collect_type_parameters | 
					
						
							| 
									
										
										
										
											2023-09-23 08:46:35 +01:00
										 |  |  |     else: | 
					
						
							|  |  |  |         raise AttributeError(f"module {__name__!r} has no attribute {attr!r}") | 
					
						
							|  |  |  |     globals()[attr] = obj | 
					
						
							|  |  |  |     return obj |