load_config()   F
last analyzed

Complexity

Conditions 12

Size

Total Lines 39

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 1
Metric Value
cc 12
c 1
b 0
f 1
dl 0
loc 39
rs 2.7855

How to fix   Complexity   

Complexity

Complex classes like load_config() often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

1
"""Configuration package. Contains functions to access YAML configuration file.
2
3
.. Authors:
4
    Philippe Dessauw
5
    [email protected]
6
7
.. Sponsor:
8
    Alden Dima
9
    [email protected]
10
    Information Systems Group
11
    Software and Systems Division
12
    Information Technology Laboratory
13
    National Institute of Standards and Technology
14
    http://www.nist.gov/itl/ssd/is
15
"""
16
import logging.config
17
from os import makedirs
18
from os.path import exists, join, isfile, splitext, dirname
19
import yaml
20
21
app_config = None
22
"""dict: Configuration of the overall application.
23
"""
24
25
26
def load_config(filename, root_directory):
27
    """Load a YAML configuration file. All data is stored in the variable :attr:`app_config`.
28
29
    Parameters:
30
        filename (str): YAML configuration file.
31
        root_directory (str): Installation directory of the app.
32
    """
33
    global app_config
34
35
    with open(filename, "r") as conf_file:
36
        app_config = yaml.load(conf_file)
37
38
    install_dir = dirname(filename)
39
40
    # Logging configuration
41
    if "log_conf" in app_config.keys():
42
        log_conf_name = join(install_dir, app_config["log_conf"])
43
        with open(log_conf_name, "r") as log_conf_file:
44
            log_conf = yaml.load(log_conf_file)
45
46
            # Create logs directory if it does not exist
47
            log_directory = join(root_directory, app_config["dirs"]["logs"])
48
            if not exists(log_directory):
49
                makedirs(log_directory)
50
51
            # Append the log folder to the log filename
52
            for handler in log_conf["handlers"].values():
53
                if "filename" in handler.keys():
54
                    handler["filename"] = join(log_directory, handler["filename"])
55
56
            logging.config.dictConfig(log_conf)
57
58
        del app_config["log_conf"]  # Information is no longer needed
59
60
    # Import other YAML configuration file
61
    for key, value in app_config.items():
62
        if type(value) == str and isfile(join(install_dir, value)) and splitext(value)[1] == ".yaml":
63
            with open(join(install_dir, value), "r") as subconf_file:
64
                app_config[key] = yaml.load(subconf_file)
65
66
67
def get_config(key):
68
    """Return value of a given key hash.
69
70
    Hashes are formatted using '/' to define parent-child relationship and '#' to define a list element.
71
72
    Example:
73
        Given the following YAML file (already loaded)::
74
75
            app:
76
                root: /path/to/root
77
                conf:
78
                    - dev: conf/dev.conf
79
                    - test: conf/test.conf
80
                    - prod: conf/prod.conf
81
82
        In order to get the path of the test configuration file you would type::
83
84
            >>> get_config('app/conf#2/test')
85
86
87
    Parameters:
88
        key (str): Key hash of the value to return.
89
90
    Returns:
91
        str: Value for the given key if it exists.
92
93
    Raises:
94
        ValueError: App config has not been loaded.
95
        KeyError: Key hash has not been found.
96
    """
97
    if app_config is None:
98
        raise ValueError("App config not loaded")
99
100
    try:
101
        if '/' in key:
102
            keys = key.split('/')
103
104
            tmp_keys = []
105
            for k in keys:
106
                sp = k.split('#')
107
108
                if len(sp) != 1:
109
                    sp[1] = int(sp[1])
110
111
                tmp_keys += sp
112
113
            keys = tmp_keys
114
            config_data = app_config
115
            for k in keys:
116
                config_data = config_data[k]
117
118
            return config_data
119
        else:
120
            return app_config[key]
121
    except:
122
        raise KeyError("Key "+str(key)+" not present in config file")
123