From cc8e1c5049f949f4ec7cbb6af4c549f35bcdb699 Mon Sep 17 00:00:00 2001 From: pixelpaws Date: Thu, 13 Nov 2025 15:52:31 +0800 Subject: [PATCH] fix(recipes): allow widget save without lora matches --- py/services/recipes/persistence_service.py | 2 -- tests/services/test_recipe_services.py | 42 ++++++++++++++++++++++ 2 files changed, 42 insertions(+), 2 deletions(-) diff --git a/py/services/recipes/persistence_service.py b/py/services/recipes/persistence_service.py index 9f7896d4..3e6db390 100644 --- a/py/services/recipes/persistence_service.py +++ b/py/services/recipes/persistence_service.py @@ -295,8 +295,6 @@ class RecipePersistenceService: lora_stack = metadata.get("loras", "") lora_matches = re.findall(r"]+)>", lora_stack) - if not lora_matches: - raise RecipeValidationError("No LoRAs found in the generation metadata") loras_data = [] base_model_counts: Dict[str, int] = {} diff --git a/tests/services/test_recipe_services.py b/tests/services/test_recipe_services.py index 1b1f5066..034b20e2 100644 --- a/tests/services/test_recipe_services.py +++ b/tests/services/test_recipe_services.py @@ -155,3 +155,45 @@ async def test_save_recipe_reports_duplicates(tmp_path): expected_image_path = os.path.normpath(result.payload["image_path"]) assert stored["file_path"] == expected_image_path assert service._exif_utils.appended[0] == expected_image_path + + +@pytest.mark.asyncio +async def test_save_recipe_from_widget_allows_empty_lora(tmp_path): + exif_utils = DummyExifUtils() + + class DummyScanner: + def __init__(self, root): + self.recipes_dir = str(root) + self.added = [] + + async def get_local_lora(self, name): # pragma: no cover - no lookups expected + return None + + async def add_recipe(self, recipe_data): + self.added.append(recipe_data) + + scanner = DummyScanner(tmp_path) + service = RecipePersistenceService( + exif_utils=exif_utils, + card_preview_width=512, + logger=logging.getLogger("test"), + ) + + metadata = { + "loras": "", # no matches present in the stack + "checkpoint": "base-model.safetensors", + "prompt": "a calm scene", + "negative_prompt": "", + } + + result = await service.save_recipe_from_widget( + recipe_scanner=scanner, + metadata=metadata, + image_bytes=b"image-bytes", + ) + + stored = json.loads(Path(result.payload["json_path"]).read_text()) + + assert stored["loras"] == [] + assert stored["title"] == "recipe" + assert scanner.added and scanner.added[0]["loras"] == []