mirror of
https://github.com/python/cpython
synced 2024-10-15 01:28:04 +00:00
bpo-44015: dataclasses should allow KW_ONLY to be specified only once per class (GH-25841)
bpo-44015: Raise a TypeError if KW_ONLY is specified more than once.
This commit is contained in:
parent
72720a2639
commit
99ad742ea9
|
@ -930,6 +930,7 @@ def _process_class(cls, init, repr, eq, order, unsafe_hash, frozen,
|
|||
# we can.
|
||||
cls_fields = []
|
||||
# Get a reference to this module for the _is_kw_only() test.
|
||||
KW_ONLY_seen = False
|
||||
dataclasses = sys.modules[__name__]
|
||||
for name, type in cls_annotations.items():
|
||||
# See if this is a marker to change the value of kw_only.
|
||||
|
@ -939,6 +940,10 @@ def _process_class(cls, init, repr, eq, order, unsafe_hash, frozen,
|
|||
_is_kw_only))):
|
||||
# Switch the default to kw_only=True, and ignore this
|
||||
# annotation: it's not a real field.
|
||||
if KW_ONLY_seen:
|
||||
raise TypeError(f'{name!r} is KW_ONLY, but KW_ONLY '
|
||||
'has already been specified')
|
||||
KW_ONLY_seen = True
|
||||
kw_only = True
|
||||
else:
|
||||
# Otherwise it's a field of some type.
|
||||
|
|
|
@ -3699,6 +3699,83 @@ class C:
|
|||
self.assertEqual(c.b, 3)
|
||||
self.assertEqual(c.c, 2)
|
||||
|
||||
def test_KW_ONLY_as_string(self):
|
||||
@dataclass
|
||||
class A:
|
||||
a: int
|
||||
_: 'dataclasses.KW_ONLY'
|
||||
b: int
|
||||
c: int
|
||||
A(3, c=5, b=4)
|
||||
msg = "takes 2 positional arguments but 4 were given"
|
||||
with self.assertRaisesRegex(TypeError, msg):
|
||||
A(3, 4, 5)
|
||||
|
||||
def test_KW_ONLY_twice(self):
|
||||
msg = "'Y' is KW_ONLY, but KW_ONLY has already been specified"
|
||||
|
||||
with self.assertRaisesRegex(TypeError, msg):
|
||||
@dataclass
|
||||
class A:
|
||||
a: int
|
||||
X: KW_ONLY
|
||||
Y: KW_ONLY
|
||||
b: int
|
||||
c: int
|
||||
|
||||
with self.assertRaisesRegex(TypeError, msg):
|
||||
@dataclass
|
||||
class A:
|
||||
a: int
|
||||
X: KW_ONLY
|
||||
b: int
|
||||
Y: KW_ONLY
|
||||
c: int
|
||||
|
||||
with self.assertRaisesRegex(TypeError, msg):
|
||||
@dataclass
|
||||
class A:
|
||||
a: int
|
||||
X: KW_ONLY
|
||||
b: int
|
||||
c: int
|
||||
Y: KW_ONLY
|
||||
|
||||
# But this usage is okay, since it's not using KW_ONLY.
|
||||
@dataclass
|
||||
class A:
|
||||
a: int
|
||||
_: KW_ONLY
|
||||
b: int
|
||||
c: int = field(kw_only=True)
|
||||
|
||||
# And if inheriting, it's okay.
|
||||
@dataclass
|
||||
class A:
|
||||
a: int
|
||||
_: KW_ONLY
|
||||
b: int
|
||||
c: int
|
||||
@dataclass
|
||||
class B(A):
|
||||
_: KW_ONLY
|
||||
d: int
|
||||
|
||||
# Make sure the error is raised in a derived class.
|
||||
with self.assertRaisesRegex(TypeError, msg):
|
||||
@dataclass
|
||||
class A:
|
||||
a: int
|
||||
_: KW_ONLY
|
||||
b: int
|
||||
c: int
|
||||
@dataclass
|
||||
class B(A):
|
||||
X: KW_ONLY
|
||||
d: int
|
||||
Y: KW_ONLY
|
||||
|
||||
|
||||
def test_post_init(self):
|
||||
@dataclass
|
||||
class A:
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
In @dataclass(), raise a TypeError if KW_ONLY is specified more than once.
|
Loading…
Reference in a new issue