Skip to content

gh-148680: Replace internal names with type_reprs of objects in string representations of ForwardRef#148682

Merged
JelleZijlstra merged 11 commits intopython:mainfrom
DavidCEllis:fix-forwardref-string-names
Apr 23, 2026
Merged

gh-148680: Replace internal names with type_reprs of objects in string representations of ForwardRef#148682
JelleZijlstra merged 11 commits intopython:mainfrom
DavidCEllis:fix-forwardref-string-names

Conversation

@DavidCEllis
Copy link
Copy Markdown
Contributor

@DavidCEllis DavidCEllis commented Apr 17, 2026

This adds a new ForwardRef.__resolved_forward_str__ attribute which takes the __forward_arg__ and replaces any internal __annotationlib_name_x__ names with the type_repr of the object they represent.

Before:

ForwardRef('ref | __annotationlib_name_1__', is_class=True, owner=<class '__main__.Example'>)
ref | __annotationlib_name_1__

After:

ForwardRef('ref | str', is_class=True, owner=<class '__main__.Example'>)
ref | str

This approach replaces the extra_names with their type_repr when the forwardref is evaluated to a string. I'm fairly sure that trying to get the original names as they are in the source would be both slower and significantly more complicated.

This logic is largely based on something I already have for my reannotate library.

Comment thread Lib/test/test_annotationlib.py
Comment thread Lib/annotationlib.py
resolved_str = type_repr(name_obj)
else:
visitor = _ExtraNameFixer(names)
ast_expr = ast.parse(resolved_str, mode="eval").body
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

We might need to cache this, it's probably pretty slow. What do you think?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

This is in fact, not very fast. Definitely worth caching if it's going to be accessed frequently.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

>>> a_anno
ForwardRef('unknown | str | int | list[str] | tuple[int, ...]', is_class=True, owner=<class '__main__.Example'>)
>>> b_anno
ForwardRef('unknown', is_class=True, owner=<class '__main__.Example'>)

>>> a = timeit(lambda: a_anno.__resolved_forward_str__, number=10_000)
>>> b = timeit(lambda: b_anno.__resolved_forward_str__, number=10_000)
>>> a
0.18359258100008446
>>> b
0.0018204959997092374
>>> a / b
100.8475607907994

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I've added a cache and ended up shortening the name of the property and the cache. Adding the cache did mean adding an extra slot to both classes.

Not completely sold on the names I have if you have something better.

Comment thread Lib/annotationlib.py Outdated
Comment thread Lib/annotationlib.py Outdated
Copy link
Copy Markdown
Member

@JelleZijlstra JelleZijlstra left a comment

Choose a reason for hiding this comment

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

Looks good, but could you add a NEWS entry?

We'll also have to decide whether to backport to 3.14. I'm leaning towards yes, because the old behavior seems genuinely buggy.

@JelleZijlstra JelleZijlstra added the needs backport to 3.14 bugs and security fixes label Apr 23, 2026
@JelleZijlstra JelleZijlstra merged commit 158dbbb into python:main Apr 23, 2026
53 checks passed
@miss-islington-app
Copy link
Copy Markdown

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

@bedevere-app
Copy link
Copy Markdown

bedevere-app Bot commented Apr 23, 2026

GH-148913 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 Apr 23, 2026
JelleZijlstra pushed a commit that referenced this pull request Apr 23, 2026
…n string representations of ForwardRef (GH-148682) (#148913)

(cherry picked from commit 158dbbb)

Co-authored-by: David Ellis <ducksual@gmail.com>
Co-authored-by: Shamil <ashm.tech@proton.me>
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.

3 participants