Skip to content

annotationlib - call_annotate_function should check VALUE_WITH_FAKE_GLOBALS is implemented before calling in a namespace with empty fake globals #138764

Description

@DavidCEllis

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

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    stdlibStandard Library Python modules in the Lib/ directorytopic-typingtype-bugAn unexpected behavior, bug, or error

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions