Skip to content

gh-125618: Make FORWARDREF format succeed more often - #132818

Merged
JelleZijlstra merged 11 commits into
python:mainfrom
JelleZijlstra:fwdref-format
May 4, 2025
Merged

gh-125618: Make FORWARDREF format succeed more often#132818
JelleZijlstra merged 11 commits into
python:mainfrom
JelleZijlstra:fwdref-format

Conversation

@JelleZijlstra

@JelleZijlstraJelleZijlstra commented Apr 22, 2025

Copy link
Copy Markdown
Member

@DavidCEllis

Copy link
Copy Markdown
Contributor

Looks like this works in the case where the object is defined globally, but this still manages to fail if the object used in the annotation is defined (or even potentially redefined) within the function.

Repro:

fromannotationlibimportget_annotations, Formatdefboom():
obj=object()
classRaisesAttributeError:
attriberr: obj.missingget_annotations(RaisesAttributeError, format=Format.FORWARDREF)
boom()

Output:

Traceback (mostrecentcalllast):
File"C:\Users\ducks\Source\cpython\.cache\annotation_examine.py", line9, in<module>boom()
~~~~^^File"C:\Users\ducks\Source\cpython\.cache\annotation_examine.py", line7, inboomget_annotations(RaisesAttributeError, format=Format.FORWARDREF)
~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^File"C:\Users\ducks\Source\cpython\Lib\annotationlib.py", line778, inget_annotationsann=_get_and_call_annotate(obj, format)
File"C:\Users\ducks\Source\cpython\Lib\annotationlib.py", line902, in_get_and_call_annotateann=call_annotate_function(annotate, format, owner=obj)
File"C:\Users\ducks\Source\cpython\Lib\annotationlib.py", line629, incall_annotate_functionresult=func(Format.VALUE_WITH_FAKE_GLOBALS)
File"C:\Users\ducks\Source\cpython\.cache\annotation_examine.py", line6, in__annotate__attriberr: obj.missing^^^^^^^^^^^File"C:\Users\ducks\Source\cpython\Lib\annotationlib.py", line380, in__getattr__returnself.__make_new(ast.Attribute(self.__get_ast(), attr))
~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^File"C:\Users\ducks\Source\cpython\Lib\annotationlib.py", line358, in__make_newself.__stringifier_dict__.stringifiers.append(stringifier)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^AttributeError: 'builtin_function_or_method'objecthasnoattribute'stringifiers'

This came up because this is how I'd written my test case for this (writing the test case was actually as far as I'd gone, because the first test case raised the other issue).

deftest_attributeerror_handled(self):
classMissingAttrib:
passclassRaisesAttributeError:
attriberr: MissingAttrib.missingwithself.assertRaises(AttributeError):
get_annotations(RaisesAttributeError, format=Format.VALUE)
self.assertEqual(
get_annotations(RaisesAttributeError, format=Format.FORWARDREF),
{
"attriberr": support.EqualToForwardRef(
"MissingAttrib.missing", owner=RaisesAttributeError,
is_class=True,
)
}
)
self.assertEqual(
get_annotations(RaisesAttributeError, format=Format.STRING),
{"attriberr": "MissingAttrib.missing"}
)

@JelleZijlstra

Copy link
Copy Markdown
MemberAuthor

Thanks! This was a silly bug that also broke test_pydoc, I will add your case as a test case so we catch this.

@JelleZijlstra
JelleZijlstra merged commit af5799f into python:mainMay 4, 2025
@JelleZijlstra
JelleZijlstra deleted the fwdref-format branch May 4, 2025 22:22
diegorusso added a commit to diegorusso/cpython that referenced this pull request May 4, 2025
* origin/main:
pythongh-125618: Make FORWARDREF format succeed more often (python#132818)
Pranjal095 pushed a commit to Pranjal095/cpython that referenced this pull request Jul 12, 2025
Sign up for freeto 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.14] annotationlib - get_annotations returns an empty annotations dict if an AttributeError is raised when __annotations__ is accessed

2 participants

@JelleZijlstra@DavidCEllis