You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Lazy imports break dataclass InitVars in extremely rare scenarios #160665
fromdataclassesimportInitVar, dataclasslazyfromtesting_2importA@dataclassclassB:
a: InitVar[A]
def__post_init__(self, a: A) ->None:
print(a)
If you run testing.py with python 3.15 you will get TypeError: B.__post_init__() missing 1 required positional argument: 'a'
The key thing that causes the error seems to be the presence of the import cycle combined with the lazy import. It's worth noting that if you use a TYPE_CHECKING guard instead as described below, it does also work on 3.15.
I found this issue while migrating a bunch of my TYPE_CHECKING guards to lazy imports - infact as PEP 810 says "Lazy imports eliminate the common need for TYPE_CHECKING guards". The version of python that breaks is cpython-3.15.0a7-linux-x86_64-gnu. The code instead works on cpython-3.14.3-linux-x86_64-gnu, if of course you replace the lazy import in testing_3.py with a if TYPE_CHECKING: block
I think this is more of a direct annotations issue than a dataclasses one.
Dataclasses is failing to pick up the InitVar because the failing lazy import causes the whole annotation to fail to evaluate, while if only the name doesn't exist, then __missing__ is triggered in the stringifier dict and the name eventually gets replaced with a ForwardRef.
Demonstrating the same idea with list[...] on the current main:
Here we get ForwardRef('list[...]') where a lazy import fails, but list[ForwardRef('...')] for a standard unresolvable name.
I think the fix is making annotationlib handle unresolvable lazy imports better, rather than making dataclasses handle strings again like in the current PR.
Activity
DavidCEllis commentedon Oct 26, 2026
I think this is more of a direct annotations issue than a dataclasses one.
Dataclasses is failing to pick up the
InitVarbecause the failing lazy import causes the whole annotation to fail to evaluate, while if only the name doesn't exist, then__missing__is triggered in the stringifier dict and the name eventually gets replaced with a ForwardRef.Demonstrating the same idea with
list[...]on the currentmain:{'a': ForwardRef('list[LazyFail]', is_class=True, owner=<class '__main__.Example'>), 'b': list[ForwardRef('FakeSucceed', is_class=True, owner=<class '__main__.Example'>)]}Here we get
ForwardRef('list[...]')where a lazy import fails, butlist[ForwardRef('...')]for a standard unresolvable name.I think the fix is making annotationlib handle unresolvable lazy imports better, rather than making dataclasses handle strings again like in the current PR.
pythongh-160665: Resolve dataclass fixture imports before defining A