refactor(backend): ♻️ align variable names, eliminate dead-code, and finalize recipe services

This commit is contained in:
hay-kot
2021-08-28 16:24:14 -08:00
parent 985ad8017d
commit 8e9280efaf
23 changed files with 132 additions and 180 deletions

View File

@@ -5,10 +5,10 @@ from fastapi import Depends, Response
from fastapi.encoders import jsonable_encoder
from sqlalchemy.orm.session import Session
from mealie.core.dependencies import is_logged_in
from mealie.core.root_logger import get_logger
from mealie.db.database import db
from mealie.db.db_setup import SessionLocal, generate_session
from mealie.core.dependencies import is_logged_in
from mealie.schema.recipe import RecipeSummary
logger = get_logger()

View File

@@ -1,41 +0,0 @@
from typing import Any
from fastapi import BackgroundTasks, Depends
from pydantic import BaseModel
from sqlalchemy.orm.session import Session
from mealie.db.db_setup import generate_session
from mealie.core.dependencies import get_current_user, is_logged_in
class CommonDeps(BaseModel):
session: Session
background_tasks: BackgroundTasks
user: Any
class Config:
arbitrary_types_allowed = True
def read_deps(
background_tasks: BackgroundTasks,
session: Session = Depends(generate_session),
current_user=Depends(is_logged_in),
):
return CommonDeps(
session=session,
background_tasks=background_tasks,
user=current_user,
)
def write_deps(
background_tasks: BackgroundTasks,
session: Session = Depends(generate_session),
current_user=Depends(get_current_user),
):
return CommonDeps(
session=session,
background_tasks=background_tasks,
user=current_user,
)

View File

@@ -1,34 +0,0 @@
from pathlib import Path
from shutil import copytree, rmtree
from mealie.core.config import app_dirs
from mealie.core.root_logger import get_logger
from mealie.schema.recipe import Recipe
logger = get_logger()
def check_assets(original_slug, recipe: Recipe) -> None:
if original_slug != recipe.slug:
current_dir = app_dirs.RECIPE_DATA_DIR.joinpath(original_slug)
try:
copytree(current_dir, recipe.directory, dirs_exist_ok=True)
except FileNotFoundError:
logger.error(f"Recipe Directory not Found: {original_slug}")
logger.info(f"Renaming Recipe Directory: {original_slug} -> {recipe.slug}")
all_asset_files = [x.file_name for x in recipe.assets]
for file in recipe.asset_dir.iterdir():
file: Path
if file.is_dir():
continue
if file.name not in all_asset_files:
file.unlink()
def delete_assets(recipe_slug):
recipe_dir = Recipe(slug=recipe_slug).directory
rmtree(recipe_dir, ignore_errors=True)
logger.info(f"Recipe Directory Removed: {recipe_slug}")

View File

@@ -1,20 +1,33 @@
from pathlib import Path
from shutil import copytree, rmtree
from typing import Union
from fastapi import BackgroundTasks, Depends, HTTPException, status
from sqlalchemy.exc import IntegrityError
from sqlalchemy.orm.session import Session
from mealie.core.config import get_settings
from mealie.core.config import get_app_dirs, get_settings
from mealie.core.dependencies import ReadDeps
from mealie.core.dependencies.grouped import WriteDeps
from mealie.core.root_logger import get_logger
from mealie.db.database import get_database
from mealie.db.db_setup import SessionLocal
from mealie.schema.recipe.recipe import CreateRecipe, Recipe
from mealie.schema.user.user import UserInDB
from mealie.services.events import create_recipe_event
from mealie.services.recipe.media import delete_assets
logger = get_logger(module=__name__)
class RecipeService:
recipe: Recipe
"""
Class Methods:
`read_existing`: Reads an existing recipe from the database.
`write_existing`: Updates an existing recipe in the database.
`base`: Requires write permissions, but doesn't perform recipe checks
"""
recipe: Recipe # Required for proper type hints
def __init__(self, session: Session, user: UserInDB, background_tasks: BackgroundTasks = None) -> None:
self.session = session or SessionLocal()
@@ -22,8 +35,9 @@ class RecipeService:
self.background_tasks = background_tasks
self.recipe: Recipe = None
# Static Globals
# Static Globals Dependency Injection
self.db = get_database()
self.app_dirs = get_app_dirs()
self.settings = get_settings()
@classmethod
@@ -99,10 +113,11 @@ class RecipeService:
raise HTTPException(status.HTTP_403_FORBIDDEN)
# CRUD METHODS
def create_recipe(self, new_recipe: CreateRecipe) -> Recipe:
def create_recipe(self, create_data: Union[Recipe, CreateRecipe]) -> Recipe:
if isinstance(create_data, CreateRecipe):
create_data = Recipe(name=create_data.name)
try:
create_data = Recipe(name=new_recipe.name)
self.recipe = self.db.recipes.create(self.session, create_data)
except IntegrityError:
raise HTTPException(status.HTTP_400_BAD_REQUEST, detail={"message": "RECIPE_ALREADY_EXISTS"})
@@ -114,6 +129,32 @@ class RecipeService:
return self.recipe
def update_recipe(self, update_data: Recipe) -> Recipe:
original_slug = self.recipe.slug
try:
self.recipe = self.db.recipes.update(self.session, original_slug, update_data)
except IntegrityError:
raise HTTPException(status.HTTP_400_BAD_REQUEST, detail={"message": "RECIPE_ALREADY_EXISTS"})
self._check_assets(original_slug)
return self.recipe
def patch_recipe(self, patch_data: Recipe) -> Recipe:
original_slug = self.recipe.slug
try:
self.recipe = self.db.recipes.patch(
self.session, original_slug, patch_data.dict(exclude_unset=True, exclude_defaults=True)
)
except IntegrityError:
raise HTTPException(status.HTTP_400_BAD_REQUEST, detail={"message": "RECIPE_ALREADY_EXISTS"})
self._check_assets(original_slug)
return self.recipe
def delete_recipe(self) -> Recipe:
"""removes a recipe from the database and purges the existing files from the filesystem.
@@ -126,7 +167,7 @@ class RecipeService:
try:
recipe: Recipe = self.db.recipes.delete(self.session, self.recipe.slug)
delete_assets(recipe_slug=self.recipe.slug)
self._delete_assets()
except Exception:
raise HTTPException(status.HTTP_400_BAD_REQUEST)
@@ -135,3 +176,27 @@ class RecipeService:
def _create_event(self, title: str, message: str) -> None:
self.background_tasks.add_task(create_recipe_event, title, message, self.session)
def _check_assets(self, original_slug) -> None:
if original_slug != self.recipe.slug:
current_dir = self.app_dirs.RECIPE_DATA_DIR.joinpath(original_slug)
try:
copytree(current_dir, self.recipe.directory, dirs_exist_ok=True)
logger.info(f"Renaming Recipe Directory: {original_slug} -> {self.recipe.slug}")
except FileNotFoundError:
logger.error(f"Recipe Directory not Found: {original_slug}")
all_asset_files = [x.file_name for x in self.recipe.assets]
for file in self.recipe.asset_dir.iterdir():
file: Path
if file.is_dir():
continue
if file.name not in all_asset_files:
file.unlink()
def _delete_assets(self) -> None:
recipe_dir = self.recipe.directory
rmtree(recipe_dir, ignore_errors=True)
logger.info(f"Recipe Directory Removed: {self.recipe.slug}")

View File

@@ -5,6 +5,4 @@ Cron = collections.namedtuple("Cron", "hours minutes")
def cron_parser(time_str: str) -> Cron:
time = time_str.split(":")
cron = Cron(hours=int(time[0]), minutes=int(time[1]))
return cron
return Cron(hours=int(time[0]), minutes=int(time[1]))