Conditions | 24 |
Total Lines | 178 |
Code Lines | 113 |
Lines | 0 |
Ratio | 0 % |
Tests | 0 |
CRAP Score | 600 |
Changes | 0 |
Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.
For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.
Commonly applied refactorings include:
If many parameters/temporary variables are present:
Complex classes like cpe_generate.main() 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 | #!/usr/bin/python3 |
||
49 | def main(): |
||
50 | args = parse_args() |
||
51 | |||
52 | # parse oval file |
||
53 | ovaltree = ssg.xml.parse_file(args.ovalfile) |
||
54 | |||
55 | # extract inventory definitions |
||
56 | # making (dubious) assumption that all inventory defs are CPE |
||
57 | defs = ovaltree.find("./{%s}definitions" % oval_ns) |
||
58 | inventory_defs = [] |
||
59 | for el in defs.findall(".//{%s}definition" % oval_ns): |
||
60 | if el.get("class") != "inventory": |
||
61 | continue |
||
62 | inventory_defs.append(el) |
||
63 | |||
64 | # Keep the list of 'id' attributes from untranslated inventory def elements |
||
65 | inventory_defs_id_attrs = [] |
||
66 | |||
67 | defs.clear() |
||
68 | [defs.append(inventory_def) for inventory_def in inventory_defs] |
||
69 | # Fill in that list |
||
70 | inventory_defs_id_attrs = \ |
||
71 | [inventory_def.get("id") for inventory_def in inventory_defs] |
||
72 | |||
73 | tests = ovaltree.find("./{%s}tests" % oval_ns) |
||
74 | cpe_tests = ssg.build_cpe.extract_referred_nodes(defs, tests, "test_ref") |
||
75 | tests.clear() |
||
76 | [tests.append(cpe_test) for cpe_test in cpe_tests] |
||
77 | |||
78 | states = ovaltree.find("./{%s}states" % oval_ns) |
||
79 | cpe_states = ssg.build_cpe.extract_referred_nodes(tests, states, "state_ref") |
||
80 | states.clear() |
||
81 | [states.append(cpe_state) for cpe_state in cpe_states] |
||
82 | |||
83 | objects = ovaltree.find("./{%s}objects" % oval_ns) |
||
84 | cpe_objects = ssg.build_cpe.extract_referred_nodes(tests, objects, "object_ref") |
||
85 | env_objects = ssg.build_cpe.extract_referred_nodes(objects, objects, "id") |
||
86 | objects.clear() |
||
87 | [objects.append(cpe_object) for cpe_object in cpe_objects] |
||
88 | |||
89 | variables = ovaltree.find("./{%s}variables" % oval_ns) |
||
90 | if variables is not None: |
||
91 | ref_var_elems = set(ssg.build_cpe.extract_referred_nodes(objects, variables, "var_ref")) |
||
92 | ref_var_elems.update(ssg.build_cpe.extract_referred_nodes(states, variables, "var_ref")) |
||
93 | |||
94 | if ref_var_elems: |
||
95 | variables.clear() |
||
96 | has_external_vars = False |
||
97 | for var in ref_var_elems: |
||
98 | if (var.tag == "{%s}external_variable" % oval_ns): |
||
99 | error_msg = "Error: External variable (%s) is referenced in a" |
||
100 | "CPE OVAL check\n" % var.get('id') |
||
101 | sys.stderr.write(error_msg) |
||
102 | has_external_vars = True |
||
103 | |||
104 | variables.append(var) |
||
105 | |||
106 | # Make sure to inlude objects referenced by a local variable |
||
107 | # But env_obj will return no objects if the local variable doesn't |
||
108 | # reference any object via object_ref |
||
109 | env_obj = ssg.build_cpe.extract_env_obj(env_objects, var) |
||
110 | if env_obj: |
||
111 | objects.append(env_obj) |
||
112 | |||
113 | if has_external_vars: |
||
114 | error_msg = "Error: External variables cannot be used by CPE OVAL checks.\n" |
||
115 | sys.stderr.write(error_msg) |
||
116 | sys.exit(1) |
||
117 | else: |
||
118 | ovaltree.remove(variables) |
||
119 | |||
120 | # turn IDs into meaningless numbers |
||
121 | translator = ssg.id_translate.IDTranslator(args.idname) |
||
122 | ovaltree = translator.translate(ovaltree) |
||
123 | |||
124 | product_yaml = ssg.products.load_product_yaml(args.product_yaml) |
||
125 | product = product_yaml["product"] |
||
126 | newovalfile = args.idname + "-" + product + "-" + os.path.basename(args.ovalfile) |
||
127 | newovalfile = newovalfile.replace("cpe-oval-unlinked", "cpe-oval") |
||
128 | ssg.xml.ElementTree.ElementTree(ovaltree).write(args.cpeoutdir + "/" + newovalfile) |
||
129 | |||
130 | # Lets scrape the shorthand for the list of platforms referenced |
||
131 | benchmark_cpe_names = set() |
||
132 | shorthandtree = ssg.xml.parse_file(args.shorthandfile) |
||
133 | for platform in shorthandtree.findall(".//{%s}platform" % XCCDF12_NS): |
||
134 | cpe_name = platform.get("idref") |
||
135 | # skip CPE AL platforms (they are handled later) |
||
136 | # this is temporary solution until we get rid of old type of platforms in the benchmark |
||
137 | if cpe_name.startswith("#"): |
||
138 | continue |
||
139 | benchmark_cpe_names.add(cpe_name) |
||
140 | # add CPE names used by factref elements in CPEAL platforms |
||
141 | for factref in shorthandtree.findall( |
||
142 | ".//ns1:fact-ref", {"ns1":ssg.constants.PREFIX_TO_NS["cpe-lang"]}): |
||
143 | cpe_factref_name = factref.get("name") |
||
144 | benchmark_cpe_names.add(cpe_factref_name) |
||
145 | |||
146 | product_cpes = ssg.build_cpe.ProductCPEs() |
||
147 | product_cpes.load_cpes_from_directory_tree(args.cpe_items_dir, product_yaml) |
||
148 | cpe_list = ssg.build_cpe.CPEList() |
||
149 | for cpe_name in benchmark_cpe_names: |
||
150 | cpe_list.add(product_cpes.get_cpe(cpe_name)) |
||
151 | |||
152 | cpedict_filename = "ssg-" + product + "-cpe-dictionary.xml" |
||
153 | cpedict_path = os.path.join(args.cpeoutdir, cpedict_filename) |
||
154 | cpe_list.to_file(cpedict_path, newovalfile) |
||
155 | |||
156 | # replace and sync IDs, href filenames in input cpe dictionary file |
||
157 | cpedicttree = ssg.xml.parse_file(cpedict_path) |
||
158 | for check in cpedicttree.findall(".//{%s}check" % cpe_ns): |
||
159 | checkhref = check.get("href") |
||
160 | # If CPE OVAL references another OVAL file |
||
161 | if checkhref == 'filename': |
||
162 | # Sanity check -- Verify the referenced OVAL is truly defined |
||
163 | # somewhere in the (sub)directory tree below CWD. In correct |
||
164 | # scenario is should be located: |
||
165 | # * either in input/oval/*.xml |
||
166 | # * or copied by former run of "combine_ovals.py" script from |
||
167 | # shared/ directory into build/ subdirectory |
||
168 | refovalfilename = check.text |
||
169 | refovalfilefound = False |
||
170 | for dirpath, dirnames, filenames in os.walk(os.curdir, topdown=True): |
||
171 | dirnames.sort() |
||
172 | filenames.sort() |
||
173 | # Case when referenced OVAL file exists |
||
174 | for location in fnmatch.filter(filenames, refovalfilename + '.xml'): |
||
175 | refovalfilefound = True |
||
176 | break # break from the inner for loop |
||
177 | |||
178 | if refovalfilefound: |
||
179 | break # break from the outer for loop |
||
180 | |||
181 | shared_dir = \ |
||
182 | os.path.dirname(os.path.dirname(os.path.realpath(__file__))) |
||
183 | if shared_dir is not None: |
||
184 | for dirpath, dirnames, filenames in os.walk(shared_dir, topdown=True): |
||
185 | dirnames.sort() |
||
186 | filenames.sort() |
||
187 | # Case when referenced OVAL file exists |
||
188 | for location in fnmatch.filter(filenames, refovalfilename + '.xml'): |
||
189 | refovalfilefound = True |
||
190 | break # break from the inner for loop |
||
191 | |||
192 | if refovalfilefound: |
||
193 | break # break from the outer for loop |
||
194 | |||
195 | # Referenced OVAL doesn't exist in the subdirtree below CWD: |
||
196 | # * there's either typo in the refenced OVAL filename, or |
||
197 | # * is has been forgotten to be placed into input/oval, or |
||
198 | # * the <platform> tag of particular shared/ OVAL wasn't modified |
||
199 | # to include the necessary referenced file. |
||
200 | # Therefore display an error and exit with failure in such cases |
||
201 | if not refovalfilefound: |
||
202 | error_msg = "\n\tError: Can't locate \"%s\" OVAL file in the \ |
||
203 | \n\tlist of OVAL checks for this product! Exiting..\n" % refovalfilename |
||
204 | sys.stderr.write(error_msg) |
||
205 | # sys.exit(1) |
||
206 | check.set("href", os.path.basename(newovalfile)) |
||
207 | |||
208 | # Sanity check to verify if inventory check OVAL id is present in the |
||
209 | # list of known "id" attributes of inventory definitions. If not it |
||
210 | # means provided ovalfile (sys.argv[1]) doesn't contain this OVAL |
||
211 | # definition (it wasn't included due to <platform> tag restrictions) |
||
212 | # Therefore display an error and exit with failure, since otherwise |
||
213 | # we might end up creating invalid $(ID)-$(PROD)-cpe-oval.xml file |
||
214 | if check.text not in inventory_defs_id_attrs: |
||
215 | error_msg = "\n\tError: Can't locate \"%s\" definition in \"%s\". \ |
||
216 | \n\tEnsure <platform> element is configured properly for \"%s\". \ |
||
217 | \n\tExiting..\n" % (check.text, args.ovalfile, check.text) |
||
218 | sys.stderr.write(error_msg) |
||
219 | sys.exit(1) |
||
220 | |||
221 | # Referenced OVAL checks passed both of the above sanity tests |
||
222 | check.text = translator.generate_id("{" + oval_ns + "}definition", check.text) |
||
223 | |||
224 | ssg.xml.ElementTree.ElementTree(cpedicttree).write(cpedict_path) |
||
225 | |||
226 | sys.exit(0) |
||
227 | |||
231 |