Passed
Push — master ( 95b531...bdcb34 )
by Emmanuel
07:38
created

stakkr.configreader.get_config_and_project_dir()   A

Complexity

Conditions 2

Size

Total Lines 10
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 6
CRAP Score 2.0116

Importance

Changes 0
Metric Value
cc 2
eloc 7
nop 1
dl 0
loc 10
ccs 6
cts 7
cp 0.8571
crap 2.0116
rs 10
c 0
b 0
f 0
1
# coding: utf-8
2 1
"""Simple Config Reader."""
3
4 1
from os import path
5 1
from sys import stderr
6 1
import anyconfig
7 1
from jsonschema.exceptions import _Error
8 1
from stakkr.file_utils import get_file, find_project_dir
9
10
11 1
class Config:
12
    """
13
    Parser of Stakkr.
14
15
    Set default values and validate stakkr.yml with specs
16
    """
17
18 1
    def __init__(self, config_file: str):
19
        """
20
        Build list of files to validate a config, set default values
21
        Then the given config file
22
        """
23 1
        self.config_file, self.project_dir = get_config_and_project_dir(config_file)
24 1
        self._build_config_files_list()
25 1
        self._build_config_schemas_list()
26 1
        self.error = ''
27
28 1
    def display_errors(self):
29
        """Display errors in STDERR."""
30 1
        from click import style
31
32 1
        msg = 'Failed validating config ('
33 1
        msg += ', '.join(self.config_files)
34 1
        msg += '):\n    - {}\n'.format(self.error)
35 1
        msg += '\nMake sure you have the right services.\n'
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
48
        # Make sure the compiled configuration is valid
49 1
        try:
50 1
            anyconfig.validate(config, schema, safe=False)
51 1
        except _Error as error:
52 1
            error_path = ' -> '.join(map(str, error.path))
53 1
            self.error = '{} ({})'.format(error.message, error_path)
54 1
            return False
55
56 1
        config['project_dir'] = path.realpath(path.dirname(self.config_file))
57 1
        if config['project_name'] == '':
58 1
            config['project_name'] = path.basename(config['project_dir'])
59
60 1
        return config
61
62 1
    def _build_config_files_list(self):
63 1
        self.config_files = [
64
            # Stakkr default config
65
            get_file('static', 'config_default.yml'),
66
            '{}/services/*/config_default.yml'.format(self.project_dir)]
67
        # Stakkr main config file finally with user's values
68 1
        self.config_files += [self.config_file]
69
70 1
    def _build_config_schemas_list(self):
71 1
        self.spec_files = [
72
            # Stakkr config validation
73
            get_file('static', 'config_schema.yml'),
74
            '{}/services/*/config_schema.yml'.format(self.project_dir)]
75
76
77 1
def get_config_and_project_dir(config_file: str):
78
    """Guess config file name and project dir"""
79 1
    if config_file is not None:
80 1
        config_file = path.abspath(config_file)
81 1
        project_dir = path.dirname(config_file)
82
    else:
83 1
        project_dir = find_project_dir()
84
        config_file = '{}/stakkr.yml'.format(project_dir)
85
86
    return config_file, project_dir
87