Failed Conditions
Pull Request — master (#1990)
by Mischa
01:34
created

coalib.parsing.ConfParser.__parse_lines()   F

Complexity

Conditions 11

Size

Total Lines 48

Duplication

Lines 0
Ratio 0 %
Metric Value
cc 11
dl 0
loc 48
rs 3.1764

How to fix   Complexity   

Complexity

Complex classes like coalib.parsing.ConfParser.__parse_lines() 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
import os
2
from collections import OrderedDict
3
4
from coalib.misc import Constants
5
from coalib.parsing.LineParser import LineParser
6
from coalib.settings.Section import Section
7
from coalib.settings.Setting import Setting
8
9
10
class ConfParser:
11
12
    def __init__(self,
13
                 key_value_delimiters=('=',),
14
                 comment_seperators=('#',),
15
                 key_delimiters=(',', ' '),
16
                 section_name_surroundings=None,
17
                 remove_empty_iter_elements=True):
18
        section_name_surroundings = section_name_surroundings or {"[": "]"}
19
20
        self.line_parser = LineParser(key_value_delimiters,
21
                                      comment_seperators,
22
                                      key_delimiters,
23
                                      section_name_surroundings)
24
25
        self.__remove_empty_iter_elements = remove_empty_iter_elements
26
27
        # Declare it
28
        self.sections = None
29
        self.__rand_helper = None
30
        self.__init_sections()
31
32
    def parse(self, input_data, overwrite=False):
33
        """
34
        Parses the input and adds the new data to the existing.
35
36
        :param input_data: The filename to parse from.
37
        :param overwrite:  If True, wipes all existing Settings inside this
38
                           instance and adds only the newly parsed ones. If
39
                           False, adds the newly parsed data to the existing
40
                           one (and overwrites already existing keys with the
41
                           newly parsed values).
42
        :return:           A dictionary with (lowercase) section names as keys
43
                           and their Setting objects as values.
44
        """
45
        if os.path.isdir(input_data):
46
            input_data = os.path.join(input_data, Constants.default_coafile)
47
48
        with open(input_data, "r", encoding='utf-8') as _file:
49
            lines = _file.readlines()
50
51
        if overwrite:
52
            self.__init_sections()
53
54
        self.__parse_lines(lines, input_data)
55
56
        return self.sections
57
58
    def get_section(self, name, create_if_not_exists=False):
59
        key = self.__refine_key(name)
60
        sec = self.sections.get(key, None)
61
        if sec is not None:
62
            return sec
63
64
        if not create_if_not_exists:
65
            raise IndexError
66
67
        retval = self.sections[key] = Section(str(name),
68
                                              self.sections["default"])
69
        return retval
70
71
    @staticmethod
72
    def __refine_key(key):
73
        return str(key).lower().strip()
74
75
    def __add_comment(self, section, comment, origin):
76
        key = "comment" + str(self.__rand_helper)
77
        self.__rand_helper += 1
78
        section.append(Setting(
79
            key,
80
            comment,
81
            origin,
82
            remove_empty_iter_elements=self.__remove_empty_iter_elements))
83
84
    def __parse_lines(self, lines, origin):
85
        current_section_name = "default"
86
        current_section = self.get_section(current_section_name)
87
        current_keys = []
88
89
        for line in lines:
90
            section_name, keys, value, comment = self.line_parser.parse(line)
91
92
            if comment != "":
93
                self.__add_comment(current_section, comment, origin)
94
95
            if section_name != "":
96
                current_section_name = section_name
97
                current_section = self.get_section(current_section_name, True)
98
                current_keys = []
99
                continue
100
101
            if comment == "" and keys == [] and value == "":
102
                self.__add_comment(current_section, "", origin)
103
                continue
104
105
            if keys != []:
106
                current_keys = keys
107
108
            for section_override, key in current_keys:
109
                if key == "":
110
                    continue
111
112
                if section_override == "":
113
                    current_section.add_or_create_setting(
114
                        Setting(key,
115
                                value,
116
                                origin,
117
                                # Ignore PEP8Bear, it fails to format that
118
                                remove_empty_iter_elements=
119
                                self.__remove_empty_iter_elements),
120
                        allow_appending=(keys == []))
121
                else:
122
                    self.get_section(
123
                        section_override,
124
                        True).add_or_create_setting(
125
                            Setting(key,
126
                                    value,
127
                                    origin,
128
                                    # Ignore PEP8Bear, it fails to format that
129
                                    remove_empty_iter_elements=
130
                                    self.__remove_empty_iter_elements),
131
                            allow_appending=(keys == []))
132
133
    def __init_sections(self):
134
        self.sections = OrderedDict()
135
        self.sections["default"] = Section("Default")
136
        self.__rand_helper = 0
137