Repository navigation
get_type_hints exposes an instance of ForwardRef (internal class) in its result, with from __future__ import annotations enabled #80015
Description
Activity
LincolnQuirk commented
on Jan 26, 2019 LincolnQuirkmannequinMannequinAuthorMore actionsConsider this code:
from __future__ import annotations import typing class A: f: 'Undef' hints = typing.get_type_hints(A)Since Undef is not defined, I should get an exception when calling get_type_hints, something like "NameError: name 'Undef' is not defined". But instead, get_type_hints returns {'f': ForwardRef('Undef')}.
If I remove the
from __future__ import annotationsline, get_type_hints correctly raises this exception.I think the behavior should be to raise an exception in both cases.
- added3.7 (EOL)end of lifeend of life3.8 (EOL)end of lifeend of lifetype-bugAn unexpected behavior, bug, or errorAn unexpected behavior, bug, or error
on Jan 26, 2019 Since Undef is not defined, I should get an exception when calling get_type_hints
One of the motives of PEP-563 is to make it easier to use forward references. I'm not sure, but it seems to me that given that, we should not get an exception. So I think the only issue here is that the ForwardReference class is not documented, and should be.
But I admit I'm not confident about my understanding of PEP-563 so I could be wrong.
Wait, I just noticed that PEP-563 says:
"Note: if an annotation was a string literal already, it will still be wrapped in a string."
https://www.python.org/dev/peps/pep-0563/#id5
In 3.8.0a I get this:
py> from __future__ import annotations
py>
py> class A:
... f: 'Undef'
...
py> A.__annotations__
{'f': "'Undef'"}which matches what the PEP says. So I expect that when calling get_type_hints it should return the unquoted string, rather than a ForwardReference.
get_type_hints(A)
expected {'f': 'Undef'}
actually got {'f': ForwardRef('Undef')}It looks like an opposite side of python/typing#508 (I wanted to work on it, but never had time to, sorry).
This question appeared couple times before, and I think there are pros and cons for both returning a ForwardRef() and for raising a NameError. So as I proposed in the issue above, there should be a flag to
get_type_hints()that controls what to do (the name of the flag, and the default are of course debatable).Of course, we should try to make
get_type_hints()behave as much similar as possible with and without PEP-563, regardless. But my point is that currently we have this "in-between" behavior, and it is harder to maintain this "in-between" behavior against PEP-563, than two clearly defined extremes.So I expect that when calling get_type_hints it should return the unquoted string, rather than a ForwardReference.
I think the values in the returned dictionary should always be types, either fully evaluated, or ForwardRefs (expecting two options is easier than expecting three).
This seems to be fixed in 3.10, and may also be fixed in earlier versions:
C:\Users\alexw\coding>python Python 3.10.4 (tags/v3.10.4:9d38120, Mar 23 2022, 23:13:41) [MSC v.1929 64 bit (AMD64)] on win32 Type "help", "copyright", "credits" or "license" for more information. >>> from __future__ import annotations >>> import typing >>> class A: ... f: 'Undef' ... >>> typing.get_type_hints(A) Traceback (most recent call last): File "<stdin>", line 1, in <module> File "C:\Users\alexw\AppData\Local\Programs\Python\Python310\lib\typing.py", line 1832, in get_type_hints value = _eval_type(value, base_globals, base_locals) File "C:\Users\alexw\AppData\Local\Programs\Python\Python310\lib\typing.py", line 327, in _eval_type return t._evaluate(globalns, localns, recursive_guard) File "C:\Users\alexw\AppData\Local\Programs\Python\Python310\lib\typing.py", line 699, in _evaluate self.__forward_value__ = _eval_type( File "C:\Users\alexw\AppData\Local\Programs\Python\Python310\lib\typing.py", line 327, in _eval_type return t._evaluate(globalns, localns, recursive_guard) File "C:\Users\alexw\AppData\Local\Programs\Python\Python310\lib\typing.py", line 694, in _evaluate eval(self.__forward_code__, globalns, localns), File "<string>", line 1, in <module> NameError: name 'Undef' is not defined
Cc. @LincolnQuirk
Note: these values reflect the state of the issue at the time it was migrated and might not reflect the current state.
Show more details
GitHub fields:
bugs.python.org fields: