mirror of https://github.com/python/cpython
gh-110273: dataclasses.replace() now raise TypeError for all invalid arguments (GH-110274)
dataclasses.replace() now raises TypeError instead of ValueError if specify keyword argument for a field declared with init=False or miss keyword argument for required InitVar field.
This commit is contained in:
parent
bfe7e72522
commit
5b9a3fd6a0
|
@ -1567,15 +1567,15 @@ def _replace(obj, /, **changes):
|
|||
if not f.init:
|
||||
# Error if this field is specified in changes.
|
||||
if f.name in changes:
|
||||
raise ValueError(f'field {f.name} is declared with '
|
||||
'init=False, it cannot be specified with '
|
||||
'replace()')
|
||||
raise TypeError(f'field {f.name} is declared with '
|
||||
f'init=False, it cannot be specified with '
|
||||
f'replace()')
|
||||
continue
|
||||
|
||||
if f.name not in changes:
|
||||
if f._field_type is _FIELD_INITVAR and f.default is MISSING:
|
||||
raise ValueError(f"InitVar {f.name!r} "
|
||||
'must be specified with replace()')
|
||||
raise TypeError(f"InitVar {f.name!r} "
|
||||
f'must be specified with replace()')
|
||||
changes[f.name] = getattr(obj, f.name)
|
||||
|
||||
# Create the new object, which calls __init__() and
|
||||
|
|
|
@ -3965,9 +3965,9 @@ class TestReplace(unittest.TestCase):
|
|||
self.assertEqual((c1.x, c1.y, c1.z, c1.t), (3, 2, 10, 100))
|
||||
|
||||
|
||||
with self.assertRaisesRegex(ValueError, 'init=False'):
|
||||
with self.assertRaisesRegex(TypeError, 'init=False'):
|
||||
replace(c, x=3, z=20, t=50)
|
||||
with self.assertRaisesRegex(ValueError, 'init=False'):
|
||||
with self.assertRaisesRegex(TypeError, 'init=False'):
|
||||
replace(c, z=20)
|
||||
replace(c, x=3, z=20, t=50)
|
||||
|
||||
|
@ -4020,10 +4020,10 @@ class TestReplace(unittest.TestCase):
|
|||
self.assertEqual((c1.x, c1.y), (5, 10))
|
||||
|
||||
# Trying to replace y is an error.
|
||||
with self.assertRaisesRegex(ValueError, 'init=False'):
|
||||
with self.assertRaisesRegex(TypeError, 'init=False'):
|
||||
replace(c, x=2, y=30)
|
||||
|
||||
with self.assertRaisesRegex(ValueError, 'init=False'):
|
||||
with self.assertRaisesRegex(TypeError, 'init=False'):
|
||||
replace(c, y=30)
|
||||
|
||||
def test_classvar(self):
|
||||
|
@ -4056,8 +4056,8 @@ class TestReplace(unittest.TestCase):
|
|||
|
||||
c = C(1, 10)
|
||||
self.assertEqual(c.x, 10)
|
||||
with self.assertRaisesRegex(ValueError, r"InitVar 'y' must be "
|
||||
"specified with replace()"):
|
||||
with self.assertRaisesRegex(TypeError, r"InitVar 'y' must be "
|
||||
r"specified with replace\(\)"):
|
||||
replace(c, x=3)
|
||||
c = replace(c, x=3, y=5)
|
||||
self.assertEqual(c.x, 15)
|
||||
|
|
|
@ -0,0 +1,3 @@
|
|||
:func:`dataclasses.replace` now raises TypeError instead of ValueError if
|
||||
specify keyword argument for a field declared with init=False or miss
|
||||
keyword argument for required InitVar field.
|
Loading…
Reference in New Issue