Passed
Push — master ( 501dda...a99175 )
by Jan
03:06 queued 11s
created

oval_graph.converter   F

Complexity

Total Complexity 92

Size/Duplication

Total Lines 366
Duplicated Lines 0 %

Test Coverage

Coverage 99.13%

Importance

Changes 0
Metric Value
eloc 298
dl 0
loc 366
ccs 229
cts 231
cp 0.9913
rs 2
c 0
b 0
f 0
wmc 92

29 Methods

Rating   Name   Duplication   Size   Complexity  
A converter.get_comment() 0 4 2
A converter.__init__() 0 32 2
A converter._get_node_icon() 0 5 1
A converter._fix_graph() 0 6 5
A converter._get_node_colors() 0 5 1
C converter._change_position() 0 35 11
A converter._move_rows() 0 10 3
A converter._get_node_style() 0 17 4
A converter.negate_bool() 0 6 1
A converter._get_color_edge() 0 2 1
A converter._count_max_y() 0 7 3
A converter._get_label() 0 20 5
B converter._remove_Duplication() 0 16 6
A converter._center_graph() 0 11 1
A converter.to_JsTree_dict() 0 16 3
A converter.get_negation_character() 0 4 1
A converter.create_list_of_id() 0 11 4
A converter._create_edge() 0 6 1
A converter._create_nodes_in_rows() 0 6 2
A converter.to_sigma_dict() 0 5 1
A converter._sort_nodes() 0 3 2
A converter._help_to_sigma_dict() 0 16 4
A converter._create_node() 0 15 1
A converter._get_node_title() 0 7 4
A converter._remove_empty_rows() 0 4 3
A converter._push_nodes_to_nodes_in_row() 0 3 2
B converter._sort() 0 17 6
A converter._convert_nodes_in_rows_to_nodes() 0 6 3
C converter._create_positions() 0 30 9

How to fix   Complexity   

Complexity

Complex classes like oval_graph.converter 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 1
import oval_graph.oval_graph
2 1
import collections
3 1
import re
4 1
import uuid
5
6
7 1
class converter():
8 1
    def __init__(self, tree):
9 1
        self.VALUE_TO_BOOTSTRAP_COLOR = {
10
            "true": "text-success",
11
            "false": "text-danger",
12
            "error": "text-dark",
13
            "unknown": "text-dark",
14
            "noteval": "text-dark",
15
            "notappl": "text-dark"
16
        }
17
18 1
        self.VALUE_TO_ICON = {
19
            "true": "glyphicon glyphicon-ok text-success",
20
            "false": "glyphicon glyphicon-remove text-danger",
21
            "error": "glyphicon glyphicon-question-sign text-dark",
22
            "unknown": "glyphicon glyphicon-question-sign text-dark",
23
            "noteval": "glyphicon glyphicon-question-sign text-dark",
24
            "notappl": "glyphicon glyphicon-question-sign text-dark"
25
        }
26
27 1
        self.VALUE_TO_HEX_COLOR = {
28
            "true": "#00ff00",
29
            "false": "#ff0000",
30
            "error": "#000000",
31
            "unknown": "#000000",
32
            "noteval": "#000000",
33
            "notappl": "#000000"
34
        }
35
36 1
        if isinstance(tree, oval_graph.oval_graph.OvalNode):
37 1
            self.tree = tree
38
        else:
39
            raise ValueError('err - this is not tree created from OvalNodes')
40
41 1
    def _get_node_icon(self):
42 1
        values = self._get_node_style()
43 1
        return dict(
44
            color=self.VALUE_TO_BOOTSTRAP_COLOR[values['negation_color']],
45
            icon=self.VALUE_TO_ICON[values['test_value']],
46
        )
47
48 1
    def get_comment(self):
49 1
        if self.tree.comment is not None:
50 1
            return str(self.tree.comment)
51 1
        return ""
52
53 1
    def to_JsTree_dict(self):
54 1
        icons = self._get_node_icon()
55 1
        label = self._get_label()
56 1
        out = {
57
            'text': (str(label['negation'] if label['negation'] else "") +
58
                     ' <strong><span class="' + icons['color'] + '">' +
59
                     label['str'] + '</span></strong>' +
60
                     ' <i>' + self.get_comment() + '</i>'
61
                     ),
62
            "icon": icons['icon'],
63
            "state": {
64
                "opened": True}}
65 1
        if self.tree.children:
66 1
            out['children'] = [converter(child).to_JsTree_dict()
67
                               for child in self.tree.children]
68 1
        return out
69
70 1
    def _get_node_style(self):
71 1
        value = self.tree.evaluate_tree()
72 1
        out_color = None
73 1
        if value is None:
74 1
            if self.tree.negation:
75 1
                out_color = self.negate_bool(self.tree.value)
76
            else:
77 1
                out_color = self.tree.value
78 1
            value = self.tree.value
79
        else:
80 1
            if self.tree.negation:
81 1
                out_color = self.negate_bool(value)
82
            else:
83 1
                out_color = value
84 1
        return dict(
85
            negation_color=out_color,
86
            test_value=value,
87
        )
88
89
# Methods for interpreting oval tree with SigmaJS
90 1
    def get_negation_character(self, value):
91 1
        return ('<strong><span class="' +
92
                self.VALUE_TO_BOOTSTRAP_COLOR[value] +
93
                '">&not;</strong></span>')
94
95 1
    def _get_label(self):
96 1
        out = dict(negation=None, str="")
97 1
        if self.tree.node_type == 'value':
98 1
            if self.tree.negation:
99 1
                out['negation'] = self.get_negation_character(self.tree.value)
100 1
            out['str'] = re.sub(
101
                '(oval:ssg-test_|oval:ssg-)|(:def:1|:tst:1)', '', str(self.tree.node_id))
102 1
            return out
103
        else:
104 1
            if str(self.tree.node_id).startswith('xccdf_org'):
105 1
                out['str'] = re.sub(
106
                    '(xccdf_org.ssgproject.content_)', '', str(
107
                        self.tree.node_id))
108 1
                return out
109
            else:
110 1
                if self.tree.negation:
111 1
                    out['negation'] = self.get_negation_character(
112
                        self.tree.evaluate_tree())
113 1
                out['str'] = (self.tree.value).upper()
114 1
                return out
115
116 1
    def negate_bool(self, value):
117 1
        values = {
118
            "true": "false",
119
            "false": "true",
120
        }
121 1
        return values[str(value)]
122
123 1
    def _get_node_colors(self):
124 1
        values = self._get_node_style()
125 1
        return dict(
126
            color=self.VALUE_TO_HEX_COLOR[values['negation_color']],
127
            borderColor=self.VALUE_TO_HEX_COLOR[values['test_value']],
128
        )
129
130 1
    def _get_node_title(self):
131 1
        value = self.tree.evaluate_tree()
132 1
        if value is None:
133 1
            value = self.tree.value
134 1
        if value == 'true' or value == 'false':
135 1
            return self.tree.node_id
136 1
        return str(self.tree.node_id) + ' ' + self.tree.value
137
138 1
    def _create_node(self, x, y):
139
        # print(self.evaluate_tree(),self.value)
140 1
        colors = self._get_node_colors()
141 1
        return {
142
            'id': self.tree.node_id,
143
            'label': self._get_label()['str'],
144
            'url': 'null',
145
            'text': self.tree.comment,
146
            'title': self._get_node_title(),
147
            "x": x,
148
            "y": y,
149
            "size": 3,
150
            "color": colors['color'],
151
            "type": "circle",
152
            "borderColor": colors['borderColor']}
153
154 1
    def _create_edge(self, id_source, id_target, target_node):
155 1
        return {
156
            "id": str(uuid.uuid4()),
157
            "source": id_source,
158
            "target": id_target,
159
            "color": self._get_color_edge(target_node)
160
        }
161
162 1
    def _get_color_edge(self, target_node):
163 1
        return target_node['color']
164
165 1
    def create_list_of_id(self, array_of_ids=None):
166 1
        if array_of_ids is None:
167 1
            array_of_ids = []
168 1
            array_of_ids.append(self.tree.node_id)
169 1
        for child in self.tree.children:
170 1
            if child.node_type != "operator":
171 1
                array_of_ids.append(child.node_id)
172
            else:
173 1
                array_of_ids.append(child.node_id)
174 1
                converter(child).create_list_of_id(array_of_ids)
175 1
        return array_of_ids
176
177 1
    def _remove_Duplication(self, graph_data):
178 1
        array_of_ids = self.create_list_of_id()
179 1
        out = dict(nodes=[], edges=graph_data['edges'])
180 1
        duplicate_ids = [item for item, count in collections.Counter(
181
            array_of_ids).items() if count > 1]
182
183 1
        for node in graph_data['nodes']:
184 1
            if node['id'] not in duplicate_ids:
185 1
                out['nodes'].append(node)
186
187 1
        for id in duplicate_ids:
188 1
            for node in graph_data['nodes']:
189 1
                if node['id'] == id:
190 1
                    out['nodes'].append(node)
191 1
                    break
192 1
        return out
193
194 1
    def _fix_graph(self, preprocessed_graph_data):
195 1
        for node in preprocessed_graph_data['nodes']:
196 1
            for node1 in preprocessed_graph_data['nodes']:
197 1
                if node['x'] == node1['x'] and node['y'] == node1['y']:
198 1
                    node['x'] = node['x'] - 1
199 1
        return preprocessed_graph_data
200
201 1
    def _help_to_sigma_dict(self, x, y, preprocessed_graph_data=None):
202 1
        if preprocessed_graph_data is None:
203 1
            preprocessed_graph_data = dict(nodes=[], edges=[])
204 1
            preprocessed_graph_data['nodes'].append(self._create_node(x, y))
205 1
        y_row = y + 1
206 1
        x_row = x
207 1
        for node in self.tree.children:
208 1
            preprocessed_graph_data['nodes'].append(
209
                converter(node)._create_node(x_row, y_row))
210 1
            preprocessed_graph_data['edges'].append(converter(node)._create_edge(
211
                self.tree.node_id, node.node_id, preprocessed_graph_data['nodes'][-1]))
212 1
            x_row = x_row + 1
213 1
            if node.children is not None:
214 1
                preprocessed_graph_data = converter(node)._help_to_sigma_dict(
215
                    x_row + 1, y_row + 1, preprocessed_graph_data)
216 1
        return self._fix_graph(preprocessed_graph_data)
217
218 1
    def _count_max_y(self, out):
219 1
        max_y = 0
220
221 1
        for node in out['nodes']:
222 1
            if max_y < node['y']:
223 1
                max_y = node['y']
224 1
        return max_y
225
226 1
    def _create_nodes_in_rows(self, rows):
227 1
        nodes_in_rows = dict()
228
229 1
        for i in range(rows + 1):
230 1
            nodes_in_rows[i] = []
231 1
        return nodes_in_rows
232
233 1
    def _push_nodes_to_nodes_in_row(self, out, nodes_in_rows):
234 1
        for node in out['nodes']:
235 1
            nodes_in_rows[node['y']].append(node)
236
237 1
    def _remove_empty_rows(self, nodes_in_rows, max_y):
238 1
        for row in range(max_y + 1):
239 1
            if not nodes_in_rows[row]:
240 1
                del nodes_in_rows[row]
241
242 1
    def _move_rows(self, nodes_in_rows):
243 1
        count = 0
244 1
        nodes_in_rows1 = dict()
245
246 1
        for row in nodes_in_rows:
247 1
            nodes_in_rows1[count] = nodes_in_rows[row]
248 1
            for node in nodes_in_rows1[count]:
249 1
                node['y'] = count
250 1
            count += 1
251 1
        return nodes_in_rows1
252
253 1
    def _create_positions(self, nodes_in_rows):
254 1
        positions = []
255 1
        for row in nodes_in_rows:
256 1
            len_of_row = len(nodes_in_rows[row])
257 1
            if len_of_row > 1:
258 1
                if (len_of_row % 2) == 1:
259 1
                    len_of_row += 1
260
261 1
                for i in range((int(-(len_of_row / 2))) * 2,
262
                               (int(+(len_of_row / 2)) + 1) * 2, 2):
263 1
                    positions.append(i)
264
265 1
                if len_of_row == 2:
266 1
                    positions.remove(0)
267
268 1
                if len(nodes_in_rows[row]) < len(positions):
269 1
                    positions.pop()
270 1
                    if len(nodes_in_rows[row]) < len(positions):
271 1
                        positions.pop(0)
272
273 1
                count = 0
274
275 1
                for pos in positions:
276 1
                    nodes_in_rows[row][count]['x'] = pos
277 1
                    count += 1
278 1
                positions = []
279
            else:
280 1
                nodes_in_rows[row][0]['x'] = 0
281
282 1
        return positions
283
284 1
    def _convert_nodes_in_rows_to_nodes(self, nodes_in_rows):
285 1
        nodes = []
286 1
        for row in nodes_in_rows:
287 1
            for node in nodes_in_rows[row]:
288 1
                nodes.append(node)
289 1
        return nodes
290
291 1
    def _change_position(self, nodes_in_rows):
292 1
        x = 0.6
293 1
        up_and_down = True
294 1
        down = False
295 1
        down_row = False
296 1
        save_x = 0
297 1
        continue_move = False
298
299 1
        for row in nodes_in_rows:
300 1
            for node in nodes_in_rows[row]:
301 1
                if (len(node['label']) > 6
302
                        and len(node['label']) < 40
303
                        or continue_move):
304 1
                    if up_and_down:
305 1
                        node['y'] = node['y'] + (0.6 * x)
306 1
                        up_and_down = False
307
                    else:
308 1
                        up_and_down = True
309 1
                    continue_move = True
310 1
                elif len(node['label']) > 30:
311 1
                    node['y'] = node['y'] + (0.6 * x)
312 1
                    x += 0.6
313 1
                    save_x = x
314 1
                    down = True
315
                else:
316 1
                    if down:
317 1
                        node['y'] = node['y'] + (0.6 * save_x)
318
319 1
                    if down_row:
320 1
                        node['y'] = node['y'] + (0.6 * save_x) - 0.7
321 1
            if down:
322 1
                down = False
323 1
                down_row = True
324 1
            continue_move = False
325 1
            x = 0.6
326
327 1
    def _sort(self, array):
328 1
        less = []
329 1
        equal = []
330 1
        greater = []
331
332 1
        if len(array) > 1:
333 1
            pivot = array[0]['x']
334 1
            for node in array:
335 1
                if node['x'] < pivot:
336
                    less.append(node)
337 1
                if node['x'] == pivot:
338 1
                    equal.append(node)
339 1
                if node['x'] > pivot:
340 1
                    greater.append(node)
341 1
            return self._sort(less) + equal + self._sort(greater)
342
        else:
343 1
            return array
344
345 1
    def _sort_nodes(self, nodes_in_rows):
346 1
        for row in nodes_in_rows:
347 1
            nodes_in_rows[row] = self._sort(nodes_in_rows[row])
348
349 1
    def _center_graph(self, out):
350 1
        max_y = self._count_max_y(out)
351 1
        nodes_in_rows = self._create_nodes_in_rows(max_y)
352 1
        self._push_nodes_to_nodes_in_row(out, nodes_in_rows)
353 1
        self._remove_empty_rows(nodes_in_rows, max_y)
354 1
        nodes_in_rows = self._move_rows(nodes_in_rows)
355 1
        self._sort_nodes(nodes_in_rows)
356 1
        self._create_positions(nodes_in_rows)
357 1
        self._change_position(nodes_in_rows)
358 1
        out['nodes'] = self._convert_nodes_in_rows_to_nodes(nodes_in_rows)
359 1
        return out
360
361 1
    def to_sigma_dict(self, x, y):
362 1
        return self._center_graph(
363
            self._remove_Duplication(
364
                self._help_to_sigma_dict(
365
                    x, y)))
366