Closed
Description
Bug report
When you call a function with incorrect key arguments or missing a required argument, you get a TypeError. But it is not always so with dataclasses.replace()
. It raises a ValueError if a keyword argument for an InitVar field is missed or if a keyword argument for a field declared with init=False is specified.
>>> from dataclasses import * >>> @dataclass ... class C: ... x: int ... y: InitVar[int] ... z: int = field(init=False, default=100) ... >>> c = C(x=11, y=22) >>> replace(c, x=1) Traceback (most recent call last): File "<stdin>", line 1, in <module> File "/home/serhiy/py/cpython3.12/Lib/dataclasses.py", line 1570, in replace raise ValueError(f"InitVar {f.name!r} " ValueError: InitVar 'y' must be specified with replace() >>> replace(c, x=1, y=2, z=3) Traceback (most recent call last): File "<stdin>", line 1, in <module> File "/home/serhiy/py/cpython3.12/Lib/dataclasses.py", line 1563, in replace raise ValueError(f'field {f.name} is declared with ' ValueError: field z is declared with init=False, it cannot be specified with replace()
It is not even consistent with constructors:
>>> C(x=1) Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: C.__init__() missing 1 required positional argument: 'y' >>> C(x=1, y=2, z=3) Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: C.__init__() got an unexpected keyword argument 'z'
And it raises a TypeError for unexpected keyword arguments.
>>> replace(c, x=1, y=2, t=3) Traceback (most recent call last): File "<stdin>", line 1, in <module> File "/home/serhiy/py/cpython3.12/Lib/dataclasses.py", line 1579, in replace return obj.__class__(**changes) ^^^^^^^^^^^^^^^^^^^^^^^^ TypeError: C.__init__() got an unexpected keyword argument 't'
I think that dataclasses.replace()
should raise TypeError in all these cases.