mymeco.config

mymeco/config.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
# coding: utf-8
"""Handle application configuration file."""
import os
import logging
import typing
import configparser

from mymeco import exceptions as exc


class Configuration():
    """Handle configuration file."""

    __log: logging.Logger = logging.getLogger()
    __filelist: typing.Iterable[str] = [
        os.path.join(os.environ.get('HOME', '/root'), '.mymeco'),
        os.path.join(
            os.environ.get(
                'XDG_CONFIG_HOME',
                os.path.join(os.environ.get('HOME', '/root'), '.config')
            ),
            'mymeco',
            'config'
        ),
        os.path.join(
            os.environ.get(
                'XDG_CONFIG_DIRS',
                os.path.join(os.sep, 'etc', 'xdg')
            ),
            'mymeco',
            'config'
        )
    ]

    __level_map: typing.Mapping[str, typing.Tuple[int, int]] = {
        'critical': (0, 3),
        'critic': (0, 3),
        'error': (0, 2),
        'warn': (0, 1),
        'warning': (0, 1),
        'info': (0, 0),
        'debug': (1, 0)
    }

    def __init__(self,
                 configfile: typing.Optional[str] = None) -> None:
        """
        Read configuration file and store config keys.

        :param configfile: Set configuration file to use a specific one. If
            not defined, will try to autodetect a configuration file at the
            following location:
                - ``$HOME/.mymeco``
                - ``$XDG_CONFIG_HOME/mymeco/config``
                  (or ``~/.config/mymeco/config``)
                - ``$XDG_CONFIG_DIRS/mymeco/config``
                  (or ``/etc/xdg/mymeco/config``)
                - ``$HOME/.config/mymeco/config``
        """
        if configfile is None:
            # Detect config file
            configfile = self.__autodetect()
        elif not os.path.isfile(configfile):
            configfile = None

        if configfile is None:
            self.__log.warning('No configuration file found')
            raise exc.NoConfigurationFile()

        self.__configfile = configfile
        self.__config = configparser.ConfigParser()
        self.__config.read(self.__configfile)

    @property
    def configfile(self) -> str:
        """
        Get configuration file found.

        :return: Full path of found configuration file where data are
            extracted.
        """
        return self.__configfile

    def log(
            self
    ) -> typing.Mapping[str, typing.Union[int, bool]]:
        """
        Get logger configuration.

        Read configuration file and extract right configuration for logger,
        ready to be passed to ``mymeco.logger.configure`` function.

        :return: Ready to use `kwargs` for ``mymeco.logger.configure`` method.
        """
        if self.__config.has_section('log'):
            level = str(self.__config['log'].get('level')).lower()
            try:
                colored = self.__config['log'].getboolean('colored')
            except ValueError:
                colored = True
            (verb, quiet) = self.__level_map.get(level, (0, 0))
        else:
            verb, quiet, colored = (0, 0, True)
        return {
            'verbosity_count': verb,
            'quiet_count': quiet,
            'colored': colored
        }

    def tmdb(
            self
    ) -> typing.Mapping[str, str]:
        """
        Get TMDb configuration.

        Read configuration file and extract The Movie Database configuration.

        :return: Configuration map to access TMDb service. Output contains at
            least the following keys:
            * `token`: access token

        :raises: ``MissingConfiguration`` exception is raised when
            configuration entry is missing.
        """
        if not self.__config.has_section('tmdb'):
            raise exc.MissingConfiguration('tmdb', None, self.configfile)

        token: typing.Union[None, str] = self.__config['tmdb'].get(
            'token', None
        )
        if token is None:
            raise exc.MissingConfiguration('tmdb', 'token', self.configfile)

        return {
            'token': token
        }

    def __autodetect(self) -> typing.Union[str, None]:
        for config in self.__filelist:
            if os.path.isfile(config):
                return config
        return None