Skip to content

Commit

Permalink
ensure that the KW_ONLY sentinel is only provided once
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
tgallant committed Aug 2, 2021
1 parent 77c7ca2 commit 75ef138
Show file tree
Hide file tree
Showing 2 changed files with 22 additions and 0 deletions.
10 changes: 10 additions & 0 deletions mypy/plugins/dataclasses.py
Original file line number Diff line number Diff line change
Expand Up @@ -341,6 +341,8 @@ def collect_attributes(self) -> Optional[List[DataclassAttribute]]:
# Ensure that arguments without a default don't follow
# arguments that have a default.
found_default = False
# Ensure that the KW_ONLY sentinel is only provided once
found_kw_sentinel = False
for attr in all_attrs:
# If we find any attribute that is_in_init, not kw_only, and that
# doesn't have a default after one that does have one,
Expand All @@ -356,6 +358,14 @@ def collect_attributes(self) -> Optional[List[DataclassAttribute]]:
)

found_default = found_default or (attr.has_default and attr.is_in_init)
if found_kw_sentinel and self._is_kw_only_type(attr.type):
context = (Context(line=attr.line, column=attr.column) if attr in attrs
else ctx.cls)
ctx.api.fail(
'There may not be more than one field with the KW_ONLY type',
context,
)
found_kw_sentinel = found_kw_sentinel or self._is_kw_only_type(attr.type)

return all_attrs

Expand Down
12 changes: 12 additions & 0 deletions test-data/unit/check-dataclasses.test
Original file line number Diff line number Diff line change
Expand Up @@ -386,6 +386,18 @@ class D(Base):

D("Hello", "World")

[case testDataclassesOrderingKwOnlyWithMultipleSentinel]
# flags: --python-version 3.10
from dataclasses import dataclass, field, KW_ONLY

@dataclass
class Base:
x: str
_: KW_ONLY
y: int = 0
__: KW_ONLY # E: There may not be more than one field with the KW_ONLY type
w: int = 1

[builtins fixtures/list.pyi]

[case testDataclassesClassmethods]
Expand Down

0 comments on commit 75ef138

Please sign in to comment.