https://github.com/python/cpython/commit/013c30e5fcee449cee63354d34585d61117... commit: 013c30e5fcee449cee63354d34585d6111782c82 branch: 3.9 author: Miss Islington (bot) <31488909+miss-islington@users.noreply.github.com> committer: ericvsmith <ericvsmith@users.noreply.github.com> date: 2021-04-05T16:07:38-04:00 summary: bpo-36470: Allow dataclasses.replace() to handle InitVars with default values (GH-20867) (GH-25200) Co-Authored-By: Claudiu Popa <pcmanticore@gmail.com> Automerge-Triggered-By: GH:ericvsmith (cherry picked from commit 75220674c07abfc90c2cd7862d04cfa2e2354450) Co-authored-by: Zackery Spytz <zspytz@gmail.com> Co-authored-by: Zackery Spytz <zspytz@gmail.com> files: A Misc/NEWS.d/next/Library/2020-06-13-23-33-32.bpo-36470.oi6Kdb.rst M Lib/dataclasses.py M Lib/test/test_dataclasses.py diff --git a/Lib/dataclasses.py b/Lib/dataclasses.py index 530d3e99574e8..21c7e0c9e2871 100644 --- a/Lib/dataclasses.py +++ b/Lib/dataclasses.py @@ -1271,7 +1271,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 b20103bdce51c..31caae9d2f393 100644 --- a/Lib/test/test_dataclasses.py +++ b/Lib/test/test_dataclasses.py @@ -3245,6 +3245,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/2020-06-13-23-33-32.bpo-36470.oi6Kdb.rst b/Misc/NEWS.d/next/Library/2020-06-13-23-33-32.bpo-36470.oi6Kdb.rst new file mode 100644 index 0000000000000..9b6ab994f3b6a --- /dev/null +++ b/Misc/NEWS.d/next/Library/2020-06-13-23-33-32.bpo-36470.oi6Kdb.rst @@ -0,0 +1,2 @@ +Fix dataclasses with ``InitVar``\s and :func:`~dataclasses.replace()`. Patch +by Claudiu Popa.