Merge ~jslarraz/review-tools:move-report into review-tools:master
- Git
- lp:~jslarraz/review-tools
- move-report
- Merge into master
Proposed by
Jorge Sancho Larraz
Status: | Merged |
---|---|
Merged at revision: | 140737139019d0bd725a3a0d3847221f52c1a884 |
Proposed branch: | ~jslarraz/review-tools:move-report |
Merge into: | review-tools:master |
Diff against target: |
540 lines (+196/-203) 5 files modified
bin/snap-review (+3/-104) bin/snap-verify-declaration (+9/-2) reviewtools/common.py (+41/-95) reviewtools/report.py (+141/-0) tests/test.sh.expected (+2/-2) |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Alex Murray | Approve | ||
Review via email:
|
Commit message
many: move Report class away from bin/snap-review, and use it also on individual checks
Description of the change
To post a comment you must log in.
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | diff --git a/bin/snap-review b/bin/snap-review | |||
2 | index 2c26158..777f418 100755 | |||
3 | --- a/bin/snap-review | |||
4 | +++ b/bin/snap-review | |||
5 | @@ -19,107 +19,7 @@ from reviewtools.common import ( | |||
6 | 19 | ) | 19 | ) |
7 | 20 | 20 | ||
8 | 21 | from reviewtools.sr_declaration import validate_json | 21 | from reviewtools.sr_declaration import validate_json |
110 | 22 | 22 | from reviewtools.report import Report | |
10 | 23 | |||
11 | 24 | class Report(object): | ||
12 | 25 | results = {} | ||
13 | 26 | errors = {} | ||
14 | 27 | warnings = {} | ||
15 | 28 | info = {} | ||
16 | 29 | |||
17 | 30 | def __init__(self, filename, verbose: bool = False): | ||
18 | 31 | self.filename = filename | ||
19 | 32 | self.verbose = verbose | ||
20 | 33 | |||
21 | 34 | # review_report[<section>][<result_type>][<review_name>] = <result> | ||
22 | 35 | # section: section of the report (one per review module) | ||
23 | 36 | # result_type: info, warn, error | ||
24 | 37 | # review_name: name of the check (prefixed with self.review_type) | ||
25 | 38 | # result: contents of the review | ||
26 | 39 | # link: url for more information | ||
27 | 40 | # manual_review: force manual review | ||
28 | 41 | # override_result_type: prefix results with [<result_type>] and set | ||
29 | 42 | # result_type to override_result_type | ||
30 | 43 | def add_result( | ||
31 | 44 | self, | ||
32 | 45 | section, | ||
33 | 46 | result_type, | ||
34 | 47 | review_name, | ||
35 | 48 | result, | ||
36 | 49 | link=None, | ||
37 | 50 | manual_review=False, | ||
38 | 51 | ): | ||
39 | 52 | """Add result to report""" | ||
40 | 53 | if section not in self.results: | ||
41 | 54 | self.results[section] = { | ||
42 | 55 | "info": {}, | ||
43 | 56 | "warn": {}, | ||
44 | 57 | "error": {}, | ||
45 | 58 | } | ||
46 | 59 | |||
47 | 60 | if result_type not in self.results[section]: | ||
48 | 61 | raise Exception("Invalid result type '%s'" % result_type) | ||
49 | 62 | |||
50 | 63 | if review_name not in self.results[section][result_type]: | ||
51 | 64 | self.results[section][result_type][review_name] = dict() | ||
52 | 65 | |||
53 | 66 | self.results[section][result_type][review_name].update( | ||
54 | 67 | {"text": "%s" % result, "manual_review": manual_review} | ||
55 | 68 | ) | ||
56 | 69 | if link is not None: | ||
57 | 70 | self.results[section][result_type][review_name]["link"] = link | ||
58 | 71 | |||
59 | 72 | def _summarise_results(self): | ||
60 | 73 | for module in self.results: | ||
61 | 74 | for key in self.results[module]["error"]: | ||
62 | 75 | self.errors[key] = self.results[module]["error"][key] | ||
63 | 76 | for key in self.results[module]["warn"]: | ||
64 | 77 | self.warnings[key] = self.results[module]["warn"][key] | ||
65 | 78 | if self.verbose: | ||
66 | 79 | for key in self.results[module]["info"]: | ||
67 | 80 | self.info[key] = self.results[module]["info"][key] | ||
68 | 81 | |||
69 | 82 | def print_findings(self, results, description): | ||
70 | 83 | """ | ||
71 | 84 | Print a summary of the issues found. | ||
72 | 85 | """ | ||
73 | 86 | if not description or not results: | ||
74 | 87 | return "" | ||
75 | 88 | print(description) | ||
76 | 89 | print("".center(len(description), "-")) | ||
77 | 90 | for key in sorted(results.keys()): | ||
78 | 91 | print(" - %s" % key) | ||
79 | 92 | print("\t%s" % results[key]["text"]) | ||
80 | 93 | if "link" in results[key]: | ||
81 | 94 | print("\t%s" % results[key]["link"]) | ||
82 | 95 | |||
83 | 96 | def show_results(self, report_type="console"): | ||
84 | 97 | self._summarise_results() | ||
85 | 98 | |||
86 | 99 | if report_type == "json": | ||
87 | 100 | print( | ||
88 | 101 | json.dumps( | ||
89 | 102 | self.results, sort_keys=True, indent=2, separators=(",", ": ") | ||
90 | 103 | ) | ||
91 | 104 | ) | ||
92 | 105 | elif report_type == "sdk": | ||
93 | 106 | for section in sorted(self.results.keys()): | ||
94 | 107 | output = self.results[section] | ||
95 | 108 | print("= %s =" % section) | ||
96 | 109 | print( | ||
97 | 110 | json.dumps(output, sort_keys=True, indent=2, separators=(",", ": ")) | ||
98 | 111 | ) | ||
99 | 112 | else: | ||
100 | 113 | self.print_findings(self.errors, "Errors") | ||
101 | 114 | self.print_findings(self.warnings, "Warnings") | ||
102 | 115 | if self.verbose: | ||
103 | 116 | self.print_findings(self.info, "Info") | ||
104 | 117 | if "runtime-errors" in self.results: | ||
105 | 118 | print("%s: RUNTIME ERROR" % self.filename) | ||
106 | 119 | elif self.warnings or self.errors: | ||
107 | 120 | print("%s: FAIL" % self.filename) | ||
108 | 121 | else: | ||
109 | 122 | print("%s: pass" % self.filename) | ||
111 | 123 | 23 | ||
112 | 124 | 24 | ||
113 | 125 | def main(): | 25 | def main(): |
114 | @@ -244,13 +144,12 @@ def main(): | |||
115 | 244 | rc = 0 | 144 | rc = 0 |
116 | 245 | report = Report(args.filename, args.verbose) | 145 | report = Report(args.filename, args.verbose) |
117 | 246 | for module in modules: | 146 | for module in modules: |
118 | 247 | section = module.replace("sr_", "snap.v2_") | ||
119 | 248 | try: | 147 | try: |
120 | 249 | review_class = modules_mod.find_main_class(module) | 148 | review_class = modules_mod.find_main_class(module) |
121 | 250 | review = review_class(args.filename, overrides=overrides) | 149 | review = review_class(args.filename, overrides=overrides) |
122 | 251 | 150 | ||
125 | 252 | review.do_checks() | 151 | review_report = review.do_checks() |
126 | 253 | report.results[section] = review.review_report | 152 | report.update(review_report) |
127 | 254 | except Exception: | 153 | except Exception: |
128 | 255 | print("Caught exception (setting rc=1 and continuing):") | 154 | print("Caught exception (setting rc=1 and continuing):") |
129 | 256 | traceback.print_exc(file=sys.stdout) | 155 | traceback.print_exc(file=sys.stdout) |
130 | diff --git a/bin/snap-verify-declaration b/bin/snap-verify-declaration | |||
131 | index 152c6c7..7d7ee40 100755 | |||
132 | --- a/bin/snap-verify-declaration | |||
133 | +++ b/bin/snap-verify-declaration | |||
134 | @@ -81,9 +81,16 @@ def main(): | |||
135 | 81 | "verify_snap_declaration() raised exception for snap decl: %s" % e, | 81 | "verify_snap_declaration() raised exception for snap decl: %s" % e, |
136 | 82 | output_type=error_output_type, | 82 | output_type=error_output_type, |
137 | 83 | ) | 83 | ) |
138 | 84 | review.set_report_type(error_output_type) | ||
139 | 85 | 84 | ||
141 | 86 | return review.do_report() | 85 | report = review.review_report |
142 | 86 | report.show_summary(error_output_type) | ||
143 | 87 | |||
144 | 88 | rc = 0 | ||
145 | 89 | if report.errors: | ||
146 | 90 | rc = 2 | ||
147 | 91 | elif report.warnings: | ||
148 | 92 | rc = 1 | ||
149 | 93 | return rc | ||
150 | 87 | 94 | ||
151 | 88 | 95 | ||
152 | 89 | if __name__ == "__main__": | 96 | if __name__ == "__main__": |
153 | diff --git a/reviewtools/common.py b/reviewtools/common.py | |||
154 | index d2c15b8..d85ecc0 100644 | |||
155 | --- a/reviewtools/common.py | |||
156 | +++ b/reviewtools/common.py | |||
157 | @@ -35,6 +35,7 @@ import types | |||
158 | 35 | import yaml | 35 | import yaml |
159 | 36 | 36 | ||
160 | 37 | from reviewtools.overrides import common_external_symlink_override | 37 | from reviewtools.overrides import common_external_symlink_override |
161 | 38 | from reviewtools.report import Report | ||
162 | 38 | 39 | ||
163 | 39 | REPORT_OUTPUT = "json" | 40 | REPORT_OUTPUT = "json" |
164 | 40 | RESULT_TYPES = ["info", "warn", "error"] | 41 | RESULT_TYPES = ["info", "warn", "error"] |
165 | @@ -156,19 +157,19 @@ class ReviewBase(object): | |||
166 | 156 | 157 | ||
167 | 157 | def __init__(self, review_type, overrides=None): | 158 | def __init__(self, review_type, overrides=None): |
168 | 158 | self.review_type = review_type | 159 | self.review_type = review_type |
169 | 159 | # TODO: rename as pkg_report | ||
170 | 160 | self.review_report = dict() | ||
171 | 161 | |||
172 | 162 | global RESULT_TYPES | ||
173 | 163 | for r in RESULT_TYPES: | ||
174 | 164 | self.review_report[r] = dict() | ||
175 | 165 | |||
176 | 166 | self.overrides = overrides if overrides is not None else {} | 160 | self.overrides = overrides if overrides is not None else {} |
177 | 161 | self.review_report = Report() | ||
178 | 162 | |||
179 | 163 | # TODO: this hack is used to generate tests/test.sh output. We may want to revisit it. | ||
180 | 164 | self.section = "snap.v2_" + self.review_type.split("-")[0] | ||
181 | 167 | 165 | ||
186 | 168 | def set_report_type(self, t): | 166 | # TODO: initialization here is only needed to ensure consistent output with tests/test.sh.expected |
187 | 169 | global REPORT_OUTPUT | 167 | # It can be removed if it is ok to not include a section in the report if that section is empty |
188 | 170 | if t is not None and t in ["console", "json"]: | 168 | self.review_report.results[self.section] = { |
189 | 171 | REPORT_OUTPUT = t | 169 | "error": {}, |
190 | 170 | "warn": {}, | ||
191 | 171 | "info": {}, | ||
192 | 172 | } | ||
193 | 172 | 173 | ||
194 | 173 | def _get_check_name(self, name, app="", extra=""): | 174 | def _get_check_name(self, name, app="", extra=""): |
195 | 174 | name = ":".join([self.review_type, name]) | 175 | name = ":".join([self.review_type, name]) |
196 | @@ -195,13 +196,11 @@ class ReviewBase(object): | |||
197 | 195 | manual_review=False, | 196 | manual_review=False, |
198 | 196 | ): | 197 | ): |
199 | 197 | """Add result to report""" | 198 | """Add result to report""" |
205 | 198 | global RESULT_TYPES | 199 | self.review_report.add_result( |
206 | 199 | report = self.review_report | 200 | self.section, result_type, review_name, result, link, manual_review |
207 | 200 | 201 | ) | |
203 | 201 | if result_type not in RESULT_TYPES: | ||
204 | 202 | error("Invalid result type '%s'" % result_type) | ||
208 | 203 | 202 | ||
210 | 204 | if review_name not in report[result_type]: | 203 | if review_name not in self.review_report.results[self.section][result_type]: |
211 | 205 | # log info about check so it can be collected into the | 204 | # log info about check so it can be collected into the |
212 | 206 | # check-names.list file | 205 | # check-names.list file |
213 | 207 | # format should be | 206 | # format should be |
214 | @@ -210,32 +209,6 @@ class ReviewBase(object): | |||
215 | 210 | name = ":".join(review_name.split(":")[:2]) | 209 | name = ":".join(review_name.split(":")[:2]) |
216 | 211 | link_text = link if link is not None else "" | 210 | link_text = link if link is not None else "" |
217 | 212 | logging.debug(msg.format(name, link_text)) | 211 | logging.debug(msg.format(name, link_text)) |
218 | 213 | report[result_type][review_name] = dict() | ||
219 | 214 | |||
220 | 215 | report[result_type][review_name].update( | ||
221 | 216 | {"text": "%s" % result, "manual_review": manual_review} | ||
222 | 217 | ) | ||
223 | 218 | if link is not None: | ||
224 | 219 | report[result_type][review_name]["link"] = link | ||
225 | 220 | |||
226 | 221 | # Only called by ./bin/* individually, not 'snap-review' | ||
227 | 222 | def do_report(self): | ||
228 | 223 | """Print report""" | ||
229 | 224 | global REPORT_OUTPUT | ||
230 | 225 | |||
231 | 226 | if REPORT_OUTPUT == "json": | ||
232 | 227 | jsonmsg(self.review_report) | ||
233 | 228 | else: | ||
234 | 229 | import pprint | ||
235 | 230 | |||
236 | 231 | pprint.pprint(self.review_report) | ||
237 | 232 | |||
238 | 233 | rc = 0 | ||
239 | 234 | if len(self.review_report["error"]): | ||
240 | 235 | rc = 2 | ||
241 | 236 | elif len(self.review_report["warn"]): | ||
242 | 237 | rc = 1 | ||
243 | 238 | return rc | ||
244 | 239 | 212 | ||
245 | 240 | def do_checks(self): | 213 | def do_checks(self): |
246 | 241 | """Run all methods that start with check_""" | 214 | """Run all methods that start with check_""" |
247 | @@ -250,9 +223,7 @@ class ReviewBase(object): | |||
248 | 250 | func = getattr(self, methodname) | 223 | func = getattr(self, methodname) |
249 | 251 | func() | 224 | func() |
250 | 252 | 225 | ||
254 | 253 | def set_review_type(self, name): | 226 | return self.review_report |
252 | 254 | """Set review name""" | ||
253 | 255 | self.review_type = name | ||
255 | 256 | 227 | ||
256 | 257 | 228 | ||
257 | 258 | # | 229 | # |
258 | @@ -263,42 +234,15 @@ class ReviewBase(object): | |||
259 | 263 | def error(out, exit_code=1, do_exit=True, output_type=None): | 234 | def error(out, exit_code=1, do_exit=True, output_type=None): |
260 | 264 | """Print error message and exit""" | 235 | """Print error message and exit""" |
261 | 265 | global REPORT_OUTPUT | 236 | global REPORT_OUTPUT |
266 | 266 | global RESULT_TYPES | 237 | if output_type is None: |
267 | 267 | 238 | output_type = REPORT_OUTPUT | |
264 | 268 | if output_type is not None: | ||
265 | 269 | ReviewBase.set_report_type(None, output_type) | ||
268 | 270 | 239 | ||
300 | 271 | try: | 240 | if output_type == "json": |
301 | 272 | if REPORT_OUTPUT == "json": | 241 | report = Report() |
302 | 273 | # mock up expected json format: | 242 | report.add_result("runtime-errors", "error", "msg", out, manual_review=True) |
303 | 274 | # { | 243 | report.show_results(output_type) |
304 | 275 | # "test-family": { | 244 | else: |
305 | 276 | # "error": { | 245 | print("ERROR: %s" % (out), file=sys.stderr) |
275 | 277 | # "test-name": { | ||
276 | 278 | # "manual_review": ..., | ||
277 | 279 | # "text": ... | ||
278 | 280 | # } | ||
279 | 281 | # }, | ||
280 | 282 | # "info": {}, | ||
281 | 283 | # "warn": {} | ||
282 | 284 | # } | ||
283 | 285 | # } | ||
284 | 286 | family = "runtime-errors" | ||
285 | 287 | name = "msg" | ||
286 | 288 | |||
287 | 289 | report = dict() | ||
288 | 290 | report[family] = dict() | ||
289 | 291 | for r in RESULT_TYPES: | ||
290 | 292 | report[family][r] = dict() | ||
291 | 293 | report[family]["error"][name] = dict() | ||
292 | 294 | report[family]["error"][name]["text"] = out | ||
293 | 295 | report[family]["error"][name]["manual_review"] = True | ||
294 | 296 | |||
295 | 297 | jsonmsg(report) | ||
296 | 298 | else: | ||
297 | 299 | print("ERROR: %s" % (out), file=sys.stderr) | ||
298 | 300 | except IOError: | ||
299 | 301 | pass | ||
306 | 302 | 246 | ||
307 | 303 | if do_exit: | 247 | if do_exit: |
308 | 304 | sys.exit(exit_code) | 248 | sys.exit(exit_code) |
309 | @@ -329,11 +273,6 @@ def debug(out): | |||
310 | 329 | pass | 273 | pass |
311 | 330 | 274 | ||
312 | 331 | 275 | ||
313 | 332 | def jsonmsg(out): | ||
314 | 333 | """Format out as json""" | ||
315 | 334 | msg(json.dumps(out, sort_keys=True, indent=2, separators=(",", ": "))) | ||
316 | 335 | |||
317 | 336 | |||
318 | 337 | def cmd(command, stdout=subprocess.PIPE, stderr=subprocess.STDOUT): | 276 | def cmd(command, stdout=subprocess.PIPE, stderr=subprocess.STDOUT): |
319 | 338 | """Try to execute the given command.""" | 277 | """Try to execute the given command.""" |
320 | 339 | debug(" ".join(command)) | 278 | debug(" ".join(command)) |
321 | @@ -782,8 +721,15 @@ def run_check(cls): | |||
322 | 782 | overrides = None | 721 | overrides = None |
323 | 783 | 722 | ||
324 | 784 | review = cls(fn, overrides=overrides) | 723 | review = cls(fn, overrides=overrides) |
327 | 785 | review.do_checks() | 724 | report = review.do_checks() |
328 | 786 | rc = review.do_report() | 725 | report.show_summary() |
329 | 726 | |||
330 | 727 | rc = 0 | ||
331 | 728 | if report.errors: | ||
332 | 729 | rc = 2 | ||
333 | 730 | elif report.warnings: | ||
334 | 731 | rc = 1 | ||
335 | 732 | |||
336 | 787 | sys.exit(rc) | 733 | sys.exit(rc) |
337 | 788 | 734 | ||
338 | 789 | 735 | ||
339 | @@ -950,25 +896,25 @@ def check_results( | |||
340 | 950 | for t in expected.keys(): | 896 | for t in expected.keys(): |
341 | 951 | for r in expected[t]: | 897 | for r in expected[t]: |
342 | 952 | testobj.assertTrue( | 898 | testobj.assertTrue( |
344 | 953 | r in report[t], | 899 | r in report.summary[t], |
345 | 954 | "Could not find '%s' (%s) in:\n%s" | 900 | "Could not find '%s' (%s) in:\n%s" |
347 | 955 | % (r, t, json.dumps(report, indent=2)), | 901 | % (r, t, json.dumps(report.summary, indent=2)), |
348 | 956 | ) | 902 | ) |
349 | 957 | for k in expected[t][r]: | 903 | for k in expected[t][r]: |
350 | 958 | testobj.assertTrue( | 904 | testobj.assertTrue( |
352 | 959 | k in report[t][r], | 905 | k in report.summary[t][r], |
353 | 960 | "Could not find '%s' (%s) in:\n%s" | 906 | "Could not find '%s' (%s) in:\n%s" |
355 | 961 | % (k, r, json.dumps(report, indent=2)), | 907 | % (k, r, json.dumps(report.summary, indent=2)), |
356 | 962 | ) | 908 | ) |
358 | 963 | testobj.assertEqual(expected[t][r][k], report[t][r][k]) | 909 | testobj.assertEqual(expected[t][r][k], report.summary[t][r][k]) |
359 | 964 | else: | 910 | else: |
360 | 965 | for k in expected_counts.keys(): | 911 | for k in expected_counts.keys(): |
361 | 966 | if expected_counts[k] is None: | 912 | if expected_counts[k] is None: |
362 | 967 | continue | 913 | continue |
363 | 968 | testobj.assertEqual( | 914 | testobj.assertEqual( |
365 | 969 | len(report[k]), | 915 | len(report.summary[k]), |
366 | 970 | expected_counts[k], | 916 | expected_counts[k], |
368 | 971 | "(%s not equal)\n%s" % (k, json.dumps(report, indent=2)), | 917 | "(%s not equal)\n%s" % (k, json.dumps(report.summary, indent=2)), |
369 | 972 | ) | 918 | ) |
370 | 973 | 919 | ||
371 | 974 | 920 | ||
372 | diff --git a/reviewtools/report.py b/reviewtools/report.py | |||
373 | 975 | new file mode 100644 | 921 | new file mode 100644 |
374 | index 0000000..0364f7c | |||
375 | --- /dev/null | |||
376 | +++ b/reviewtools/report.py | |||
377 | @@ -0,0 +1,141 @@ | |||
378 | 1 | import json | ||
379 | 2 | import pprint | ||
380 | 3 | |||
381 | 4 | |||
382 | 5 | class Report(object): | ||
383 | 6 | def __init__(self, snap_name=None, verbose: bool = False): | ||
384 | 7 | self.snap_name = snap_name if snap_name is not None else "" | ||
385 | 8 | self.verbose = verbose | ||
386 | 9 | |||
387 | 10 | self.results = {} | ||
388 | 11 | self._summary = { | ||
389 | 12 | "info": {}, | ||
390 | 13 | "warn": {}, | ||
391 | 14 | "error": {}, | ||
392 | 15 | } | ||
393 | 16 | |||
394 | 17 | @property | ||
395 | 18 | def summary(self) -> dict: | ||
396 | 19 | self._summarise_results() | ||
397 | 20 | return self._summary | ||
398 | 21 | |||
399 | 22 | @property | ||
400 | 23 | def errors(self) -> dict: | ||
401 | 24 | return self.summary["error"] | ||
402 | 25 | |||
403 | 26 | @property | ||
404 | 27 | def warnings(self) -> dict: | ||
405 | 28 | return self.summary["warn"] | ||
406 | 29 | |||
407 | 30 | @property | ||
408 | 31 | def info(self) -> dict: | ||
409 | 32 | return self.summary["info"] | ||
410 | 33 | |||
411 | 34 | def __iter__(self): | ||
412 | 35 | # Required for compatibility with test_sr_* | ||
413 | 36 | return self.summary.__iter__() | ||
414 | 37 | |||
415 | 38 | def __getitem__(self, item): | ||
416 | 39 | # Required for compatibility with test_sr_* | ||
417 | 40 | return self.summary[item] | ||
418 | 41 | |||
419 | 42 | # review_report[<section>][<result_type>][<review_name>] = <result> | ||
420 | 43 | # section: section of the report (one per review module) | ||
421 | 44 | # result_type: info, warn, error | ||
422 | 45 | # review_name: name of the check (prefixed with self.review_type) | ||
423 | 46 | # result: contents of the review | ||
424 | 47 | # link: url for more information | ||
425 | 48 | # manual_review: force manual review | ||
426 | 49 | # override_result_type: prefix results with [<result_type>] and set | ||
427 | 50 | # result_type to override_result_type | ||
428 | 51 | def add_result( | ||
429 | 52 | self, | ||
430 | 53 | section, | ||
431 | 54 | result_type, | ||
432 | 55 | review_name, | ||
433 | 56 | result, | ||
434 | 57 | link=None, | ||
435 | 58 | manual_review=False, | ||
436 | 59 | ): | ||
437 | 60 | """Add result to report""" | ||
438 | 61 | if section not in self.results: | ||
439 | 62 | self.results[section] = { | ||
440 | 63 | "info": {}, | ||
441 | 64 | "warn": {}, | ||
442 | 65 | "error": {}, | ||
443 | 66 | } | ||
444 | 67 | |||
445 | 68 | if result_type not in self.results[section]: | ||
446 | 69 | raise Exception("Invalid result type '%s'" % result_type) | ||
447 | 70 | |||
448 | 71 | if review_name not in self.results[section][result_type]: | ||
449 | 72 | self.results[section][result_type][review_name] = dict() | ||
450 | 73 | |||
451 | 74 | self.results[section][result_type][review_name].update( | ||
452 | 75 | {"text": "%s" % result, "manual_review": manual_review} | ||
453 | 76 | ) | ||
454 | 77 | if link is not None: | ||
455 | 78 | self.results[section][result_type][review_name]["link"] = link | ||
456 | 79 | |||
457 | 80 | def update(self, report): | ||
458 | 81 | self.results.update(report.results) | ||
459 | 82 | |||
460 | 83 | def _summarise_results(self): | ||
461 | 84 | for module in self.results: | ||
462 | 85 | for key in self.results[module]["error"]: | ||
463 | 86 | self._summary["error"][key] = self.results[module]["error"][key] | ||
464 | 87 | for key in self.results[module]["warn"]: | ||
465 | 88 | self._summary["warn"][key] = self.results[module]["warn"][key] | ||
466 | 89 | for key in self.results[module]["info"]: | ||
467 | 90 | self._summary["info"][key] = self.results[module]["info"][key] | ||
468 | 91 | |||
469 | 92 | def print_findings(self, results, description): | ||
470 | 93 | """ | ||
471 | 94 | Print a summary of the issues found. | ||
472 | 95 | """ | ||
473 | 96 | if not description or not results: | ||
474 | 97 | return "" | ||
475 | 98 | print(description) | ||
476 | 99 | print("".center(len(description), "-")) | ||
477 | 100 | for key in sorted(results.keys()): | ||
478 | 101 | print(" - %s" % key) | ||
479 | 102 | print("\t%s" % results[key]["text"]) | ||
480 | 103 | if "link" in results[key]: | ||
481 | 104 | print("\t%s" % results[key]["link"]) | ||
482 | 105 | |||
483 | 106 | def show_results(self, report_type="console"): | ||
484 | 107 | if report_type == "json": | ||
485 | 108 | print( | ||
486 | 109 | json.dumps( | ||
487 | 110 | self.results, sort_keys=True, indent=2, separators=(",", ": ") | ||
488 | 111 | ) | ||
489 | 112 | ) | ||
490 | 113 | elif report_type == "sdk": | ||
491 | 114 | for section in sorted(self.results.keys()): | ||
492 | 115 | output = self.results[section] | ||
493 | 116 | print("= %s =" % section) | ||
494 | 117 | print( | ||
495 | 118 | json.dumps(output, sort_keys=True, indent=2, separators=(",", ": ")) | ||
496 | 119 | ) | ||
497 | 120 | else: | ||
498 | 121 | self.print_findings(self.summary["error"], "Errors") | ||
499 | 122 | self.print_findings(self.summary["warn"], "Warnings") | ||
500 | 123 | if self.verbose: | ||
501 | 124 | self.print_findings(self.summary["info"], "Info") | ||
502 | 125 | if "runtime-errors" in self.results: | ||
503 | 126 | print("%s: RUNTIME ERROR" % self.snap_name) | ||
504 | 127 | elif self.summary["warn"] or self.summary["error"]: | ||
505 | 128 | print("%s: FAIL" % self.snap_name) | ||
506 | 129 | else: | ||
507 | 130 | print("%s: pass" % self.snap_name) | ||
508 | 131 | |||
509 | 132 | def show_summary(self, report_type="json"): | ||
510 | 133 | if report_type == "json": | ||
511 | 134 | print( | ||
512 | 135 | json.dumps( | ||
513 | 136 | self.summary, sort_keys=True, indent=2, separators=(",", ": ") | ||
514 | 137 | ) | ||
515 | 138 | ) | ||
516 | 139 | |||
517 | 140 | else: | ||
518 | 141 | pprint.pprint(self.summary) | ||
519 | diff --git a/tests/test.sh.expected b/tests/test.sh.expected | |||
520 | index 1c726c3..24fbaef 100644 | |||
521 | --- a/tests/test.sh.expected | |||
522 | +++ b/tests/test.sh.expected | |||
523 | @@ -119215,7 +119215,7 @@ hello-world_25.snap: FAIL | |||
524 | 119215 | "info": {}, | 119215 | "info": {}, |
525 | 119216 | "warn": {} | 119216 | "warn": {} |
526 | 119217 | } | 119217 | } |
528 | 119218 | = snap.v2_extra_tests = | 119218 | = snap.v2_extras = |
529 | 119219 | { | 119219 | { |
530 | 119220 | "error": { | 119220 | "error": { |
531 | 119221 | "extras-tests-v2:error": { | 119221 | "extras-tests-v2:error": { |
532 | @@ -119501,7 +119501,7 @@ hello-world_25.snap: FAIL | |||
533 | 119501 | "info": {}, | 119501 | "info": {}, |
534 | 119502 | "warn": {} | 119502 | "warn": {} |
535 | 119503 | }, | 119503 | }, |
537 | 119504 | "snap.v2_extra_tests": { | 119504 | "snap.v2_extras": { |
538 | 119505 | "error": { | 119505 | "error": { |
539 | 119506 | "extras-tests-v2:error": { | 119506 | "extras-tests-v2:error": { |
540 | 119507 | "manual_review": false, | 119507 | "manual_review": false, |
LGTM - yay removal of more global variables!