-
-
Notifications
You must be signed in to change notification settings - Fork 33.2k
Description
Bug report
Bug description:
The documentation for annotate functions only requires that they implement format.VALUE.
However if a user created annotate function does not implement the other formats, it will likely behave badly when accessed through call_annotate_function using STRING or FORWARDREF formats.
Example:
from annotationlib import call_annotate_function, Format
def annotate(format, /):
if format == Format.VALUE:
print("pass")
return {}
else:
print("fail")
raise NotImplementedError(format)
call_annotate_function(annotate, Format.STRING)Output:
fail
{}The "fail" is expected, as annotate(Format.STRING) is called first and is clearly not supported.
The empty dictionary is returned because annotate(Format.VALUE_WITH_FAKE_GLOBALS) is called, but in a fake globals context where the globals namespace is empty. Format.VALUE in this context becomes a _Stringifier, so format == Format.VALUE becomes a _Stringifier which evaluates to True. print is also a _Stringifier which is why "pass" is never printed.
Note that if you change the condition to check format == Format.VALUE_WITH_FAKE_GLOBALS first, the condition will pass (for the wrong reason) but the function will fail with a TypeError instead, because NotImplementedError is also a _Stringifier and exceptions must derive from BaseException.
Format.FORWARDREF should probably check for NotImplementedError on the first call where globals do exist and reraise in that case, I don't see a way of handling Format.STRING without an extra check before it calls the function in the fake globals environment.
CPython versions tested on:
3.14, CPython main branch
Operating systems tested on:
No response
Linked PRs
- gh-138764: annotationlib - Check if the
VALUE_WITH_FAKE_GLOBALSformat is implemented before calling an__annotate__function with empty fake globals #138788 - gh-138764: annotationlib - Make
call_annotate_functionfallback to usingVALUEannotations if both the requested format andVALUE_WITH_FAKE_GLOBALSare not implemented #138803 - [3.14] gh-138764: annotationlib: Make
call_annotate_functionfallback to usingVALUEannotations if both the requested format andVALUE_WITH_FAKE_GLOBALSare not implemented (GH-138803) #140426