-
-
Notifications
You must be signed in to change notification settings - Fork 30.1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
dataclasses.asdict breaks with defaultdict fields #79721
Comments
_asdict_inner attempts to manually recursively deepcopy dicts by calling type(obj) with a generator of transformed keyvalue tuples @ Line 1080 in b2f642c
import collections
import dataclasses as dc
@dc.dataclass()
class C:
d: dict
c = C(collections.defaultdict(lambda: 3, {}))
d = dc.asdict(c)
=> Traceback (most recent call last):
File "boom.py", line 9, in <module>
d = dc.asdict(c)
File "/Users/spinlock/.pyenv/versions/3.7.1/lib/python3.7/dataclasses.py", line 1019, in asdict
return _asdict_inner(obj, dict_factory)
File "/Users/spinlock/.pyenv/versions/3.7.1/lib/python3.7/dataclasses.py", line 1026, in _asdict_inner
value = _asdict_inner(getattr(obj, f.name), dict_factory)
File "/Users/spinlock/.pyenv/versions/3.7.1/lib/python3.7/dataclasses.py", line 1058, in _asdict_inner
for k, v in obj.items())
TypeError: first argument must be callable or None I understand that it isn't this bit of code's job to support every dict (and list etc.) subclass under the sun but given defaultdict is stdlib it's imo worth supporting explicitly. |
Considering that if isinstance(obj, dict):
new_keys = tuple((_asdict_inner(k, dict_factory),
_asdict_inner(v, dict_factory))
for k, v in obj.items())
Another more general alternative would be to add a type registry for In any case I think it's quite unfortunate that we can't easily just support anything that has a deepcopy defined. There may be some crazy solution that involves passing a class with a custom getitem to the |
I checked and it appears that Using I think changing the default behavior like that would be a backwards-incompatible change at this point (and one that it's really hard to warn about, unfortunately), but we could still use the "fall back to dict_factory" behavior by trying to construct a |
I was wondering if this issue is still being tracked for resolution? I found the same bug in Python 3.8. |
I am seeing this bug with 3.9.7 |
Fixed in #32056. Thanks! |
Note: these values reflect the state of the issue at the time it was migrated and might not reflect the current state.
Show more details
GitHub fields:
bugs.python.org fields:
The text was updated successfully, but these errors were encountered: