ConfParser.__parse_lines()   F
last analyzed

Complexity

Conditions 11

Size

Total Lines 48

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 11
dl 0
loc 48
rs 3.1764
c 0
b 0
f 0

How to fix   Complexity   

Complexity

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