From 2dca685a13c8824565554f612ab35d5d92531ff8 Mon Sep 17 00:00:00 2001 From: Claudiu Popa Date: Mon, 2 Dec 2019 21:11:15 +0100 Subject: [PATCH] bpo-36470: Allow dataclasses.replace() to work InitVar with default values If a dataclass contain an InitVar, that InitVar must be specified in the call to replace(), unless it has a default value, in which case replace() should not raise a `ValueError` if the value was not specified in the call to replace(). Patch by Claudiu Popa. --- Lib/dataclasses.py | 2 +- Lib/test/test_dataclasses.py | 18 ++++++++++++++++++ .../2019-12-02-21-03-41.bpo-36470.Gy9Sff.rst | 1 + 3 files changed, 20 insertions(+), 1 deletion(-) create mode 100644 Misc/NEWS.d/next/Library/2019-12-02-21-03-41.bpo-36470.Gy9Sff.rst diff --git a/Lib/dataclasses.py b/Lib/dataclasses.py index 91c1f6f80fc684..fdfbf34c0be2a8 100644 --- a/Lib/dataclasses.py +++ b/Lib/dataclasses.py @@ -1249,7 +1249,7 @@ class C: continue if f.name not in changes: - if f._field_type is _FIELD_INITVAR: + if f._field_type is _FIELD_INITVAR and f.default is MISSING: raise ValueError(f"InitVar {f.name!r} " 'must be specified with replace()') changes[f.name] = getattr(obj, f.name) diff --git a/Lib/test/test_dataclasses.py b/Lib/test/test_dataclasses.py index 238335e7d9edad..e11428f345141d 100644 --- a/Lib/test/test_dataclasses.py +++ b/Lib/test/test_dataclasses.py @@ -3214,6 +3214,24 @@ def __post_init__(self, y): c = replace(c, x=3, y=5) self.assertEqual(c.x, 15) + def test_initvar_with_default_value(self): + @dataclass + class C: + x: int + y: InitVar[int] = None + z: InitVar[int] = 42 + + def __post_init__(self, y, z): + if y is not None: + self.x += y + if z is not None: + self.x += z + + c = C(x=1, y=10, z=1) + self.assertEqual(replace(c), C(x=12)) + self.assertEqual(replace(c, y=4), C(x=12, y=4, z=42)) + self.assertEqual(replace(c, y=4, z=1), C(x=12, y=4, z=1)) + def test_recursive_repr(self): @dataclass class C: diff --git a/Misc/NEWS.d/next/Library/2019-12-02-21-03-41.bpo-36470.Gy9Sff.rst b/Misc/NEWS.d/next/Library/2019-12-02-21-03-41.bpo-36470.Gy9Sff.rst new file mode 100644 index 00000000000000..a7b16eeaf0ad63 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2019-12-02-21-03-41.bpo-36470.Gy9Sff.rst @@ -0,0 +1 @@ +Fix dataclasses with InitVars and replace(). Patch by Claudiu Popa.