mirror of
https://github.com/mealie-recipes/mealie.git
synced 2026-02-08 08:53:10 -05:00
fix: strict optional errors (#1759)
* fix strict optional errors * fix typing in repository * fix backup db files location * update workspace settings
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
from pathlib import Path
|
||||
|
||||
from mealie.core.exceptions import UnexpectedNone
|
||||
from mealie.repos.repository_factory import AllRepositories
|
||||
from mealie.schema.group.group_exports import GroupDataExport
|
||||
from mealie.schema.recipe import CategoryBase
|
||||
@@ -41,6 +42,9 @@ class RecipeBulkActionsService(BaseService):
|
||||
|
||||
group = self.repos.groups.get_one(self.group.id)
|
||||
|
||||
if group is None:
|
||||
raise UnexpectedNone("Failed to purge exports for group, no group found")
|
||||
|
||||
for match in group.directory.glob("**/export/*zip"):
|
||||
if match.is_file():
|
||||
match.unlink()
|
||||
@@ -52,8 +56,8 @@ class RecipeBulkActionsService(BaseService):
|
||||
for slug in recipes:
|
||||
recipe = self.repos.recipes.get_one(slug)
|
||||
|
||||
if recipe is None:
|
||||
self.logger.error(f"Failed to set settings for recipe {slug}, no recipe found")
|
||||
if recipe is None or recipe.settings is None:
|
||||
raise UnexpectedNone(f"Failed to set settings for recipe {slug}, no recipe found")
|
||||
|
||||
settings.locked = recipe.settings.locked
|
||||
recipe.settings = settings
|
||||
@@ -69,9 +73,12 @@ class RecipeBulkActionsService(BaseService):
|
||||
recipe = self.repos.recipes.get_one(slug)
|
||||
|
||||
if recipe is None:
|
||||
self.logger.error(f"Failed to tag recipe {slug}, no recipe found")
|
||||
raise UnexpectedNone(f"Failed to tag recipe {slug}, no recipe found")
|
||||
|
||||
recipe.tags += tags
|
||||
if recipe.tags is None:
|
||||
recipe.tags = []
|
||||
|
||||
recipe.tags += tags # type: ignore
|
||||
|
||||
try:
|
||||
self.repos.recipes.update(slug, recipe)
|
||||
@@ -84,9 +91,12 @@ class RecipeBulkActionsService(BaseService):
|
||||
recipe = self.repos.recipes.get_one(slug)
|
||||
|
||||
if recipe is None:
|
||||
self.logger.error(f"Failed to categorize recipe {slug}, no recipe found")
|
||||
raise UnexpectedNone(f"Failed to categorize recipe {slug}, no recipe found")
|
||||
|
||||
recipe.recipe_category += categories
|
||||
if recipe.recipe_category is None:
|
||||
recipe.recipe_category = []
|
||||
|
||||
recipe.recipe_category += categories # type: ignore
|
||||
|
||||
try:
|
||||
self.repos.recipes.update(slug, recipe)
|
||||
|
||||
@@ -50,6 +50,8 @@ class RecipeService(BaseService):
|
||||
return recipe
|
||||
|
||||
def can_update(self, recipe: Recipe) -> bool:
|
||||
if recipe.settings is None:
|
||||
raise exceptions.UnexpectedNone("Recipe Settings is None")
|
||||
return recipe.settings.locked is False or self.user.id == recipe.user_id
|
||||
|
||||
def can_lock_unlock(self, recipe: Recipe) -> bool:
|
||||
@@ -66,6 +68,9 @@ class RecipeService(BaseService):
|
||||
except FileNotFoundError:
|
||||
self.logger.error(f"Recipe Directory not Found: {original_slug}")
|
||||
|
||||
if recipe.assets is None:
|
||||
recipe.assets = []
|
||||
|
||||
all_asset_files = [x.file_name for x in recipe.assets]
|
||||
|
||||
for file in recipe.asset_dir.iterdir():
|
||||
@@ -92,7 +97,7 @@ class RecipeService(BaseService):
|
||||
additional_attrs["group_id"] = user.group_id
|
||||
|
||||
if additional_attrs.get("tags"):
|
||||
for i in range(len(additional_attrs.get("tags"))):
|
||||
for i in range(len(additional_attrs.get("tags", []))):
|
||||
additional_attrs["tags"][i]["group_id"] = user.group_id
|
||||
|
||||
if not additional_attrs.get("recipe_ingredient"):
|
||||
@@ -105,6 +110,9 @@ class RecipeService(BaseService):
|
||||
|
||||
def create_one(self, create_data: Union[Recipe, CreateRecipe]) -> Recipe:
|
||||
|
||||
if create_data.name is None:
|
||||
create_data.name = "New Recipe"
|
||||
|
||||
data: Recipe = self._recipe_creation_factory(
|
||||
self.user,
|
||||
name=create_data.name,
|
||||
@@ -134,8 +142,8 @@ class RecipeService(BaseService):
|
||||
with temp_path.open("wb") as buffer:
|
||||
shutil.copyfileobj(archive.file, buffer)
|
||||
|
||||
recipe_dict = None
|
||||
recipe_image = None
|
||||
recipe_dict: dict | None = None
|
||||
recipe_image: bytes | None = None
|
||||
|
||||
with ZipFile(temp_path) as myzip:
|
||||
for file in myzip.namelist():
|
||||
@@ -146,10 +154,15 @@ class RecipeService(BaseService):
|
||||
with myzip.open(file) as myfile:
|
||||
recipe_image = myfile.read()
|
||||
|
||||
if recipe_dict is None:
|
||||
raise exceptions.UnexpectedNone("No json data found in Zip")
|
||||
|
||||
recipe = self.create_one(Recipe(**recipe_dict))
|
||||
|
||||
if recipe:
|
||||
if recipe and recipe.id:
|
||||
data_service = RecipeDataService(recipe.id)
|
||||
|
||||
if recipe_image:
|
||||
data_service.write_image(recipe_image, "webp")
|
||||
|
||||
return recipe
|
||||
@@ -172,6 +185,10 @@ class RecipeService(BaseService):
|
||||
"""
|
||||
|
||||
recipe = self._get_recipe(slug)
|
||||
|
||||
if recipe is None or recipe.settings is None:
|
||||
raise exceptions.NoEntryFound("Recipe not found.")
|
||||
|
||||
if not self.can_update(recipe):
|
||||
raise exceptions.PermissionDenied("You do not have permission to edit this recipe.")
|
||||
|
||||
@@ -189,9 +206,12 @@ class RecipeService(BaseService):
|
||||
return new_data
|
||||
|
||||
def patch_one(self, slug: str, patch_data: Recipe) -> Recipe:
|
||||
recipe = self._pre_update_check(slug, patch_data)
|
||||
recipe: Recipe | None = self._pre_update_check(slug, patch_data)
|
||||
recipe = self.repos.recipes.by_group(self.group.id).get_one(slug)
|
||||
|
||||
if recipe is None:
|
||||
raise exceptions.NoEntryFound("Recipe not found.")
|
||||
|
||||
new_data = self.repos.recipes.by_group(self.group.id).patch(recipe.slug, patch_data.dict(exclude_unset=True))
|
||||
|
||||
self.check_assets(new_data, recipe.slug)
|
||||
@@ -210,6 +230,6 @@ class RecipeService(BaseService):
|
||||
# =================================================================
|
||||
# Recipe Template Methods
|
||||
|
||||
def render_template(self, recipe: Recipe, temp_dir: Path, template: str = None) -> Path:
|
||||
def render_template(self, recipe: Recipe, temp_dir: Path, template: str) -> Path:
|
||||
t_service = TemplateService(temp_dir)
|
||||
return t_service.render(recipe, template)
|
||||
|
||||
@@ -16,7 +16,7 @@ class TemplateType(str, enum.Enum):
|
||||
|
||||
|
||||
class TemplateService(BaseService):
|
||||
def __init__(self, temp: Path = None) -> None:
|
||||
def __init__(self, temp: Path | None = None) -> None:
|
||||
"""Creates a template service that can be used for multiple template generations
|
||||
A temporary directory must be provided as a place holder for where to render all templates
|
||||
Args:
|
||||
@@ -58,7 +58,7 @@ class TemplateService(BaseService):
|
||||
|
||||
return TemplateType(t_type)
|
||||
|
||||
def render(self, recipe: Recipe, template: str = None) -> Path:
|
||||
def render(self, recipe: Recipe, template: str) -> Path:
|
||||
"""
|
||||
Renders a TemplateType in a temporary directory and returns the path to the file.
|
||||
|
||||
@@ -87,6 +87,9 @@ class TemplateService(BaseService):
|
||||
"""
|
||||
self.__check_temp(self._render_json)
|
||||
|
||||
if self.temp is None:
|
||||
raise ValueError("Temporary directory must be provided for method _render_json")
|
||||
|
||||
save_path = self.temp.joinpath(f"{recipe.slug}.json")
|
||||
with open(save_path, "w") as f:
|
||||
f.write(recipe.json(indent=4, by_alias=True))
|
||||
@@ -100,6 +103,9 @@ class TemplateService(BaseService):
|
||||
"""
|
||||
self.__check_temp(self._render_jinja2)
|
||||
|
||||
if j2_template is None:
|
||||
raise ValueError("Template must be provided for method _render_jinja2")
|
||||
|
||||
j2_path: Path = self.directories.TEMPLATE_DIR / j2_template
|
||||
|
||||
if not j2_path.is_file():
|
||||
@@ -113,6 +119,9 @@ class TemplateService(BaseService):
|
||||
|
||||
save_name = f"{recipe.slug}{j2_path.suffix}"
|
||||
|
||||
if self.temp is None:
|
||||
raise ValueError("Temporary directory must be provided for method _render_jinja2")
|
||||
|
||||
save_path = self.temp.joinpath(save_name)
|
||||
|
||||
with open(save_path, "w") as f:
|
||||
@@ -124,6 +133,10 @@ class TemplateService(BaseService):
|
||||
self.__check_temp(self._render_jinja2)
|
||||
|
||||
image_asset = recipe.image_dir.joinpath(RecipeImageTypes.original.value)
|
||||
|
||||
if self.temp is None:
|
||||
raise ValueError("Temporary directory must be provided for method _render_zip")
|
||||
|
||||
zip_temp = self.temp.joinpath(f"{recipe.slug}.zip")
|
||||
|
||||
with ZipFile(zip_temp, "w") as myzip:
|
||||
|
||||
Reference in New Issue
Block a user