Skip to content

Conversation

@JelleZijlstra
Copy link
Member

@JelleZijlstra JelleZijlstra commented Sep 15, 2025

This issue appears specifically for TypedDicts because the TypedDict constructor
code converts string annotations to ForwardRef objects, and those are not evaluated
properly by the get_type_hints() stack because of other shenanigans with type
parameters.

This issue does not affect normal generic classes because their annotations are not
pre-converted to ForwardRefs.

The fix attempts to restore the pre- #137227 behavior in the narrow scenario where
the issue manifests. It mostly makes changes only in the paths accessible from get_type_hints(),
ensuring that newer APIs (such as evaluate_forward_ref() and annotationlib) are not affected
by get_type_hints()'s past odd choices. This PR does not fix issue #138949, an older issue I
discovered while playing around with this one; we'll need a separate and perhaps more
invasive fix for that, but it should wait until after 3.14.0.

…gified annotations

This issue appears specifically for TypedDicts because the TypedDict constructor
code converts string annotations to ForwardRef objects, and those are not evaluated
properly by the get_type_hints() stack because of other shenanigans with type
parameters.

This issue does not affect normal generic classes because their annotations are not
pre-converted to ForwardRefs.

The fix attempts to restore the pre- python#137227 behavior in the narrow scenario where
the issue manifests. It mostly makes changes only in the paths accessible from get_type_hints(),
ensuring that newer APIs (such as evaluate_forward_ref() and annotationlib) are not affected
by get_type_hints()'s past odd choices. This PR does not fix python#138949, an older issue I
discovered while playing around with this one; we'll need a separate and perhaps more
invasive fix for that, but it should wait until after 3.14.0.
bswck

This comment was marked as resolved.

@hugovk

This comment was marked as resolved.

Copy link
Member

@AlexWaygood AlexWaygood left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM. Some small nits/questions but nothing blocking; can always merge this and address this later if @hugovk wants it in ASAP!


def _eval_type(t, globalns, localns, type_params, *, recursive_guard=frozenset(),
format=None, owner=None, parent_fwdref=None):
format=None, owner=None, parent_fwdref=None, prefer_fwd_module=False):
Copy link
Member

@AlexWaygood AlexWaygood Sep 16, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could we add a description of this parameter to the docstring?

Should this default to True? Third-party users of this function may be expecting the legacy get_type_hints behaviour? They're obviously asking for breakage if they're using an undocumented, private implementation detail though. So I don't have a strong opinion here.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the False behavior is more sensible so I want to default to it. I know this function gets used in the wild and we shouldn't go out of our way to break such uses, but at the end of the day it's a private function.

@AlexWaygood AlexWaygood added the needs backport to 3.14 bugs and security fixes label Sep 16, 2025
@JelleZijlstra JelleZijlstra merged commit 6d6aba2 into python:main Sep 16, 2025
51 checks passed
@miss-islington-app
Copy link

Thanks @JelleZijlstra for the PR 🌮🎉.. I'm working now to backport this PR to: 3.14.
🐍🍒⛏🤖

@miss-islington-app
Copy link

Sorry, @JelleZijlstra, I could not cleanly backport this to 3.14 due to a conflict.
Please backport using cherry_picker on command line.

cherry_picker 6d6aba252301cdf9d5ae3189629e1e43101dd58f 3.14

@JelleZijlstra JelleZijlstra deleted the generictd branch September 16, 2025 14:28
JelleZijlstra added a commit to JelleZijlstra/cpython that referenced this pull request Sep 16, 2025
…h stringified annotations (pythonGH-138953)

This issue appears specifically for TypedDicts because the TypedDict constructor
code converts string annotations to ForwardRef objects, and those are not evaluated
properly by the get_type_hints() stack because of other shenanigans with type
parameters.

This issue does not affect normal generic classes because their annotations are not
pre-converted to ForwardRefs.

The fix attempts to restore the pre- pythonGH-137227 behavior in the narrow scenario where
the issue manifests. It mostly makes changes only in the paths accessible from get_type_hints(),
ensuring that newer APIs (such as evaluate_forward_ref() and annotationlib) are not affected
by get_type_hints()'s past odd choices. This PR does not fix issue pythonGH-138949, an older issue I
discovered while playing around with this one; we'll need a separate and perhaps more
invasive fix for that, but it should wait until after 3.14.0.
(cherry picked from commit 6d6aba2)

Co-authored-by: Jelle Zijlstra <[email protected]>
@bedevere-app
Copy link

bedevere-app bot commented Sep 16, 2025

GH-138989 is a backport of this pull request to the 3.14 branch.

@bedevere-app bedevere-app bot removed the needs backport to 3.14 bugs and security fixes label Sep 16, 2025
hugovk pushed a commit that referenced this pull request Sep 17, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants