py2docfx 0.1.15.dev2038852__py3-none-any.whl → 0.1.16__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (35) hide show
  1. py2docfx/docfx_yaml/process_doctree.py +21 -34
  2. py2docfx/docfx_yaml/tests/test_method_arguments.py +1 -7
  3. py2docfx/docfx_yaml/tests/test_process_doctree.py +120 -0
  4. py2docfx/venv/basevenv/Lib/site-packages/setuptools/_distutils/_msvccompiler.py +11 -0
  5. py2docfx/venv/basevenv/Lib/site-packages/setuptools/_distutils/command/__init__.py +8 -27
  6. py2docfx/venv/basevenv/Lib/site-packages/setuptools/config/_apply_pyprojecttoml.py +3 -2
  7. py2docfx/venv/basevenv/Lib/site-packages/setuptools/dist.py +53 -42
  8. py2docfx/venv/basevenv/Lib/site-packages/setuptools/tests/config/test_setupcfg.py +42 -29
  9. py2docfx/venv/basevenv/Lib/site-packages/setuptools/tests/integration/test_pip_install_sdist.py +1 -1
  10. py2docfx/venv/venv1/Lib/site-packages/google/protobuf/__init__.py +1 -1
  11. py2docfx/venv/venv1/Lib/site-packages/google/protobuf/any_pb2.py +2 -2
  12. py2docfx/venv/venv1/Lib/site-packages/google/protobuf/api_pb2.py +2 -2
  13. py2docfx/venv/venv1/Lib/site-packages/google/protobuf/compiler/plugin_pb2.py +2 -2
  14. py2docfx/venv/venv1/Lib/site-packages/google/protobuf/descriptor_pb2.py +2 -2
  15. py2docfx/venv/venv1/Lib/site-packages/google/protobuf/duration_pb2.py +2 -2
  16. py2docfx/venv/venv1/Lib/site-packages/google/protobuf/empty_pb2.py +2 -2
  17. py2docfx/venv/venv1/Lib/site-packages/google/protobuf/field_mask_pb2.py +2 -2
  18. py2docfx/venv/venv1/Lib/site-packages/google/protobuf/runtime_version.py +1 -1
  19. py2docfx/venv/venv1/Lib/site-packages/google/protobuf/source_context_pb2.py +2 -2
  20. py2docfx/venv/venv1/Lib/site-packages/google/protobuf/struct_pb2.py +2 -2
  21. py2docfx/venv/venv1/Lib/site-packages/google/protobuf/timestamp_pb2.py +2 -2
  22. py2docfx/venv/venv1/Lib/site-packages/google/protobuf/type_pb2.py +2 -2
  23. py2docfx/venv/venv1/Lib/site-packages/google/protobuf/wrappers_pb2.py +2 -2
  24. py2docfx/venv/venv1/Lib/site-packages/pyasn1_modules/__init__.py +1 -1
  25. py2docfx/venv/venv1/Lib/site-packages/setuptools/_distutils/_msvccompiler.py +11 -0
  26. py2docfx/venv/venv1/Lib/site-packages/setuptools/_distutils/command/__init__.py +8 -27
  27. py2docfx/venv/venv1/Lib/site-packages/setuptools/config/_apply_pyprojecttoml.py +3 -2
  28. py2docfx/venv/venv1/Lib/site-packages/setuptools/dist.py +53 -42
  29. py2docfx/venv/venv1/Lib/site-packages/setuptools/tests/config/test_setupcfg.py +42 -29
  30. py2docfx/venv/venv1/Lib/site-packages/setuptools/tests/integration/test_pip_install_sdist.py +1 -1
  31. py2docfx/venv/venv1/Lib/site-packages/typing_extensions.py +999 -74
  32. {py2docfx-0.1.15.dev2038852.dist-info → py2docfx-0.1.16.dist-info}/METADATA +1 -1
  33. {py2docfx-0.1.15.dev2038852.dist-info → py2docfx-0.1.16.dist-info}/RECORD +35 -34
  34. {py2docfx-0.1.15.dev2038852.dist-info → py2docfx-0.1.16.dist-info}/WHEEL +0 -0
  35. {py2docfx-0.1.15.dev2038852.dist-info → py2docfx-0.1.16.dist-info}/top_level.txt +0 -0
@@ -1,9 +1,12 @@
1
1
  import abc
2
+ import builtins
2
3
  import collections
3
4
  import collections.abc
4
5
  import contextlib
6
+ import enum
5
7
  import functools
6
8
  import inspect
9
+ import keyword
7
10
  import operator
8
11
  import sys
9
12
  import types as _types
@@ -62,8 +65,11 @@ __all__ = [
62
65
  'dataclass_transform',
63
66
  'deprecated',
64
67
  'Doc',
68
+ 'evaluate_forward_ref',
65
69
  'get_overloads',
66
70
  'final',
71
+ 'Format',
72
+ 'get_annotations',
67
73
  'get_args',
68
74
  'get_origin',
69
75
  'get_original_bases',
@@ -83,6 +89,7 @@ __all__ = [
83
89
  'Text',
84
90
  'TypeAlias',
85
91
  'TypeAliasType',
92
+ 'TypeForm',
86
93
  'TypeGuard',
87
94
  'TypeIs',
88
95
  'TYPE_CHECKING',
@@ -91,6 +98,8 @@ __all__ = [
91
98
  'ReadOnly',
92
99
  'Required',
93
100
  'NotRequired',
101
+ 'NoDefault',
102
+ 'NoExtraItems',
94
103
 
95
104
  # Pure aliases, have always been in typing
96
105
  'AbstractSet',
@@ -117,7 +126,6 @@ __all__ = [
117
126
  'MutableMapping',
118
127
  'MutableSequence',
119
128
  'MutableSet',
120
- 'NoDefault',
121
129
  'Optional',
122
130
  'Pattern',
123
131
  'Reversible',
@@ -138,6 +146,9 @@ PEP_560 = True
138
146
  GenericMeta = type
139
147
  _PEP_696_IMPLEMENTED = sys.version_info >= (3, 13, 0, "beta")
140
148
 
149
+ # Added with bpo-45166 to 3.10.1+ and some 3.9 versions
150
+ _FORWARD_REF_HAS_CLASS = "__forward_is_class__" in typing.ForwardRef.__slots__
151
+
141
152
  # The functions below are modified copies of typing internal helpers.
142
153
  # They are needed by _ProtocolMeta and they provide support for PEP 646.
143
154
 
@@ -867,6 +878,63 @@ def _ensure_subclassable(mro_entries):
867
878
  return inner
868
879
 
869
880
 
881
+ _NEEDS_SINGLETONMETA = (
882
+ not hasattr(typing, "NoDefault") or not hasattr(typing, "NoExtraItems")
883
+ )
884
+
885
+ if _NEEDS_SINGLETONMETA:
886
+ class SingletonMeta(type):
887
+ def __setattr__(cls, attr, value):
888
+ # TypeError is consistent with the behavior of NoneType
889
+ raise TypeError(
890
+ f"cannot set {attr!r} attribute of immutable type {cls.__name__!r}"
891
+ )
892
+
893
+
894
+ if hasattr(typing, "NoDefault"):
895
+ NoDefault = typing.NoDefault
896
+ else:
897
+ class NoDefaultType(metaclass=SingletonMeta):
898
+ """The type of the NoDefault singleton."""
899
+
900
+ __slots__ = ()
901
+
902
+ def __new__(cls):
903
+ return globals().get("NoDefault") or object.__new__(cls)
904
+
905
+ def __repr__(self):
906
+ return "typing_extensions.NoDefault"
907
+
908
+ def __reduce__(self):
909
+ return "NoDefault"
910
+
911
+ NoDefault = NoDefaultType()
912
+ del NoDefaultType
913
+
914
+ if hasattr(typing, "NoExtraItems"):
915
+ NoExtraItems = typing.NoExtraItems
916
+ else:
917
+ class NoExtraItemsType(metaclass=SingletonMeta):
918
+ """The type of the NoExtraItems singleton."""
919
+
920
+ __slots__ = ()
921
+
922
+ def __new__(cls):
923
+ return globals().get("NoExtraItems") or object.__new__(cls)
924
+
925
+ def __repr__(self):
926
+ return "typing_extensions.NoExtraItems"
927
+
928
+ def __reduce__(self):
929
+ return "NoExtraItems"
930
+
931
+ NoExtraItems = NoExtraItemsType()
932
+ del NoExtraItemsType
933
+
934
+ if _NEEDS_SINGLETONMETA:
935
+ del SingletonMeta
936
+
937
+
870
938
  # Update this to something like >=3.13.0b1 if and when
871
939
  # PEP 728 is implemented in CPython
872
940
  _PEP_728_IMPLEMENTED = False
@@ -913,7 +981,9 @@ else:
913
981
  break
914
982
 
915
983
  class _TypedDictMeta(type):
916
- def __new__(cls, name, bases, ns, *, total=True, closed=False):
984
+
985
+ def __new__(cls, name, bases, ns, *, total=True, closed=None,
986
+ extra_items=NoExtraItems):
917
987
  """Create new typed dict class object.
918
988
 
919
989
  This method is called when TypedDict is subclassed,
@@ -925,6 +995,8 @@ else:
925
995
  if type(base) is not _TypedDictMeta and base is not typing.Generic:
926
996
  raise TypeError('cannot inherit from both a TypedDict type '
927
997
  'and a non-TypedDict base class')
998
+ if closed is not None and extra_items is not NoExtraItems:
999
+ raise TypeError(f"Cannot combine closed={closed!r} and extra_items")
928
1000
 
929
1001
  if any(issubclass(b, typing.Generic) for b in bases):
930
1002
  generic_base = (typing.Generic,)
@@ -964,7 +1036,7 @@ else:
964
1036
  optional_keys = set()
965
1037
  readonly_keys = set()
966
1038
  mutable_keys = set()
967
- extra_items_type = None
1039
+ extra_items_type = extra_items
968
1040
 
969
1041
  for base in bases:
970
1042
  base_dict = base.__dict__
@@ -974,13 +1046,12 @@ else:
974
1046
  optional_keys.update(base_dict.get('__optional_keys__', ()))
975
1047
  readonly_keys.update(base_dict.get('__readonly_keys__', ()))
976
1048
  mutable_keys.update(base_dict.get('__mutable_keys__', ()))
977
- base_extra_items_type = base_dict.get('__extra_items__', None)
978
- if base_extra_items_type is not None:
979
- extra_items_type = base_extra_items_type
980
1049
 
981
- if closed and extra_items_type is None:
982
- extra_items_type = Never
983
- if closed and "__extra_items__" in own_annotations:
1050
+ # This was specified in an earlier version of PEP 728. Support
1051
+ # is retained for backwards compatibility, but only for Python
1052
+ # 3.13 and lower.
1053
+ if (closed and sys.version_info < (3, 14)
1054
+ and "__extra_items__" in own_annotations):
984
1055
  annotation_type = own_annotations.pop("__extra_items__")
985
1056
  qualifiers = set(_get_typeddict_qualifiers(annotation_type))
986
1057
  if Required in qualifiers:
@@ -1019,8 +1090,7 @@ else:
1019
1090
  tp_dict.__optional_keys__ = frozenset(optional_keys)
1020
1091
  tp_dict.__readonly_keys__ = frozenset(readonly_keys)
1021
1092
  tp_dict.__mutable_keys__ = frozenset(mutable_keys)
1022
- if not hasattr(tp_dict, '__total__'):
1023
- tp_dict.__total__ = total
1093
+ tp_dict.__total__ = total
1024
1094
  tp_dict.__closed__ = closed
1025
1095
  tp_dict.__extra_items__ = extra_items_type
1026
1096
  return tp_dict
@@ -1036,7 +1106,16 @@ else:
1036
1106
  _TypedDict = type.__new__(_TypedDictMeta, 'TypedDict', (), {})
1037
1107
 
1038
1108
  @_ensure_subclassable(lambda bases: (_TypedDict,))
1039
- def TypedDict(typename, fields=_marker, /, *, total=True, closed=False, **kwargs):
1109
+ def TypedDict(
1110
+ typename,
1111
+ fields=_marker,
1112
+ /,
1113
+ *,
1114
+ total=True,
1115
+ closed=None,
1116
+ extra_items=NoExtraItems,
1117
+ **kwargs
1118
+ ):
1040
1119
  """A simple typed namespace. At runtime it is equivalent to a plain dict.
1041
1120
 
1042
1121
  TypedDict creates a dictionary type such that a type checker will expect all
@@ -1096,9 +1175,14 @@ else:
1096
1175
  "using the functional syntax, pass an empty dictionary, e.g. "
1097
1176
  ) + example + "."
1098
1177
  warnings.warn(deprecation_msg, DeprecationWarning, stacklevel=2)
1099
- if closed is not False and closed is not True:
1178
+ # Support a field called "closed"
1179
+ if closed is not False and closed is not True and closed is not None:
1100
1180
  kwargs["closed"] = closed
1101
- closed = False
1181
+ closed = None
1182
+ # Or "extra_items"
1183
+ if extra_items is not NoExtraItems:
1184
+ kwargs["extra_items"] = extra_items
1185
+ extra_items = NoExtraItems
1102
1186
  fields = kwargs
1103
1187
  elif kwargs:
1104
1188
  raise TypeError("TypedDict takes either a dict or keyword arguments,"
@@ -1120,7 +1204,8 @@ else:
1120
1204
  # Setting correct module is necessary to make typed dict classes pickleable.
1121
1205
  ns['__module__'] = module
1122
1206
 
1123
- td = _TypedDictMeta(typename, (), ns, total=total, closed=closed)
1207
+ td = _TypedDictMeta(typename, (), ns, total=total, closed=closed,
1208
+ extra_items=extra_items)
1124
1209
  td.__orig_bases__ = (TypedDict,)
1125
1210
  return td
1126
1211
 
@@ -1232,10 +1317,90 @@ else: # <=3.13
1232
1317
  )
1233
1318
  else: # 3.8
1234
1319
  hint = typing.get_type_hints(obj, globalns=globalns, localns=localns)
1320
+ if sys.version_info < (3, 11):
1321
+ _clean_optional(obj, hint, globalns, localns)
1322
+ if sys.version_info < (3, 9):
1323
+ # In 3.8 eval_type does not flatten Optional[ForwardRef] correctly
1324
+ # This will recreate and and cache Unions.
1325
+ hint = {
1326
+ k: (t
1327
+ if get_origin(t) != Union
1328
+ else Union[t.__args__])
1329
+ for k, t in hint.items()
1330
+ }
1235
1331
  if include_extras:
1236
1332
  return hint
1237
1333
  return {k: _strip_extras(t) for k, t in hint.items()}
1238
1334
 
1335
+ _NoneType = type(None)
1336
+
1337
+ def _could_be_inserted_optional(t):
1338
+ """detects Union[..., None] pattern"""
1339
+ # 3.8+ compatible checking before _UnionGenericAlias
1340
+ if get_origin(t) is not Union:
1341
+ return False
1342
+ # Assume if last argument is not None they are user defined
1343
+ if t.__args__[-1] is not _NoneType:
1344
+ return False
1345
+ return True
1346
+
1347
+ # < 3.11
1348
+ def _clean_optional(obj, hints, globalns=None, localns=None):
1349
+ # reverts injected Union[..., None] cases from typing.get_type_hints
1350
+ # when a None default value is used.
1351
+ # see https://github.com/python/typing_extensions/issues/310
1352
+ if not hints or isinstance(obj, type):
1353
+ return
1354
+ defaults = typing._get_defaults(obj) # avoid accessing __annotations___
1355
+ if not defaults:
1356
+ return
1357
+ original_hints = obj.__annotations__
1358
+ for name, value in hints.items():
1359
+ # Not a Union[..., None] or replacement conditions not fullfilled
1360
+ if (not _could_be_inserted_optional(value)
1361
+ or name not in defaults
1362
+ or defaults[name] is not None
1363
+ ):
1364
+ continue
1365
+ original_value = original_hints[name]
1366
+ # value=NoneType should have caused a skip above but check for safety
1367
+ if original_value is None:
1368
+ original_value = _NoneType
1369
+ # Forward reference
1370
+ if isinstance(original_value, str):
1371
+ if globalns is None:
1372
+ if isinstance(obj, _types.ModuleType):
1373
+ globalns = obj.__dict__
1374
+ else:
1375
+ nsobj = obj
1376
+ # Find globalns for the unwrapped object.
1377
+ while hasattr(nsobj, '__wrapped__'):
1378
+ nsobj = nsobj.__wrapped__
1379
+ globalns = getattr(nsobj, '__globals__', {})
1380
+ if localns is None:
1381
+ localns = globalns
1382
+ elif localns is None:
1383
+ localns = globalns
1384
+ if sys.version_info < (3, 9):
1385
+ original_value = ForwardRef(original_value)
1386
+ else:
1387
+ original_value = ForwardRef(
1388
+ original_value,
1389
+ is_argument=not isinstance(obj, _types.ModuleType)
1390
+ )
1391
+ original_evaluated = typing._eval_type(original_value, globalns, localns)
1392
+ if sys.version_info < (3, 9) and get_origin(original_evaluated) is Union:
1393
+ # Union[str, None, "str"] is not reduced to Union[str, None]
1394
+ original_evaluated = Union[original_evaluated.__args__]
1395
+ # Compare if values differ. Note that even if equal
1396
+ # value might be cached by typing._tp_cache contrary to original_evaluated
1397
+ if original_evaluated != value or (
1398
+ # 3.10: ForwardRefs of UnionType might be turned into _UnionGenericAlias
1399
+ hasattr(_types, "UnionType")
1400
+ and isinstance(original_evaluated, _types.UnionType)
1401
+ and not isinstance(value, _types.UnionType)
1402
+ ):
1403
+ hints[name] = original_evaluated
1239
1404
 
1240
1405
  # Python 3.9+ has PEP 593 (Annotated)
1241
1406
  if hasattr(typing, 'Annotated'):
@@ -1443,34 +1608,6 @@ else:
1443
1608
  )
1444
1609
 
1445
1610
 
1446
- if hasattr(typing, "NoDefault"):
1447
- NoDefault = typing.NoDefault
1448
- else:
1449
- class NoDefaultTypeMeta(type):
1450
- def __setattr__(cls, attr, value):
1451
- # TypeError is consistent with the behavior of NoneType
1452
- raise TypeError(
1453
- f"cannot set {attr!r} attribute of immutable type {cls.__name__!r}"
1454
- )
1455
-
1456
- class NoDefaultType(metaclass=NoDefaultTypeMeta):
1457
- """The type of the NoDefault singleton."""
1458
-
1459
- __slots__ = ()
1460
-
1461
- def __new__(cls):
1462
- return globals().get("NoDefault") or object.__new__(cls)
1463
-
1464
- def __repr__(self):
1465
- return "typing_extensions.NoDefault"
1466
-
1467
- def __reduce__(self):
1468
- return "NoDefault"
1469
-
1470
- NoDefault = NoDefaultType()
1471
- del NoDefaultType, NoDefaultTypeMeta
1472
-
1473
-
1474
1611
  def _set_default(type_param, default):
1475
1612
  type_param.has_default = lambda: default is not NoDefault
1476
1613
  type_param.__default__ = default
@@ -1761,6 +1898,23 @@ else:
1761
1898
  # 3.8-3.9
1762
1899
  if not hasattr(typing, 'Concatenate'):
1763
1900
  # Inherits from list as a workaround for Callable checks in Python < 3.9.2.
1901
+
1902
+ # 3.9.0-1
1903
+ if not hasattr(typing, '_type_convert'):
1904
+ def _type_convert(arg, module=None, *, allow_special_forms=False):
1905
+ """For converting None to type(None), and strings to ForwardRef."""
1906
+ if arg is None:
1907
+ return type(None)
1908
+ if isinstance(arg, str):
1909
+ if sys.version_info <= (3, 9, 6):
1910
+ return ForwardRef(arg)
1911
+ if sys.version_info <= (3, 9, 7):
1912
+ return ForwardRef(arg, module=module)
1913
+ return ForwardRef(arg, module=module, is_class=allow_special_forms)
1914
+ return arg
1915
+ else:
1916
+ _type_convert = typing._type_convert
1917
+
1764
1918
  class _ConcatenateGenericAlias(list):
1765
1919
 
1766
1920
  # Trick Generic into looking into this for __parameters__.
@@ -1792,27 +1946,171 @@ if not hasattr(typing, 'Concatenate'):
1792
1946
  tp for tp in self.__args__ if isinstance(tp, (typing.TypeVar, ParamSpec))
1793
1947
  )
1794
1948
 
1949
+ # 3.8; needed for typing._subst_tvars
1950
+ # 3.9 used by __getitem__ below
1951
+ def copy_with(self, params):
1952
+ if isinstance(params[-1], _ConcatenateGenericAlias):
1953
+ params = (*params[:-1], *params[-1].__args__)
1954
+ elif isinstance(params[-1], (list, tuple)):
1955
+ return (*params[:-1], *params[-1])
1956
+ elif (not (params[-1] is ... or isinstance(params[-1], ParamSpec))):
1957
+ raise TypeError("The last parameter to Concatenate should be a "
1958
+ "ParamSpec variable or ellipsis.")
1959
+ return self.__class__(self.__origin__, params)
1960
+
1961
+ # 3.9; accessed during GenericAlias.__getitem__ when substituting
1962
+ def __getitem__(self, args):
1963
+ if self.__origin__ in (Generic, Protocol):
1964
+ # Can't subscript Generic[...] or Protocol[...].
1965
+ raise TypeError(f"Cannot subscript already-subscripted {self}")
1966
+ if not self.__parameters__:
1967
+ raise TypeError(f"{self} is not a generic class")
1968
+
1969
+ if not isinstance(args, tuple):
1970
+ args = (args,)
1971
+ args = _unpack_args(*(_type_convert(p) for p in args))
1972
+ params = self.__parameters__
1973
+ for param in params:
1974
+ prepare = getattr(param, "__typing_prepare_subst__", None)
1975
+ if prepare is not None:
1976
+ args = prepare(self, args)
1977
+ # 3.8 - 3.9 & typing.ParamSpec
1978
+ elif isinstance(param, ParamSpec):
1979
+ i = params.index(param)
1980
+ if (
1981
+ i == len(args)
1982
+ and getattr(param, '__default__', NoDefault) is not NoDefault
1983
+ ):
1984
+ args = [*args, param.__default__]
1985
+ if i >= len(args):
1986
+ raise TypeError(f"Too few arguments for {self}")
1987
+ # Special case for Z[[int, str, bool]] == Z[int, str, bool]
1988
+ if len(params) == 1 and not _is_param_expr(args[0]):
1989
+ assert i == 0
1990
+ args = (args,)
1991
+ elif (
1992
+ isinstance(args[i], list)
1993
+ # 3.8 - 3.9
1994
+ # This class inherits from list do not convert
1995
+ and not isinstance(args[i], _ConcatenateGenericAlias)
1996
+ ):
1997
+ args = (*args[:i], tuple(args[i]), *args[i + 1:])
1795
1998
 
1796
- # 3.8-3.9
1999
+ alen = len(args)
2000
+ plen = len(params)
2001
+ if alen != plen:
2002
+ raise TypeError(
2003
+ f"Too {'many' if alen > plen else 'few'} arguments for {self};"
2004
+ f" actual {alen}, expected {plen}"
2005
+ )
2006
+
2007
+ subst = dict(zip(self.__parameters__, args))
2008
+ # determine new args
2009
+ new_args = []
2010
+ for arg in self.__args__:
2011
+ if isinstance(arg, type):
2012
+ new_args.append(arg)
2013
+ continue
2014
+ if isinstance(arg, TypeVar):
2015
+ arg = subst[arg]
2016
+ if (
2017
+ (isinstance(arg, typing._GenericAlias) and _is_unpack(arg))
2018
+ or (
2019
+ hasattr(_types, "GenericAlias")
2020
+ and isinstance(arg, _types.GenericAlias)
2021
+ and getattr(arg, "__unpacked__", False)
2022
+ )
2023
+ ):
2024
+ raise TypeError(f"{arg} is not valid as type argument")
2025
+
2026
+ elif isinstance(arg,
2027
+ typing._GenericAlias
2028
+ if not hasattr(_types, "GenericAlias") else
2029
+ (typing._GenericAlias, _types.GenericAlias)
2030
+ ):
2031
+ subparams = arg.__parameters__
2032
+ if subparams:
2033
+ subargs = tuple(subst[x] for x in subparams)
2034
+ arg = arg[subargs]
2035
+ new_args.append(arg)
2036
+ return self.copy_with(tuple(new_args))
2037
+
2038
+ # 3.10+
2039
+ else:
2040
+ _ConcatenateGenericAlias = typing._ConcatenateGenericAlias
2041
+
2042
+ # 3.10
2043
+ if sys.version_info < (3, 11):
2044
+
2045
+ class _ConcatenateGenericAlias(typing._ConcatenateGenericAlias, _root=True):
2046
+ # needed for checks in collections.abc.Callable to accept this class
2047
+ __module__ = "typing"
2048
+
2049
+ def copy_with(self, params):
2050
+ if isinstance(params[-1], (list, tuple)):
2051
+ return (*params[:-1], *params[-1])
2052
+ if isinstance(params[-1], typing._ConcatenateGenericAlias):
2053
+ params = (*params[:-1], *params[-1].__args__)
2054
+ elif not (params[-1] is ... or isinstance(params[-1], ParamSpec)):
2055
+ raise TypeError("The last parameter to Concatenate should be a "
2056
+ "ParamSpec variable or ellipsis.")
2057
+ return super(typing._ConcatenateGenericAlias, self).copy_with(params)
2058
+
2059
+ def __getitem__(self, args):
2060
+ value = super().__getitem__(args)
2061
+ if isinstance(value, tuple) and any(_is_unpack(t) for t in value):
2062
+ return tuple(_unpack_args(*(n for n in value)))
2063
+ return value
2064
+
2065
+
2066
+ # 3.8-3.9.2
2067
+ class _EllipsisDummy: ...
2068
+
2069
+
2070
+ # 3.8-3.10
2071
+ def _create_concatenate_alias(origin, parameters):
2072
+ if parameters[-1] is ... and sys.version_info < (3, 9, 2):
2073
+ # Hack: Arguments must be types, replace it with one.
2074
+ parameters = (*parameters[:-1], _EllipsisDummy)
2075
+ if sys.version_info >= (3, 10, 2):
2076
+ concatenate = _ConcatenateGenericAlias(origin, parameters,
2077
+ _typevar_types=(TypeVar, ParamSpec),
2078
+ _paramspec_tvars=True)
2079
+ else:
2080
+ concatenate = _ConcatenateGenericAlias(origin, parameters)
2081
+ if parameters[-1] is not _EllipsisDummy:
2082
+ return concatenate
2083
+ # Remove dummy again
2084
+ concatenate.__args__ = tuple(p if p is not _EllipsisDummy else ...
2085
+ for p in concatenate.__args__)
2086
+ if sys.version_info < (3, 10):
2087
+ # backport needs __args__ adjustment only
2088
+ return concatenate
2089
+ concatenate.__parameters__ = tuple(p for p in concatenate.__parameters__
2090
+ if p is not _EllipsisDummy)
2091
+ return concatenate
2092
+
2093
+
2094
+ # 3.8-3.10
1797
2095
  @typing._tp_cache
1798
2096
  def _concatenate_getitem(self, parameters):
1799
2097
  if parameters == ():
1800
2098
  raise TypeError("Cannot take a Concatenate of no types.")
1801
2099
  if not isinstance(parameters, tuple):
1802
2100
  parameters = (parameters,)
1803
- if not isinstance(parameters[-1], ParamSpec):
2101
+ if not (parameters[-1] is ... or isinstance(parameters[-1], ParamSpec)):
1804
2102
  raise TypeError("The last parameter to Concatenate should be a "
1805
- "ParamSpec variable.")
2103
+ "ParamSpec variable or ellipsis.")
1806
2104
  msg = "Concatenate[arg, ...]: each arg must be a type."
1807
- parameters = tuple(typing._type_check(p, msg) for p in parameters)
1808
- return _ConcatenateGenericAlias(self, parameters)
2105
+ parameters = (*(typing._type_check(p, msg) for p in parameters[:-1]),
2106
+ parameters[-1])
2107
+ return _create_concatenate_alias(self, parameters)
1809
2108
 
1810
2109
 
1811
- # 3.10+
1812
- if hasattr(typing, 'Concatenate'):
2110
+ # 3.11+; Concatenate does not accept ellipsis in 3.10
2111
+ if sys.version_info >= (3, 11):
1813
2112
  Concatenate = typing.Concatenate
1814
- _ConcatenateGenericAlias = typing._ConcatenateGenericAlias
1815
- # 3.9
2113
+ # 3.9-3.10
1816
2114
  elif sys.version_info[:2] >= (3, 9):
1817
2115
  @_ExtensionsSpecialForm
1818
2116
  def Concatenate(self, parameters):
@@ -1976,7 +2274,7 @@ elif sys.version_info[:2] >= (3, 9):
1976
2274
 
1977
2275
  1. The return value is a boolean.
1978
2276
  2. If the return value is ``True``, the type of its argument
1979
- is the intersection of the type inside ``TypeGuard`` and the argument's
2277
+ is the intersection of the type inside ``TypeIs`` and the argument's
1980
2278
  previously known type.
1981
2279
 
1982
2280
  For example::
@@ -2024,7 +2322,7 @@ else:
2024
2322
 
2025
2323
  1. The return value is a boolean.
2026
2324
  2. If the return value is ``True``, the type of its argument
2027
- is the intersection of the type inside ``TypeGuard`` and the argument's
2325
+ is the intersection of the type inside ``TypeIs`` and the argument's
2028
2326
  previously known type.
2029
2327
 
2030
2328
  For example::
@@ -2042,6 +2340,69 @@ else:
2042
2340
  PEP 742 (Narrowing types with TypeIs).
2043
2341
  """)
2044
2342
 
2343
+ # 3.14+?
2344
+ if hasattr(typing, 'TypeForm'):
2345
+ TypeForm = typing.TypeForm
2346
+ # 3.9
2347
+ elif sys.version_info[:2] >= (3, 9):
2348
+ class _TypeFormForm(_ExtensionsSpecialForm, _root=True):
2349
+ # TypeForm(X) is equivalent to X but indicates to the type checker
2350
+ # that the object is a TypeForm.
2351
+ def __call__(self, obj, /):
2352
+ return obj
2353
+
2354
+ @_TypeFormForm
2355
+ def TypeForm(self, parameters):
2356
+ """A special form representing the value that results from the evaluation
2357
+ of a type expression. This value encodes the information supplied in the
2358
+ type expression, and it represents the type described by that type expression.
2359
+
2360
+ When used in a type expression, TypeForm describes a set of type form objects.
2361
+ It accepts a single type argument, which must be a valid type expression.
2362
+ ``TypeForm[T]`` describes the set of all type form objects that represent
2363
+ the type T or types that are assignable to T.
2364
+
2365
+ Usage:
2366
+
2367
+ def cast[T](typ: TypeForm[T], value: Any) -> T: ...
2368
+
2369
+ reveal_type(cast(int, "x")) # int
2370
+
2371
+ See PEP 747 for more information.
2372
+ """
2373
+ item = typing._type_check(parameters, f'{self} accepts only a single type.')
2374
+ return typing._GenericAlias(self, (item,))
2375
+ # 3.8
2376
+ else:
2377
+ class _TypeFormForm(_ExtensionsSpecialForm, _root=True):
2378
+ def __getitem__(self, parameters):
2379
+ item = typing._type_check(parameters,
2380
+ f'{self._name} accepts only a single type')
2381
+ return typing._GenericAlias(self, (item,))
2382
+
2383
+ def __call__(self, obj, /):
2384
+ return obj
2385
+
2386
+ TypeForm = _TypeFormForm(
2387
+ 'TypeForm',
2388
+ doc="""A special form representing the value that results from the evaluation
2389
+ of a type expression. This value encodes the information supplied in the
2390
+ type expression, and it represents the type described by that type expression.
2391
+
2392
+ When used in a type expression, TypeForm describes a set of type form objects.
2393
+ It accepts a single type argument, which must be a valid type expression.
2394
+ ``TypeForm[T]`` describes the set of all type form objects that represent
2395
+ the type T or types that are assignable to T.
2396
+
2397
+ Usage:
2398
+
2399
+ def cast[T](typ: TypeForm[T], value: Any) -> T: ...
2400
+
2401
+ reveal_type(cast(int, "x")) # int
2402
+
2403
+ See PEP 747 for more information.
2404
+ """)
2405
+
2045
2406
 
2046
2407
  # Vendored from cpython typing._SpecialFrom
2047
2408
  class _SpecialForm(typing._Final, _root=True):
@@ -2344,7 +2705,9 @@ elif sys.version_info[:2] >= (3, 9): # 3.9+
2344
2705
  self.__doc__ = _UNPACK_DOC
2345
2706
 
2346
2707
  class _UnpackAlias(typing._GenericAlias, _root=True):
2347
- __class__ = typing.TypeVar
2708
+ if sys.version_info < (3, 11):
2709
+ # needed for compatibility with Generic[Unpack[Ts]]
2710
+ __class__ = typing.TypeVar
2348
2711
 
2349
2712
  @property
2350
2713
  def __typing_unpacked_tuple_args__(self):
@@ -2357,6 +2720,17 @@ elif sys.version_info[:2] >= (3, 9): # 3.9+
2357
2720
  return arg.__args__
2358
2721
  return None
2359
2722
 
2723
+ @property
2724
+ def __typing_is_unpacked_typevartuple__(self):
2725
+ assert self.__origin__ is Unpack
2726
+ assert len(self.__args__) == 1
2727
+ return isinstance(self.__args__[0], TypeVarTuple)
2728
+
2729
+ def __getitem__(self, args):
2730
+ if self.__typing_is_unpacked_typevartuple__:
2731
+ return args
2732
+ return super().__getitem__(args)
2733
+
2360
2734
  @_UnpackSpecialForm
2361
2735
  def Unpack(self, parameters):
2362
2736
  item = typing._type_check(parameters, f'{self._name} accepts only a single type.')
@@ -2369,6 +2743,28 @@ else: # 3.8
2369
2743
  class _UnpackAlias(typing._GenericAlias, _root=True):
2370
2744
  __class__ = typing.TypeVar
2371
2745
 
2746
+ @property
2747
+ def __typing_unpacked_tuple_args__(self):
2748
+ assert self.__origin__ is Unpack
2749
+ assert len(self.__args__) == 1
2750
+ arg, = self.__args__
2751
+ if isinstance(arg, typing._GenericAlias):
2752
+ if arg.__origin__ is not tuple:
2753
+ raise TypeError("Unpack[...] must be used with a tuple type")
2754
+ return arg.__args__
2755
+ return None
2756
+
2757
+ @property
2758
+ def __typing_is_unpacked_typevartuple__(self):
2759
+ assert self.__origin__ is Unpack
2760
+ assert len(self.__args__) == 1
2761
+ return isinstance(self.__args__[0], TypeVarTuple)
2762
+
2763
+ def __getitem__(self, args):
2764
+ if self.__typing_is_unpacked_typevartuple__:
2765
+ return args
2766
+ return super().__getitem__(args)
2767
+
2372
2768
  class _UnpackForm(_ExtensionsSpecialForm, _root=True):
2373
2769
  def __getitem__(self, parameters):
2374
2770
  item = typing._type_check(parameters,
@@ -2381,21 +2777,22 @@ else: # 3.8
2381
2777
  return isinstance(obj, _UnpackAlias)
2382
2778
 
2383
2779
 
2780
+ def _unpack_args(*args):
2781
+ newargs = []
2782
+ for arg in args:
2783
+ subargs = getattr(arg, '__typing_unpacked_tuple_args__', None)
2784
+ if subargs is not None and (not (subargs and subargs[-1] is ...)):
2785
+ newargs.extend(subargs)
2786
+ else:
2787
+ newargs.append(arg)
2788
+ return newargs
2789
+
2790
+
2384
2791
  if _PEP_696_IMPLEMENTED:
2385
2792
  from typing import TypeVarTuple
2386
2793
 
2387
2794
  elif hasattr(typing, "TypeVarTuple"): # 3.11+
2388
2795
 
2389
- def _unpack_args(*args):
2390
- newargs = []
2391
- for arg in args:
2392
- subargs = getattr(arg, '__typing_unpacked_tuple_args__', None)
2393
- if subargs is not None and not (subargs and subargs[-1] is ...):
2394
- newargs.extend(subargs)
2395
- else:
2396
- newargs.append(arg)
2397
- return newargs
2398
-
2399
2796
  # Add default parameter - PEP 696
2400
2797
  class TypeVarTuple(metaclass=_TypeVarLikeMeta):
2401
2798
  """Type variable tuple."""
@@ -2845,13 +3242,21 @@ else:
2845
3242
  __init_subclass__.__deprecated__ = msg
2846
3243
  return arg
2847
3244
  elif callable(arg):
3245
+ import asyncio.coroutines
2848
3246
  import functools
3247
+ import inspect
2849
3248
 
2850
3249
  @functools.wraps(arg)
2851
3250
  def wrapper(*args, **kwargs):
2852
3251
  warnings.warn(msg, category=category, stacklevel=stacklevel + 1)
2853
3252
  return arg(*args, **kwargs)
2854
3253
 
3254
+ if asyncio.coroutines.iscoroutinefunction(arg):
3255
+ if sys.version_info >= (3, 12):
3256
+ wrapper = inspect.markcoroutinefunction(wrapper)
3257
+ else:
3258
+ wrapper._is_coroutine = asyncio.coroutines._is_coroutine
3259
+
2855
3260
  arg.__deprecated__ = wrapper.__deprecated__ = msg
2856
3261
  return wrapper
2857
3262
  else:
@@ -2860,6 +3265,24 @@ else:
2860
3265
  f"a class or callable, not {arg!r}"
2861
3266
  )
2862
3267
 
3268
+ if sys.version_info < (3, 10):
3269
+ def _is_param_expr(arg):
3270
+ return arg is ... or isinstance(
3271
+ arg, (tuple, list, ParamSpec, _ConcatenateGenericAlias)
3272
+ )
3273
+ else:
3274
+ def _is_param_expr(arg):
3275
+ return arg is ... or isinstance(
3276
+ arg,
3277
+ (
3278
+ tuple,
3279
+ list,
3280
+ ParamSpec,
3281
+ _ConcatenateGenericAlias,
3282
+ typing._ConcatenateGenericAlias,
3283
+ ),
3284
+ )
3285
+
2863
3286
 
2864
3287
  # We have to do some monkey patching to deal with the dual nature of
2865
3288
  # Unpack/TypeVarTuple:
@@ -2874,6 +3297,17 @@ if not hasattr(typing, "TypeVarTuple"):
2874
3297
 
2875
3298
  This gives a nice error message in case of count mismatch.
2876
3299
  """
3300
+ # If substituting a single ParamSpec with multiple arguments
3301
+ # we do not check the count
3302
+ if (inspect.isclass(cls) and issubclass(cls, typing.Generic)
3303
+ and len(cls.__parameters__) == 1
3304
+ and isinstance(cls.__parameters__[0], ParamSpec)
3305
+ and parameters
3306
+ and not _is_param_expr(parameters[0])
3307
+ ):
3308
+ # Generic modifies parameters variable, but here we cannot do this
3309
+ return
3310
+
2877
3311
  if not elen:
2878
3312
  raise TypeError(f"{cls} is not a generic class")
2879
3313
  if elen is _marker:
@@ -3007,7 +3441,10 @@ if hasattr(typing, '_collect_type_vars'):
3007
3441
  for t in types:
3008
3442
  if _is_unpacked_typevartuple(t):
3009
3443
  type_var_tuple_encountered = True
3010
- elif isinstance(t, typevar_types) and t not in tvars:
3444
+ elif (
3445
+ isinstance(t, typevar_types) and not isinstance(t, _UnpackAlias)
3446
+ and t not in tvars
3447
+ ):
3011
3448
  if enforce_default_ordering:
3012
3449
  has_default = getattr(t, '__default__', NoDefault) is not NoDefault
3013
3450
  if has_default:
@@ -3022,6 +3459,13 @@ if hasattr(typing, '_collect_type_vars'):
3022
3459
  tvars.append(t)
3023
3460
  if _should_collect_from_parameters(t):
3024
3461
  tvars.extend([t for t in t.__parameters__ if t not in tvars])
3462
+ elif isinstance(t, tuple):
3463
+ # Collect nested type_vars
3464
+ # tuple wrapped by _prepare_paramspec_params(cls, params)
3465
+ for x in t:
3466
+ for collected in _collect_type_vars([x]):
3467
+ if collected not in tvars:
3468
+ tvars.append(collected)
3025
3469
  return tuple(tvars)
3026
3470
 
3027
3471
  typing._collect_type_vars = _collect_type_vars
@@ -3379,8 +3823,9 @@ else:
3379
3823
  return typing.Union[other, self]
3380
3824
 
3381
3825
 
3382
- if hasattr(typing, "TypeAliasType"):
3826
+ if sys.version_info >= (3, 14):
3383
3827
  TypeAliasType = typing.TypeAliasType
3828
+ # 3.8-3.13
3384
3829
  else:
3385
3830
  def _is_unionable(obj):
3386
3831
  """Corresponds to is_unionable() in unionobject.c in CPython."""
@@ -3391,6 +3836,37 @@ else:
3391
3836
  TypeAliasType,
3392
3837
  ))
3393
3838
 
3839
+ if sys.version_info < (3, 10):
3840
+ # Copied and pasted from https://github.com/python/cpython/blob/986a4e1b6fcae7fe7a1d0a26aea446107dd58dd2/Objects/genericaliasobject.c#L568-L582,
3841
+ # so that we emulate the behaviour of `types.GenericAlias`
3842
+ # on the latest versions of CPython
3843
+ _ATTRIBUTE_DELEGATION_EXCLUSIONS = frozenset({
3844
+ "__class__",
3845
+ "__bases__",
3846
+ "__origin__",
3847
+ "__args__",
3848
+ "__unpacked__",
3849
+ "__parameters__",
3850
+ "__typing_unpacked_tuple_args__",
3851
+ "__mro_entries__",
3852
+ "__reduce_ex__",
3853
+ "__reduce__",
3854
+ "__copy__",
3855
+ "__deepcopy__",
3856
+ })
3857
+
3858
+ class _TypeAliasGenericAlias(typing._GenericAlias, _root=True):
3859
+ def __getattr__(self, attr):
3860
+ if attr in _ATTRIBUTE_DELEGATION_EXCLUSIONS:
3861
+ return object.__getattr__(self, attr)
3862
+ return getattr(self.__origin__, attr)
3863
+
3864
+ if sys.version_info < (3, 9):
3865
+ def __getitem__(self, item):
3866
+ result = super().__getitem__(item)
3867
+ result.__class__ = type(self)
3868
+ return result
3869
+
3394
3870
  class TypeAliasType:
3395
3871
  """Create named, parameterized type aliases.
3396
3872
 
@@ -3422,11 +3898,29 @@ else:
3422
3898
  def __init__(self, name: str, value, *, type_params=()):
3423
3899
  if not isinstance(name, str):
3424
3900
  raise TypeError("TypeAliasType name must be a string")
3901
+ if not isinstance(type_params, tuple):
3902
+ raise TypeError("type_params must be a tuple")
3425
3903
  self.__value__ = value
3426
3904
  self.__type_params__ = type_params
3427
3905
 
3906
+ default_value_encountered = False
3428
3907
  parameters = []
3429
3908
  for type_param in type_params:
3909
+ if (
3910
+ not isinstance(type_param, (TypeVar, TypeVarTuple, ParamSpec))
3911
+ # 3.8-3.11
3912
+ # Unpack Backport passes isinstance(type_param, TypeVar)
3913
+ or _is_unpack(type_param)
3914
+ ):
3915
+ raise TypeError(f"Expected a type param, got {type_param!r}")
3916
+ has_default = (
3917
+ getattr(type_param, '__default__', NoDefault) is not NoDefault
3918
+ )
3919
+ if default_value_encountered and not has_default:
3920
+ raise TypeError(f"non-default type parameter '{type_param!r}'"
3921
+ " follows default type parameter")
3922
+ if has_default:
3923
+ default_value_encountered = True
3430
3924
  if isinstance(type_param, TypeVarTuple):
3431
3925
  parameters.extend(type_param)
3432
3926
  else:
@@ -3463,16 +3957,49 @@ else:
3463
3957
  def __repr__(self) -> str:
3464
3958
  return self.__name__
3465
3959
 
3960
+ if sys.version_info < (3, 11):
3961
+ def _check_single_param(self, param, recursion=0):
3962
+ # Allow [], [int], [int, str], [int, ...], [int, T]
3963
+ if param is ...:
3964
+ return ...
3965
+ if param is None:
3966
+ return None
3967
+ # Note in <= 3.9 _ConcatenateGenericAlias inherits from list
3968
+ if isinstance(param, list) and recursion == 0:
3969
+ return [self._check_single_param(arg, recursion+1)
3970
+ for arg in param]
3971
+ return typing._type_check(
3972
+ param, f'Subscripting {self.__name__} requires a type.'
3973
+ )
3974
+
3975
+ def _check_parameters(self, parameters):
3976
+ if sys.version_info < (3, 11):
3977
+ return tuple(
3978
+ self._check_single_param(item)
3979
+ for item in parameters
3980
+ )
3981
+ return tuple(typing._type_check(
3982
+ item, f'Subscripting {self.__name__} requires a type.'
3983
+ )
3984
+ for item in parameters
3985
+ )
3986
+
3466
3987
  def __getitem__(self, parameters):
3988
+ if not self.__type_params__:
3989
+ raise TypeError("Only generic type aliases are subscriptable")
3467
3990
  if not isinstance(parameters, tuple):
3468
3991
  parameters = (parameters,)
3469
- parameters = [
3470
- typing._type_check(
3471
- item, f'Subscripting {self.__name__} requires a type.'
3472
- )
3473
- for item in parameters
3474
- ]
3475
- return typing._GenericAlias(self, tuple(parameters))
3992
+ # Using 3.9 here will create problems with Concatenate
3993
+ if sys.version_info >= (3, 10):
3994
+ return _types.GenericAlias(self, parameters)
3995
+ type_vars = _collect_type_vars(parameters)
3996
+ parameters = self._check_parameters(parameters)
3997
+ alias = _TypeAliasGenericAlias(self, parameters)
3998
+ # alias.__parameters__ is not complete if Concatenate is present
3999
+ # as it is converted to a list from which no parameters are extracted.
4000
+ if alias.__parameters__ != type_vars:
4001
+ alias.__parameters__ = type_vars
4002
+ return alias
3476
4003
 
3477
4004
  def __reduce__(self):
3478
4005
  return self.__name__
@@ -3599,6 +4126,404 @@ if _CapsuleType is not None:
3599
4126
  __all__.append("CapsuleType")
3600
4127
 
3601
4128
 
4129
+ # Using this convoluted approach so that this keeps working
4130
+ # whether we end up using PEP 649 as written, PEP 749, or
4131
+ # some other variation: in any case, inspect.get_annotations
4132
+ # will continue to exist and will gain a `format` parameter.
4133
+ _PEP_649_OR_749_IMPLEMENTED = (
4134
+ hasattr(inspect, 'get_annotations')
4135
+ and inspect.get_annotations.__kwdefaults__ is not None
4136
+ and "format" in inspect.get_annotations.__kwdefaults__
4137
+ )
4138
+
4139
+
4140
+ class Format(enum.IntEnum):
4141
+ VALUE = 1
4142
+ FORWARDREF = 2
4143
+ STRING = 3
4144
+
4145
+
4146
+ if _PEP_649_OR_749_IMPLEMENTED:
4147
+ get_annotations = inspect.get_annotations
4148
+ else:
4149
+ def get_annotations(obj, *, globals=None, locals=None, eval_str=False,
4150
+ format=Format.VALUE):
4151
+ """Compute the annotations dict for an object.
4152
+
4153
+ obj may be a callable, class, or module.
4154
+ Passing in an object of any other type raises TypeError.
4155
+
4156
+ Returns a dict. get_annotations() returns a new dict every time
4157
+ it's called; calling it twice on the same object will return two
4158
+ different but equivalent dicts.
4159
+
4160
+ This is a backport of `inspect.get_annotations`, which has been
4161
+ in the standard library since Python 3.10. See the standard library
4162
+ documentation for more:
4163
+
4164
+ https://docs.python.org/3/library/inspect.html#inspect.get_annotations
4165
+
4166
+ This backport adds the *format* argument introduced by PEP 649. The
4167
+ three formats supported are:
4168
+ * VALUE: the annotations are returned as-is. This is the default and
4169
+ it is compatible with the behavior on previous Python versions.
4170
+ * FORWARDREF: return annotations as-is if possible, but replace any
4171
+ undefined names with ForwardRef objects. The implementation proposed by
4172
+ PEP 649 relies on language changes that cannot be backported; the
4173
+ typing-extensions implementation simply returns the same result as VALUE.
4174
+ * STRING: return annotations as strings, in a format close to the original
4175
+ source. Again, this behavior cannot be replicated directly in a backport.
4176
+ As an approximation, typing-extensions retrieves the annotations under
4177
+ VALUE semantics and then stringifies them.
4178
+
4179
+ The purpose of this backport is to allow users who would like to use
4180
+ FORWARDREF or STRING semantics once PEP 649 is implemented, but who also
4181
+ want to support earlier Python versions, to simply write:
4182
+
4183
+ typing_extensions.get_annotations(obj, format=Format.FORWARDREF)
4184
+
4185
+ """
4186
+ format = Format(format)
4187
+
4188
+ if eval_str and format is not Format.VALUE:
4189
+ raise ValueError("eval_str=True is only supported with format=Format.VALUE")
4190
+
4191
+ if isinstance(obj, type):
4192
+ # class
4193
+ obj_dict = getattr(obj, '__dict__', None)
4194
+ if obj_dict and hasattr(obj_dict, 'get'):
4195
+ ann = obj_dict.get('__annotations__', None)
4196
+ if isinstance(ann, _types.GetSetDescriptorType):
4197
+ ann = None
4198
+ else:
4199
+ ann = None
4200
+
4201
+ obj_globals = None
4202
+ module_name = getattr(obj, '__module__', None)
4203
+ if module_name:
4204
+ module = sys.modules.get(module_name, None)
4205
+ if module:
4206
+ obj_globals = getattr(module, '__dict__', None)
4207
+ obj_locals = dict(vars(obj))
4208
+ unwrap = obj
4209
+ elif isinstance(obj, _types.ModuleType):
4210
+ # module
4211
+ ann = getattr(obj, '__annotations__', None)
4212
+ obj_globals = obj.__dict__
4213
+ obj_locals = None
4214
+ unwrap = None
4215
+ elif callable(obj):
4216
+ # this includes types.Function, types.BuiltinFunctionType,
4217
+ # types.BuiltinMethodType, functools.partial, functools.singledispatch,
4218
+ # "class funclike" from Lib/test/test_inspect... on and on it goes.
4219
+ ann = getattr(obj, '__annotations__', None)
4220
+ obj_globals = getattr(obj, '__globals__', None)
4221
+ obj_locals = None
4222
+ unwrap = obj
4223
+ elif hasattr(obj, '__annotations__'):
4224
+ ann = obj.__annotations__
4225
+ obj_globals = obj_locals = unwrap = None
4226
+ else:
4227
+ raise TypeError(f"{obj!r} is not a module, class, or callable.")
4228
+
4229
+ if ann is None:
4230
+ return {}
4231
+
4232
+ if not isinstance(ann, dict):
4233
+ raise ValueError(f"{obj!r}.__annotations__ is neither a dict nor None")
4234
+
4235
+ if not ann:
4236
+ return {}
4237
+
4238
+ if not eval_str:
4239
+ if format is Format.STRING:
4240
+ return {
4241
+ key: value if isinstance(value, str) else typing._type_repr(value)
4242
+ for key, value in ann.items()
4243
+ }
4244
+ return dict(ann)
4245
+
4246
+ if unwrap is not None:
4247
+ while True:
4248
+ if hasattr(unwrap, '__wrapped__'):
4249
+ unwrap = unwrap.__wrapped__
4250
+ continue
4251
+ if isinstance(unwrap, functools.partial):
4252
+ unwrap = unwrap.func
4253
+ continue
4254
+ break
4255
+ if hasattr(unwrap, "__globals__"):
4256
+ obj_globals = unwrap.__globals__
4257
+
4258
+ if globals is None:
4259
+ globals = obj_globals
4260
+ if locals is None:
4261
+ locals = obj_locals or {}
4262
+
4263
+ # "Inject" type parameters into the local namespace
4264
+ # (unless they are shadowed by assignments *in* the local namespace),
4265
+ # as a way of emulating annotation scopes when calling `eval()`
4266
+ if type_params := getattr(obj, "__type_params__", ()):
4267
+ locals = {param.__name__: param for param in type_params} | locals
4268
+
4269
+ return_value = {key:
4270
+ value if not isinstance(value, str) else eval(value, globals, locals)
4271
+ for key, value in ann.items() }
4272
+ return return_value
4273
+
4274
+
4275
+ if hasattr(typing, "evaluate_forward_ref"):
4276
+ evaluate_forward_ref = typing.evaluate_forward_ref
4277
+ else:
4278
+ # Implements annotationlib.ForwardRef.evaluate
4279
+ def _eval_with_owner(
4280
+ forward_ref, *, owner=None, globals=None, locals=None, type_params=None
4281
+ ):
4282
+ if forward_ref.__forward_evaluated__:
4283
+ return forward_ref.__forward_value__
4284
+ if getattr(forward_ref, "__cell__", None) is not None:
4285
+ try:
4286
+ value = forward_ref.__cell__.cell_contents
4287
+ except ValueError:
4288
+ pass
4289
+ else:
4290
+ forward_ref.__forward_evaluated__ = True
4291
+ forward_ref.__forward_value__ = value
4292
+ return value
4293
+ if owner is None:
4294
+ owner = getattr(forward_ref, "__owner__", None)
4295
+
4296
+ if (
4297
+ globals is None
4298
+ and getattr(forward_ref, "__forward_module__", None) is not None
4299
+ ):
4300
+ globals = getattr(
4301
+ sys.modules.get(forward_ref.__forward_module__, None), "__dict__", None
4302
+ )
4303
+ if globals is None:
4304
+ globals = getattr(forward_ref, "__globals__", None)
4305
+ if globals is None:
4306
+ if isinstance(owner, type):
4307
+ module_name = getattr(owner, "__module__", None)
4308
+ if module_name:
4309
+ module = sys.modules.get(module_name, None)
4310
+ if module:
4311
+ globals = getattr(module, "__dict__", None)
4312
+ elif isinstance(owner, _types.ModuleType):
4313
+ globals = getattr(owner, "__dict__", None)
4314
+ elif callable(owner):
4315
+ globals = getattr(owner, "__globals__", None)
4316
+
4317
+ # If we pass None to eval() below, the globals of this module are used.
4318
+ if globals is None:
4319
+ globals = {}
4320
+
4321
+ if locals is None:
4322
+ locals = {}
4323
+ if isinstance(owner, type):
4324
+ locals.update(vars(owner))
4325
+
4326
+ if type_params is None and owner is not None:
4327
+ # "Inject" type parameters into the local namespace
4328
+ # (unless they are shadowed by assignments *in* the local namespace),
4329
+ # as a way of emulating annotation scopes when calling `eval()`
4330
+ type_params = getattr(owner, "__type_params__", None)
4331
+
4332
+ # type parameters require some special handling,
4333
+ # as they exist in their own scope
4334
+ # but `eval()` does not have a dedicated parameter for that scope.
4335
+ # For classes, names in type parameter scopes should override
4336
+ # names in the global scope (which here are called `localns`!),
4337
+ # but should in turn be overridden by names in the class scope
4338
+ # (which here are called `globalns`!)
4339
+ if type_params is not None:
4340
+ globals = dict(globals)
4341
+ locals = dict(locals)
4342
+ for param in type_params:
4343
+ param_name = param.__name__
4344
+ if (
4345
+ _FORWARD_REF_HAS_CLASS and not forward_ref.__forward_is_class__
4346
+ ) or param_name not in globals:
4347
+ globals[param_name] = param
4348
+ locals.pop(param_name, None)
4349
+
4350
+ arg = forward_ref.__forward_arg__
4351
+ if arg.isidentifier() and not keyword.iskeyword(arg):
4352
+ if arg in locals:
4353
+ value = locals[arg]
4354
+ elif arg in globals:
4355
+ value = globals[arg]
4356
+ elif hasattr(builtins, arg):
4357
+ return getattr(builtins, arg)
4358
+ else:
4359
+ raise NameError(arg)
4360
+ else:
4361
+ code = forward_ref.__forward_code__
4362
+ value = eval(code, globals, locals)
4363
+ forward_ref.__forward_evaluated__ = True
4364
+ forward_ref.__forward_value__ = value
4365
+ return value
4366
+
4367
+ def _lax_type_check(
4368
+ value, msg, is_argument=True, *, module=None, allow_special_forms=False
4369
+ ):
4370
+ """
4371
+ A lax Python 3.11+ like version of typing._type_check
4372
+ """
4373
+ if hasattr(typing, "_type_convert"):
4374
+ if _FORWARD_REF_HAS_CLASS:
4375
+ type_ = typing._type_convert(
4376
+ value,
4377
+ module=module,
4378
+ allow_special_forms=allow_special_forms,
4379
+ )
4380
+ # module was added with bpo-41249 before is_class (bpo-46539)
4381
+ elif "__forward_module__" in typing.ForwardRef.__slots__:
4382
+ type_ = typing._type_convert(value, module=module)
4383
+ else:
4384
+ type_ = typing._type_convert(value)
4385
+ else:
4386
+ if value is None:
4387
+ return type(None)
4388
+ if isinstance(value, str):
4389
+ return ForwardRef(value)
4390
+ type_ = value
4391
+ invalid_generic_forms = (Generic, Protocol)
4392
+ if not allow_special_forms:
4393
+ invalid_generic_forms += (ClassVar,)
4394
+ if is_argument:
4395
+ invalid_generic_forms += (Final,)
4396
+ if (
4397
+ isinstance(type_, typing._GenericAlias)
4398
+ and get_origin(type_) in invalid_generic_forms
4399
+ ):
4400
+ raise TypeError(f"{type_} is not valid as type argument") from None
4401
+ if type_ in (Any, LiteralString, NoReturn, Never, Self, TypeAlias):
4402
+ return type_
4403
+ if allow_special_forms and type_ in (ClassVar, Final):
4404
+ return type_
4405
+ if (
4406
+ isinstance(type_, (_SpecialForm, typing._SpecialForm))
4407
+ or type_ in (Generic, Protocol)
4408
+ ):
4409
+ raise TypeError(f"Plain {type_} is not valid as type argument") from None
4410
+ if type(type_) is tuple: # lax version with tuple instead of callable
4411
+ raise TypeError(f"{msg} Got {type_!r:.100}.")
4412
+ return type_
4413
+
4414
+ def evaluate_forward_ref(
4415
+ forward_ref,
4416
+ *,
4417
+ owner=None,
4418
+ globals=None,
4419
+ locals=None,
4420
+ type_params=None,
4421
+ format=Format.VALUE,
4422
+ _recursive_guard=frozenset(),
4423
+ ):
4424
+ """Evaluate a forward reference as a type hint.
4425
+
4426
+ This is similar to calling the ForwardRef.evaluate() method,
4427
+ but unlike that method, evaluate_forward_ref() also:
4428
+
4429
+ * Recursively evaluates forward references nested within the type hint.
4430
+ * Rejects certain objects that are not valid type hints.
4431
+ * Replaces type hints that evaluate to None with types.NoneType.
4432
+ * Supports the *FORWARDREF* and *STRING* formats.
4433
+
4434
+ *forward_ref* must be an instance of ForwardRef. *owner*, if given,
4435
+ should be the object that holds the annotations that the forward reference
4436
+ derived from, such as a module, class object, or function. It is used to
4437
+ infer the namespaces to use for looking up names. *globals* and *locals*
4438
+ can also be explicitly given to provide the global and local namespaces.
4439
+ *type_params* is a tuple of type parameters that are in scope when
4440
+ evaluating the forward reference. This parameter must be provided (though
4441
+ it may be an empty tuple) if *owner* is not given and the forward reference
4442
+ does not already have an owner set. *format* specifies the format of the
4443
+ annotation and is a member of the annotationlib.Format enum.
4444
+
4445
+ """
4446
+ if format == Format.STRING:
4447
+ return forward_ref.__forward_arg__
4448
+ if forward_ref.__forward_arg__ in _recursive_guard:
4449
+ return forward_ref
4450
+
4451
+ # Evaluate the forward reference
4452
+ try:
4453
+ value = _eval_with_owner(
4454
+ forward_ref,
4455
+ owner=owner,
4456
+ globals=globals,
4457
+ locals=locals,
4458
+ type_params=type_params,
4459
+ )
4460
+ except NameError:
4461
+ if format == Format.FORWARDREF:
4462
+ return forward_ref
4463
+ else:
4464
+ raise
4465
+
4466
+ msg = "Forward references must evaluate to types."
4467
+ if not _FORWARD_REF_HAS_CLASS:
4468
+ allow_special_forms = not forward_ref.__forward_is_argument__
4469
+ else:
4470
+ allow_special_forms = forward_ref.__forward_is_class__
4471
+ type_ = _lax_type_check(
4472
+ value,
4473
+ msg,
4474
+ is_argument=forward_ref.__forward_is_argument__,
4475
+ allow_special_forms=allow_special_forms,
4476
+ )
4477
+
4478
+ # Recursively evaluate the type
4479
+ if isinstance(type_, ForwardRef):
4480
+ if getattr(type_, "__forward_module__", True) is not None:
4481
+ globals = None
4482
+ return evaluate_forward_ref(
4483
+ type_,
4484
+ globals=globals,
4485
+ locals=locals,
4486
+ type_params=type_params, owner=owner,
4487
+ _recursive_guard=_recursive_guard, format=format
4488
+ )
4489
+ if sys.version_info < (3, 12, 5) and type_params:
4490
+ # Make use of type_params
4491
+ locals = dict(locals) if locals else {}
4492
+ for tvar in type_params:
4493
+ if tvar.__name__ not in locals: # lets not overwrite something present
4494
+ locals[tvar.__name__] = tvar
4495
+ if sys.version_info < (3, 9):
4496
+ return typing._eval_type(
4497
+ type_,
4498
+ globals,
4499
+ locals,
4500
+ )
4501
+ if sys.version_info < (3, 12, 5):
4502
+ return typing._eval_type(
4503
+ type_,
4504
+ globals,
4505
+ locals,
4506
+ recursive_guard=_recursive_guard | {forward_ref.__forward_arg__},
4507
+ )
4508
+ if sys.version_info < (3, 14):
4509
+ return typing._eval_type(
4510
+ type_,
4511
+ globals,
4512
+ locals,
4513
+ type_params,
4514
+ recursive_guard=_recursive_guard | {forward_ref.__forward_arg__},
4515
+ )
4516
+ return typing._eval_type(
4517
+ type_,
4518
+ globals,
4519
+ locals,
4520
+ type_params,
4521
+ recursive_guard=_recursive_guard | {forward_ref.__forward_arg__},
4522
+ format=format,
4523
+ owner=owner,
4524
+ )
4525
+
4526
+
3602
4527
  # Aliases for items that have always been in typing.
3603
4528
  # Explicitly assign these (rather than using `from typing import *` at the top),
3604
4529
  # so that we get a CI error if one of these is deleted from typing.py