Passed
Push — master ( ab2fc5...0b781a )
by Matěj
02:32 queued 12s
created

oval_graph.client.Client.prepare_parser()   A

Complexity

Conditions 1

Size

Total Lines 29
Code Lines 28

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 8
CRAP Score 1

Importance

Changes 0
Metric Value
cc 1
eloc 28
nop 1
dl 0
loc 29
rs 9.208
c 0
b 0
f 0
ccs 8
cts 8
cp 1
crap 1
1 1
import re
2 1
import argparse
3 1
import tempfile
4 1
import os
5 1
import webbrowser
6 1
import json
7 1
import shutil
8 1
from datetime import datetime
9
10 1
from .xml_parser import XmlParser
11 1
from .converter import Converter
12
13
14 1
class Client():
15 1
    def __init__(self, args):
16 1
        self.parser = None
17 1
        self.arg = self.parse_arguments(args)
18 1
        self.remove_pass_tests = self.arg.remove_pass_tests
19 1
        self.show_fail_rules = self.arg.show_fail_rules
20 1
        self.show_not_selected_rules = self.arg.show_not_selected_rules
21 1
        self.source_filename = self.arg.source_filename
22 1
        self.rule_name = self.arg.rule_id
23 1
        self.out = self.arg.output
24 1
        self.xml_parser = XmlParser(
25
            self.source_filename)
26 1
        if self.remove_pass_tests:
27
            raise NotImplementedError('Not implemented!')
28
29 1
    def run_gui_and_return_answers(self):
30 1
        try:
31 1
            import inquirer
32
            return inquirer.prompt(self.get_questions())
33 1
        except ImportError:
34 1
            print(self.get_selection_rules())
35 1
            return None
36
37 1
    def get_list_of_matched_rules(self):
38 1
        rules = self.search_rules_id()
39 1
        if self.show_fail_rules:
40 1
            rules = self._get_only_fail_rule(rules)
41 1
        return rules
42
43 1
    def get_list_of_lines(self):
44 1
        lines = ['== The Rule IDs ==']
45 1
        for rule in self.get_list_of_matched_rules():
46 1
            lines.append("'" + rule['id_rule'] + r'\b' + "'")
47 1
        if self.show_not_selected_rules:
48 1
            lines.append('== The not selected rule IDs ==')
49 1
            for rule in self._get_wanted_not_selected_rules():
50 1
                lines.append(rule['id_rule'] + '(Not selected)')
51 1
        lines.append(
52
            "You haven't got installed inquirer lib. "
53
            "Please copy id rule with you want use and put it in command")
54 1
        return lines
55
56 1
    def get_selection_rules(self):
57 1
        return "\n".join(self.get_list_of_lines())
58
59 1
    def get_questions(self):
60 1
        rules = self.search_rules_id()
61 1
        if self.show_fail_rules:
62 1
            rules = self._get_only_fail_rule(rules)
63 1
        choices_ = []
64 1
        for rule in rules:
65 1
            choices_.append(rule['id_rule'])
66 1
        if self.show_not_selected_rules:
67 1
            print('== The not selected rule IDs ==')
68 1
            for rule in self._get_wanted_not_selected_rules():
69 1
                print(rule['id_rule'] + '(Not selected)')
70 1
        from inquirer.questions import Checkbox as checkbox
71 1
        questions = [
72
            checkbox(
73
                'rules',
74
                message=(
75
                    "= The Rules IDs = (move - UP and DOWN arrows,"
76
                    " select - SPACE or LEFT and RIGHT arrows, submit - ENTER)"),
77
                choices=choices_,
78
            ),
79
        ]
80 1
        return questions
81
82 1
    def _get_only_fail_rule(self, rules):
83 1
        return list(filter(lambda rule: rule['result'] == 'fail', rules))
84
85 1
    def _get_wanted_rules(self):
86 1
        return [
87
            x for x in self.xml_parser.get_used_rules() if re.search(
88
                self.rule_name, x['id_rule'])]
89
90 1
    def _get_wanted_not_selected_rules(self):
91 1
        return [
92
            x for x in self.xml_parser.get_notselected_rules() if re.search(
93
                self.rule_name, x['id_rule'])]
94
95 1
    def create_dict_of_rule(self, rule_id):
96 1
        converter = Converter(self.xml_parser.get_oval_tree(rule_id))
97 1
        return converter.to_JsTree_dict()
98
99 1
    def save_dict(self, dict_, src):
100
        with open(os.path.join(src, 'data.js'), "w+") as data_file:
101
            data_file.write("var data_json =" + str(json.dumps(
102
                dict_, sort_keys=False, indent=4) + ";"))
103
104 1
    def get_src(self, src):
105 1
        _dir = os.path.dirname(os.path.realpath(__file__))
106 1
        FIXTURE_DIR = os.path.join(_dir, src)
107 1
        return str(FIXTURE_DIR)
108
109 1
    def copy_interpreter(self, dst):
110 1
        src = self.get_src('tree_html_interpreter')
111 1
        os.mkdir(dst)
112 1
        for item in os.listdir(src):
113 1
            s = os.path.join(src, item)
114 1
            d = os.path.join(dst, item)
115 1
            if os.path.isdir(s):
116 1
                shutil.copytree(s, d)
117
            else:
118 1
                shutil.copy2(s, d)
119
120 1
    def open_web_browser(self, src):
121 1
        if not self.off_webbrowser:
122
            src = os.path.join(src, 'index.html')
123
            try:
124
                webbrowser.get('firefox').open_new_tab(src)
125
            except BaseException:
126
                webbrowser.open_new_tab(src)
127
128 1
    def search_rules_id(self):
129 1
        rules = self._get_wanted_rules()
130 1
        notselected_rules = self._get_wanted_not_selected_rules()
131 1
        if len(notselected_rules) and not rules:
132 1
            raise ValueError(
133
                ('err- rule(s) "{}" was not selected, '
134
                 "so there are no results. The rule is"
135
                 ' "notselected" because it'
136
                 " wasn't a part of the executed profile"
137
                 " and therefore it wasn't evaluated "
138
                 "during the scan.")
139
                .format(notselected_rules[0]['id_rule']))
140 1
        elif not notselected_rules and not rules:
141 1
            raise ValueError('err- 404 rule not found!')
142
        else:
143 1
            return rules
144
145 1
    def save_dict(self, dict_, src):
146 1
        with open(os.path.join(src, 'data.js'), "w+") as data_file:
147 1
            data_file.write("var data_json =" + str(json.dumps(
148
                dict_, sort_keys=False, indent=4) + ";"))
149
150 1
    def get_save_src(self, rule):
151 1
        date = str(datetime.now().strftime("-%d_%m_%Y-%H_%M_%S"))
152 1
        if self.out is not None:
153 1
            if not os.path.isdir(self.out):
154 1
                os.mkdir(self.out)
155 1
                return os.path.join(self.out, 'graph-of-' + rule + date)
156
            return os.path.join(
157
                self.out,
158
                'graph-of-' + rule + date)
159 1
        return os.path.join(
160
            os.getcwd(),
161
            'graph-of-' + rule + date)
162
163 1
    def parse_arguments(self, args):
164 1
        self.prepare_parser()
165 1
        args = self.parser.parse_args(args)
166 1
        return args
167
168 1
    def prepare_parser(self):
169 1
        self.parser = argparse.ArgumentParser(
170
            description="Client for visualization of SCAP rule evaluation results")
171 1
        self.parser.add_argument(
172
            '--show-fail-rules',
173
            action="store_true",
174
            default=False,
175
            help="Show only FAIL rules")
176 1
        self.parser.add_argument(
177
            '--show-not-selected-rules',
178
            action="store_true",
179
            default=False,
180
            help="Show notselected rules. These rules will not be visualized.")
181 1
        self.parser.add_argument(
182
            '--output',
183
            action="store",
184
            default=None,
185
            help="The directory where to save output files.")
186 1
        self.parser.add_argument(
187
            '--remove-pass-tests',
188
            action="store_true",
189
            default=False,
190
            help=(
191
                "Do not display passing tests for better orientation in"
192
                " graphs that contain a large amount of nodes.(Not implemented)"))
193 1
        self.parser.add_argument("source_filename", help="ARF scan file")
194 1
        self.parser.add_argument(
195
            "rule_id", help=(
196
                "Rule ID to be visualized. A part from the full rule ID"
197
                " a part of the ID or a regular expression can be used."
198
                " If brackets are used in the regular expression "
199
                "the regular expression must be quoted."))
200