From 8a89726e2918c667cdddad52d622e6a5b4ea2300 Mon Sep 17 00:00:00 2001 From: jableader Date: Sat, 13 Jan 2024 22:37:39 +1100 Subject: [PATCH] Better unit matching, search for recipes --- main.py | 16 +++++++++++++--- recipes/__init__.py | 29 ++++++++++++++++++----------- recipes/db.py | 12 ++++++++++-- units.py | 8 ++++---- 4 files changed, 45 insertions(+), 20 deletions(-) diff --git a/main.py b/main.py index 4d7d802..3f3cb43 100644 --- a/main.py +++ b/main.py @@ -65,11 +65,21 @@ async def load_full_recipe(conn: sqlite3.Connection, id: int) -> recipes.Recipe: return r @app.get("/recipes/") -async def get_recipes(conn: sqlite3.Connection = Depends(get_db)) -> List[recipes.Recipe]: +async def get_recipes(q: str | None = None, conn: sqlite3.Connection = Depends(get_db)) -> List[recipes.Recipe]: result = [] - async for recipe in recipes.get_all(conn): - result.append(recipe) + if q: + async for recipe in recipes.find_recipes_by_name(conn, q): + result.append(recipe) + else: + async for recipe in recipes.get_all(conn): + result.append(recipe) + for recipe in result: + recipe.ingredients = [] + async for ingredient in recipes.find_ingredients_by_recipe_id(conn, recipe.id): + ingredient.product = await products.find_product_by_id(conn, ingredient.product_id) + recipe.ingredients.append(ingredient) + return result @app.get("/recipes/{recipe_id}") diff --git a/recipes/__init__.py b/recipes/__init__.py index af051ea..c7a7e90 100644 --- a/recipes/__init__.py +++ b/recipes/__init__.py @@ -1,5 +1,5 @@ from products import Product, find_product_by_tag -from recipes.db import Recipe, Ingredient, insert_recipe, insert_ingredient, find_recipe_by_id, find_ingredients_by_recipe_id, get_all +from recipes.db import Recipe, Ingredient, insert_recipe, insert_ingredient, find_recipe_by_id, find_ingredients_by_recipe_id, get_all, find_recipes_by_name from recipes.scraping import scrape_recipe from ingredient_parser import parse_multiple_ingredients @@ -17,17 +17,21 @@ def parse_ingredient_from_nlp(ingredients: List[str]) -> Ingredient: for ingredient in parse_multiple_ingredients(ingredients): name = ingredient.name.text if ingredient.name else '' - quantity, unit = 1, units.ITEMS.name - if ingredient.amount: - amount = ingredient.amount[0] - quantity = amount.quantity if amount.quantity else 1 - - real_unit = units.get_unit(unit) - if real_unit: - unit = real_unit.name - elif not name: - name = unit + quantity, unit = None, None + for amount in ingredient.amount: + if quantity is None and amount.quantity: + quantity = amount.quantity + if unit is None and amount.unit: + real_unit = units.get_unit(amount.unit) + if real_unit: + unit = real_unit.name + + if quantity is None: + quantity = 1 + if unit is None: + unit = units.ITEMS.name + results.append(Ingredient(id=0, line=ingredient.sentence, name=name, @@ -52,6 +56,9 @@ async def _get_recipe_from_ldata(conn, url: str, ldata: dict) -> dict: ingredients = await match_existing_products(conn, ingredients) name = ldata['name'] if 'name' in ldata else url images = ldata['image'] if 'image' in ldata else [] + if isinstance(images, str): + images = [images] + return Recipe( id=0, name=name, diff --git a/recipes/db.py b/recipes/db.py index 7049a7d..c59965f 100644 --- a/recipes/db.py +++ b/recipes/db.py @@ -61,13 +61,13 @@ async def insert_ingredient(conn, ingredient: Ingredient): async def insert_recipe(conn, recipe: Recipe): async with conn.execute(''' INSERT INTO Recipe (name, link, raw_data, image_urls) - VALUES (?, ?, ?) + VALUES (?, ?, ?, ?) ''', (recipe.name, recipe.link, recipe.raw_data, json.dumps(recipe.image_urls))) as cursor: recipe.id = cursor.lastrowid def row_to_recipe(row) -> Recipe: d = {k:v for k,v in zip(Recipe.KEYS, row)} - d['img_urls'] = json.loads(d['img_urls']) + d['image_urls'] = json.loads(d['image_urls']) return Recipe(**d) async def find_recipe_by_id(conn, recipe_id: int) -> Recipe: @@ -87,6 +87,14 @@ async def find_ingredients_by_recipe_id(conn, recipe_id: int) -> List[Ingredient async for row in cursor: yield Ingredient(**{k:v for k,v in zip(Ingredient.KEYS, row)}) +async def find_recipes_by_name(conn, name: str) -> List[Recipe]: + async with conn.execute(f''' + SELECT {','.join(Recipe.KEYS)} FROM Recipe + WHERE name LIKE ? + ''', (f'%{name}%',)) as cursor: + async for row in cursor: + yield row_to_recipe(row) + async def get_all(conn) -> List[Recipe]: async with conn.execute(f''' SELECT {','.join(Recipe.KEYS)} FROM Recipe diff --git a/units.py b/units.py index ba800b1..5780846 100644 --- a/units.py +++ b/units.py @@ -21,11 +21,11 @@ LITRE = Unit("Litre", ["litre", "liter", "l"], "volume", 1) GRAM = Unit("Gram", ["gram", "g"], "weight", 1) # Add conversion factors for common cooking measurements -CUP = Unit("Cup", ["cup", "c"], "volume", 240) -TABLESPOON = Unit("Tablespoon", ["tablespoon", "tablespoons", "tbsp"], "volume", 15) -TEASPOON = Unit("Teaspoon", ["teaspoon", "teaspoons", "tsp"], "volume", 5) +CUP = Unit("Cup", ["cup", "cups", "c"], "volume", 240) +TABLESPOON = Unit("Tablespoon", ["tablespoon", "tablespoons", "tbsp", "tbsps"], "volume", 15) +TEASPOON = Unit("Teaspoon", ["teaspoon", "teaspoons", "tsp", "tsps"], "volume", 5) OUNCE = Unit("Ounce", ["ounce", "ounces", "oz"], "weight", 28.3495) -POUND = Unit("Pound", ["pound", "pounds", "lb"], "weight", 453.592) +POUND = Unit("Pound", ["pound", "pounds", "lb", "lbs"], "weight", 453.592) FLUID_OUNCE = Unit("Fluid Ounce", ["fluid ounce", "fl oz"], "volume", 29.5735) PINT = Unit("Pint", ["pint", "pt"], "volume", 473.176) QUART = Unit("Quart", ["quart", "qt"], "volume", 946.353)