Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 6ec6a83

Browse files
Handle dataclasses.MISSING and dataclasses.KW_ONLY as sentinels
Signed-off-by: Edgar Ramírez Mondragón <[email protected]>
1 parent d85759f commit 6ec6a83

2 files changed

Lines changed: 64 additions & 0 deletions

File tree

mypy/plugins/dataclasses.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@
6363
LiteralType,
6464
NoneType,
6565
ProperType,
66+
SentinelValue,
6667
TupleType,
6768
Type,
6869
TypeOfAny,
@@ -799,6 +800,9 @@ def _is_kw_only_type(self, node: Type | None) -> bool:
799800
if node is None:
800801
return False
801802
node_type = get_proper_type(node)
803+
if isinstance(node_type, LiteralType) and isinstance(node_type.value, SentinelValue):
804+
# PEP 661 sentinel: `KW_ONLY = sentinel("KW_ONLY")` (Python 3.15+).
805+
return node_type.value.fullname == "dataclasses.KW_ONLY"
802806
if not isinstance(node_type, Instance):
803807
return False
804808
return node_type.type.fullname == "dataclasses.KW_ONLY"

test-data/unit/check-dataclasses.test

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -448,6 +448,66 @@ Application('name', rating=123) # E: Too many positional arguments for "Applica
448448

449449
[builtins fixtures/dataclasses.pyi]
450450

451+
[case testDataclassesOrderingKwOnlyWithPEP661Sentinel]
452+
-- Regression test for KW_ONLY implemented as a PEP 661 sentinel, as in
453+
-- https://github.com/python/cpython/commit/16952218d0535904236e8a39851133688c9ce1f0
454+
-- `_is_kw_only_type` must recognize this shape too, or `_` stops being excluded
455+
-- from `__init__` and kw-only ordering enforcement silently stops firing.
456+
from dataclasses import dataclass, KW_ONLY
457+
458+
@dataclass
459+
class Application:
460+
_: KW_ONLY
461+
name: str = 'Unnamed'
462+
rating: int
463+
464+
Application(rating=5)
465+
Application('name', 123) # E: Too many positional arguments for "Application"
466+
467+
[file dataclasses.pyi]
468+
from typing import Any, Callable, TypeVar, overload
469+
from typing_extensions import sentinel
470+
471+
_T = TypeVar("_T")
472+
473+
KW_ONLY = sentinel("KW_ONLY")
474+
MISSING = sentinel("MISSING")
475+
476+
class Field:
477+
default: Any
478+
default_factory: Any
479+
480+
def field(
481+
*,
482+
default: Any = ...,
483+
default_factory: Any = ...,
484+
init: bool = ...,
485+
repr: bool = ...,
486+
hash: Any = ...,
487+
compare: bool = ...,
488+
metadata: Any = ...,
489+
kw_only: Any = ...,
490+
) -> Any: ...
491+
@overload
492+
def dataclass(cls: type[_T]) -> type[_T]: ...
493+
@overload
494+
def dataclass(
495+
cls: None = ...,
496+
*,
497+
init: bool = ...,
498+
repr: bool = ...,
499+
eq: bool = ...,
500+
order: bool = ...,
501+
unsafe_hash: bool = ...,
502+
frozen: bool = ...,
503+
match_args: bool = ...,
504+
kw_only: bool = ...,
505+
slots: bool = ...,
506+
weakref_slot: bool = ...,
507+
) -> Callable[[type[_T]], type[_T]]: ...
508+
509+
[builtins fixtures/dataclasses.pyi]
510+
451511
[case testDataclassesOrderingKwOnlyWithSentinelAndFieldOverride]
452512
from dataclasses import dataclass, field, KW_ONLY
453513

0 commit comments

Comments
 (0)