Passed
Pull Request — master (#34)
by Jan
06:54 queued 01:47
created

graph.converter   F

Complexity

Total Complexity 92

Size/Duplication

Total Lines 351
Duplicated Lines 0 %

Test Coverage

Coverage 99.11%

Importance

Changes 0
Metric Value
eloc 286
dl 0
loc 351
ccs 223
cts 225
cp 0.9911
rs 2
c 0
b 0
f 0
wmc 92

28 Methods

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

How to fix   Complexity   

Complexity

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