Failed Conditions
Pull Request — master (#2076)
by Abdeali
02:04
created

coalib/settings/Section.py (53 issues)

1
import copy
2
import os
3
import sys
4
from collections import OrderedDict
5
6
from coalib.collecting.Collectors import collect_registered_bears_dirs
7
from coalib.misc.Decorators import enforce_signature, generate_repr
8
from coalib.misc.DictUtilities import update_ordered_dict_key
9
from coalib.settings.Setting import Setting, path_list
10
from coalib.parsing.Globbing import glob_escape
11
12
13
def append_to_sections(sections,
14
                       key,
15
                       value,
16
                       origin,
17
                       section_name=None,
18
                       from_cli=False):
19
    """
20
    Appends the given data as a Setting to a Section with the given name. If
21
    the Section does not exist before it will be created empty.
22
23
    :param sections:     The sections dictionary to add to.
24
    :param key:          The key of the setting to add.
25
    :param value:        The value of the setting to add.
26
    :param origin:       The origin value of the setting to add.
27
    :param section_name: The name of the section to add to.
28
    :param from_cli:     Whether or not this data comes from the CLI.
29
    """
30
    if key == '' or value is None:
31
        return
32
33
    if section_name == "" or section_name is None:
34
        section_name = "default"
35
36
    if not section_name.lower() in sections:
37
        sections[section_name.lower()] = Section(section_name)
38
39
    sections[section_name.lower()].append(
40
        Setting(key, str(value), origin, from_cli=from_cli))
41
42
43
@generate_repr()
44
class Section:
45
    """
46
    This class holds a set of settings.
47
    """
48
49
    @staticmethod
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable staticmethod does not seem to be defined.
Loading history...
50
    def __prepare_key(key):
51
        return str(key).lower().strip()
52
53
    def __init__(self,
54
                 name,
55
                 defaults=None):
56
        if defaults is not None and not isinstance(defaults, Section):
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable Section does not seem to be defined.
Loading history...
Comprehensibility Best Practice introduced by
The variable defaults does not seem to be defined.
Loading history...
57
            raise TypeError("defaults has to be a Section object or None.")
58
        if defaults is self:
59
            raise ValueError("defaults may not be self for non-recursivity.")
60
61
        self.name = str(name)
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable name does not seem to be defined.
Loading history...
62
        self.defaults = defaults
63
        self.contents = OrderedDict()
64
65
    def bear_dirs(self):
66
        bear_dirs = path_list(self.get("bear_dirs", ""))
67
        for bear_dir in bear_dirs:
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable bear_dirs does not seem to be defined.
Loading history...
68
            sys.path.append(bear_dir)
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable bear_dir does not seem to be defined.
Loading history...
69
        bear_dir_globs = [
70
            os.path.join(glob_escape(bear_dir), "**")
71
            for bear_dir in bear_dirs]
72
        bear_dir_globs += [
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable bear_dir_globs does not seem to be defined.
Loading history...
73
            os.path.join(glob_escape(bear_dir), "**")
74
            for bear_dir in collect_registered_bears_dirs('coalabears')]
75
        return bear_dir_globs
76
77
    def is_enabled(self, targets):
78
        """
79
        Checks if this section is enabled or, if targets is not empty, if it is
80
        included in the targets list.
81
82
        :param targets: List of target section names, all lower case.
83
        :return:        True or False
84
        """
85
        if len(targets) == 0:
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable targets does not seem to be defined.
Loading history...
86
            return bool(self.get("enabled", "true"))
87
88
        return self.name.lower() in targets
89
90
    def append(self, setting, custom_key=None):
91
        if not isinstance(setting, Setting):
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable setting does not seem to be defined.
Loading history...
Comprehensibility Best Practice introduced by
The variable Setting does not seem to be defined.
Loading history...
92
            raise TypeError
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable TypeError does not seem to be defined.
Loading history...
93
        if custom_key is None:
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable custom_key does not seem to be defined.
Loading history...
94
            key = self.__prepare_key(setting.key)
95
        else:
96
            key = self.__prepare_key(custom_key)
97
98
        # Setting asserts key != "" for us
99
        self.contents[key] = setting
100
101
    def add_or_create_setting(self,
102
                              setting,
103
                              custom_key=None,
104
                              allow_appending=True):
105
        """
106
        Adds the value of the setting to an existing setting if there is
107
        already a setting  with the key. Otherwise creates a new setting.
108
        """
109
        if custom_key is None:
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable custom_key does not seem to be defined.
Loading history...
110
            key = setting.key
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable setting does not seem to be defined.
Loading history...
111
        else:
112
            key = custom_key
113
114
        if self.__contains__(key, ignore_defaults=True) and allow_appending:
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable key does not seem to be defined.
Loading history...
Comprehensibility Best Practice introduced by
The variable allow_appending does not seem to be defined.
Loading history...
115
            val = self[key]
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable self does not seem to be defined.
Loading history...
116
            val.value = str(val.value) + "\n" + setting.value
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable val does not seem to be defined.
Loading history...
117
        else:
118
            self.append(setting, custom_key=key)
119
120
    @enforce_signature
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable enforce_signature does not seem to be defined.
Loading history...
121
    def __setitem__(self, key: str, value: (str, Setting)):
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable Setting does not seem to be defined.
Loading history...
Comprehensibility Best Practice introduced by
The variable str does not seem to be defined.
Loading history...
122
        """
123
        Creates a Setting object from the given value if needed and assigns the
124
        setting to the key:
125
126
        >>> section = Section('section_name')
127
        >>> section['key'] = 'value'
128
        >>> section['key'].value
129
        'value'
130
131
        :param key:   Argument whose value is to be set
132
        :param value: The value of the given key
133
        :return:      Returns nothing.
134
        """
135
        if isinstance(value, Setting):
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable value does not seem to be defined.
Loading history...
136
            self.append(value, custom_key=key)
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable key does not seem to be defined.
Loading history...
137
        else:  # It must be a string since signature is enforced
138
            self.append(Setting(key, value))
139
140
    def __iter__(self, ignore_defaults=False):
141
        joined = self.contents.copy()
142
        if self.defaults is not None and not ignore_defaults:
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable ignore_defaults does not seem to be defined.
Loading history...
Comprehensibility Best Practice introduced by
The variable self does not seem to be defined.
Loading history...
143
            # Since we only return the iterator of joined (which doesnt contain
144
            # values) it's ok to override values here
145
            joined.update(self.defaults.contents)
146
147
        return iter(joined)
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable joined does not seem to be defined.
Loading history...
148
149
    def __contains__(self, item, ignore_defaults=False):
150
        try:
151
            self.__getitem__(item, ignore_defaults)
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable item does not seem to be defined.
Loading history...
Comprehensibility Best Practice introduced by
The variable ignore_defaults does not seem to be defined.
Loading history...
152
153
            return True
154
        except IndexError:
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable IndexError does not seem to be defined.
Loading history...
155
            return False
156
157
    def __getitem__(self, item, ignore_defaults=False):
158
        key = self.__prepare_key(item)
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable item does not seem to be defined.
Loading history...
159
        if key == "":
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable key does not seem to be defined.
Loading history...
160
            raise IndexError("Empty keys are invalid.")
161
162
        res = self.contents.get(key, None)
163
        if res is not None:
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable res does not seem to be defined.
Loading history...
164
            return res
165
166
        if self.defaults is None or ignore_defaults:
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable self does not seem to be defined.
Loading history...
Comprehensibility Best Practice introduced by
The variable ignore_defaults does not seem to be defined.
Loading history...
167
            raise IndexError("Required index is unavailable.")
168
169
        return self.defaults[key]
170
171
    def __str__(self):
172
        value_list = ", ".join(key + " : " + repr(str(self.contents[key]))
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable key does not seem to be defined.
Loading history...
Comprehensibility Best Practice introduced by
The variable self does not seem to be defined.
Loading history...
173
                               for key in self.contents)
174
        return self.name + " {" + value_list + "}"
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable value_list does not seem to be defined.
Loading history...
175
176
    def get(self, key, default="", ignore_defaults=False):
177
        """
178
        Retrieves the item without raising an exception. If the item is not
179
        available an appropriate Setting will be generated from your provided
180
        default value.
181
182
        :param key:             The key of the setting to return.
183
        :param default:         The default value
184
        :param ignore_defaults: Whether or not to ignore the default section.
185
        :return:                The setting.
186
        """
187
        try:
188
            return self.__getitem__(key, ignore_defaults)
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable ignore_defaults does not seem to be defined.
Loading history...
Comprehensibility Best Practice introduced by
The variable key does not seem to be defined.
Loading history...
189
        except IndexError:
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable IndexError does not seem to be defined.
Loading history...
190
            return Setting(key, str(default))
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable default does not seem to be defined.
Loading history...
191
192
    def copy(self):
193
        """
194
        :return: a deep copy of this object
195
        """
196
        result = copy.copy(self)
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable self does not seem to be defined.
Loading history...
197
        result.contents = copy.deepcopy(self.contents)
198
        if self.defaults is not None:
199
            result.defaults = self.defaults.copy()
200
201
        return result
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable result does not seem to be defined.
Loading history...
202
203
    def update(self, other_section, ignore_defaults=False):
204
        """
205
        Incorporates all keys and values from the other section into this one.
206
        Values from the other section override the ones from this one.
207
208
        Default values from the other section override the default values from
209
        this only.
210
211
        :param other_section:   Another Section
212
        :param ignore_defaults: If set to true, do not take default values from
213
                                other
214
        :return:                self
215
        """
216
        if not isinstance(other_section, Section):
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable other_section does not seem to be defined.
Loading history...
Comprehensibility Best Practice introduced by
The variable Section does not seem to be defined.
Loading history...
217
            raise TypeError("other_section has to be a Section")
218
219
        self.contents.update(other_section.contents)
220
221
        if not ignore_defaults and other_section.defaults is not None:
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable ignore_defaults does not seem to be defined.
Loading history...
222
            if self.defaults is None:
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable self does not seem to be defined.
Loading history...
223
                self.defaults = other_section.defaults.copy()
224
            else:
225
                self.defaults.update(other_section.defaults)
226
227
        return self
228
229
    def update_setting(self,
230
                       key,
231
                       new_key=None,
232
                       new_value=None):
233
        """
234
        Updates a setting with new values.
235
        :param key:       The old key string.
236
        :param new_key:   The new key string.
237
        :param new_value: The new value for the setting
238
        """
239
        if new_key is not None:
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable new_key does not seem to be defined.
Loading history...
240
            self.contents[key].key = new_key
241
            self.contents = update_ordered_dict_key(self.contents,
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable self does not seem to be defined.
Loading history...
242
                                                    key,
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable key does not seem to be defined.
Loading history...
243
                                                    new_key)
244
        if new_value is not None:
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable new_value does not seem to be defined.
Loading history...
245
            if new_key is not None:
246
                self.contents[new_key].value = new_value
247
            else:
248
                self.contents[key].value = new_value
249
250
    def delete_setting(self, key):
251
        """
252
        Delete a setting
253
        :param key: The key of the setting to be deleted
254
        """
255
        del self.contents[key]
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable self does not seem to be defined.
Loading history...
Comprehensibility Best Practice introduced by
The variable key does not seem to be defined.
Loading history...
256