From 69e578dba45e48d0de7605d15be97f3b834d9eb7 Mon Sep 17 00:00:00 2001 From: Emi Vasilek Date: Tue, 28 Nov 2023 12:28:52 +0000 Subject: [PATCH] allow using a single string as an ingredient instead of a dict --- .pylintrc | 2 +- comfyrecipes/builder.py | 3 ++- comfyrecipes/parsing.py | 37 +++++++++++++++++++++++++++--- comfyrecipes/schemas/recipe.json | 27 +++++++++++++--------- comfyrecipes/templates/recipe.html | 7 +++++- 5 files changed, 59 insertions(+), 17 deletions(-) diff --git a/.pylintrc b/.pylintrc index 4ff7ab7..6555d60 100644 --- a/.pylintrc +++ b/.pylintrc @@ -3,4 +3,4 @@ disable= missing-module-docstring, missing-class-docstring, missing-function-docstring, - too-few-public-methods \ No newline at end of file + too-few-public-methods diff --git a/comfyrecipes/builder.py b/comfyrecipes/builder.py index abdebf5..ba38fae 100644 --- a/comfyrecipes/builder.py +++ b/comfyrecipes/builder.py @@ -139,7 +139,8 @@ class Builder: def collect_unitnames(rec: parsing.Recipe) -> List[str]: results: List[str] = [] for ing in rec.ingredients: - results.append(ing.unit.name) + if ing.unit is not None: + results.append(ing.unit.name) return results unitnamelists = self.foreach_recipe(collect_unitnames) diff --git a/comfyrecipes/parsing.py b/comfyrecipes/parsing.py index 49f6e9f..65ae589 100644 --- a/comfyrecipes/parsing.py +++ b/comfyrecipes/parsing.py @@ -1,5 +1,6 @@ from abc import abstractmethod import collections +import re from typing import Any, Dict, List, Optional, Self import comfyrecipes.settings as settings @@ -178,8 +179,8 @@ class IngredientInstance(Element): self, ctx: Context, name: str, - amount: float, - unit: Unit, + amount: Optional[float], + unit: Optional[Unit], alternatives: List["IngredientInstance"], note: str, price: Optional["PriceDB"], @@ -193,7 +194,37 @@ class IngredientInstance(Element): self.price = price @classmethod - def from_dict(cls, ctx: Context, dct: Dict[str, Any]) -> Self: + def from_dict(cls, ctx: Context, dct: str | Dict[str, Any]) -> Self: + if isinstance(dct, str): + string = dct.strip() + p = re.compile(r"^(?:([0-9\.]+) ([a-zA-Z]+) )?([\w ]+)(?: \((.*)\))?$") + match = p.match(string) + if match is None: + raise RuntimeError( + "ingredient {string} regex not matched, it should be in the format [amount(num) unit(string, one word)] name(string, any number of words) [(note(string))]" + ) + amount = float(match.group(1)) + unitstr = match.group(2) + unit = ctx.default_unit + if unit is not None: + unitx = ctx.units.get(unitstr) + if unitx is None: + ctx.issues.error(issues.ISSUE_UNKNOWN_UNIT, "unknown unit {unitstr}") + else: + unit = unitx + name = match.group(3) + note = match.group(4) + if note is None: + note = "" + return cls( + ctx=ctx, + name=name, + amount=amount, + unit=unit, + alternatives=[], + note=note, + price=None, + ) name = dct["name"] ingredient = ctx.ingredients.get(name) diff --git a/comfyrecipes/schemas/recipe.json b/comfyrecipes/schemas/recipe.json index 0ca33bd..fc34f3c 100644 --- a/comfyrecipes/schemas/recipe.json +++ b/comfyrecipes/schemas/recipe.json @@ -13,17 +13,22 @@ "ingredients": { "type": "array", "items": { - "$id": "https://example.com/ingredient.json", - "type": "object", - "additionalProperties": false, - "required": [ "name" ], - "properties": { - "name": { "type": "string" }, - "amount": { "type": "number" }, - "unit": { "type": "string" }, - "or": { "items": { "$ref": "/ingredient.json" } }, - "note": { "type": "string" } - } + "oneOf": [ + { "type": "string" }, + { + "$id": "https://example.com/ingredient.json", + "type": "object", + "additionalProperties": false, + "required": [ "name" ], + "properties": { + "name": { "type": "string" }, + "amount": { "type": "number" }, + "unit": { "type": "string" }, + "or": { "items": { "$ref": "/ingredient.json" } }, + "note": { "type": "string" } + } + } + ] } }, "steps": { diff --git a/comfyrecipes/templates/recipe.html b/comfyrecipes/templates/recipe.html index d7824cb..2ffc5b1 100644 --- a/comfyrecipes/templates/recipe.html +++ b/comfyrecipes/templates/recipe.html @@ -1,6 +1,11 @@ {% extends "base.html" %} {% macro ingredientpart(ing) -%} -{% if recipe.price != None %}{{price(ing.price)}} {%endif%}{{ing.amount|amountprint}} {{ing["unit"].name}} {{ ing.name }} {{ing.note}} +{% if recipe.price != None %}{{price(ing.price)}} {%endif%} +{% if ing.amount != None %} {{ing.amount|amountprint}} +{% if ing.unit != None %} {{ing.unit.name}}{% endif %} +{%endif%} + {{ ing.name }} +{% if ing.note != "" %} {{ing.note}}{% endif %} {%- endmacro %} {% macro ingredient(ing) -%}