You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Add function signature hooks for dataclasses functions: replace, asdict, astuple #5152
Currently, the plugin only supports dataclass creation (i.e. generation of dunder methods with correct types, including __init__). However, some functions in the dataclass modules have quite broad types in typeshed, for example:
defreplace(obj: _T, **changes: Any) ->_T: ...
so that arbitrary arguments can be give for changes, etc. The plugin should be able to give more precise type for these functions. In particular, asdict could return a TypedDict.
It's not a 100% correspondence, I'm using TS' Record type instead of dataclass and just one single changes argument instead of a **changes keyword argument. But in essence it's the type I want to give replace from the dataclasses module.
This hole is allowing errors to leak through in some of my production code. Lacking a 'typeof' operator as well, it's difficult to ensure the types are correct.
If I may, I'd like to make a case for this issue. dataclasses.replace() is equivalent to the with keyword in F#. For anyone wishing to do typed functional programming in Python, having replace() checked at compile time is critical. This issue was opened 5 years ago and even the mypy documentation says:
Some functions in the dataclasses module, such as replace() and asdict(), have imprecise (too permissive) types. This will be fixed in future releases.
I can only assume that this isn't a trivial issue to fix.
It seems I haven't made a strong case for this issue after all--I've only managed to express my frustration 😢. It's just that the next time someone asks me if it's possible to do typed functional programming in Python, I'd love to say "Yes!" instead of "Almost!"
With asdict returning an anonymous TypedDict (as planned in #8583), would this bring us any closer to closing this issue?
If the TypedDict was not anonymous, and better yet if it was part of dataclasses (e.g. if a dataclass would have __TYPED_DICT__ and in particular __PARTIAL_TYPED_DICT__ that's total=False) then this could perhaps be done in the type definition a'la
Otherwise we could try something like #14526 where we determine the signature in a function sig hook. Curiously while in attrs.evolve we can take the __init__ signature and mutate it to be all-ARG_NAMED_OPT, for replace we must make init=True arguments ARG_NAMED since they must be explicitly re-specified during replace.
FWIW I remember I thought #8583 was an OK solution. But we also need to support other methods: astuple() and replace(). They should be quite straightforward to implement, it is just a matter of spending time on carefully writing the code.
Activity
Implement support for returning TypedDict for dataclasses.asdict
Implement support for returning TypedDict for dataclasses.asdict
Implement support for returning TypedDict for dataclasses.asdict
Implement support for returning TypedDict for dataclasses.asdict
Implement support for returning TypedDict for dataclasses.asdict
danr commentedon Mar 25, 2021
How would one go about to fix the type signature for
replace? In TypeScript it is possible to give a replace function this type:It's not a 100% correspondence, I'm using TS'
Recordtype instead ofdataclassand just one singlechangesargument instead of a**changeskeyword argument. But in essence it's the type I want to givereplacefrom thedataclassesmodule.edaqa-uncountable commentedon Sep 14, 2021
This hole is allowing errors to leak through in some of my production code. Lacking a 'typeof' operator as well, it's difficult to ensure the types are correct.
OlegAlexander commentedon Mar 3, 2023
Hello and thank you for creating mypy!!
If I may, I'd like to make a case for this issue.
dataclasses.replace()is equivalent to thewithkeyword in F#. For anyone wishing to do typed functional programming in Python, havingreplace()checked at compile time is critical. This issue was opened 5 years ago and even the mypy documentation says:I can only assume that this isn't a trivial issue to fix.
It seems I haven't made a strong case for this issue after all--I've only managed to express my frustration 😢. It's just that the next time someone asks me if it's possible to do typed functional programming in Python, I'd love to say "Yes!" instead of "Almost!"
ikonst commentedon Mar 6, 2023
With
asdictreturning an anonymous TypedDict (as planned in #8583), would this bring us any closer to closing this issue?If the
TypedDictwas not anonymous, and better yet if it was part of dataclasses (e.g. if a dataclass would have__TYPED_DICT__and in particular__PARTIAL_TYPED_DICT__that'stotal=False) then this could perhaps be done in the type definition a'laOtherwise we could try something like #14526 where we determine the signature in a function sig hook. Curiously while in
attrs.evolvewe can take the__init__signature and mutate it to be all-ARG_NAMED_OPT, forreplacewe must makeinit=TrueargumentsARG_NAMEDsince they must be explicitly re-specified duringreplace.ilevkivskyi commentedon Mar 7, 2023
FWIW I remember I thought #8583 was an OK solution. But we also need to support other methods:
astuple()andreplace(). They should be quite straightforward to implement, it is just a matter of spending time on carefully writing the code.Add signature for dataclasses.replace (#14849)
OlegAlexander commentedon Sep 16, 2023
dataclasses.replaceworks properly since mypy 1.5.0. Thank you for fixing this!!