Coverage for src/configuraptor/dump.py: 100%

31 statements  

« prev     ^ index     » next       coverage.py v7.2.7, created at 2023-06-15 16:40 +0200

1""" 

2Method to dump classes to other formats. 

3""" 

4 

5import json 

6import typing 

7 

8import tomlkit 

9import yaml 

10 

11from .core import instance_of_custom_class, is_custom_class 

12from .helpers import camel_to_snake 

13 

14 

15def asdict(inst: typing.Any, _level: int = 0, /, with_top_level_key: bool = True) -> dict[str, typing.Any]: 

16 """ 

17 Dump a config instance to a dictionary (recursively). 

18 """ 

19 data = {} 

20 

21 for key, value in inst.__dict__.items(): 

22 cls = value.__class__ 

23 if is_custom_class(cls): 

24 value = asdict(value, _level + 1) 

25 elif isinstance(value, list): 

26 value = [asdict(_, _level + 1) if instance_of_custom_class(_) else _ for _ in value] 

27 elif isinstance(value, dict): 

28 value = {k: asdict(v, _level + 1) if instance_of_custom_class(v) else v for k, v in value.items()} 

29 

30 data[key] = value 

31 

32 if _level == 0 and with_top_level_key: 

33 # top-level: add an extra key indicating the class' name 

34 cls_name = camel_to_snake(inst.__class__.__name__) 

35 return {cls_name: data} 

36 

37 return data 

38 

39 

40def astoml(inst: typing.Any, sort_keys: bool = False) -> str: 

41 """ 

42 Dump a config instance to toml (recursively). 

43 """ 

44 data = asdict(inst) 

45 return tomlkit.dumps(data, sort_keys=sort_keys) 

46 

47 

48def asjson(inst: typing.Any, **kw: typing.Any) -> str: 

49 """ 

50 Dump a config instance to json (recursively). 

51 """ 

52 data = asdict(inst) 

53 return json.dumps(data, **kw) 

54 

55 

56def asyaml(inst: typing.Any, **kw: typing.Any) -> str: 

57 """ 

58 Dump a config instance to yaml (recursively). 

59 """ 

60 data = asdict(inst) 

61 output = yaml.dump(data, encoding=None, **kw) 

62 # output is already a str but mypy doesn't know that 

63 return typing.cast(str, output)