bpo-36470: Allow dataclasses.replace() to handle InitVars with default values (GH-20867)

Co-Authored-By: Claudiu Popa <pcmanticore@gmail.com>

Automerge-Triggered-By: GH:ericvsmith
This commit is contained in:
Zackery Spytz 2021-04-05 13:41:01 -06:00 committed by GitHub
parent 14829b09eb
commit 75220674c0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 21 additions and 1 deletions

View File

@ -1300,7 +1300,7 @@ def replace(obj, /, **changes):
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)

View File

@ -3251,6 +3251,24 @@ class TestReplace(unittest.TestCase):
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:

View File

@ -0,0 +1,2 @@
Fix dataclasses with ``InitVar``\s and :func:`~dataclasses.replace()`. Patch
by Claudiu Popa.