Skip to content

Commit 75ef138

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 77c7ca2 commit 75ef138

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
@@ -341,6 +341,8 @@ def collect_attributes(self) -> Optional[List[DataclassAttribute]]:
341341
# Ensure that arguments without a default don't follow
342342
# arguments that have a default.
343343
found_default = False
344+
# Ensure that the KW_ONLY sentinel is only provided once
345+
found_kw_sentinel = False
344346
for attr in all_attrs:
345347
# If we find any attribute that is_in_init, not kw_only, and that
346348
# doesn't have a default after one that does have one,
@@ -356,6 +358,14 @@ def collect_attributes(self) -> Optional[List[DataclassAttribute]]:
356358
)
357359

358360
found_default = found_default or (attr.has_default and attr.is_in_init)
361+
if found_kw_sentinel and self._is_kw_only_type(attr.type):
362+
context = (Context(line=attr.line, column=attr.column) if attr in attrs
363+
else ctx.cls)
364+
ctx.api.fail(
365+
'There may not be more than one field with the KW_ONLY type',
366+
context,
367+
)
368+
found_kw_sentinel = found_kw_sentinel or self._is_kw_only_type(attr.type)
359369

360370
return all_attrs
361371

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)