From e82cb5c1495bf403062acf19cf4daa169ac502cb Mon Sep 17 00:00:00 2001 From: Dion Moult Date: Mon, 20 Feb 2023 17:05:07 +1100 Subject: [PATCH] IfcTester can now create reports in ODS format --- src/ifctester/ifctester/__main__.py | 2 + src/ifctester/ifctester/reporter.py | 94 +++++++++++++++++++++++++++++ 2 files changed, 96 insertions(+) diff --git a/src/ifctester/ifctester/__main__.py b/src/ifctester/ifctester/__main__.py index 7e76232522..591b053421 100644 --- a/src/ifctester/ifctester/__main__.py +++ b/src/ifctester/ifctester/__main__.py @@ -55,6 +55,8 @@ elif args.reporter == "Json": engine = reporter.Json(specs) elif args.reporter == "Html": engine = reporter.Html(specs) +elif args.reporter == "Ods": + engine = reporter.Ods(specs) engine.report() diff --git a/src/ifctester/ifctester/reporter.py b/src/ifctester/ifctester/reporter.py index 5cfe1a4128..0c8613ac53 100644 --- a/src/ifctester/ifctester/reporter.py +++ b/src/ifctester/ifctester/reporter.py @@ -227,6 +227,100 @@ class Html(Json): return outfile.write(pystache.render(file.read(), self.results)) +class Ods(Json): + def __init__(self, ids): + super().__init__(ids) + self.colours = { + "h": "cccccc", # Header + "p": "97cc64", # Pass + "f": "fb5a3e", # Fail + "t": "ffffff", # Regular text + } + self.results = {} + + def to_file(self, filepath): + from odf.opendocument import OpenDocumentSpreadsheet + from odf.style import Style, TableCellProperties + from odf.table import Table, TableRow, TableCell + from odf.text import P + + self.doc = OpenDocumentSpreadsheet() + + self.cell_formats = {} + for key, value in self.colours.items(): + style = Style(name=key, family="table-cell") + style.addElement(TableCellProperties(backgroundcolor="#" + value)) + self.doc.automaticstyles.addElement(style) + self.cell_formats[key] = style + + table = Table(name=self.results["title"]) + tr = TableRow() + for header in ["Specification", "Status", "Total Compliant", "Total Applicable", "Percentage Compliant"]: + tc = TableCell(valuetype="string", stylename="h") + tc.addElement(P(text=header)) + tr.addElement(tc) + table.addElement(tr) + + rows = [] + for specification in self.results["specifications"]: + rows.append( + [ + specification["name"], + "Pass" if specification["status"] else "Fail", + str(specification["total_successes"]), + str(specification["total"]), + str(specification["percentage"]), + ] + ) + + for row in rows: + tr = TableRow() + c = 0 + stylename = "p" if row[1] == "Pass" else "f" + for col in row: + tc = TableCell(valuetype="string", stylename=stylename) + if col is None: + col = "NULL" + tc.addElement(P(text=col)) + tr.addElement(tc) + c += 1 + table.addElement(tr) + self.doc.spreadsheet.addElement(table) + + for specification in self.results["specifications"]: + if specification["status"]: + continue + table = Table(name=specification["name"]) + tr = TableRow() + for header in ["Requirement", "Problem", "Element"]: + tc = TableCell(valuetype="string", stylename="h") + tc.addElement(P(text=header)) + tr.addElement(tc) + table.addElement(tr) + for requirement in specification["requirements"]: + if requirement["status"]: + continue + for failure in requirement["failed_entities"]: + row = [ + requirement["description"], + failure.get("reason", "No reason provided"), + str(failure.get("element", "No element found")), + ] + tr = TableRow() + c = 0 + for col in row: + tc = TableCell(valuetype="string", stylename="t") + if col is None: + col = "NULL" + tc.addElement(P(text=col)) + tr.addElement(tc) + c += 1 + table.addElement(tr) + self.doc.spreadsheet.addElement(table) + + self.doc.save(filepath, True) + + class Bcf(Reporter): def __init__(self, ids, with_viewpoint=True, filepath=None, group=False): super().__init__(ids)