Skip to content

Commit e8a72a0

Browse files
authored
Fix dataclass plugin interaction with member expressions (python#6739)
Fixes python#6516 It also fixes minor corner case that affects tests cases proposed in the issue.
1 parent d041379 commit e8a72a0

File tree

2 files changed

+22
-3
lines changed

2 files changed

+22
-3
lines changed

mypy/plugins/dataclasses.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33

44
from mypy.nodes import (
55
ARG_OPT, ARG_POS, MDEF, Argument, AssignmentStmt, CallExpr,
6-
Context, Expression, FuncDef, JsonDict, NameExpr,
6+
Context, Expression, FuncDef, JsonDict, NameExpr, RefExpr,
77
SymbolTableNode, TempNode, TypeInfo, Var, TypeVarExpr
88
)
99
from mypy.plugin import ClassDefContext
@@ -300,7 +300,7 @@ def collect_attributes(self) -> List[DataclassAttribute]:
300300
Context(line=attr.line, column=attr.column),
301301
)
302302

303-
found_default = found_default or attr.has_default
303+
found_default = found_default or (attr.has_default and attr.is_in_init)
304304

305305
return all_attrs
306306

@@ -337,7 +337,7 @@ def _collect_field_args(expr: Expression) -> Tuple[bool, Dict[str, Expression]]:
337337
"""
338338
if (
339339
isinstance(expr, CallExpr) and
340-
isinstance(expr.callee, NameExpr) and
340+
isinstance(expr.callee, RefExpr) and
341341
expr.callee.fullname == 'dataclasses.field'
342342
):
343343
# field() only takes keyword arguments.

test-data/unit/check-dataclasses.test

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -586,3 +586,22 @@ class B:
586586

587587
reveal_type(B) # E: Revealed type is 'def (x: Any) -> __main__.B'
588588
[builtins fixtures/list.pyi]
589+
590+
[case testMemberExprWorksAsField]
591+
import dataclasses
592+
593+
@dataclasses.dataclass
594+
class A:
595+
x: int = dataclasses.field(metadata={"doc": "foo"})
596+
y: str
597+
598+
@dataclasses.dataclass
599+
class B:
600+
x: int = dataclasses.field(init=False, default=1)
601+
y: str
602+
603+
@dataclasses.dataclass
604+
class C:
605+
x: int = dataclasses.field(default=1)
606+
y: str = dataclasses.field(metadata={"doc": "foo"}) # E: Attributes without a default cannot follow attributes with one
607+
[builtins fixtures/dict.pyi]

0 commit comments

Comments
 (0)