]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
gh-110273: dataclasses.replace() now raise TypeError for all invalid arguments (GH...
authorSerhiy Storchaka <storchaka@gmail.com>
Wed, 4 Oct 2023 06:20:14 +0000 (09:20 +0300)
committerGitHub <noreply@github.com>
Wed, 4 Oct 2023 06:20:14 +0000 (09:20 +0300)
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.

Lib/dataclasses.py
Lib/test/test_dataclasses/__init__.py
Misc/NEWS.d/next/Library/2023-10-03-14-07-05.gh-issue-110273.QaDUmS.rst [new file with mode: 0644]

index 84f8d68ce092a4502c54db77058fc8efd19643aa..31dc6f8abce91a7c57d026b5769e1b53fe6510f4 100644 (file)
@@ -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
index 7c07dfc77de208d2dc2c04a9c4b352a99827bd33..f629d7bb53959b271996745b654f5905b542864a 100644 (file)
@@ -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)
diff --git a/Misc/NEWS.d/next/Library/2023-10-03-14-07-05.gh-issue-110273.QaDUmS.rst b/Misc/NEWS.d/next/Library/2023-10-03-14-07-05.gh-issue-110273.QaDUmS.rst
new file mode 100644 (file)
index 0000000..98d87da
--- /dev/null
@@ -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.