Coverage for opt/mealie/lib/python3.12/site-packages/mealie/services/recipe/template_service.py: 44%
55 statements
« prev ^ index » next coverage.py v7.15.2, created at 2026-10-07 03:04 +0000
« prev ^ index » next coverage.py v7.15.2, created at 2026-10-07 03:04 +0000
1import enum
2from pathlib import Path
3from zipfile import ZipFile
5from mealie.schema.recipe import Recipe
6from mealie.schema.recipe.recipe_image_types import RecipeImageTypes
7from mealie.services._base_service import BaseService
10class TemplateType(str, enum.Enum):
11 json = "json"
12 zip = "zip"
15class TemplateService(BaseService):
16 def __init__(self, temp: Path | None = None) -> None:
17 """Creates a template service that can be used for multiple template generations
18 A temporary directory must be provided as a place holder for where to render all templates
19 Args:
20 temp (Path): [description]
21 """
22 self.temp = temp
23 self.types = TemplateType
24 super().__init__()
26 @property
27 def templates(self) -> dict[str, list[str]]:
28 """
29 Returns a list of all templates available to render.
30 """
31 return {
32 TemplateType.json.value: ["raw"],
33 TemplateType.zip.value: ["zip"],
34 }
36 def __check_temp(self, method) -> None:
37 """
38 Checks if the temporary directory was provided on initialization
39 """
41 if self.temp is None:
42 raise ValueError(f"Temporary directory must be provided for method {method.__name__}")
44 def template_type(self, template: str) -> TemplateType:
45 # Determine Type:
46 t_type = None
47 for key, value in self.templates.items():
48 if template in value: 48 ↛ 49line 48 didn't jump to line 49 because the condition on line 48 was never true
49 t_type = key
50 break
52 if t_type is None: 52 ↛ 55line 52 didn't jump to line 55 because the condition on line 52 was always true
53 raise ValueError(f"Template '{template}' not found.")
55 return TemplateType(t_type)
57 def render(self, recipe: Recipe, template: str) -> Path:
58 """
59 Renders a TemplateType in a temporary directory and returns the path to the file.
61 Args:
62 t_type (TemplateType): The type of template to render
63 recipe (Recipe): The recipe to render
64 template (str): The template to render
65 """
66 t_type = self.template_type(template)
68 if t_type == TemplateType.json:
69 return self._render_json(recipe)
71 if t_type == TemplateType.zip:
72 return self._render_zip(recipe)
74 raise ValueError(f"Template Type '{t_type}' not found.")
76 def _render_json(self, recipe: Recipe) -> Path:
77 """
78 Renders a JSON file in a temporary directory and returns
79 the path to the file.
80 """
81 self.__check_temp(self._render_json)
83 if self.temp is None:
84 raise ValueError("Temporary directory must be provided for method _render_json")
86 save_path = self.temp.joinpath(f"{recipe.slug}.json")
87 with open(save_path, "w") as f:
88 f.write(recipe.model_dump_json(indent=4, by_alias=True))
90 return save_path
92 def _render_zip(self, recipe: Recipe) -> Path:
93 self.__check_temp(self._render_zip)
95 image_asset = recipe.image_dir.joinpath(RecipeImageTypes.original.value)
97 if self.temp is None:
98 raise ValueError("Temporary directory must be provided for method _render_zip")
100 zip_temp = self.temp.joinpath(f"{recipe.slug}.zip")
102 with ZipFile(zip_temp, "w") as myzip:
103 myzip.writestr(f"{recipe.slug}.json", recipe.model_dump_json())
105 if image_asset.is_file():
106 myzip.write(image_asset, arcname=image_asset.name)
108 return zip_temp