Coverage for src/configuraptor/dump.py: 100%
38 statements
« prev ^ index » next coverage.py v7.2.7, created at 2023-09-20 09:58 +0200
« prev ^ index » next coverage.py v7.2.7, created at 2023-09-20 09:58 +0200
1"""
2Method to dump classes to other formats.
3"""
5import json
6import typing
8import tomli_w
9import yaml
11from .helpers import camel_to_snake, instance_of_custom_class, is_custom_class
12from .loaders.register import register_dumper
14if typing.TYPE_CHECKING: # pragma: no cover
15 from .binary_config import BinaryConfig
18@register_dumper("dict")
19def asdict(inst: typing.Any, _level: int = 0, /, with_top_level_key: bool = True) -> dict[str, typing.Any]:
20 """
21 Dump a config instance to a dictionary (recursively).
22 """
23 data: dict[str, typing.Any] = {}
25 for key, value in inst.__dict__.items():
26 cls = value.__class__
27 if is_custom_class(cls):
28 value = asdict(value, _level + 1)
29 elif isinstance(value, list):
30 value = [asdict(_, _level + 1) if instance_of_custom_class(_) else _ for _ in value]
31 elif isinstance(value, dict):
32 value = {k: asdict(v, _level + 1) if instance_of_custom_class(v) else v for k, v in value.items()}
34 data[key] = value
36 if _level == 0 and with_top_level_key:
37 # top-level: add an extra key indicating the class' name
38 cls_name = camel_to_snake(inst.__class__.__name__)
39 return {cls_name: data}
41 return data
44@register_dumper("toml")
45def astoml(inst: typing.Any, multiline_strings: bool = False, **kw: typing.Any) -> str:
46 """
47 Dump a config instance to toml (recursively).
48 """
49 data = asdict(inst, with_top_level_key=kw.pop("with_top_level_key", True))
50 return tomli_w.dumps(data, multiline_strings=multiline_strings)
53@register_dumper("json")
54def asjson(inst: typing.Any, **kw: typing.Any) -> str:
55 """
56 Dump a config instance to json (recursively).
57 """
58 data = asdict(inst, with_top_level_key=kw.pop("with_top_level_key", True))
59 return json.dumps(data, **kw)
62@register_dumper("yaml")
63def asyaml(inst: typing.Any, **kw: typing.Any) -> str:
64 """
65 Dump a config instance to yaml (recursively).
66 """
67 data = asdict(inst, with_top_level_key=kw.pop("with_top_level_key", True))
68 output = yaml.dump(data, encoding=None, **kw)
69 # output is already a str but mypy doesn't know that
70 return typing.cast(str, output)
73@register_dumper("bytes")
74def asbytes(inst: "BinaryConfig", **_: typing.Any) -> bytes:
75 """
76 Dumper for binary config to 'pack' into a bytestring.
77 """
78 return inst._pack()