You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
get_type_hints exposes an instance of ForwardRef (internal class) in its result, with from __future__ import annotations enabled #80015
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:
assignee=Noneclosed_at=Nonecreated_at=<Date2019-01-26.17:00:18.126>labels= ['3.8', 'type-bug', '3.7']
title='get_type_hints exposes an instance of ForwardRef (internal class) in its result, with `from __future__ import annotations` enabled'updated_at=<Date2019-01-27.10:31:35.689>user='https://bugs.python.org/LincolnQuirk'
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 annotations line, get_type_hints correctly raises this exception.
I think the behavior should be to raise an exception in both cases.
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.
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).
Activity
LincolnQuirk commentedon Jan 26, 2019
Consider this code:
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.
stevendaprano commentedon Jan 26, 2019
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.
stevendaprano commentedon Jan 26, 2019
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.
expected {'f': 'Undef'}
actually got {'f': ForwardRef('Undef')}
ilevkivskyi commentedon Jan 27, 2019
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.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).
AlexWaygood commentedon Apr 14, 2022
This seems to be fixed in 3.10, and may also be fixed in earlier versions:
Cc. @LincolnQuirk