Coverage for mymeco/config.py: 100%

46 statements  

« prev     ^ index     » next       coverage.py v7.4.1, created at 2024-12-11 22:07 +0000

1# coding: utf-8 

2"""Handle application configuration file.""" 

3import os 

4import logging 

5import typing 

6import configparser 

7 

8from mymeco import exceptions as exc 

9 

10 

11class Configuration(): 

12 """Handle configuration file.""" 

13 

14 __log: logging.Logger = logging.getLogger() 

15 __filelist: typing.Iterable[str] = [ 

16 os.path.join(os.environ.get('HOME', '/root'), '.mymeco'), 

17 os.path.join( 

18 os.environ.get( 

19 'XDG_CONFIG_HOME', 

20 os.path.join(os.environ.get('HOME', '/root'), '.config') 

21 ), 

22 'mymeco', 

23 'config' 

24 ), 

25 os.path.join( 

26 os.environ.get( 

27 'XDG_CONFIG_DIRS', 

28 os.path.join(os.sep, 'etc', 'xdg') 

29 ), 

30 'mymeco', 

31 'config' 

32 ) 

33 ] 

34 

35 __level_map: typing.Mapping[str, typing.Tuple[int, int]] = { 

36 'critical': (0, 3), 

37 'critic': (0, 3), 

38 'error': (0, 2), 

39 'warn': (0, 1), 

40 'warning': (0, 1), 

41 'info': (0, 0), 

42 'debug': (1, 0) 

43 } 

44 

45 def __init__(self, 

46 configfile: typing.Optional[str] = None) -> None: 

47 """ 

48 Read configuration file and store config keys. 

49 

50 :param configfile: Set configuration file to use a specific one. If 

51 not defined, will try to autodetect a configuration file at the 

52 following location: 

53 - ``$HOME/.mymeco`` 

54 - ``$XDG_CONFIG_HOME/mymeco/config`` 

55 (or ``~/.config/mymeco/config``) 

56 - ``$XDG_CONFIG_DIRS/mymeco/config`` 

57 (or ``/etc/xdg/mymeco/config``) 

58 - ``$HOME/.config/mymeco/config`` 

59 """ 

60 if configfile is None: 

61 # Detect config file 

62 configfile = self.__autodetect() 

63 elif not os.path.isfile(configfile): 

64 configfile = None 

65 

66 if configfile is None: 

67 self.__log.warning('No configuration file found') 

68 raise exc.NoConfigurationFile() 

69 

70 self.__configfile = configfile 

71 self.__config = configparser.ConfigParser() 

72 self.__config.read(self.__configfile) 

73 

74 @property 

75 def configfile(self) -> str: 

76 """ 

77 Get configuration file found. 

78 

79 :return: Full path of found configuration file where data are 

80 extracted. 

81 """ 

82 return self.__configfile 

83 

84 def log( 

85 self 

86 ) -> typing.Mapping[str, typing.Union[int, bool]]: 

87 """ 

88 Get logger configuration. 

89 

90 Read configuration file and extract right configuration for logger, 

91 ready to be passed to ``mymeco.logger.configure`` function. 

92 

93 :return: Ready to use `kwargs` for ``mymeco.logger.configure`` method. 

94 """ 

95 if self.__config.has_section('log'): 

96 level = str(self.__config['log'].get('level')).lower() 

97 try: 

98 colored = self.__config['log'].getboolean('colored') 

99 except ValueError: 

100 colored = True 

101 (verb, quiet) = self.__level_map.get(level, (0, 0)) 

102 else: 

103 verb, quiet, colored = (0, 0, True) 

104 return { 

105 'verbosity_count': verb, 

106 'quiet_count': quiet, 

107 'colored': colored 

108 } 

109 

110 def tmdb( 

111 self 

112 ) -> typing.Mapping[str, str]: 

113 """ 

114 Get TMDb configuration. 

115 

116 Read configuration file and extract The Movie Database configuration. 

117 

118 :return: Configuration map to access TMDb service. Output contains at 

119 least the following keys: 

120 * `token`: access token 

121 

122 :raises: ``MissingConfiguration`` exception is raised when 

123 configuration entry is missing. 

124 """ 

125 if not self.__config.has_section('tmdb'): 

126 raise exc.MissingConfiguration('tmdb', None, self.configfile) 

127 

128 token: typing.Union[None, str] = self.__config['tmdb'].get( 

129 'token', None 

130 ) 

131 if token is None: 

132 raise exc.MissingConfiguration('tmdb', 'token', self.configfile) 

133 

134 return { 

135 'token': token 

136 } 

137 

138 def __autodetect(self) -> typing.Union[str, None]: 

139 for config in self.__filelist: 

140 if os.path.isfile(config): 

141 return config 

142 return None