Coverage for gws-app/gws/lib/inifile/__init__.py: 100%

32 statements  

« prev     ^ index     » next       coverage.py v7.15.4, created at 2026-08-24 12:46 +0200

1"""Tools to deal with ini config files.""" 

2 

3import configparser 

4import io 

5 

6 

7def from_paths(*paths: str) -> dict: 

8 """Merges the key-value pairs of `.ini` files into a dictionary. 

9 

10 Args: 

11 paths: Paths to `.ini` files. 

12 

13 Returns: 

14 Nested dictionary with sections as keys and options as sub-keys. 

15 """ 

16 

17 res = {} 

18 cc = _from_paths(paths) 

19 

20 for sec in cc.sections(): 

21 for opt in cc.options(sec): 

22 res.setdefault(sec, {})[opt] = cc.get(sec, opt) 

23 

24 return res 

25 

26 

27def from_paths_flat(*paths: str) -> dict: 

28 """Merges the key-value pairs of `.ini` files into a flat dictionary. 

29 

30 Args: 

31 paths: Paths to `.ini` files. 

32 

33 Returns: 

34 Flat dictionary with the section names as prefixes. 

35 """ 

36 res = {} 

37 cc = _from_paths(paths) 

38 

39 for sec in cc.sections(): 

40 for opt in cc.options(sec): 

41 res[f'{sec}.{opt}'] = cc.get(sec, opt) 

42 

43 return res 

44 

45 

46def _from_paths(paths): 

47 cc = configparser.ConfigParser() 

48 cc.optionxform = lambda optionstr: str(optionstr) 

49 

50 for path in paths: 

51 cc.read(path) 

52 

53 return cc 

54 

55 

56def to_string(d: dict) -> str: 

57 """Converts key-value pairs in a dictionary to a string grouped in sections. 

58 

59 Args: 

60 d: Key-value pairs. 

61 

62 Returns: 

63 String formatted like `.ini` files. 

64 """ 

65 

66 cc = configparser.ConfigParser() 

67 

68 for k, v in d.items(): 

69 sec, _, name = k.partition('.') 

70 if not cc.has_section(sec): 

71 cc.add_section(sec) 

72 cc.set(sec, name, v) 

73 

74 with io.StringIO() as fp: 

75 cc.write(fp, space_around_delimiters=False) 

76 return fp.getvalue()