Make copy.replace more strongly typed#14819
Make copy.replace more strongly typed#14819decorator-factory wants to merge 4 commits intopython:mainfrom
copy.replace more strongly typed#14819Conversation
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
1 similar comment
|
According to mypy_primer, this change has no effect on the checked open source code. 🤖🎉 |
LSP-wise, a |
|
@jorenham Yes, unfortunately there's a tradeoff here
Pyright currently synthesizes a Another consideration: if you call @dataclass
class Fruit:
name: str
apple = Fruit("apple")
banana = copy.replace(apple, name=None)it's not going to complain. So accepting positional arguments while catching kwargs with incorrect types can find bugs that don't cause an immediate runtime error. I'm not sure if a good survey can be taken since |
|
Hack suggestion: add an optional positional argument with an unsatisfiable type. def replace(
obj: _SupportsReplace[_P, _RT_co],
_hack: Never = ..., # HACK: disallow positional arguments
/, *_: _P.args, **changes: _P.kwargs,
) -> _RT_co: ...With this change, calling Downsides: the error and the signature will have a confusing |
That's a pretty awesome hack, IMO. But let's see if the maintainers agree. |
|
Personally, I think the argument that In any case, the current situation seems worse, where The topic has also come up on DPO: https://discuss.python.org/t/better-typing-for-copy-replace-functions-that-operate-on-dataclasses/105004 |
The current stub for
copy.replaceaccepts arbitrary keyword arguments. We can useParamSpecto link the signature ofobj.__replace__to the supplied keyword arguments.This allows passing positional arguments to
copy.replace, but I think it's fine, given that__replace__isn't supposed to contain positional arguments in the signature anyway (docs forobject.__replace__)Demo of the proposed stub for
copy.replacein the pyright playground: