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

oval_graph.oval_graph   B

Complexity

Total Complexity 51

Size/Duplication

Total Lines 208
Duplicated Lines 0 %

Test Coverage

Coverage 100%

Importance

Changes 0
Metric Value
eloc 150
dl 0
loc 208
ccs 106
cts 106
cp 1
rs 7.92
c 0
b 0
f 0
wmc 51

13 Methods

Rating   Name   Duplication   Size   Complexity  
A OvalNode.add_child() 0 8 2
A OvalNode.__init__() 0 19 3
A OvalNode.save_tree_to_dict() 0 17 2
A OvalNode.change_tree_value() 0 2 1
A OvalNode.validate_negation() 0 4 2
B OvalNode.find_node_with_ID() 0 10 6
A OvalNode.add_to_tree() 0 2 1
C OvalNode._get_result_counts() 0 27 9
A OvalNode.validate_children() 0 3 3
A OvalNode.__repr__() 0 2 1
A OvalNode.validate_type() 0 5 3
A OvalNode.validate_type_and_value() 0 20 5
C OvalNode.evaluate_tree() 0 21 10

2 Functions

Rating   Name   Duplication   Size   Complexity  
A build_nodes_form_xml() 0 3 1
A restore_dict_to_tree() 0 15 2

How to fix   Complexity   

Complexity

Complex classes like oval_graph.oval_graph 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
'''
2
    Modules form my lib and for create ID
3
'''
4 1
import oval_graph.xml_parser
5 1
import oval_graph.evaluate
6 1
import uuid
7
8
9
'''
10
    This module contains methods and classes for
11
    constructing and controlling an oval tree.
12
'''
13
14
15 1
class OvalNode():
16
    '''
17
    The OvalNode object is one node of oval oval_graph.
18
19
    Args:
20
        node_id (str|int): identifies node
21
        input_node_type (str): type of node (value or operator)
22
        input_value (str): value of node
23
        children ([OvalNode]): array of children of node
24
25
    Attributes:
26
        node_id (str): id of node
27
        node_type (str): type node
28
        value (str): value of node for operator and,
29
        or, one etc... and for value true, false, error etc...
30
        children ([OvalNode]): children of node
31
    '''
32
33 1
    def __init__(
34
            self,
35
            node_id,
36
            input_node_type,
37
            input_value,
38
            input_negation,
39
            comment,
40
            children=None
41
    ):
42 1
        self.comment = comment
43 1
        self.node_id = node_id
44 1
        self.negation = self.validate_negation(input_negation)
45 1
        self.node_type = self.validate_type(input_node_type)
46 1
        self.value = self.validate_type_and_value(input_value)
47 1
        self.children = []
48 1
        self.validate_children(children)
49 1
        if children:
50 1
            for child in children:
51 1
                self.add_child(child)
52
53 1
    def validate_negation(self, input_negation):
54 1
        if not isinstance(input_negation, bool):
55 1
            raise ValueError("err- negation is bool (only True or False)")
56 1
        return input_negation
57
58 1
    def validate_type(self, input_node_type):
59 1
        node_type = input_node_type.lower()
60 1
        if node_type != "value" and node_type != "operator":
61 1
            raise ValueError("err- unknown type")
62 1
        return node_type
63
64 1
    def validate_type_and_value(self, input_value):
65 1
        value = input_value.lower()
66
67 1
        allowed_values = [
68
            "true",
69
            "false",
70
            "error",
71
            "unknown",
72
            "noteval",
73
            "notappl"]
74 1
        allowed_operators = ["or", "and", "one", "xor"]
75
76 1
        if self.node_type == "value":
77 1
            if value not in allowed_values:
78 1
                raise ValueError("err- unknown value")
79
80 1
        if self.node_type == "operator":
81 1
            if value not in allowed_operators:
82 1
                raise ValueError("err- unknown operator")
83 1
        return value
84
85 1
    def validate_children(self, children):
86 1
        if children is None and self.node_type == "operator":
87 1
            raise ValueError('err- Operator node has child!')
88
89 1
    def __repr__(self):
90 1
        return self.value
91
92 1
    def add_child(self, node):
93 1
        if self.node_type == "operator":
94 1
            assert isinstance(node, OvalNode)
95 1
            self.children.append(node)
96
        else:
97 1
            self.children = None
98 1
            raise ValueError(
99
                "err- Value node don't has any child!")
100
101 1
    def _get_result_counts(self):
102 1
        result = {
103
            'true_cnt': 0,
104
            'false_cnt': 0,
105
            'error_cnt': 0,
106
            'unknown_cnt': 0,
107
            'noteval_cnt': 0,
108
            'notappl_cnt': 0
109
        }
110
111 1
        for child in self.children:
112 1
            if child.value == 'true':
113 1
                result['true_cnt'] += 1
114 1
            elif child.value == 'false':
115 1
                result['false_cnt'] += 1
116 1
            elif child.value == 'error':
117 1
                result['error_cnt'] += 1
118 1
            elif child.value == 'unknown':
119 1
                result['unknown_cnt'] += 1
120 1
            elif child.value == 'noteval':
121 1
                result['noteval_cnt'] += 1
122 1
            elif child.value == 'notappl':
123 1
                result['notappl_cnt'] += 1
124
            else:
125 1
                if self.node_type == "operator":
126 1
                    result[child.evaluate_tree() + "_cnt"] += 1
127 1
        return result
128
129 1
    def evaluate_tree(self):
130 1
        result = self._get_result_counts()
131 1
        out_result = None
132 1
        if oval_graph.evaluate.is_notapp_result(result):
133 1
            out_result = "notappl"
134
        else:
135 1
            if self.value == "or":
136 1
                out_result = oval_graph.evaluate.oval_operator_or(result)
137 1
            elif self.value == "and":
138 1
                out_result = oval_graph.evaluate.oval_operator_and(result)
139 1
            elif self.value == "one":
140 1
                out_result = oval_graph.evaluate.oval_operator_one(result)
141 1
            elif self.value == "xor":
142 1
                out_result = oval_graph.evaluate.oval_operator_xor(result)
143
144 1
        if out_result == 'true' and self.negation:
145 1
            out_result = 'false'
146 1
        elif out_result == 'false' and self.negation:
147 1
            out_result = 'true'
148
149 1
        return out_result
150
151 1
    def save_tree_to_dict(self):
152 1
        if not self.children:
153 1
            return {
154
                'node_id': self.node_id,
155
                'type': self.node_type,
156
                'value': self.value,
157
                'negation': self.negation,
158
                'comment': self.comment,
159
                'child': None
160
            }
161 1
        return {
162
            'node_id': self.node_id,
163
            'type': self.node_type,
164
            'value': self.value,
165
            'negation': self.negation,
166
            'comment': self.comment,
167
            'child': [child.save_tree_to_dict() for child in self.children]
168
        }
169
170 1
    def find_node_with_ID(self, node_id):
171 1
        if self.node_id == node_id:
172 1
            return self
173
        else:
174 1
            for child in self.children:
175 1
                if child.node_id == node_id:
176 1
                    return child
177 1
            for child in self.children:
178 1
                if child.children != []:
179 1
                    return child.find_node_with_ID(node_id)
180
181 1
    def add_to_tree(self, node_id, newNode):
182 1
        self.find_node_with_ID(node_id).add_child(newNode)
183
184 1
    def change_tree_value(self, node_id, value):
185 1
        self.find_node_with_ID(node_id).value = value
186
187
188 1
def build_nodes_form_xml(xml_src, rule_id):
189 1
    parser = oval_graph.xml_parser.xml_parser(xml_src)
190 1
    return parser.get_oval_graph(rule_id)
191
192
193 1
def restore_dict_to_tree(dict_of_tree):
194 1
    if dict_of_tree["child"] is None:
195 1
        return OvalNode(
196
            dict_of_tree["node_id"],
197
            dict_of_tree["type"],
198
            dict_of_tree["value"],
199
            dict_of_tree["negation"],
200
            dict_of_tree['comment'])
201 1
    return OvalNode(
202
        dict_of_tree["node_id"],
203
        dict_of_tree["type"],
204
        dict_of_tree["value"],
205
        dict_of_tree["negation"],
206
        dict_of_tree['comment'],
207
        [restore_dict_to_tree(i) for i in dict_of_tree["child"]])
208