Bug report
Bug description:
This can happen internally in get_annotations and means subsequent attempts to evaluate it will fail even if the names have since been defined.
Underlying logic:
fromannotationlibimportget_annotations, FormatclassDemo:
x: Sequence[undefined]
annos=get_annotations(Demo, format=Format.FORWARDREF)
x_anno=annos['x']
# Try to evaluate the reference, but just give a forwardref if it failsx_repeat_anno=x_anno.evaluate(format=Format.FORWARDREF)
# The resulting reference no longer shares the globals namespace with the annotate functionprint(f"{x_anno.__globals__isDemo.__annotate__.__globals__=}") # Trueprint(f"{x_repeat_anno.__globals__isDemo.__annotate__.__globals__=}") # False# Define the previously undefined attributesfromcollections.abcimportSequenceundefined=str# This means evaluation fails in the second caseprint(f"{x_anno.evaluate() =}") # collections.abc.Sequence[str]print(f"{x_repeat_anno.evaluate() =}") # NameErrorThis evaluate call happens internally if get_annotations has to rely on the fallback behaviour for an unexpected exception, such as an AttributeError:
fromannotationlibimportget_annotations, FormatimporttypingclassWorks:
a: Sequence[undefined]
b: unknowable# Intentionally set up an annotation that will raise AttributeError on evaluationclassFails:
a: Sequence[undefined]
b: typing.doesnotexista_works=get_annotations(Works, format=Format.FORWARDREF)['a']
a_fails=get_annotations(Fails, format=Format.FORWARDREF)['a']
# Realise the referencesfromcollections.abcimportSequenceundefined=strprint(f"{a_works.evaluate() =}") # collections.abc.Sequence[str]print(f"{a_fails.evaluate() =}") # NameErrorThis appears to be caused by the creation of a new globals dict here:
| iftype_paramsisnotNone: |
| globals=dict(globals) |
| forparamintype_params: |
| globals[param.__name__] =param |
Commenting this out makes these examples succeed, but obviously breaks type parameters.
CPython versions tested on:
CPython main branch, 3.14
Operating systems tested on:
No response
Linked PRs
Bug report
Bug description:
This can happen internally in
get_annotationsand means subsequent attempts to evaluate it will fail even if the names have since been defined.Underlying logic:
This
evaluatecall happens internally ifget_annotationshas to rely on the fallback behaviour for an unexpected exception, such as anAttributeError:This appears to be caused by the creation of a new globals dict here:
cpython/Lib/annotationlib.py
Lines 164 to 167 in e39255e
Commenting this out makes these examples succeed, but obviously breaks type parameters.
CPython versions tested on:
CPython main branch, 3.14
Operating systems tested on:
No response
Linked PRs
ref.evaluate(format=Format.FORWARDREF)objects #138075ref.evaluate(format=Format.FORWARDREF)objects (GH-138075) #140929ref.evaluate(format=Format.FORWARDREF)objects (#138075)" #140930ref.evaluate(format=Format.FORWARDREF)objects (GH-138075) (#140929)" #140931ForwardRefs which rely on globals #140974ForwardRefs which rely on globals (GH-140974) #141527