Passed
Push — master ( ee9159...d47bb7 )
by Matěj
02:05 queued 11s
created

oval_graph.oval_node.OvalNode.add_child()   A

Complexity

Conditions 2

Size

Total Lines 8
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 6
CRAP Score 2

Importance

Changes 0
Metric Value
cc 2
eloc 7
nop 2
dl 0
loc 8
ccs 6
cts 6
cp 1
crap 2
rs 10
c 0
b 0
f 0
1
'''
2
    Modules form my lib and for create ID
3
'''
4 1
import uuid
5
6 1
import oval_graph.evaluate
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_graph.
18
19
    Attributes:
20
        node_id (str): id of node
21
        node_type (str): type node
22
        value (str): value of node for operator and, or, one etc... and for value true,
23
        false, error etc...
24
        negation (bool): value indicating whether the node is negated
25
        comment (str): some comment about node
26
        tag (str): tag specifies if the node represents OVAL test,
27
        OVAL definition or XCCDF rule
28
        test_result_details (dict|None): information about test
29
        children ([OvalNode]): children of node
30
    '''
31
32 1
    def __init__(self, **kwargs):
33
        """
34
        Note:
35
            This metode construct OvalNode and validate values of parameteres.
36
37
        Required args:
38
            node_id (str|int): identifies node
39
            node_type (str): type of node (value or operator)
40
            value (str): value of node
41
42
        Optional args:
43
            negation (bool): value indicating whether the node is negated (empty eq False)
44
            comment (str): text about node (empty eq None)
45
            tag (str): tag specifies if the node represents OVAL test,
46
            OVAL definition or XCCDF rule (empty eq None)
47
            test_result_details (dict|None): information about test (empty eq None)
48
            children ([OvalNode]): array of children of node (empty eq empty array)
49
        """
50 1
        try:
51 1
            self.node_id = kwargs['node_id']
52 1
            self.node_type = self._validate_type(kwargs['node_type'])
53 1
            self.value = self._validate_value(kwargs['value'])
54
55 1
            self._check_missing_children_for_operator(
56
                kwargs.get('children', None))
57 1
            self.negation = self._validate_negation(
58
                kwargs.get('negation', False))
59 1
        except KeyError:
60 1
            raise Exception("err - Missing required argument!")
61
62 1
        self.comment = kwargs.get('comment', None)
63 1
        self.tag = kwargs.get('tag', None)
64 1
        self.test_result_details = kwargs.get('test_result_details', None)
65
66 1
        input_children = kwargs.get('children', None)
67 1
        self.children = []
68 1
        if input_children:
69 1
            for child in input_children:
70 1
                self._add_child(child)
71
72 1
    def _validate_negation(self, input_negation):
73 1
        if not isinstance(input_negation, bool):
74 1
            raise TypeError("err - Bad value of negation argument!")
75 1
        return input_negation
76
77 1
    def _validate_type(self, input_node_type):
78 1
        node_type = input_node_type.lower()
79 1
        if node_type not in ("value", "operator"):
80 1
            raise TypeError("err - Bad value of node_type argument!")
81 1
        return node_type
82
83 1
    def _validate_value(self, input_value):
84 1
        value = input_value.lower()
85
86 1
        allowed_values = [
87
            "true",
88
            "false",
89
            "error",
90
            "unknown",
91
            "noteval",
92
            "notappl"]
93 1
        allowed_operators = ["or", "and", "one", "xor"]
94
95 1
        if self.node_type == "value" and value not in allowed_values:
96 1
            raise TypeError(
97
                "err - Bad value of value argument for value type!")
98
99 1
        if self.node_type == "operator" and value not in allowed_operators:
100 1
            raise TypeError(
101
                "err - Bad value of value argument for operator type!")
102
103 1
        return value
104
105 1
    def _check_missing_children_for_operator(self, children):
106 1
        if children is None and self.node_type == "operator":
107 1
            raise ValueError(
108
                "err- Operator node must has child!")
109
110 1
    def __repr__(self):
111 1
        return self.value
112
113 1
    def _add_child(self, node):
114 1
        if self.node_type == "operator":
115 1
            assert isinstance(node, OvalNode)
116 1
            self.children.append(node)
117
        else:
118 1
            self.children = None
119 1
            raise ValueError(
120
                "err- Value node don't has any child!")
121
122 1
    def _get_result_counts(self):
123 1
        result = {
124
            'true_cnt': 0,
125
            'false_cnt': 0,
126
            'error_cnt': 0,
127
            'unknown_cnt': 0,
128
            'noteval_cnt': 0,
129
            'notappl_cnt': 0
130
        }
131
132 1
        for child in self.children:
133 1
            if child.value == 'true' and not child.negation:
134 1
                result['true_cnt'] += 1
135 1
            elif child.value == 'true' and child.negation:
136 1
                result['false_cnt'] += 1
137 1
            elif child.value == 'false' and not child.negation:
138 1
                result['false_cnt'] += 1
139 1
            elif child.value == 'false' and child.negation:
140 1
                result['true_cnt'] += 1
141
            else:
142 1
                if child.node_type == "operator":
143 1
                    result[child.evaluate_tree() + "_cnt"] += 1
144
                else:
145 1
                    result[child.value + "_cnt"] += 1
146 1
        return result
147
148 1
    def evaluate_tree(self):
149 1
        result = self._get_result_counts()
150 1
        out_result = None
151 1
        if oval_graph.evaluate.is_notapp_result(result):
152 1
            out_result = "notappl"
153
        else:
154 1
            if self.value == "or":
155 1
                out_result = oval_graph.evaluate.oval_operator_or(result)
156 1
            elif self.value == "and":
157 1
                out_result = oval_graph.evaluate.oval_operator_and(result)
158 1
            elif self.value == "one":
159 1
                out_result = oval_graph.evaluate.oval_operator_one(result)
160 1
            elif self.value == "xor":
161 1
                out_result = oval_graph.evaluate.oval_operator_xor(result)
162
163 1
        if out_result == 'true' and self.negation:
164 1
            out_result = 'false'
165 1
        elif out_result == 'false' and self.negation:
166 1
            out_result = 'true'
167
168 1
        return out_result
169
170 1
    def save_tree_to_dict(self):
171 1
        if not self.children:
172 1
            return {
173
                'node_id': self.node_id,
174
                'type': self.node_type,
175
                'value': self.value,
176
                'negation': self.negation,
177
                'comment': self.comment,
178
                'tag': self.tag,
179
                'test_result_details': self.test_result_details,
180
                'child': None
181
            }
182 1
        return {
183
            'node_id': self.node_id,
184
            'type': self.node_type,
185
            'value': self.value,
186
            'negation': self.negation,
187
            'comment': self.comment,
188
            'tag': self.tag,
189
            'test_result_details': self.test_result_details,
190
            'child': [child.save_tree_to_dict() for child in self.children]
191
        }
192
193 1
    def find_node_with_ID(self, node_id):
194 1
        if self.node_id == node_id:
195 1
            return self
196
        else:
197 1
            for child in self.children:
198 1
                if child.node_id == node_id:
199 1
                    return child
200 1
            for child in self.children:
201 1
                if child.children != []:
202 1
                    return child.find_node_with_ID(node_id)
203
204 1
    def add_to_tree(self, node_id, newNode):
205 1
        self.find_node_with_ID(node_id)._add_child(newNode)
206
207 1
    def change_tree_value(self, node_id, value):
208 1
        self.find_node_with_ID(node_id).value = value
209
210
211 1
def restore_dict_to_tree(dict_of_tree):
212 1
    if dict_of_tree["child"] is None:
213 1
        return OvalNode(
214
            node_id=dict_of_tree["node_id"],
215
            node_type=dict_of_tree["type"],
216
            value=dict_of_tree["value"],
217
            negation=dict_of_tree["negation"],
218
            comment=dict_of_tree["comment"],
219
            tag=dict_of_tree["tag"],
220
            test_result_details=dict_of_tree["test_result_details"])
221 1
    return OvalNode(
222
        node_id=dict_of_tree["node_id"],
223
        node_type=dict_of_tree["type"],
224
        value=dict_of_tree["value"],
225
        negation=dict_of_tree["negation"],
226
        comment=dict_of_tree["comment"],
227
        tag=dict_of_tree["tag"],
228
        test_result_details=dict_of_tree["test_result_details"],
229
        children=[restore_dict_to_tree(i) for i in dict_of_tree["child"]])
230