Skip to content

Conversation

@JelleZijlstra
Copy link
Member

@JelleZijlstraJelleZijlstra commented Apr 22, 2025

@DavidCEllis
Copy link
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
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.

@JelleZijlstraJelleZijlstra merged commit af5799f into python:mainMay 4, 2025
39 checks passed
@JelleZijlstraJelleZijlstra 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