aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/Lib/typing.py
diff options
context:
space:
mode:
Diffstat (limited to 'Lib/typing.py')
-rw-r--r--Lib/typing.py50
1 files changed, 29 insertions, 21 deletions
diff --git a/Lib/typing.py b/Lib/typing.py
index ed1dd4fc641..f1455c273d3 100644
--- a/Lib/typing.py
+++ b/Lib/typing.py
@@ -407,6 +407,17 @@ def _tp_cache(func=None, /, *, typed=False):
return decorator
+def _rebuild_generic_alias(alias: GenericAlias, args: tuple[object, ...]) -> GenericAlias:
+ is_unpacked = alias.__unpacked__
+ if _should_unflatten_callable_args(alias, args):
+ t = alias.__origin__[(args[:-1], args[-1])]
+ else:
+ t = alias.__origin__[args]
+ if is_unpacked:
+ t = Unpack[t]
+ return t
+
+
def _deprecation_warning_for_no_type_params_passed(funcname: str) -> None:
import warnings
@@ -426,20 +437,14 @@ class _Sentinel:
return '<sentinel>'
-_sentinel = _Sentinel()
-
-
-def _eval_type(t, globalns, localns, type_params=_sentinel, *, recursive_guard=frozenset(),
- format=None, owner=None):
+def _eval_type(t, globalns, localns, type_params, *, recursive_guard=frozenset(),
+ format=None, owner=None, parent_fwdref=None):
"""Evaluate all forward references in the given type t.
For use of globalns and localns see the docstring for get_type_hints().
recursive_guard is used to prevent infinite recursion with a recursive
ForwardRef.
"""
- if type_params is _sentinel:
- _deprecation_warning_for_no_type_params_passed("typing._eval_type")
- type_params = ()
if isinstance(t, _lazy_annotationlib.ForwardRef):
# 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.
@@ -451,28 +456,23 @@ def _eval_type(t, globalns, localns, type_params=_sentinel, *, recursive_guard=f
if isinstance(t, (_GenericAlias, GenericAlias, Union)):
if isinstance(t, GenericAlias):
args = tuple(
- _make_forward_ref(arg) if isinstance(arg, str) else arg
+ _make_forward_ref(arg, parent_fwdref=parent_fwdref) if isinstance(arg, str) else arg
for arg in t.__args__
)
- is_unpacked = t.__unpacked__
- if _should_unflatten_callable_args(t, args):
- t = t.__origin__[(args[:-1], args[-1])]
- else:
- t = t.__origin__[args]
- if is_unpacked:
- t = Unpack[t]
+ else:
+ args = t.__args__
ev_args = tuple(
_eval_type(
a, globalns, localns, type_params, recursive_guard=recursive_guard,
format=format, owner=owner,
)
- for a in t.__args__
+ for a in args
)
if ev_args == t.__args__:
return t
if isinstance(t, GenericAlias):
- return GenericAlias(t.__origin__, ev_args)
+ return _rebuild_generic_alias(t, ev_args)
if isinstance(t, Union):
return functools.reduce(operator.or_, ev_args)
else:
@@ -936,7 +936,12 @@ def TypeIs(self, parameters):
return _GenericAlias(self, (item,))
-def _make_forward_ref(code, **kwargs):
+def _make_forward_ref(code, *, parent_fwdref=None, **kwargs):
+ if parent_fwdref is not None:
+ if parent_fwdref.__forward_module__ is not None:
+ kwargs['module'] = parent_fwdref.__forward_module__
+ if parent_fwdref.__owner__ is not None:
+ kwargs['owner'] = parent_fwdref.__owner__
forward_ref = _lazy_annotationlib.ForwardRef(code, **kwargs)
# For compatibility, eagerly compile the forwardref's code.
forward_ref.__forward_code__
@@ -1001,6 +1006,7 @@ def evaluate_forward_ref(
recursive_guard=_recursive_guard | {forward_ref.__forward_arg__},
format=format,
owner=owner,
+ parent_fwdref=forward_ref,
)
@@ -1860,7 +1866,9 @@ def _allow_reckless_class_checks(depth=2):
The abc and functools modules indiscriminately call isinstance() and
issubclass() on the whole MRO of a user class, which may contain protocols.
"""
- return _caller(depth) in {'abc', 'functools', None}
+ # gh-136047: When `_abc` module is not available, `_py_abc` is required to
+ # allow `_py_abc.ABCMeta` fallback.
+ return _caller(depth) in {'abc', '_py_abc', 'functools', None}
_PROTO_ALLOWLIST = {
@@ -2404,7 +2412,7 @@ def _strip_annotations(t):
stripped_args = tuple(_strip_annotations(a) for a in t.__args__)
if stripped_args == t.__args__:
return t
- return GenericAlias(t.__origin__, stripped_args)
+ return _rebuild_generic_alias(t, stripped_args)
if isinstance(t, Union):
stripped_args = tuple(_strip_annotations(a) for a in t.__args__)
if stripped_args == t.__args__: