Skip to content

Commit 7567680

Browse files
committed
bpo-35540: Fix dataclasses.asdict support for defaultdict fields
dataclasses.asdict breaks when there are `defaultdict`s in the dataclass attributes because it assumes `defaultdict` and `dict` are the same thing, but in reality `defaultdict` takes a default_factory as the first argument in its constructor. This change adds support for defaultdict fields.
1 parent 9b889b5 commit 7567680

File tree

2 files changed

+9
-0
lines changed

2 files changed

+9
-0
lines changed

Lib/dataclasses.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1295,6 +1295,14 @@ def _asdict_inner(obj, dict_factory):
12951295
# generator (which is not true for namedtuples, handled
12961296
# above).
12971297
return type(obj)(_asdict_inner(v, dict_factory) for v in obj)
1298+
elif isinstance(obj, dict) and hasattr(obj, 'default_factory'):
1299+
# obj is a defaultdict, which has a different constructor from
1300+
# dict as it requires the default_factory as its first arg.
1301+
# https://bugs.python.org/issue35540
1302+
result = type(obj)(getattr(obj, 'default_factory'))
1303+
for k, v in obj.items():
1304+
result[_asdict_inner(k, dict_factory)] = _asdict_inner(v, dict_factory)
1305+
return result
12981306
elif isinstance(obj, dict):
12991307
return type(obj)((_asdict_inner(k, dict_factory),
13001308
_asdict_inner(v, dict_factory))
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Fix :func:`dataclasses.asdict` crash when :class:`collections.defaultdict`s are present in the attributes.

0 commit comments

Comments
 (0)