-
-
Notifications
You must be signed in to change notification settings - Fork 31.9k
bpo-41341: Recursive evaluation of ForwardRef in get_type_hints #21553
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
bpo-41341: Recursive evaluation of ForwardRef in get_type_hints #21553
Conversation
The issue raised by recursive evaluation is infinite recursion with recursive types. In that case, only the first recursive ForwardRef is evaluated.
This comment has been minimized.
This comment has been minimized.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@isidentical This might help moving https://bugs.python.org/issue38605 forward (make from __future__ import annotations
the default).
@ambv Assuming we get this to work, what would you think of backporting it to 3.9, even though beta5 is already released? On the one hand it's awfully late for such a change (and experience with the bpo issue above suggests it's not painful). On the other hand getting the same behavior for forward refs in 3.9 with from __future__ import annotations
as it will have in 3.10 (regardless of that import) seems useful.
@@ -2456,6 +2456,12 @@ def foo(a: tuple[ForwardRef('T')]): | |||
self.assertEqual(get_type_hints(foo, globals(), locals()), | |||
{'a': tuple[T]}) | |||
|
|||
def test_double_forward(self): | |||
def foo(a: 'List[\'int\']'): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I was about to approve this PR when I realized that we should make this work with list
-- I tried and it doesn't currently.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You're right concerning the fact that it doesn't work with list
, but I've found that it's not related to this PR; actually, I think there is a significant defect in current PEP 585 implementation. In fact:
from dataclasses import dataclass, field
from typing import get_type_hints, List, ForwardRef
@dataclass
class Node:
children: list["Node"] = field(default_factory=list)
children2: List["Node"] = field(default_factory=list)
assert get_type_hints(Node) == {"children": list["Node"], "children2": List[Node]}
assert List["Node"].__args__ == (ForwardRef("Node"),)
assert list["Node"].__args__ == ("Node",) # No ForwardRef here, so no evaluation by get_type_hints
I will open an issue on bugs.python.org to discuss about this, because I think this PR is not the best place to do it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Heh, you're right, thanks for the analysis. We probably will not ever support this: importing ForwardRef
from the built-in generic alias code would be problematic, and once from __future__ import annotations
is always on there's no need to quote the argument anyway. Sorry for the hiccup. I will now approve your PR.
I had my own implementations, but I think I am going to rebase because it was kind of a workaround. |
@gvanrossum: Please replace |
@ambv @pablogsal can I please have a decision on whether to backport this to 3.9? See my previous comment. |
I think it makes sense, but being this |
Thanks @wyfo for the PR, and @gvanrossum for merging it 🌮🎉.. I'm working now to backport this PR to: 3.9. |
…onGH-21553) The issue raised by recursive evaluation is infinite recursion with recursive types. In that case, only the first recursive ForwardRef is evaluated. (cherry picked from commit 653f420) Co-authored-by: wyfo <[email protected]>
GH-21629 is a backport of this pull request to the 3.9 branch. |
…1553) The issue raised by recursive evaluation is infinite recursion with recursive types. In that case, only the first recursive ForwardRef is evaluated. (cherry picked from commit 653f420) Co-authored-by: wyfo <[email protected]>
…on#21553) The issue raised by recursive evaluation is infinite recursion with recursive types. In that case, only the first recursive ForwardRef is evaluated.
…on#21553) The issue raised by recursive evaluation is infinite recursion with recursive types. In that case, only the first recursive ForwardRef is evaluated.
…on#21553) The issue raised by recursive evaluation is infinite recursion with recursive types. In that case, only the first recursive ForwardRef is evaluated.
…f or str Related: python/cpython#21553 (comment) Signed-off-by: John Andersen <[email protected]>
…f or str Related: python/cpython#21553 (comment) Signed-off-by: John Andersen <[email protected]>
…f or str Related: python/cpython#21553 (comment) Signed-off-by: John Andersen <[email protected]>
…f or str Related: python/cpython#21553 (comment) Signed-off-by: John Andersen <[email protected]>
…f or str Related: python/cpython#21553 (comment) Signed-off-by: John Andersen <[email protected]>
recursive_guard argument was added in python/cpython#21553
…f or str Related: python/cpython#21553 (comment) Signed-off-by: John Andersen <[email protected]>
The issue raised by recursive evaluation is infinite recursion with
recursive types. In that case, only the first recursive ForwardRef is
evaluated.
https://bugs.python.org/issue41341