Skip to content

Commit 010da0b

Browse files
authored
attrs, dataclasses: don't enforce slots when base doesn't (#15976)
Doing the same thing we do for regular classes. Fixes #15975
1 parent d7b2451 commit 010da0b

File tree

4 files changed

+42
-0
lines changed

4 files changed

+42
-0
lines changed

mypy/plugins/attrs.py

+5
Original file line numberDiff line numberDiff line change
@@ -893,6 +893,11 @@ def _add_attrs_magic_attribute(
893893

894894

895895
def _add_slots(ctx: mypy.plugin.ClassDefContext, attributes: list[Attribute]) -> None:
896+
if any(p.slots is None for p in ctx.cls.info.mro[1:-1]):
897+
# At least one type in mro (excluding `self` and `object`)
898+
# does not have concrete `__slots__` defined. Ignoring.
899+
return
900+
896901
# Unlike `@dataclasses.dataclass`, `__slots__` is rewritten here.
897902
ctx.cls.info.slots = {attr.name for attr in attributes}
898903

mypy/plugins/dataclasses.py

+6
Original file line numberDiff line numberDiff line change
@@ -443,6 +443,12 @@ def add_slots(
443443
self._cls,
444444
)
445445
return
446+
447+
if any(p.slots is None for p in info.mro[1:-1]):
448+
# At least one type in mro (excluding `self` and `object`)
449+
# does not have concrete `__slots__` defined. Ignoring.
450+
return
451+
446452
info.slots = generated_slots
447453

448454
# Now, insert `.__slots__` attribute to class namespace:

test-data/unit/check-dataclasses.test

+16
Original file line numberDiff line numberDiff line change
@@ -1519,6 +1519,22 @@ class Some:
15191519
self.y = 1 # E: Trying to assign name "y" that is not in "__slots__" of type "__main__.Some"
15201520
[builtins fixtures/dataclasses.pyi]
15211521

1522+
[case testDataclassWithSlotsDerivedFromNonSlot]
1523+
# flags: --python-version 3.10
1524+
from dataclasses import dataclass
1525+
1526+
class A:
1527+
pass
1528+
1529+
@dataclass(slots=True)
1530+
class B(A):
1531+
x: int
1532+
1533+
def __post_init__(self) -> None:
1534+
self.y = 42
1535+
1536+
[builtins fixtures/dataclasses.pyi]
1537+
15221538
[case testDataclassWithSlotsConflict]
15231539
# flags: --python-version 3.10
15241540
from dataclasses import dataclass

test-data/unit/check-plugin-attrs.test

+15
Original file line numberDiff line numberDiff line change
@@ -1677,6 +1677,21 @@ class C:
16771677
self.c = 2 # E: Trying to assign name "c" that is not in "__slots__" of type "__main__.C"
16781678
[builtins fixtures/plugin_attrs.pyi]
16791679

1680+
[case testAttrsClassWithSlotsDerivedFromNonSlots]
1681+
import attrs
1682+
1683+
class A:
1684+
pass
1685+
1686+
@attrs.define(slots=True)
1687+
class B(A):
1688+
x: int
1689+
1690+
def __attrs_post_init__(self) -> None:
1691+
self.y = 42
1692+
1693+
[builtins fixtures/plugin_attrs.pyi]
1694+
16801695
[case testRuntimeSlotsAttr]
16811696
from attr import dataclass
16821697

0 commit comments

Comments
 (0)