Converts the dataclass *obj* to a dict (by using the
factory function *dict_factory*). Each dataclass is converted
to a dict of its fields, as ``name: value`` pairs. dataclasses, dicts,
- lists, and tuples are recursed into. Other objects are copied with
- :func:`copy.deepcopy`.
+ frozendicts, lists, and tuples are recursed into. Other objects are copied
+ with :func:`copy.deepcopy`.
Example of using :func:`!asdict` on nested dataclasses::
Converts the dataclass *obj* to a tuple (by using the
factory function *tuple_factory*). Each dataclass is converted
- to a tuple of its field values. dataclasses, dicts, lists, and
- tuples are recursed into. Other objects are copied with
+ to a tuple of its field values. dataclasses, dicts, frozendicts, lists,
+ and tuples are recursed into. Other objects are copied with
:func:`copy.deepcopy`.
Continuing from the previous example::
If given, 'dict_factory' will be used instead of built-in dict.
The function applies recursively to field values that are
dataclass instances. This will also look into built-in containers:
- tuples, lists, and dicts. Other objects are copied with 'copy.deepcopy()'.
+ tuples, lists, dicts, and frozendicts. Other objects are copied
+ with 'copy.deepcopy()'.
"""
if not _is_dataclass_instance(obj):
raise TypeError("asdict() should be called on dataclass instances")
return obj_type(*[_asdict_inner(v, dict_factory) for v in obj])
else:
return obj_type(_asdict_inner(v, dict_factory) for v in obj)
- elif issubclass(obj_type, dict):
+ elif issubclass(obj_type, (dict, frozendict)):
if hasattr(obj_type, 'default_factory'):
# obj is a defaultdict, which has a different constructor from
# dict as it requires the default_factory as its first arg.
If given, 'tuple_factory' will be used instead of built-in tuple.
The function applies recursively to field values that are
dataclass instances. This will also look into built-in containers:
- tuples, lists, and dicts. Other objects are copied with 'copy.deepcopy()'.
+ tuples, lists, dicts, and frozendicts. Other objects are copied
+ with 'copy.deepcopy()'.
"""
if not _is_dataclass_instance(obj):
# generator (which is not true for namedtuples, handled
# above).
return type(obj)(_astuple_inner(v, tuple_factory) for v in obj)
- elif isinstance(obj, dict):
+ elif isinstance(obj, (dict, frozendict)):
obj_type = type(obj)
if hasattr(obj_type, 'default_factory'):
# obj is a defaultdict, which has a different constructor from
class GroupDict:
id: int
users: Dict[str, User]
+ @dataclass
+ class GroupFrozenDict:
+ id: int
+ users: frozendict[str, User]
a = User('Alice', 1)
b = User('Bob', 2)
gl = GroupList(0, [a, b])
gt = GroupTuple(0, (a, b))
gd = GroupDict(0, {'first': a, 'second': b})
+ gfd = GroupFrozenDict(0, frozendict({'first': a, 'second': b}))
self.assertEqual(asdict(gl), {'id': 0, 'users': [{'name': 'Alice', 'id': 1},
{'name': 'Bob', 'id': 2}]})
self.assertEqual(asdict(gt), {'id': 0, 'users': ({'name': 'Alice', 'id': 1},
{'name': 'Bob', 'id': 2})})
- self.assertEqual(asdict(gd), {'id': 0, 'users': {'first': {'name': 'Alice', 'id': 1},
- 'second': {'name': 'Bob', 'id': 2}}})
+ expected_dict = {'id': 0, 'users': {'first': {'name': 'Alice', 'id': 1},
+ 'second': {'name': 'Bob', 'id': 2}}}
+ self.assertEqual(asdict(gd), expected_dict)
+ self.assertEqual(asdict(gfd), expected_dict)
def test_helper_asdict_builtin_object_containers(self):
@dataclass
class GroupDict:
id: int
users: Dict[str, User]
+ @dataclass
+ class GroupFrozenDict:
+ id: int
+ users: frozendict[str, User]
a = User('Alice', 1)
b = User('Bob', 2)
gl = GroupList(0, [a, b])
gt = GroupTuple(0, (a, b))
gd = GroupDict(0, {'first': a, 'second': b})
+ gfd = GroupFrozenDict(0, frozendict({'first': a, 'second': b}))
self.assertEqual(astuple(gl), (0, [('Alice', 1), ('Bob', 2)]))
self.assertEqual(astuple(gt), (0, (('Alice', 1), ('Bob', 2))))
- self.assertEqual(astuple(gd), (0, {'first': ('Alice', 1), 'second': ('Bob', 2)}))
+ d = {'first': ('Alice', 1), 'second': ('Bob', 2)}
+ self.assertEqual(astuple(gd), (0, d))
+ self.assertEqual(astuple(gfd), (0, frozendict(d)))
def test_helper_astuple_builtin_object_containers(self):
@dataclass
--- /dev/null
+Add support for :class:`frozendict` in :meth:`dataclasses.asdict` and :meth:`dataclasses.astuple`.