Skip to content

Commit dfaef66

Browse files
committed
ensure that the KW_ONLY sentinel is only provided once
https://docs.python.org/3.10/library/dataclasses.html#dataclasses.KW_ONLY In this section in the documentation it states: In a single dataclass, it is an error to specify more than one field whose type is KW_ONLY. This commit handles raising a mypy failure if this case is detected.
1 parent 5dcabc5 commit dfaef66

File tree

2 files changed

+22
-0
lines changed

2 files changed

+22
-0
lines changed

mypy/plugins/dataclasses.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -337,6 +337,8 @@ def collect_attributes(self) -> Optional[List[DataclassAttribute]]:
337337
# Ensure that arguments without a default don't follow
338338
# arguments that have a default.
339339
found_default = False
340+
# Ensure that the KW_ONLY sentinel is only provided once
341+
found_kw_sentinel = False
340342
for attr in all_attrs:
341343
# If we find any attribute that is_in_init, not kw_only, and that
342344
# doesn't have a default after one that does have one,
@@ -352,6 +354,14 @@ def collect_attributes(self) -> Optional[List[DataclassAttribute]]:
352354
)
353355

354356
found_default = found_default or (attr.has_default and attr.is_in_init)
357+
if found_kw_sentinel and self._is_kw_only_type(attr.type):
358+
context = (Context(line=attr.line, column=attr.column) if attr in attrs
359+
else ctx.cls)
360+
ctx.api.fail(
361+
'There may not be more than one field with the KW_ONLY type',
362+
context,
363+
)
364+
found_kw_sentinel = found_kw_sentinel or self._is_kw_only_type(attr.type)
355365

356366
return all_attrs
357367

test-data/unit/check-dataclasses.test

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -386,6 +386,18 @@ class D(Base):
386386

387387
D("Hello", "World")
388388

389+
[case testDataclassesOrderingKwOnlyWithMultipleSentinel]
390+
# flags: --python-version 3.10
391+
from dataclasses import dataclass, field, KW_ONLY
392+
393+
@dataclass
394+
class Base:
395+
x: str
396+
_: KW_ONLY
397+
y: int = 0
398+
__: KW_ONLY # E: There may not be more than one field with the KW_ONLY type
399+
w: int = 1
400+
389401
[builtins fixtures/list.pyi]
390402

391403
[case testDataclassesClassmethods]

0 commit comments

Comments
 (0)