Coverage for muuntaa/config.py: 98.18%

39 statements  

« prev     ^ index     » next       coverage.py v7.6.0, created at 2024-07-21 12:16:47 +00:00

1"""Handling functions for configuration resources.""" 

2 

3import logging 

4import pkgutil 

5from typing import Iterable, Union 

6 

7import yaml 

8 

9from muuntaa import BOOLEAN_KEYS, ConfigType, ENCODING, Pathlike, ScopedMessages 

10 

11CONFIG_RESOURCE = 'resource/config.yml' 

12 

13 

14def boolify(configuration: ConfigType, boolean_keys: Union[Iterable[str], None] = None) -> ScopedMessages: 

15 """Modify configuration in place to ensure the values of boolean keys are converted to booleans.""" 

16 scoped_messages: ScopedMessages = [] 

17 if boolean_keys is None: 

18 boolean_keys = BOOLEAN_KEYS 

19 for key in boolean_keys: 

20 try: 

21 incoming = configuration[key] 

22 except KeyError as err: 

23 scoped_messages.append( 

24 (logging.CRITICAL, f'Parsing configuration failed. Missing config key {key}: {err}.'), 

25 ) 

26 continue 

27 

28 try: 

29 if isinstance(incoming, bool): 

30 configuration[key] = incoming 

31 continue 

32 if isinstance(incoming, str): 32 ↛ 40line 32 didn't jump to line 40 because the condition on line 32 was always true

33 canonical = incoming.strip().lower() 

34 if canonical in {'true', 'yes', '1', 'y'}: 

35 configuration[key] = True 

36 continue 

37 if canonical in {'false', 'no', '0', 'n'}: 

38 configuration[key] = False 

39 continue 

40 raise ValueError('unexpected value') 

41 except (AttributeError, ValueError) as err: 

42 scoped_messages.append( 

43 ( 

44 logging.CRITICAL, 

45 f'Parsing configuration failed. Invalid value for config key {key}: {incoming} {err}.', 

46 ), 

47 ) 

48 

49 return scoped_messages 

50 

51 

52def load(external_path: Union[None, Pathlike] = None) -> ConfigType: 

53 """Load the configuration either from the package resources (default) or an external path.""" 

54 if external_path: 

55 with open(external_path, 'rt', encoding=ENCODING) as handle: 

56 return yaml.safe_load(handle) # type: ignore 

57 else: 

58 return yaml.safe_load(pkgutil.get_data(__package__, CONFIG_RESOURCE).decode(encoding=ENCODING)) # type: ignore 

59 

60 

61def eject() -> str: 

62 """Dump the configuration from the package resources to a YAML string.""" 

63 return pkgutil.get_data(__package__, CONFIG_RESOURCE).decode(encoding=ENCODING) # type: ignore