error messages for jsonschema validation and return code

This commit is contained in:
Emi Vasilek 2023-11-06 05:30:43 +01:00
parent 2f183c758f
commit 0b97f45a72

View file

@ -1,3 +1,4 @@
import sys
from typing import Dict, List, Any, Optional, Set from typing import Dict, List, Any, Optional, Set
import os import os
import json import json
@ -5,6 +6,7 @@ import json
import yaml import yaml
import jinja2 import jinja2
import jsonschema import jsonschema
import jsonschema.exceptions
class Context: class Context:
@ -12,6 +14,7 @@ class Context:
self.units = Units() self.units = Units()
self.ingredients = Ingredients(self) self.ingredients = Ingredients(self)
class Conversion: class Conversion:
def load(self, units: List["Unit"], dct: Dict[str, Any]) -> None: def load(self, units: List["Unit"], dct: Dict[str, Any]) -> None:
def find_unit(name: str) -> Optional[Unit]: def find_unit(name: str) -> Optional[Unit]:
@ -32,6 +35,7 @@ class Conversion:
self.ratio = dct["ratio"] self.ratio = dct["ratio"]
class Unit: class Unit:
def load(self, units: List["Unit"], dct: Dict[str, Any]) -> None: def load(self, units: List["Unit"], dct: Dict[str, Any]) -> None:
self.name = dct["name"] self.name = dct["name"]
@ -43,7 +47,9 @@ class Unit:
if "conversions" in dct: if "conversions" in dct:
for convdct in dct["conversions"]: for convdct in dct["conversions"]:
if "from" 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 convdct["from"] = self.name
conversion = Conversion() conversion = Conversion()
conversion.load(unitsx, convdct) conversion.load(unitsx, convdct)
@ -267,6 +273,7 @@ class Builder:
loader=jinja2.FileSystemLoader("templates"), loader=jinja2.FileSystemLoader("templates"),
autoescape=jinja2.select_autoescape(), autoescape=jinja2.select_autoescape(),
) )
def numprint(input: int) -> str: def numprint(input: int) -> str:
out = str(input) out = str(input)
if out.endswith(".0"): if out.endswith(".0"):
@ -279,7 +286,7 @@ class Builder:
return "3/4" return "3/4"
return out return out
self.jinjaenv.filters['numprint'] = numprint self.jinjaenv.filters["numprint"] = numprint
self.ctx = Context() self.ctx = Context()
# list of output files that will be built # list of output files that will be built
self.outfiles: Set[str] = set() self.outfiles: Set[str] = set()
@ -305,25 +312,30 @@ class Builder:
f.write(outstr) f.write(outstr)
self.outfiles.add(file) self.outfiles.add(file)
def load(self) -> None: def load(self) -> int:
issues: List[str] = [] issues: List[str] = []
unitsdct = self.load_file("recipes/units.yaml") unitsdct = self.load_file("recipes/units.yaml")
unitsschema = self.load_file("schemas/units.json") unitsschema = self.load_file("schemas/units.json")
jsonschema.validate(instance=unitsdct, schema=unitsschema) jsonschema.validate(instance=unitsdct, schema=unitsschema)
issues += self.ctx.units.load(unitsdct) 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") ingredientsdct = self.load_file("recipes/ingredients.yaml")
ingredientsschema = self.load_file("schemas/ingredients.json") ingredientsschema = self.load_file("schemas/ingredients.json")
jsonschema.validate(instance=ingredientsdct, schema=ingredientsschema) jsonschema.validate(instance=ingredientsdct, schema=ingredientsschema)
issues += self.ctx.ingredients.load(ingredientsdct) issues += self.ctx.ingredients.load(ingredientsdct)
if len(issues) != 0: if len(issues) != 0:
for issue in issues: for issue in issues:
print("ERROR", issue) print("ERROR in ingredients.yaml:", issue)
return return 1
def run(self) -> None: return 0
def run(self) -> int:
issues = [] issues = []
files = [] files = []
for _, _, filesx in os.walk("recipes/recipes"): for _, _, filesx in os.walk("recipes/recipes"):
@ -347,15 +359,16 @@ class Builder:
if len(issues) != 0: if len(issues) != 0:
for issue in issues: for issue in issues:
print("ERROR", issue) print("ERROR", issue)
return return 1
self.rendertemplate("index.html", "html", "index.html", {"recipes": recipes}) self.rendertemplate("index.html", "html", "index.html", {"recipes": recipes})
for recipe in recipes: for recipe in recipes:
self.rendertemplate( self.rendertemplate(
"recipe.html", "html", recipe.outpath, {"recipe": recipe} "recipe.html", "html", recipe.outpath, {"recipe": recipe}
) )
return 0
def finish(self) -> None: def finish(self) -> int:
files = set() files = set()
for _, _, filesx in os.walk("out/html"): for _, _, filesx in os.walk("out/html"):
files = set(filesx) files = set(filesx)
@ -365,13 +378,21 @@ class Builder:
for file in extra_files: for file in extra_files:
print(f"removing obsolete {file}") print(f"removing obsolete {file}")
os.remove(f"out/html/{file}") os.remove(f"out/html/{file}")
return 0
def main(self) -> None: def main(self) -> int:
self.load() fcs = [self.load, self.run, self.finish]
self.run() for func in fcs:
self.finish() try:
ret = func()
if ret != 0:
return ret
except jsonschema.exceptions.ValidationError as e:
print("ERROR:", e)
return 1
return 0
if __name__ == "__main__": if __name__ == "__main__":
builder = Builder() builder = Builder()
builder.main() sys.exit(builder.main())