Skip to content

Commit 5ed1f00

Browse files
committed
Fix multiple inheritance false positives in dataclasses and attrs classes
Multiple inheritance from dataclasses and attrs classes works at runtime, so don't complain about `__match_args__` or `__attrs_attrs__` which tend to have incompatible types in subclasses. Fixes #12349. Fixes #12008. Fixes #12065.
1 parent 8427df1 commit 5ed1f00

File tree

5 files changed

+36
-4
lines changed

5 files changed

+36
-4
lines changed

mypy/checker.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2103,8 +2103,9 @@ class C(B, A[int]): ... # this is unsafe because...
21032103
self.msg.cant_override_final(name, base2.name, ctx)
21042104
if is_final_node(first.node):
21052105
self.check_if_final_var_override_writable(name, second.node, ctx)
2106-
# __slots__ and __deletable__ are special and the type can vary across class hierarchy.
2107-
if name in ('__slots__', '__deletable__'):
2106+
# Some attributes like __slots__ and __deletable__ are special, and the type can
2107+
# vary across class hierarchy.
2108+
if name in ('__slots__', '__deletable__', '__match_args__', '__attrs_attrs__'):
21082109
ok = True
21092110
if not ok:
21102111
self.msg.base_class_definitions_incompatible(name, base1, base2,

mypy/plugins/attrs.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -778,7 +778,6 @@ def _add_match_args(ctx: 'mypy.plugin.ClassDefContext',
778778
cls=ctx.cls,
779779
name='__match_args__',
780780
typ=match_args,
781-
final=True,
782781
)
783782

784783

mypy/plugins/dataclasses.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -227,7 +227,7 @@ def transform(self) -> None:
227227
literals: List[Type] = [LiteralType(attr.name, str_type)
228228
for attr in attributes if attr.is_in_init]
229229
match_args_type = TupleType(literals, ctx.api.named_type("builtins.tuple"))
230-
add_attribute_to_class(ctx.api, ctx.cls, "__match_args__", match_args_type, final=True)
230+
add_attribute_to_class(ctx.api, ctx.cls, "__match_args__", match_args_type)
231231

232232
self._add_dataclass_fields_magic_attribute()
233233

test-data/unit/check-attr.test

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1539,3 +1539,19 @@ n: NoMatchArgs
15391539
reveal_type(n.__match_args__) # E: "NoMatchArgs" has no attribute "__match_args__" \
15401540
# N: Revealed type is "Any"
15411541
[builtins fixtures/attr.pyi]
1542+
1543+
[case testAttrsMultipleInheritance]
1544+
# flags: --python-version 3.10
1545+
import attr
1546+
1547+
@attr.s
1548+
class A:
1549+
x = attr.ib(type=int)
1550+
1551+
@attr.s
1552+
class B:
1553+
y = attr.ib(type=int)
1554+
1555+
class AB(A, B):
1556+
pass
1557+
[builtins fixtures/attr.pyi]

test-data/unit/check-dataclasses.test

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1536,3 +1536,19 @@ A(a=1, b=2)
15361536
A(1)
15371537
A(a="foo") # E: Argument "a" to "A" has incompatible type "str"; expected "int"
15381538
[builtins fixtures/dataclasses.pyi]
1539+
1540+
[case testDataclassMultipleInheritance]
1541+
# flags: --python-version 3.10
1542+
from dataclasses import dataclass
1543+
1544+
@dataclass
1545+
class A:
1546+
prop_a: str
1547+
1548+
@dataclass
1549+
class B:
1550+
prop_b: bool
1551+
1552+
class Derived(A, B):
1553+
pass
1554+
[builtins fixtures/dataclasses.pyi]

0 commit comments

Comments
 (0)