Passed
Push — master ( 39cacf...a737a2 )
by Fabien
01:21 queued 13s
created

Jinja2Interpolation.__init__()   A

Complexity

Conditions 2

Size

Total Lines 6
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 6
dl 0
loc 6
rs 10
c 0
b 0
f 0
cc 2
nop 3
1
import sys
2
import os
3
import jinja2
4
5
if sys.version_info[:2] < (3, 5):
6
    # pylint: disable=E0401
7
    from backports import configparser
8
else:
9
    # pylint: disable=E0401
10
    import configparser
11
12
13
MFCONFIG = os.environ.get("MFCONFIG", "GENERIC").lower()
14
IS_PYTHON_2 = sys.version_info < (3, 0)
15
16
17
def get_real_option(option):
18
    return option.split("[")[0]
19
20
21
def get_variant(option):
22
    if "[" not in option or "]" not in option:
23
        return None
24
    tmp = option.split("[")[1].split("]")[0]
25
    if len(tmp) == 0:
26
        return None
27
    return tmp
28
29
30
def get_score(variant, configuration_name):
31
    if variant == configuration_name:
32
        return sys.maxsize
33
    if variant is None:
34
        return 0.5
35
    tmp = configuration_name.split("_")
36
    if len(tmp) > 1:
37
        for i in range(len(tmp) - 1, 0, -1):
38
            tmp2 = "_".join(tmp[0:i])
39
            if variant == tmp2:
40
                return i
41
    return 0
42
43
44
class Jinja2Interpolation(configparser.Interpolation):
45
46
    def __init__(self, jinja2_context, **template_kwargs):
47
        if "undefined" not in template_kwargs:
48
            template_kwargs["undefined"] = jinja2.Undefined
49
        self.__template_kwargs = template_kwargs
50
        self.__jinja2_context = jinja2_context
51
        configparser.Interpolation.__init__(self)
52
53
    def before_get(self, parser, section, option, value, defaults):
54
        template = jinja2.Template(value, **self.__template_kwargs)
55
        return template.render(self.__jinja2_context)
56
57
58
class OpinionatedConfigParser(configparser.ConfigParser):
59
    def __init__(
60
        self,
61
        configuration_name=None,
62
        ignore_sections_starting_with="_",
63
        *args,
64
        **kwargs
65
    ):
66
        if configuration_name is not None:
67
            self.configuration_name = configuration_name.lower()
68
        else:
69
            self.configuration_name = MFCONFIG
70
        if "default_section" in kwargs:
71
            # we can't use configparser default_section feature
72
            # so we will emulate later in the code
73
            self.__default_section = kwargs["default_section"]
74
        else:
75
            self.__default_section = None
76
        kwargs["default_section"] = None
77
        if "interpolation" not in kwargs:
78
            if IS_PYTHON_2:
79
                tmp = {}
80
                for x, y in os.environ.items():
81
                    try:
82
                        tmp[x] = y.decode('utf8')
83
                    except Exception:
84
                        print(x)
85
                        # probably a unicode error
86
                        pass
87
                kwargs["interpolation"] = Jinja2Interpolation(tmp)
88
            else:
89
                kwargs["interpolation"] = Jinja2Interpolation(os.environ)
90
        self.ignore_sections_starting_with = ignore_sections_starting_with
91
        configparser.ConfigParser.__init__(self, *args, **kwargs)
92
93
    def read(self, *args, **kwargs):
94
        configparser.ConfigParser.read(self, *args, **kwargs)
95
        self._resolve_variant()
96
97
    def read_dict(self, *args, **kwargs):
98
        configparser.ConfigParser.read_dict(self, *args, **kwargs)
99
        self._resolve_variant()
100
101
    def read_string(self, *args, **kwargs):
102
        configparser.ConfigParser.read_string(self, *args, **kwargs)
103
        self._resolve_variant()
104
105
    def read_file(self, *args, **kwargs):
106
        configparser.ConfigParser.read_file(self, *args, **kwargs)
107
        self._resolve_variant()
108
109
    def _resolve_variant(self):
110
        def deal_with_option(tmp, read_section, write_section, option):
111
            real_option = get_real_option(option)
112
            variant = get_variant(option)
113
            score = get_score(variant, self.configuration_name)
114
            if score == 0:
115
                return
116
            if real_option in tmp[write_section]:
117
                if score <= tmp[write_section][real_option][0]:
118
                    # not better score
119
                    return
120
            value = self.get(read_section, option)
121
            tmp[write_section][real_option] = (score, value)
122
123
        has_default = (
124
            self.__default_section is not None
125
            and self.__default_section in self.sections()
126
        )
127
        # first pass
128
        tmp = {}
129
        for section in self.sections():
130
            tmp[section] = {}
131
            for option in self.options(section):
132
                deal_with_option(tmp, section, section, option)
133
            if has_default:
134
                for option in self.options(self.__default_section):
135
                    deal_with_option(
136
                        tmp, self.__default_section, section, option
137
                    )
138
        # clear
139
        self.clear()
140
        # second pass
141
        for section in tmp.keys():
142
            if self.ignore_sections_starting_with and section.startswith(
143
                self.ignore_sections_starting_with
144
            ):
145
                continue
146
            for real_option in tmp[section].keys():
147
                value = tmp[section][real_option][1]
148
                if not self.has_section(section):
149
                    self.add_section(section)
150
                self.set(section, real_option, value)
151