From 0b97f45a7221cc9934e130ec80207a77ea828ac5 Mon Sep 17 00:00:00 2001 From: Emi Vasilek Date: Mon, 6 Nov 2023 05:30:43 +0100 Subject: [PATCH] error messages for jsonschema validation and return code --- recipes.py | 49 +++++++++++++++++++++++++++++++++++-------------- 1 file changed, 35 insertions(+), 14 deletions(-) diff --git a/recipes.py b/recipes.py index 8246a38..4dbab2f 100644 --- a/recipes.py +++ b/recipes.py @@ -1,3 +1,4 @@ +import sys from typing import Dict, List, Any, Optional, Set import os import json @@ -5,6 +6,7 @@ import json import yaml import jinja2 import jsonschema +import jsonschema.exceptions class Context: @@ -12,6 +14,7 @@ class Context: self.units = Units() self.ingredients = Ingredients(self) + class Conversion: def load(self, units: List["Unit"], dct: Dict[str, Any]) -> None: def find_unit(name: str) -> Optional[Unit]: @@ -32,6 +35,7 @@ class Conversion: self.ratio = dct["ratio"] + class Unit: def load(self, units: List["Unit"], dct: Dict[str, Any]) -> None: self.name = dct["name"] @@ -43,7 +47,9 @@ class Unit: if "conversions" in dct: for convdct in dct["conversions"]: if "from" in dct["conversions"]: - raise RuntimeError(f"conversions in units.yaml cannot have a from field, it is automatically assigned from the unit name") + raise RuntimeError( + f"conversions in units.yaml cannot have a from field, it is automatically assigned from the unit name" + ) convdct["from"] = self.name conversion = Conversion() conversion.load(unitsx, convdct) @@ -267,6 +273,7 @@ class Builder: loader=jinja2.FileSystemLoader("templates"), autoescape=jinja2.select_autoescape(), ) + def numprint(input: int) -> str: out = str(input) if out.endswith(".0"): @@ -279,7 +286,7 @@ class Builder: return "3/4" return out - self.jinjaenv.filters['numprint'] = numprint + self.jinjaenv.filters["numprint"] = numprint self.ctx = Context() # list of output files that will be built self.outfiles: Set[str] = set() @@ -305,25 +312,30 @@ class Builder: f.write(outstr) self.outfiles.add(file) - def load(self) -> None: + def load(self) -> int: issues: List[str] = [] unitsdct = self.load_file("recipes/units.yaml") unitsschema = self.load_file("schemas/units.json") jsonschema.validate(instance=unitsdct, schema=unitsschema) issues += self.ctx.units.load(unitsdct) + if len(issues) != 0: + for issue in issues: + print("ERROR in units.yaml:", issue) + return 1 ingredientsdct = self.load_file("recipes/ingredients.yaml") ingredientsschema = self.load_file("schemas/ingredients.json") jsonschema.validate(instance=ingredientsdct, schema=ingredientsschema) issues += self.ctx.ingredients.load(ingredientsdct) - if len(issues) != 0: for issue in issues: - print("ERROR", issue) - return + print("ERROR in ingredients.yaml:", issue) + return 1 - def run(self) -> None: + return 0 + + def run(self) -> int: issues = [] files = [] for _, _, filesx in os.walk("recipes/recipes"): @@ -347,15 +359,16 @@ class Builder: if len(issues) != 0: for issue in issues: print("ERROR", issue) - return + return 1 self.rendertemplate("index.html", "html", "index.html", {"recipes": recipes}) for recipe in recipes: self.rendertemplate( "recipe.html", "html", recipe.outpath, {"recipe": recipe} ) + return 0 - def finish(self) -> None: + def finish(self) -> int: files = set() for _, _, filesx in os.walk("out/html"): files = set(filesx) @@ -365,13 +378,21 @@ class Builder: for file in extra_files: print(f"removing obsolete {file}") os.remove(f"out/html/{file}") + return 0 - def main(self) -> None: - self.load() - self.run() - self.finish() + def main(self) -> int: + fcs = [self.load, self.run, self.finish] + for func in fcs: + try: + ret = func() + if ret != 0: + return ret + except jsonschema.exceptions.ValidationError as e: + print("ERROR:", e) + return 1 + return 0 if __name__ == "__main__": builder = Builder() - builder.main() + sys.exit(builder.main())