Completed
Push — master ( 291ee9...9d841e )
by Matěj
20s queued 12s
created

ssg._parse_oval._check_sanity()   B

Complexity

Conditions 6

Size

Total Lines 18
Code Lines 16

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 6
eloc 16
nop 2
dl 0
loc 18
rs 8
c 0
b 0
f 0
1
0 ignored issues
show
Coding Style introduced by
This module should have a docstring.

The coding style of this project requires that you add a docstring to this code element. Below, you find an example for methods:

class SomeClass:
    def some_method(self):
        """Do x and return foo."""

If you would like to know more about docstrings, we recommend to read PEP-257: Docstring Conventions.

Loading history...
2
from __future__ import print_function
3
4
from ssg._xml import ElementTree as ET
5
6
7
REFERENCE_TO_GROUP = dict(
8
    var_ref="variables",
9
    test_ref="tests",
10
    object_ref="objects",
11
    state_ref="states",
12
)
13
14
15
CONTAINER_GROUPS = set((
16
    "definitions",
17
    "objects",
18
    "states",
19
    "tests",
20
    "variables",
21
))
22
23
24
class ElementFinder(object):
0 ignored issues
show
Coding Style introduced by
This class should have a docstring.

The coding style of this project requires that you add a docstring to this code element. Below, you find an example for methods:

class SomeClass:
    def some_method(self):
        """Do x and return foo."""

If you would like to know more about docstrings, we recommend to read PEP-257: Docstring Conventions.

Loading history...
Unused Code introduced by
The variable __class__ seems to be unused.
Loading history...
25
    def __init__(self, oval_groups):
26
        self.oval_groups = oval_groups
27
        self.target = None
28
        self.attrib = None
29
        self.result = set()
30
31
    def find_element(self, start_element, target_element_name, sought_attrib):
0 ignored issues
show
Coding Style introduced by
This method should have a docstring.

The coding style of this project requires that you add a docstring to this code element. Below, you find an example for methods:

class SomeClass:
    def some_method(self):
        """Do x and return foo."""

If you would like to know more about docstrings, we recommend to read PEP-257: Docstring Conventions.

Loading history...
32
        self.target = target_element_name
33
        self.attrib = sought_attrib
34
        self.result = set()
35
        self._recurse(start_element)
36
37
    def _recurse(self, element):
38
        if element.tag.endswith(self.target):
39
            self.result.add(element.attrib[self.attrib])
40
            return
41
42
        self._examine_element(element)
43
        for child in element:
44
            self._recurse(child)
45
46
    def _examine_element(self, element):
47
        name = _strip_ns_from_tag(element.tag)
48
        new_root = None
49
50
        if name in REFERENCE_TO_GROUP:
51
            reference_target = REFERENCE_TO_GROUP[name]
52
            new_root = self.oval_groups[reference_target][element.text]
53
        else:
54
            x = _search_element_for_reference_attributes(element)
0 ignored issues
show
Coding Style Naming introduced by
The name x does not conform to the variable naming conventions ((([a-z][a-z0-9_]{2,30})|(_[a-z0-9_]*))$).

This check looks for invalid names for a range of different identifiers.

You can set regular expressions to which the identifiers must conform if the defaults do not match your requirements.

If your project includes a Pylint configuration file, the settings contained in that file take precedence.

To find out more about Pylint, please refer to their site.

Loading history...
55
            if x is not None:
56
                ref_attribute_name, entity_id = x
57
                reference_target = REFERENCE_TO_GROUP[ref_attribute_name]
58
                new_root = self.oval_groups[reference_target][entity_id]
59
60
        if new_root is not None:
61
            self._recurse(new_root)
62
63
64
def _sort_by_id(elements):
65
    ret = dict()
66
    for el in elements:
0 ignored issues
show
Coding Style Naming introduced by
The name el does not conform to the variable naming conventions ((([a-z][a-z0-9_]{2,30})|(_[a-z0-9_]*))$).

This check looks for invalid names for a range of different identifiers.

You can set regular expressions to which the identifiers must conform if the defaults do not match your requirements.

If your project includes a Pylint configuration file, the settings contained in that file take precedence.

To find out more about Pylint, please refer to their site.

Loading history...
67
        ret[el.attrib["id"]] = el
68
    return ret
69
70
71
def _search_dict_for_items_that_end_with(dic, what_to_look_for):
72
    for it in dic:
0 ignored issues
show
Coding Style Naming introduced by
The name it does not conform to the variable naming conventions ((([a-z][a-z0-9_]{2,30})|(_[a-z0-9_]*))$).

This check looks for invalid names for a range of different identifiers.

You can set regular expressions to which the identifiers must conform if the defaults do not match your requirements.

If your project includes a Pylint configuration file, the settings contained in that file take precedence.

To find out more about Pylint, please refer to their site.

Loading history...
73
        if it.endswith(what_to_look_for):
74
            return dic[it]
75
    return None
76
77
78
def _search_element_for_reference_attributes(element):
79
    for ref_attribute_name in REFERENCE_TO_GROUP:
80
        occurence = _search_dict_for_items_that_end_with(
81
            element.attrib, ref_attribute_name)
82
        if occurence is not None:
83
            return ref_attribute_name, occurence
84
    return None
85
86
87
def resolve_definition(oval_groups, defn):
0 ignored issues
show
Coding Style introduced by
This function should have a docstring.

The coding style of this project requires that you add a docstring to this code element. Below, you find an example for methods:

class SomeClass:
    def some_method(self):
        """Do x and return foo."""

If you would like to know more about docstrings, we recommend to read PEP-257: Docstring Conventions.

Loading history...
88
    finder = ElementFinder(oval_groups)
89
    finder.find_element(defn, "external_variable", "id")
90
    return finder.result
91
92
93
def find_extending_defs(oval_groups, defn):
0 ignored issues
show
Coding Style introduced by
This function should have a docstring.

The coding style of this project requires that you add a docstring to this code element. Below, you find an example for methods:

class SomeClass:
    def some_method(self):
        """Do x and return foo."""

If you would like to know more about docstrings, we recommend to read PEP-257: Docstring Conventions.

Loading history...
94
    finder = ElementFinder(oval_groups)
95
    finder.find_element(defn, "extend_definition", "definition_ref")
96
    return finder.result
97
98
99
def get_container_groups(fname):
0 ignored issues
show
Coding Style introduced by
This function should have a docstring.

The coding style of this project requires that you add a docstring to this code element. Below, you find an example for methods:

class SomeClass:
    def some_method(self):
        """Do x and return foo."""

If you would like to know more about docstrings, we recommend to read PEP-257: Docstring Conventions.

Loading history...
100
    et = ET.parse(fname)
0 ignored issues
show
Coding Style Naming introduced by
The name et does not conform to the variable naming conventions ((([a-z][a-z0-9_]{2,30})|(_[a-z0-9_]*))$).

This check looks for invalid names for a range of different identifiers.

You can set regular expressions to which the identifiers must conform if the defaults do not match your requirements.

If your project includes a Pylint configuration file, the settings contained in that file take precedence.

To find out more about Pylint, please refer to their site.

Loading history...
101
102
    return _get_container_oval_groups_from_tree(et)
103
104
105
def _strip_ns_from_tag(tag_name):
106
    return tag_name.split("}", 1)[1]
107
108
109
def _get_container_oval_groups_from_tree(et):
0 ignored issues
show
Coding Style Naming introduced by
The name et does not conform to the argument naming conventions ((([a-z][a-z0-9_]{2,30})|(_[a-z0-9_]*))$).

This check looks for invalid names for a range of different identifiers.

You can set regular expressions to which the identifiers must conform if the defaults do not match your requirements.

If your project includes a Pylint configuration file, the settings contained in that file take precedence.

To find out more about Pylint, please refer to their site.

Loading history...
110
    root = et.getroot()
111
112
    oval_groups = {}
113
    for child in root:
114
        group_name = _strip_ns_from_tag(child.tag)
115
        if group_name in CONTAINER_GROUPS:
116
            oval_groups[group_name] = _sort_by_id(child)
117
118
    return oval_groups
119
120
121
def _get_resolved_definitions(oval_groups):
122
    def_id_to_vars_ids = {}
123
    for def_id, def_el in oval_groups["definitions"].items():
124
        def_id_to_vars_ids[def_id] = resolve_definition(oval_groups, def_el)
125
    return def_id_to_vars_ids
126
127
128
def _check_sanity(oval_groups, resolved_defns):
129
    all_external_variables = set()
130
    for var_id, var_el in oval_groups["variables"].items():
131
        if var_el.tag.endswith("external_variable"):
132
            all_external_variables.add(var_id)
133
134
    all_caught_variables = set()
135
    for var in resolved_defns.values():
136
        all_caught_variables.update(var)
137
138
    skipped_variables = all_external_variables.difference(all_caught_variables)
139
    if skipped_variables:
140
        print("These variables managed to slip past:", skipped_variables)
141
        strange_variables = all_caught_variables.difference(
142
            all_external_variables)
143
        assert not strange_variables, \
144
            ("There were unexpected caught variables: {}"
145
             .format(str(strange_variables)))
146
147
148
def _check_sanity_on_file(fname):
149
    oval_groups = get_container_groups(fname)
150
    resolved_defns = _get_resolved_definitions(oval_groups)
151
    _check_sanity(oval_groups, resolved_defns)
152