From 795c2cf5752b3958abf3ba914819559213f63aa6 Mon Sep 17 00:00:00 2001 From: "gpotter@gmail.com" <119442226+parumpum@users.noreply.github.com> Date: Tue, 7 Jan 2025 07:55:59 -0800 Subject: [PATCH] fix: Allow scraping calories as number (#4854) Co-authored-by: Kuchenpirat <24235032+Kuchenpirat@users.noreply.github.com> --- mealie/services/scraper/cleaner.py | 29 +++++++++++++++---- .../scraper_tests/test_cleaner_parts.py | 18 ++++++++++++ 2 files changed, 42 insertions(+), 5 deletions(-) diff --git a/mealie/services/scraper/cleaner.py b/mealie/services/scraper/cleaner.py index 661792022b6..1089008c4e8 100644 --- a/mealie/services/scraper/cleaner.py +++ b/mealie/services/scraper/cleaner.py @@ -120,7 +120,8 @@ def clean_image(image: str | list | dict | None = None, default: str = "no image case str(image): return [image] case [str(_), *_]: - return [x for x in image if x] # Only return non-null strings in list + # Only return non-null strings in list + return [x for x in image if x] case [{"url": str(_)}, *_]: return [x["url"] for x in image if "url" in x] case {"url": str(image)}: @@ -128,7 +129,10 @@ def clean_image(image: str | list | dict | None = None, default: str = "no image case [{"@id": str(_)}, *_]: return [x["@id"] for x in image if "@id" in x] case _: - logger.exception(f"Unexpected type for image: {type(image)}, {image}") + logger.exception( + f"Unexpected type for image: { + type(image)}, {image}" + ) return [default] @@ -223,7 +227,10 @@ def clean_instructions(steps_object: list | dict | str, default: list | None = N ) ) case _: - raise TypeError(f"Unexpected type for instructions: {type(steps_object)}, {steps_object}") + raise TypeError( + f"Unexpected type for instructions: { + type(steps_object)}, {steps_object}" + ) def _sanitize_instruction_text(line: str | dict) -> str: @@ -283,7 +290,10 @@ def clean_ingredients(ingredients: list | str | None, default: list | None = Non case str(ingredients): return [clean_string(ingredient) for ingredient in ingredients.splitlines() if ingredient.strip()] case _: - raise TypeError(f"Unexpected type for ingredients: {type(ingredients)}, {ingredients}") + raise TypeError( + f"Unexpected type for ingredients: { + type(ingredients)}, {ingredients}" + ) def clean_int(val: str | int | None, min: int | None = None, max: int | None = None): @@ -521,7 +531,10 @@ def clean_categories(category: str | list) -> list[str]: # return [cat["name"] for cat in category if "name" in cat] case _: - raise TypeError(f"Unexpected type for category: {type(category)}, {category}") + raise TypeError( + f"Unexpected type for category: { + type(category)}, {category}" + ) def clean_tags(data: str | list[str]) -> list[str]: @@ -570,4 +583,10 @@ def clean_nutrition(nutrition: dict | None) -> dict[str, str]: with contextlib.suppress(AttributeError, TypeError): output_nutrition[key] = str(float(output_nutrition[key]) * 1000) + for key in ["calories"]: + if val := nutrition.get(key, None): + if isinstance(val, int | float): + with contextlib.suppress(AttributeError, TypeError): + output_nutrition[key] = str(val) + return output_nutrition diff --git a/tests/unit_tests/services_tests/scraper_tests/test_cleaner_parts.py b/tests/unit_tests/services_tests/scraper_tests/test_cleaner_parts.py index 98bf636dced..61e2e86b8a0 100644 --- a/tests/unit_tests/services_tests/scraper_tests/test_cleaner_parts.py +++ b/tests/unit_tests/services_tests/scraper_tests/test_cleaner_parts.py @@ -537,6 +537,24 @@ def test_cleaner_clean_tags(case: CleanerCase): "fatContent": "10", }, ), + CleanerCase( + test_id="calories as int", + input={ + "calories": 100, + }, + expected={ + "calories": "100", + }, + ), + CleanerCase( + test_id="calories as float", + input={ + "calories": 100.0, + }, + expected={ + "calories": "100.0", + }, + ), CleanerCase( test_id="invalid keys get removed", input={