Skip to content

Commit

Permalink
attrs, dataclasses: don't enforce slots when base doesn't (#15976)
Browse files Browse the repository at this point in the history
Doing the same thing we do for regular classes.

Fixes #15975
  • Loading branch information
ikonst authored Aug 28, 2023
1 parent d7b2451 commit 010da0b
Show file tree
Hide file tree
Showing 4 changed files with 42 additions and 0 deletions.
5 changes: 5 additions & 0 deletions mypy/plugins/attrs.py
Original file line number Diff line number Diff line change
Expand Up @@ -893,6 +893,11 @@ def _add_attrs_magic_attribute(


def _add_slots(ctx: mypy.plugin.ClassDefContext, attributes: list[Attribute]) -> None:
if any(p.slots is None for p in ctx.cls.info.mro[1:-1]):
# At least one type in mro (excluding `self` and `object`)
# does not have concrete `__slots__` defined. Ignoring.
return

# Unlike `@dataclasses.dataclass`, `__slots__` is rewritten here.
ctx.cls.info.slots = {attr.name for attr in attributes}

Expand Down
6 changes: 6 additions & 0 deletions mypy/plugins/dataclasses.py
Original file line number Diff line number Diff line change
Expand Up @@ -443,6 +443,12 @@ def add_slots(
self._cls,
)
return

if any(p.slots is None for p in info.mro[1:-1]):
# At least one type in mro (excluding `self` and `object`)
# does not have concrete `__slots__` defined. Ignoring.
return

info.slots = generated_slots

# Now, insert `.__slots__` attribute to class namespace:
Expand Down
16 changes: 16 additions & 0 deletions test-data/unit/check-dataclasses.test
Original file line number Diff line number Diff line change
Expand Up @@ -1519,6 +1519,22 @@ class Some:
self.y = 1 # E: Trying to assign name "y" that is not in "__slots__" of type "__main__.Some"
[builtins fixtures/dataclasses.pyi]

[case testDataclassWithSlotsDerivedFromNonSlot]
# flags: --python-version 3.10
from dataclasses import dataclass

class A:
pass

@dataclass(slots=True)
class B(A):
x: int

def __post_init__(self) -> None:
self.y = 42

[builtins fixtures/dataclasses.pyi]

[case testDataclassWithSlotsConflict]
# flags: --python-version 3.10
from dataclasses import dataclass
Expand Down
15 changes: 15 additions & 0 deletions test-data/unit/check-plugin-attrs.test
Original file line number Diff line number Diff line change
Expand Up @@ -1677,6 +1677,21 @@ class C:
self.c = 2 # E: Trying to assign name "c" that is not in "__slots__" of type "__main__.C"
[builtins fixtures/plugin_attrs.pyi]

[case testAttrsClassWithSlotsDerivedFromNonSlots]
import attrs

class A:
pass

@attrs.define(slots=True)
class B(A):
x: int

def __attrs_post_init__(self) -> None:
self.y = 42

[builtins fixtures/plugin_attrs.pyi]

[case testRuntimeSlotsAttr]
from attr import dataclass

Expand Down

0 comments on commit 010da0b

Please sign in to comment.