Skip to content

Commit 5b9a3fd

Browse files
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.
1 parent bfe7e72 commit 5b9a3fd

File tree

3 files changed

+14
-11
lines changed

3 files changed

+14
-11
lines changed

Lib/dataclasses.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1567,15 +1567,15 @@ def _replace(obj, /, **changes):
15671567
if not f.init:
15681568
# Error if this field is specified in changes.
15691569
if f.name in changes:
1570-
raise ValueError(f'field {f.name} is declared with '
1571-
'init=False, it cannot be specified with '
1572-
'replace()')
1570+
raise TypeError(f'field {f.name} is declared with '
1571+
f'init=False, it cannot be specified with '
1572+
f'replace()')
15731573
continue
15741574

15751575
if f.name not in changes:
15761576
if f._field_type is _FIELD_INITVAR and f.default is MISSING:
1577-
raise ValueError(f"InitVar {f.name!r} "
1578-
'must be specified with replace()')
1577+
raise TypeError(f"InitVar {f.name!r} "
1578+
f'must be specified with replace()')
15791579
changes[f.name] = getattr(obj, f.name)
15801580

15811581
# Create the new object, which calls __init__() and

Lib/test/test_dataclasses/__init__.py

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3965,9 +3965,9 @@ class C:
39653965
self.assertEqual((c1.x, c1.y, c1.z, c1.t), (3, 2, 10, 100))
39663966

39673967

3968-
with self.assertRaisesRegex(ValueError, 'init=False'):
3968+
with self.assertRaisesRegex(TypeError, 'init=False'):
39693969
replace(c, x=3, z=20, t=50)
3970-
with self.assertRaisesRegex(ValueError, 'init=False'):
3970+
with self.assertRaisesRegex(TypeError, 'init=False'):
39713971
replace(c, z=20)
39723972
replace(c, x=3, z=20, t=50)
39733973

@@ -4020,10 +4020,10 @@ class C:
40204020
self.assertEqual((c1.x, c1.y), (5, 10))
40214021

40224022
# Trying to replace y is an error.
4023-
with self.assertRaisesRegex(ValueError, 'init=False'):
4023+
with self.assertRaisesRegex(TypeError, 'init=False'):
40244024
replace(c, x=2, y=30)
40254025

4026-
with self.assertRaisesRegex(ValueError, 'init=False'):
4026+
with self.assertRaisesRegex(TypeError, 'init=False'):
40274027
replace(c, y=30)
40284028

40294029
def test_classvar(self):
@@ -4056,8 +4056,8 @@ def __post_init__(self, y):
40564056

40574057
c = C(1, 10)
40584058
self.assertEqual(c.x, 10)
4059-
with self.assertRaisesRegex(ValueError, r"InitVar 'y' must be "
4060-
"specified with replace()"):
4059+
with self.assertRaisesRegex(TypeError, r"InitVar 'y' must be "
4060+
r"specified with replace\(\)"):
40614061
replace(c, x=3)
40624062
c = replace(c, x=3, y=5)
40634063
self.assertEqual(c.x, 15)
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
:func:`dataclasses.replace` now raises TypeError instead of ValueError if
2+
specify keyword argument for a field declared with init=False or miss
3+
keyword argument for required InitVar field.

0 commit comments

Comments
 (0)