Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions mypy/plugins/dataclasses.py
Original file line number Diff line number Diff line change
Expand Up @@ -965,6 +965,9 @@ def dataclass_tag_callback(ctx: ClassDefContext) -> None:

def dataclass_class_maker_callback(ctx: ClassDefContext) -> bool:
"""Hooks into the class typechecking process to add support for dataclasses."""
if any(i.is_named_tuple for i in ctx.cls.info.mro):
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

While we are at it: what about TypedDict?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

dataclass is also not really compatible with TypedDict, but here, things work a little differently, and Mypy's understanding seems to be consistent with Python's runtime behaviour:

from dataclasses import dataclass
from typing import TypedDict

@dataclass
class A(TypedDict):
    i: int

a = A(i=1)
assert a["i"] == 1
a.i
# Mypy -> error: "A" has not attribute "i" [attr-defined]
# Python -> AttributeError: 'dict' object has no attribute 'i'

ctx.api.fail("A NamedTuple cannot be a dataclass.", ctx=ctx.cls.info)
return True
transformer = DataclassTransformer(
ctx.cls, ctx.reason, _get_transform_spec(ctx.reason), ctx.api
)
Expand Down
17 changes: 17 additions & 0 deletions test-data/unit/check-dataclasses.test
Original file line number Diff line number Diff line change
Expand Up @@ -2576,3 +2576,20 @@ reveal_type(m.b) # N: Revealed type is "builtins.int"
m.a = 1 # E: Cannot assign to final attribute "a"
m.b = 2 # E: Cannot assign to final attribute "b"
[builtins fixtures/tuple.pyi]

[case testNoCrashForDataclassNamedTupleCombination]
# flags: --python-version 3.13
from dataclasses import dataclass
from typing import NamedTuple

@dataclass
class A(NamedTuple): # E: A NamedTuple cannot be a dataclass.
i: int

class B1(NamedTuple):
i: int
@dataclass
class B2(B1): # E: A NamedTuple cannot be a dataclass.
pass

[builtins fixtures/tuple.pyi]