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
Circular import under if TYPE_CHECKING breaks subclass initialization signature #12259
Consider an App class with a method that creates Widget instances based on a spec. Widget is a base class, and the spec determines which child class gets instantiated.
Now, the widgets keep a reference to the App, so in an attempt to avoid circular imports, the file containing the Widget definition uses an if TYPE_CHECKING: guard like so:
The RedWidget child class is empty, but the BlueWidget class adds an attribute:
# src/foobar/widgets/blue.pyimportattrfrom .baseimportWidget@attr.defineclassBlueWidget(Widget):
nessness: int=attr.field(init=False)
def__attrs_post_init__(self) ->None:
ifself.spec.nessnessisNone:
raiseValueError("Blue widgets must be nessy")
self.nessness=self.spec.nessness
Now, if we put this all together and run mypy, we get an erroneous error:
src/foobar/app.py:9: error: Unexpected keyword argument "app" for "BlueWidget" [call-arg]
return BlueWidget(app=self, spec=spec)
^
src/foobar/app.py:9: error: Unexpected keyword argument "spec" for "BlueWidget" [call-arg]
return BlueWidget(app=self, spec=spec)
^
Found 2 errors in 1 file (checked 6 source files)
Note that mypy only complains about the instantiation of BlueWidget, not RedWidget. Also note that the same error occurs if attrs is replaced with dataclasses.
I believe that this problem is caused by the circular import beneath the if TYPE_CHECKING: guard for some reason, as commenting it out and changing the Widget.app annotation to Any gets the type-checking to pass.
Activity
jwodder commentedon Oct 2, 2023
As of mypy 1.5.1, this bug is no longer reproduceable.