From 3d70f7aef614c396f516b5fccedeebe98598714d Mon Sep 17 00:00:00 2001 From: Dong-hee Na Date: Sat, 23 Jun 2018 23:46:32 +0900 Subject: [PATCH] bpo-33805: Improve error message of dataclasses.replace() (GH-7580) --- Lib/dataclasses.py | 3 +++ Lib/test/test_dataclasses.py | 16 ++++++++++++++++ .../2018-06-10-15-14-17.bpo-33805.5LAz5a.rst | 1 + 3 files changed, 20 insertions(+) create mode 100644 Misc/NEWS.d/next/Library/2018-06-10-15-14-17.bpo-33805.5LAz5a.rst diff --git a/Lib/dataclasses.py b/Lib/dataclasses.py index 96bf6e1df4..ad7bf0f759 100644 --- a/Lib/dataclasses.py +++ b/Lib/dataclasses.py @@ -1173,6 +1173,9 @@ def replace(obj, **changes): continue if f.name not in changes: + if f._field_type is _FIELD_INITVAR: + raise ValueError(f"InitVar {f.name!r} " + 'must be specified with replace()') changes[f.name] = getattr(obj, f.name) # Create the new object, which calls __init__() and diff --git a/Lib/test/test_dataclasses.py b/Lib/test/test_dataclasses.py index 929793119d..d9556c7ff9 100755 --- a/Lib/test/test_dataclasses.py +++ b/Lib/test/test_dataclasses.py @@ -3024,6 +3024,22 @@ class TestReplace(unittest.TestCase): replace(c, x=5) + def test_initvar_is_specified(self): + @dataclass + class C: + x: int + y: InitVar[int] + + def __post_init__(self, y): + self.x *= y + + c = C(1, 10) + self.assertEqual(c.x, 10) + with self.assertRaisesRegex(ValueError, r"InitVar 'y' must be " + "specified with replace()"): + replace(c, x=3) + c = replace(c, x=3, y=5) + self.assertEqual(c.x, 15) ## def test_initvar(self): ## @dataclass ## class C: diff --git a/Misc/NEWS.d/next/Library/2018-06-10-15-14-17.bpo-33805.5LAz5a.rst b/Misc/NEWS.d/next/Library/2018-06-10-15-14-17.bpo-33805.5LAz5a.rst new file mode 100644 index 0000000000..74bcf6d7c8 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2018-06-10-15-14-17.bpo-33805.5LAz5a.rst @@ -0,0 +1 @@ +Improve error message of dataclasses.replace() when an InitVar is not specified -- 2.50.0