mirror of
https://github.com/python/cpython.git
synced 2025-12-03 08:04:34 +00:00
gh-137226: Fix behavior of ForwardRef.evaluate with type_params (#137227)
The previous behavior was copied from earlier typing code. It works around the way typing.get_type_hints passes its namespaces, but I don't think the behavior is logical or correct.
This commit is contained in:
parent
70730ad041
commit
089a324a42
4 changed files with 47 additions and 14 deletions
|
|
@ -2366,10 +2366,13 @@ def get_type_hints(obj, globalns=None, localns=None, include_extras=False,
|
|||
# *base_globals* first rather than *base_locals*.
|
||||
# This only affects ForwardRefs.
|
||||
base_globals, base_locals = base_locals, base_globals
|
||||
type_params = base.__type_params__
|
||||
base_globals, base_locals = _add_type_params_to_scope(
|
||||
type_params, base_globals, base_locals, True)
|
||||
for name, value in ann.items():
|
||||
if isinstance(value, str):
|
||||
value = _make_forward_ref(value, is_argument=False, is_class=True)
|
||||
value = _eval_type(value, base_globals, base_locals, base.__type_params__,
|
||||
value = _eval_type(value, base_globals, base_locals, (),
|
||||
format=format, owner=obj)
|
||||
if value is None:
|
||||
value = type(None)
|
||||
|
|
@ -2405,6 +2408,7 @@ def get_type_hints(obj, globalns=None, localns=None, include_extras=False,
|
|||
elif localns is None:
|
||||
localns = globalns
|
||||
type_params = getattr(obj, "__type_params__", ())
|
||||
globalns, localns = _add_type_params_to_scope(type_params, globalns, localns, False)
|
||||
for name, value in hints.items():
|
||||
if isinstance(value, str):
|
||||
# class-level forward refs were handled above, this must be either
|
||||
|
|
@ -2414,13 +2418,27 @@ def get_type_hints(obj, globalns=None, localns=None, include_extras=False,
|
|||
is_argument=not isinstance(obj, types.ModuleType),
|
||||
is_class=False,
|
||||
)
|
||||
value = _eval_type(value, globalns, localns, type_params, format=format, owner=obj)
|
||||
value = _eval_type(value, globalns, localns, (), format=format, owner=obj)
|
||||
if value is None:
|
||||
value = type(None)
|
||||
hints[name] = value
|
||||
return hints if include_extras else {k: _strip_annotations(t) for k, t in hints.items()}
|
||||
|
||||
|
||||
# Add type parameters to the globals and locals scope. This is needed for
|
||||
# compatibility.
|
||||
def _add_type_params_to_scope(type_params, globalns, localns, is_class):
|
||||
if not type_params:
|
||||
return globalns, localns
|
||||
globalns = dict(globalns)
|
||||
localns = dict(localns)
|
||||
for param in type_params:
|
||||
if not is_class or param.__name__ not in globalns:
|
||||
globalns[param.__name__] = param
|
||||
localns.pop(param.__name__, None)
|
||||
return globalns, localns
|
||||
|
||||
|
||||
def _strip_annotations(t):
|
||||
"""Strip the annotations from a given type."""
|
||||
if isinstance(t, _AnnotatedAlias):
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue