From 22aee123308c570b3a476601b1aa7afddd99ff12 Mon Sep 17 00:00:00 2001 From: Dong-hee Na Date: Sun, 10 Jun 2018 15:14:24 +0900 Subject: [PATCH] bpo-33805: Improve error message of dataclasses.replace() --- 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 96bf6e1df47a0d..ad7bf0f7593a13 100644 --- a/Lib/dataclasses.py +++ b/Lib/dataclasses.py @@ -1173,6 +1173,9 @@ class C: 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 929793119d72b6..d9556c7ff9cecc 100755 --- a/Lib/test/test_dataclasses.py +++ b/Lib/test/test_dataclasses.py @@ -3024,6 +3024,22 @@ class C: 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 00000000000000..74bcf6d7c8c8b6 --- /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