Skip to content

__annotate__ does not get called if __annotations__ exist#122285

@sobolevn

Description

@sobolevn

This code:

classA: x: inty: strdef__annotate__(format): return{'a': bool} importannotationlibprint(A.__annotations__) print(annotationlib.get_annotations(A, format=annotationlib.Format.VALUE)) print(annotationlib.get_annotations(A, format=annotationlib.Format.FORWARDREF)) print(annotationlib.get_annotations(A, format=annotationlib.Format.SOURCE))

Produces:

{'x': <class 'int'>, 'y': <class 'str'>}{'x': <class 'int'>, 'y': <class 'str'>}{'x': <class 'int'>, 'y': <class 'str'>}{'x': 'int', 'y': 'str'} 

PEP 649 specifies this as: https://peps.python.org/pep-0649/#annotate-and-annotations

When o.__annotations__ is evaluated, and the internal storage for o.__annotations__ is unset, and o.__annotate__ is set to a callable, the getter for o.__annotations__ calls o.__annotate__(1), then caches the result in its internal storage and returns the result. To explicitly clarify one question that has come up multiple times: this o.__annotations__ cache is the only caching mechanism defined in this PEP. There are no other caching mechanisms defined in this PEP. The __annotate__ functions generated by the Python compiler explicitly don’t cache any of the values they compute. 

Comment them out:

classA: # x: int# y: strdef__annotate__(format): return{'a': bool} importannotationlibprint(A.__annotations__) print(annotationlib.get_annotations(A, format=annotationlib.Format.VALUE)) print(annotationlib.get_annotations(A, format=annotationlib.Format.FORWARDREF)) print(annotationlib.get_annotations(A, format=annotationlib.Format.SOURCE))

Produces:

{'a':<class'bool'>}{'a':<class'bool'>}{'a':<class'bool'>}{'a':<class'bool'>}

Let's discuss this.

Metadata

Metadata

Assignees

Labels

3.14bugs and security fixestype-bugAn unexpected behavior, bug, or error

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions