overhaul warning and error handling
This commit is contained in:
parent
ffa0253193
commit
5d9ddf60b7
1 changed files with 58 additions and 18 deletions
76
recipes.py
76
recipes.py
|
@ -1,5 +1,6 @@
|
||||||
from abc import abstractmethod
|
from abc import abstractmethod
|
||||||
from collections import defaultdict
|
from collections import defaultdict
|
||||||
|
import collections
|
||||||
import sys
|
import sys
|
||||||
from typing import Dict, List, Any, Optional, Set
|
from typing import Dict, List, Any, Optional, Set
|
||||||
import os
|
import os
|
||||||
|
@ -10,6 +11,38 @@ import jinja2
|
||||||
import jsonschema
|
import jsonschema
|
||||||
import jsonschema.exceptions
|
import jsonschema.exceptions
|
||||||
|
|
||||||
|
ISSUE_UNKNOWN_UNIT = "unknown-unit"
|
||||||
|
ISSUE_UNKNOWN_INGREDIENT = "unknown-ingredient"
|
||||||
|
ISSUE_DUPLICATE_UNITS = "duplicate-units"
|
||||||
|
ISSUE_KNOWN_PRICE_UNKNOWN_CONVERSION = "known-price-unknown-conversion"
|
||||||
|
|
||||||
|
class Issue:
|
||||||
|
def __init__(self, id: str, msg: str) -> None:
|
||||||
|
self.id = id
|
||||||
|
self.msg = msg
|
||||||
|
|
||||||
|
class Issues:
|
||||||
|
def __init__(self) -> None:
|
||||||
|
self.errors: List[Issue] = []
|
||||||
|
self.warnings: List[Issue] = []
|
||||||
|
|
||||||
|
def error(self, id: str, msg: str) -> None:
|
||||||
|
self.errors.append(Issue(id, msg))
|
||||||
|
|
||||||
|
def warn(self, id: str, msg: str) -> None:
|
||||||
|
self.warnings.append(Issue(id, msg))
|
||||||
|
|
||||||
|
def check(self) -> int:
|
||||||
|
retcode = len(self.errors) != 0
|
||||||
|
|
||||||
|
for msg in self.errors:
|
||||||
|
print(f"ERROR {msg.id}: {msg.msg}")
|
||||||
|
for msg in self.warnings:
|
||||||
|
print(f"WARNING {msg.id}: {msg.msg}")
|
||||||
|
|
||||||
|
self.errors.clear()
|
||||||
|
self.warnings.clear()
|
||||||
|
return retcode
|
||||||
|
|
||||||
class Context:
|
class Context:
|
||||||
def __init__(self) -> None:
|
def __init__(self) -> None:
|
||||||
|
@ -17,7 +50,7 @@ class Context:
|
||||||
self.default_unit = Unit(self, {"name": "piece"})
|
self.default_unit = Unit(self, {"name": "piece"})
|
||||||
self.units.units.append(self.default_unit)
|
self.units.units.append(self.default_unit)
|
||||||
self.ingredients = Ingredients(self)
|
self.ingredients = Ingredients(self)
|
||||||
self.issues: List[str] = []
|
self.issues = Issues()
|
||||||
|
|
||||||
|
|
||||||
class Element:
|
class Element:
|
||||||
|
@ -103,12 +136,20 @@ class Units:
|
||||||
return unit
|
return unit
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
def validate(self) -> None:
|
||||||
|
unitnames = []
|
||||||
|
for unit in self.units:
|
||||||
|
unitnames.append(unit["name"])
|
||||||
|
for unitname, num in collections.Counter(unitnames).items():
|
||||||
|
if num>1:
|
||||||
|
self.ctx.issues.error(ISSUE_DUPLICATE_UNITS, f"units.yaml: {unitname} should only have one entry, found {num}")
|
||||||
|
|
||||||
|
|
||||||
class Ingredient(Element):
|
class Ingredient(Element):
|
||||||
def load(self, dct: Dict[str, Any]) -> None:
|
def load(self, dct: Dict[str, Any]) -> None:
|
||||||
if "prices" in dct:
|
if "prices" in dct:
|
||||||
pricedb = PriceDBs(self.ctx)
|
pricedb = PriceDBs(self.ctx)
|
||||||
self.ctx.issues += pricedb.load(dct["prices"])
|
pricedb.load(dct["prices"])
|
||||||
self["prices"] = pricedb
|
self["prices"] = pricedb
|
||||||
|
|
||||||
conversions = []
|
conversions = []
|
||||||
|
@ -155,8 +196,8 @@ class Ingredient(Element):
|
||||||
# find path between conversions
|
# find path between conversions
|
||||||
path = self.dfs(conversions, unitfrom["name"], unitto["name"])
|
path = self.dfs(conversions, unitfrom["name"], unitto["name"])
|
||||||
if path is None:
|
if path is None:
|
||||||
print(
|
self.ctx.issues.warn(ISSUE_KNOWN_PRICE_UNKNOWN_CONVERSION,
|
||||||
f'WARNING: {self["name"]} has a known price, but conversion {unitfrom["name"]} -> {unitto["name"]} not known'
|
f'{self["name"]} has a known price, but conversion {unitfrom["name"]} -> {unitto["name"]} not known'
|
||||||
)
|
)
|
||||||
return None
|
return None
|
||||||
assert len(path) != 0
|
assert len(path) != 0
|
||||||
|
@ -210,11 +251,10 @@ class PriceDBs:
|
||||||
self.ctx = ctx
|
self.ctx = ctx
|
||||||
self.pricedbs: List[PriceDB] = []
|
self.pricedbs: List[PriceDB] = []
|
||||||
|
|
||||||
def load(self, lst: List[Any]) -> List[str]:
|
def load(self, lst: List[Any]) -> None:
|
||||||
for elem in lst:
|
for elem in lst:
|
||||||
pricedb = PriceDB(self.ctx, elem)
|
pricedb = PriceDB(self.ctx, elem)
|
||||||
self.pricedbs.append(pricedb)
|
self.pricedbs.append(pricedb)
|
||||||
return self.ctx.issues
|
|
||||||
|
|
||||||
def __repr__(self) -> str:
|
def __repr__(self) -> str:
|
||||||
return self.pricedbs.__repr__()
|
return self.pricedbs.__repr__()
|
||||||
|
@ -229,7 +269,7 @@ class PriceDB(Element):
|
||||||
unitstr = dct["unit"]
|
unitstr = dct["unit"]
|
||||||
self["unit"] = self.ctx.units.get(unitstr)
|
self["unit"] = self.ctx.units.get(unitstr)
|
||||||
if self["unit"] is None:
|
if self["unit"] is None:
|
||||||
self.ctx.issues.append(f"unknown unit {unitstr}")
|
self.ctx.issues.error(ISSUE_UNKNOWN_UNIT, f"unknown unit {unitstr}")
|
||||||
else:
|
else:
|
||||||
self["unit"] = self.ctx.default_unit
|
self["unit"] = self.ctx.default_unit
|
||||||
|
|
||||||
|
@ -238,7 +278,7 @@ class IngredientInstance(Element):
|
||||||
def load(self, dct: Dict[str, Any]) -> None:
|
def load(self, dct: Dict[str, Any]) -> None:
|
||||||
ingredient = self.ctx.ingredients.get(dct["name"])
|
ingredient = self.ctx.ingredients.get(dct["name"])
|
||||||
if ingredient is None:
|
if ingredient is None:
|
||||||
self.ctx.issues.append(f"unknown ingredient {dct['name']}")
|
self.ctx.issues.error(ISSUE_UNKNOWN_INGREDIENT, f"unknown ingredient {dct['name']}")
|
||||||
self["ingredient"] = ingredient
|
self["ingredient"] = ingredient
|
||||||
|
|
||||||
if "amount" not in dct:
|
if "amount" not in dct:
|
||||||
|
@ -248,7 +288,7 @@ class IngredientInstance(Element):
|
||||||
unitstr = dct["unit"]
|
unitstr = dct["unit"]
|
||||||
self["unit"] = self.ctx.units.get(unitstr)
|
self["unit"] = self.ctx.units.get(unitstr)
|
||||||
if self["unit"] is None:
|
if self["unit"] is None:
|
||||||
self.ctx.issues.append("unknown unit {unitstr}")
|
self.ctx.issues.error(ISSUE_UNKNOWN_UNIT, "unknown unit {unitstr}")
|
||||||
else:
|
else:
|
||||||
self["unit"] = self.ctx.default_unit
|
self["unit"] = self.ctx.default_unit
|
||||||
|
|
||||||
|
@ -356,18 +396,17 @@ class Builder:
|
||||||
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)
|
||||||
self.ctx.units.load(unitsdct)
|
self.ctx.units.load(unitsdct)
|
||||||
if len(self.ctx.issues) != 0:
|
retcode = self.ctx.issues.check()
|
||||||
for issue in self.ctx.issues:
|
if retcode != 0:
|
||||||
print("ERROR in units.yaml:", issue)
|
|
||||||
return 1
|
return 1
|
||||||
|
self.ctx.units.validate()
|
||||||
|
|
||||||
ingredientsdct = self.load_file(dir + "/ingredients.yaml")
|
ingredientsdct = self.load_file(dir + "/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)
|
||||||
self.ctx.ingredients.load(ingredientsdct)
|
self.ctx.ingredients.load(ingredientsdct)
|
||||||
if len(self.ctx.issues) != 0:
|
retcode = self.ctx.issues.check()
|
||||||
for issue in self.ctx.issues:
|
if retcode != 0:
|
||||||
print("ERROR in ingredients.yaml:", issue)
|
|
||||||
return 1
|
return 1
|
||||||
|
|
||||||
return 0
|
return 0
|
||||||
|
@ -389,11 +428,12 @@ class Builder:
|
||||||
recipe = Recipe(self.ctx, recipedct)
|
recipe = Recipe(self.ctx, recipedct)
|
||||||
recipe.srcpath = file
|
recipe.srcpath = file
|
||||||
recipe.outpath = file[:-5] + ".html"
|
recipe.outpath = file[:-5] + ".html"
|
||||||
|
if self.ctx.issues.check() != 0:
|
||||||
|
continue
|
||||||
recipes.append(recipe)
|
recipes.append(recipe)
|
||||||
|
|
||||||
if len(self.ctx.issues) != 0:
|
retcode = self.ctx.issues.check()
|
||||||
for issue in self.ctx.issues:
|
if retcode != 0:
|
||||||
print("ERROR", issue)
|
|
||||||
return 1
|
return 1
|
||||||
|
|
||||||
self.rendertemplate(
|
self.rendertemplate(
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue