[issue41370] PEP 585 and ForwardRef
Niklas Rosenstein
report at bugs.python.org
Tue Jan 25 17:07:42 EST 2022
Niklas Rosenstein <rosensteinniklas at gmail.com> added the comment:
Interesting! Representing the entire type hint as a string is something I haven't thought about, but it makes sense that it works.
It is my understanding that `get_type_hint()` already walks through the entire type hint recursively. If it weren't, it would not resolve `List['N']` to `List[__main__.N]` in the example below.
>>> from typing import get_type_hints, Mapping, List
>>>
>>> class N:
... a: Mapping['str', list[List['N']]]
...
>>> get_type_hints(N)
{'a': typing.Mapping[str, list[typing.List[__main__.N]]]}
Upon closer inspection of the `typing` code, I can see that `_eval_type()` is doing that recursion. Applying the change your proposed in your previous message to that function seems to work at least in a trivial test case.
diff --git a/Lib/typing.py b/Lib/typing.py
index e3e098b1fc..ac56b545b4 100644
--- a/Lib/typing.py
+++ b/Lib/typing.py
@@ -331,6 +331,12 @@ def _eval_type(t, globalns, localns, recursive_guard=frozenset()):
if isinstance(t, ForwardRef):
return t._evaluate(globalns, localns, recursive_guard)
if isinstance(t, (_GenericAlias, GenericAlias, types.UnionType)):
+ if isinstance(t, GenericAlias):
+ args = tuple(
+ ForwardRef(arg) if isinstance(arg, str) else arg
+ for arg in t.__args__
+ )
+ t = t.__origin__[(*args,)]
ev_args = tuple(_eval_type(a, globalns, localns, recursive_guard) for a in t.__args__)
if ev_args == t.__args__:
return t
Testcase:
>>> from typing import get_type_hints, Mapping, List
>>> class N:
... a: Mapping['str', List[list['N']]]
...
>>> get_type_hints(N)
{'a': typing.Mapping[str, typing.List[list[__main__.N]]]}
I believe that this would be enough, but then again I haven't yet had enough time to crack at other implications this might have.
> How will it interact with from __future__ import annotations?
I've never used this future, but from my current, possibly limited, understanding it should have no side effects on how `get_type_hints()` will evaluate fully stringified annotations (as you have already shown, a fully stringified type hint actually works fine with PEP 585 generics).
> And can we sell this as a bugfix for 3.10, or will this be a new feature in 3.11?
I will throw in my personal opinion that this could be a bugfix, but I'm obviously biased as being on the "experiencing end" of this behaviour we're trying to change.
----------
_______________________________________
Python tracker <report at bugs.python.org>
<https://bugs.python.org/issue41370>
_______________________________________
More information about the Python-bugs-list
mailing list