Test Failed
Push — master ( 21d6d5...2715e8 )
by Jan
02:44 queued 11s
created

put._fix_var_sub_in_text()   A

Complexity

Conditions 1

Size

Total Lines 4
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 4
nop 4
dl 0
loc 4
rs 10
c 0
b 0
f 0
1
import collections
2
import os
3
import sys
4
import re
5
6
import argparse
7
8
import ssg.build_yaml
9
import ssg.constants
10
11
import template_renderer
12
13
14
def process_refs(ref_format, relevant_refs):
15
    matching_relevant_refs = []
16
    not_matching_relevant_refs = []
17
18
    for ref in relevant_refs:
19
        match = re.match(ref_format, ref)
20
        if match:
21
            matching_relevant_refs.append(ref)
22
        else:
23
            not_matching_relevant_refs.append(ref)
24
25
    sorted_relevant_refs = matching_relevant_refs + not_matching_relevant_refs
26
    return sorted_relevant_refs
27
28
29
def shorten_relevant_ref(ref_format, ref):
30
    match = re.match(ref_format, ref)
31
    if match:
32
        groups = []
33
        for refpart in match.groups():
34
            if refpart is None:
35
                refpart = ""
36
            try:
37
                refpart = "{0:07d}".format(int(refpart))
38
            except ValueError:
39
                pass
40
            groups.append(refpart)
41
        return tuple(groups)
42
    else:
43
        return TableHtmlOutput.DEFAULT_SHORTENED_REF
44
45
46
class TableHtmlOutput(template_renderer.Renderer):
47
    DEFAULT_SHORTENED_REF = ("~",)
48
49
    def __init__(self, * args, ** kwargs):
50
        super(TableHtmlOutput, self).__init__(* args, ** kwargs)
51
52
        self.rules_root = os.path.join(self.built_content_path, "rules")
53
        self.var_root = os.path.join(self.built_content_path, "values")
54
55
    def _get_var_value(self, varname):
56
        return self._get_var_value_from_default(varname)
57
58
    def _get_var_value_from_default(self, varname):
59
        var_path = os.path.join(self.var_root, varname + ".yml")
60
        var = ssg.build_yaml.Value.from_yaml(var_path, self.env_yaml)
61
        return var.options["default"]
62
63
    def _fix_var_sub_in_text(self, text, varname, value):
64
        return re.sub(
65
            r'<sub\s+idref="{var}"\s*/>'.format(var=varname),
66
            r"<tt>{val}</tt>".format(val=value), text)
67
68
    def _resolve_var_substitutions(self, rule):
69
        # The <sub .../> here is not the HTML subscript element <sub>...</sub>,
70
        # and therefore is invalid HTML.
71
        # so this code substitutes the whole sub element with contents of its idref prefixed by $
72
        # as occurrence of sub with idref implies that substitution of XCCDF values takes place
73
        variables = re.findall(r'<sub\s+idref="([^"]*)"\s*/>', rule.description)
74
        variables = set(variables)
75
        rule.substitutions = dict()
76
        for var in variables:
77
            val = self._get_var_value(var)
78
            rule.description = self._fix_var_sub_in_text(rule.description, var, val)
79
            rule.substitutions[var] = val
80
81
    def _get_eligible_rules(self, refcat):
82
        raise NotImplementedError
83
84
    def _generate_shortened_ref(self, reference, rule):
85
        shortened_ref = shorten_relevant_ref(reference.regex_with_groups, rule.relevant_refs[0])
86
        if not shortened_ref:
87
            shortened_ref = self.DEFAULT_SHORTENED_REF
88
        return shortened_ref
89
90
    def process_rules(self, reference):
91
        eligible_rules = self._get_eligible_rules(reference.id)
92
93
        output_rules = collections.defaultdict(list)
94
        for rule in eligible_rules:
95
            rid = rule.id_
96
            self._resolve_var_substitutions(rule)
97
98
            relevant_refs = rule.references.get(reference.id, "")
99
            relevant_refs = relevant_refs.split(",")
100
101
            rule.relevant_refs = process_refs(reference.regex_with_groups, relevant_refs)
102
            shortened_ref = self._generate_shortened_ref(reference, rule)
103
            output_rules[shortened_ref].append(rule)
104
105
        self.template_data["rules_by_shortref"] = output_rules
106
        self.template_data["sorted_refs"] = sorted(list(output_rules.keys()))
107
        self.template_data["reference_title"] = reference.name
108
        self.template_data["product"] = self.product
109
        self.template_data["product_full_name"] = self.product
110
        for full, short in ssg.constants.FULL_NAME_TO_PRODUCT_MAPPING.items():
111
            if short == self.product:
112
                self.template_data["product_full_name"] = full
113
                break
114
115
116
def update_parser(parser):
117
    parser.add_argument(
118
        "refcategory", metavar="REFERENCE_ID",
119
        choices=ssg.constants.REFERENCES.keys(), help="Category of the rule reference")
120