Skip to content

PEP 649 behavior for partially executed modules #130907

@JelleZijlstra

Description

@JelleZijlstra

Bug report

Bug description:

Consider this package:

$ ls recmod/
__main__.py	a.py		b.py
$ cat recmod/__main__.py 
from . import a

print(a.__annotations__)
$ cat recmod/a.py 
v1: int

from . import b

v2: int
$ cat recmod/b.py 
from . import a

print(a.__annotations__)

On 3.13, this produces:

$ python3.13 -m recmod
{'v1': <class 'int'>}
{'v1': <class 'int'>, 'v2': <class 'int'>}

But on main, we get this:

$ ~/py/cpython/python.exe -m recmod
{}
{}

This is because we only set the __annotate__ function at the end of the module execution, so when we access annotations on the partially executed module a (in b.py), there aren't any yet. But this also populates the __annotations__ cache, so even accesses to __annotations__ after a has been fully executed still return an empty dictionary.

Should we fix this and how? I don't care much what happens if you access __annotations__ while the module is partially evaluated. However, it seems bad that such access poisons the cache forever. To fix that, we should make ModuleType.__annotations__ not cache its return value if the module is not yet fully evaluated.

CPython versions tested on:

CPython main branch

Operating systems tested on:

macOS

Linked PRs

Metadata

Metadata

Assignees

No one assigned

    Labels

    interpreter-core(Objects, Python, Grammar, and Parser dirs)type-bugAn unexpected behavior, bug, or error

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions