Closed randolf-scholz closed 1 month ago
Pyright is working as intended here, so I don't consider this a bug.
You've created a circular reference here that cannot be resolved.
The issue is that dataclasses can (and do) contain fields that refer to the dataclass type itself. For example, PointA
in your example, could contain a field defined as a: "PointA"
. In this case, "PointA"
refers to the decorated PointA
— i.e. the version of the class that has all of its class decorators applied. For that reason, pyright processes class decorations on the class before processing any of the fields, whose types affect synthesized dataclass methods. That means __dataclass_fields__
has not yet been synthesized at the point where your dataclass_decorator
call is evaluated for PointA
.
In the case of PointB
, you have broken the circularity by applying the decorator independently. This is the approach I recommend if your dataclass class decorator depends on the presence of synthesized methods and fields.
In the example below,
pyright
complains that the decorator is untyped and claims thatPointA
lacks the__dataclass_fields__
attribute. Yet, when the decorator is applied as a function to the equivalent classPointB
, no such diagnostics are produced, so presumably either one must be incorrect. (mypy playground with--strict
shows no errors)Code sample in pyright playground
Maybe related to https://github.com/microsoft/pyright/issues/4339? The typeshed source contains a comment that such a Dataclass Protocol might produce unexpected results in
pyright
.