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.