From 0a8af00417ff7c852616b75935c6bf46d39aba90 Mon Sep 17 00:00:00 2001 From: Jakub Kadlcik Date: Feb 19 2023 23:32:12 +0000 Subject: Generate review.json alongside the review.txt file Fix #310 --- diff --git a/src/FedoraReview/checks.py b/src/FedoraReview/checks.py index b22b4d9..cbd86e9 100644 --- a/src/FedoraReview/checks.py +++ b/src/FedoraReview/checks.py @@ -28,7 +28,7 @@ from operator import attrgetter from straight.plugin import load # pylint: disable=F0401 from .datasrc import BuildFilesSource, RpmDataSource, SourcesDataSource -from .reports import write_template, write_xml_report +from .reports import write_template, write_xml_report, write_json from .review_error import ReviewError from .settings import Settings from .spec_file import SpecFile @@ -391,7 +391,9 @@ class Checks(_ChecksLoader): if writedown: key_getter = attrgetter("group", "type", "name") - write_template(output, sorted(results, key=key_getter), issues, attachments) + sorted_results = sorted(results, key=key_getter) + write_template(output, sorted_results, issues, attachments) + write_json(sorted_results, issues, attachments) write_xml_report(self.spec, results) else: with open(".testlog.txt", "w") as f: diff --git a/src/FedoraReview/reports.py b/src/FedoraReview/reports.py index 9977db8..70c0899 100644 --- a/src/FedoraReview/reports.py +++ b/src/FedoraReview/reports.py @@ -21,6 +21,7 @@ """ Functions to create the xml report. """ import os.path +import json import xml.dom.minidom import xml.etree.ElementTree as ET from glob import glob @@ -204,3 +205,75 @@ def write_xml_report(spec, results): prettyxml = dom.toprettyxml(indent=" ", encoding="utf-8") with open("report.xml", "wb") as f: f.write(prettyxml) + + +def write_json(results, issues, attachments): + """ + Create a review.json file in the result directory. + Trying to provide similar interface to `write_template` function + """ + report = JSONReport(results, issues, attachments) + report.dump() + + +class JSONReport: + """ + Generate a review report in a JSON format + """ + + def __init__(self, results, issues, attachments): + self.results = results + self.issues = issues + self.attachments = attachments + self.types = ["MUST", "SHOULD", "EXTRA"] + + def dump(self, path="review.json"): + """ + Save the review report as a JSON file + """ + with open(path, "w") as f: + json.dump(self.dumps(), f, indent=2) + + def dumps(self): + """ + Return the review report as a JSON string + """ + return { + "issues": self._get_issues(), + "results": self._get_results(), + "attachments": self._get_attachments(), + } + + def _get_issues(self): + return [self._result2dict(x) for x in self.issues] + + def _get_results(self): + output = {} + for result_type in self.types: + output[result_type] = {} + + for result in self.results: + group = result.group.split(".")[0] + assert result.type in self.types + output[result.type].setdefault(group, []) + output[result.type][group].append(self._result2dict(result)) + + return output + + def _get_attachments(self): + return [self._attachment2dict(x) for x in self.attachments] + + def _result2dict(self, result): + return { + "result": result.result, + "text": result.text, + "note": result.output_extra, + "name": result.name, + "url": result.url, + } + + def _attachment2dict(self, att): + return { + "header": att.header, + "text": att.text, + }