Passed
Push — master ( 868477...1b1f92 )
by Emmanuel
06:17
created

stakkr.configreader   A

Complexity

Total Complexity 9

Size/Duplication

Total Lines 85
Duplicated Lines 0 %

Test Coverage

Coverage 97.67%

Importance

Changes 0
Metric Value
eloc 48
dl 0
loc 85
ccs 42
cts 43
cp 0.9767
rs 10
c 0
b 0
f 0
wmc 9

1 Function

Rating   Name   Duplication   Size   Complexity  
A get_config_and_project_dir() 0 10 2

5 Methods

Rating   Name   Duplication   Size   Complexity  
A Config.__init__() 0 9 1
A Config.read() 0 21 3
A Config.display_errors() 0 8 1
A Config._build_config_files_list() 0 7 1
A Config._build_config_schemas_list() 0 5 1
1
# coding: utf-8
2 1
"""Simple Config Reader."""
3
4 1
from collections.abc import Iterable
0 ignored issues
show
Unused Code introduced by
Unused Iterable imported from collections.abc
Loading history...
5 1
from os import path
6 1
from sys import stderr
7 1
import anyconfig
8 1
from jsonschema.exceptions import _Error
0 ignored issues
show
introduced by
third party import "from jsonschema.exceptions import _Error" should be placed before "import anyconfig"
Loading history...
9 1
from stakkr.file_utils import get_file, find_project_dir
10
11
12 1
class Config:
13
    """
14
    Parser of Stakkr.
15
16
    Set default values and validate stakkr.yml with specs
17
    """
18
19 1
    def __init__(self, config_file: str):
20
        """
21
        Build list of files to validate a config, set default values
22
        Then the given config file
23
        """
24 1
        self.config_file, self.project_dir = get_config_and_project_dir(config_file)
25 1
        self._build_config_files_list()
26 1
        self._build_config_schemas_list()
27 1
        self.error = ''
28
29 1
    def display_errors(self):
30
        """Display errors in STDOUT."""
31 1
        from click import style
32
33 1
        msg = 'Failed validating config ('
34 1
        msg += ', '.join(self.config_files)
35 1
        msg += '):\n    - {}\n'.format(self.error)
36 1
        stderr.write(style(msg, fg='red'))
37
38 1
    def read(self):
39
        """
40
        Parse the configs and validate it.
41
42
        It could be either local or from a local services
43
        (first local then packages by alphabetical order).
44
        """
45 1
        schema = anyconfig.multi_load(self.spec_files)
46 1
        config = anyconfig.multi_load(self.config_files)
47
        # Make sure the compiled configuration is valid
48 1
        try:
49 1
            anyconfig.validate(config, schema, safe=False)
50 1
        except _Error as error:
51 1
            self.error = '{} ({})'.format(error.message, ' -> '.join(map(str, error.path)))
52 1
            return False
53
54 1
        config['project_dir'] = path.realpath(path.dirname(self.config_file))
55 1
        if config['project_name'] == '':
56 1
            config['project_name'] = path.basename(config['project_dir'])
57
58 1
        return config
59
60 1
    def _build_config_files_list(self):
61 1
        self.config_files = [
62
            # Stakkr default config
63
            get_file('static', 'config_default.yml'),
64
            '{}/services/*/config_default.yml'.format(self.project_dir)]
65
        # Stakkr main config file finally with user's values
66 1
        self.config_files += [self.config_file]
67
68 1
    def _build_config_schemas_list(self):
69 1
        self.spec_files = [
70
            # Stakkr config validation
71
            get_file('static', 'config_schema.yml'),
72
            '{}/services/*/config_schema.yml'.format(self.project_dir)]
73
74
75 1
def get_config_and_project_dir(config_file: str):
76
    """Guess config file name and project dir"""
77 1
    if config_file is not None:
78 1
        config_file = path.abspath(config_file)
79 1
        project_dir = path.dirname(config_file)
80
    else:
81 1
        project_dir = find_project_dir()
82
        config_file = '{}/stakkr.yml'.format(project_dir)
83
84
    return config_file, project_dir
85