mirror of
https://github.com/hay-kot/mealie.git
synced 2025-08-22 14:33:33 -07:00
refactor/remove duplicate code
This commit is contained in:
parent
423b264e4f
commit
11b5e7733d
6 changed files with 64 additions and 91 deletions
|
@ -13,11 +13,6 @@ from mealie.services.scraper.cleaner import Cleaner
|
||||||
from mealie.utils.unzip import unpack_zip
|
from mealie.utils.unzip import unpack_zip
|
||||||
from pydantic import BaseModel
|
from pydantic import BaseModel
|
||||||
|
|
||||||
try:
|
|
||||||
from yaml import CLoader as Loader
|
|
||||||
except ImportError:
|
|
||||||
from yaml import Loader
|
|
||||||
|
|
||||||
|
|
||||||
class MigrationAlias(BaseModel):
|
class MigrationAlias(BaseModel):
|
||||||
"""A datatype used by MigrationBase to pre-process a recipe dictionary to rewrite
|
"""A datatype used by MigrationBase to pre-process a recipe dictionary to rewrite
|
||||||
|
@ -115,19 +110,6 @@ class MigrationBase(BaseModel):
|
||||||
image.write_image(dest_slug, src, extension=src.suffix)
|
image.write_image(dest_slug, src, extension=src.suffix)
|
||||||
minify.migrate_images() # TODO: Refactor to support single file minification that doesn't suck
|
minify.migrate_images() # TODO: Refactor to support single file minification that doesn't suck
|
||||||
|
|
||||||
def get_recipe_from_file(self, file) -> Recipe:
|
|
||||||
"""This is the method called to read a file path and transform that data
|
|
||||||
into a recipe object. The expected return value is a Recipe object that is then
|
|
||||||
passed to
|
|
||||||
|
|
||||||
Args:
|
|
||||||
file ([type]): [description]
|
|
||||||
|
|
||||||
Raises:
|
|
||||||
NotImplementedError: [description]
|
|
||||||
"""
|
|
||||||
|
|
||||||
raise NotImplementedError("Migration Type not Implemented")
|
|
||||||
|
|
||||||
def rewrite_alias(self, recipe_dict: dict) -> dict:
|
def rewrite_alias(self, recipe_dict: dict) -> dict:
|
||||||
"""A helper function to reassign attributes by an alias using a list
|
"""A helper function to reassign attributes by an alias using a list
|
||||||
|
@ -162,7 +144,7 @@ class MigrationBase(BaseModel):
|
||||||
"""Calls the rewrite_alias function and the Cleaner.clean function on a
|
"""Calls the rewrite_alias function and the Cleaner.clean function on a
|
||||||
dictionary and returns the result unpacked into a Recipe object"""
|
dictionary and returns the result unpacked into a Recipe object"""
|
||||||
recipe_dict = self.rewrite_alias(recipe_dict)
|
recipe_dict = self.rewrite_alias(recipe_dict)
|
||||||
recipe_dict = Cleaner.clean(recipe_dict)
|
recipe_dict = Cleaner.clean(recipe_dict, url=recipe_dict.get("orgURL", None))
|
||||||
|
|
||||||
return Recipe(**recipe_dict)
|
return Recipe(**recipe_dict)
|
||||||
|
|
||||||
|
|
|
@ -3,25 +3,17 @@ from typing import Optional
|
||||||
|
|
||||||
from mealie.core.config import app_dirs
|
from mealie.core.config import app_dirs
|
||||||
from mealie.schema.migration import MigrationImport
|
from mealie.schema.migration import MigrationImport
|
||||||
from mealie.services.migrations._migration_base import (MigrationAlias,
|
from mealie.services.migrations import helpers
|
||||||
MigrationBase)
|
from mealie.services.migrations._migration_base import MigrationAlias, MigrationBase
|
||||||
from sqlalchemy.orm.session import Session
|
from sqlalchemy.orm.session import Session
|
||||||
|
|
||||||
|
|
||||||
def process_tags(all_tags):
|
|
||||||
return [x.title() for x in all_tags.split(",")]
|
|
||||||
|
|
||||||
|
|
||||||
def process_instructions(all_instructions):
|
|
||||||
return [{"text": instruction} for instruction in all_instructions]
|
|
||||||
|
|
||||||
|
|
||||||
class ChowdownMigration(MigrationBase):
|
class ChowdownMigration(MigrationBase):
|
||||||
key_aliases: Optional[list[MigrationAlias]] = [
|
key_aliases: Optional[list[MigrationAlias]] = [
|
||||||
MigrationAlias(key="name", alias="title", func=None),
|
MigrationAlias(key="name", alias="title", func=None),
|
||||||
MigrationAlias(key="recipeIngredient", alias="ingredients", func=None),
|
MigrationAlias(key="recipeIngredient", alias="ingredients", func=None),
|
||||||
MigrationAlias(key="recipeInstructions", alias="directions", func=process_instructions),
|
MigrationAlias(key="recipeInstructions", alias="directions", func=None),
|
||||||
MigrationAlias(key="tags", alias="tags", func=process_tags),
|
MigrationAlias(key="tags", alias="tags", func=helpers.split_by_comma),
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
|
|
12
mealie/services/migrations/helpers.py
Normal file
12
mealie/services/migrations/helpers.py
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
def split_by_comma(tag_string: str):
|
||||||
|
"""Splits a single string by ',' performs a line strip and then title cases the resulting string
|
||||||
|
|
||||||
|
Args:
|
||||||
|
tag_string (str): [description]
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
[type]: [description]
|
||||||
|
"""
|
||||||
|
if not isinstance(tag_string, str):
|
||||||
|
return None
|
||||||
|
return [x.title().lstrip() for x in tag_string.split(",") if x != ""]
|
|
@ -3,18 +3,13 @@ from pathlib import Path
|
||||||
from typing import Optional
|
from typing import Optional
|
||||||
|
|
||||||
from mealie.schema.migration import MigrationImport
|
from mealie.schema.migration import MigrationImport
|
||||||
from mealie.services.migrations._migration_base import MigrationAlias, MigrationBase
|
from mealie.services.migrations import helpers
|
||||||
|
from mealie.services.migrations._migration_base import (MigrationAlias,
|
||||||
|
MigrationBase)
|
||||||
from slugify import slugify
|
from slugify import slugify
|
||||||
from sqlalchemy.orm.session import Session
|
from sqlalchemy.orm.session import Session
|
||||||
|
|
||||||
|
|
||||||
def clean_nextcloud_tags(nextcloud_tags: str):
|
|
||||||
if not isinstance(nextcloud_tags, str):
|
|
||||||
return None
|
|
||||||
|
|
||||||
return [x.title().lstrip() for x in nextcloud_tags.split(",") if x != ""]
|
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
@dataclass
|
||||||
class NextcloudDir:
|
class NextcloudDir:
|
||||||
name: str
|
name: str
|
||||||
|
@ -42,7 +37,8 @@ class NextcloudDir:
|
||||||
|
|
||||||
class NextcloudMigration(MigrationBase):
|
class NextcloudMigration(MigrationBase):
|
||||||
key_aliases: Optional[list[MigrationAlias]] = [
|
key_aliases: Optional[list[MigrationAlias]] = [
|
||||||
MigrationAlias(key="tags", alias="keywords", func=clean_nextcloud_tags)
|
MigrationAlias(key="tags", alias="keywords", func=helpers.split_by_comma),
|
||||||
|
MigrationAlias(key="orgURL", alias="url", func=None),
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
|
@ -53,8 +49,9 @@ def migrate(session: Session, zip_path: Path) -> list[MigrationImport]:
|
||||||
with nc_migration.temp_dir as dir:
|
with nc_migration.temp_dir as dir:
|
||||||
potential_recipe_dirs = NextcloudMigration.glob_walker(dir, glob_str="**/[!.]*.json", return_parent=True)
|
potential_recipe_dirs = NextcloudMigration.glob_walker(dir, glob_str="**/[!.]*.json", return_parent=True)
|
||||||
|
|
||||||
nextcloud_dirs = [NextcloudDir.from_dir(x) for x in potential_recipe_dirs]
|
# nextcloud_dirs = [NextcloudDir.from_dir(x) for x in potential_recipe_dirs]
|
||||||
nextcloud_dirs = {x.slug: x for x in nextcloud_dirs}
|
nextcloud_dirs = {y.slug: y for x in potential_recipe_dirs if (y := NextcloudDir.from_dir(x))}
|
||||||
|
# nextcloud_dirs = {x.slug: x for x in nextcloud_dirs}
|
||||||
|
|
||||||
all_recipes = []
|
all_recipes = []
|
||||||
for _, nc_dir in nextcloud_dirs.items():
|
for _, nc_dir in nextcloud_dirs.items():
|
||||||
|
|
|
@ -9,7 +9,6 @@ from tests.app_routes import AppRoutes
|
||||||
from tests.test_config import TEST_CHOWDOWN_DIR, TEST_NEXTCLOUD_DIR
|
from tests.test_config import TEST_CHOWDOWN_DIR, TEST_NEXTCLOUD_DIR
|
||||||
|
|
||||||
|
|
||||||
# Chowdown
|
|
||||||
@pytest.fixture(scope="session")
|
@pytest.fixture(scope="session")
|
||||||
def chowdown_zip():
|
def chowdown_zip():
|
||||||
zip = TEST_CHOWDOWN_DIR.joinpath("test_chowdown-gh-pages.zip")
|
zip = TEST_CHOWDOWN_DIR.joinpath("test_chowdown-gh-pages.zip")
|
||||||
|
@ -42,14 +41,10 @@ def test_import_chowdown_directory(api_client: TestClient, api_routes: AppRoutes
|
||||||
|
|
||||||
assert response.status_code == 200
|
assert response.status_code == 200
|
||||||
|
|
||||||
report = json.loads(response.content)
|
reports = json.loads(response.content)
|
||||||
assert report["failed"] == []
|
|
||||||
|
|
||||||
expected_slug = "roasted-okra"
|
for report in reports:
|
||||||
|
assert report.get("status") is True
|
||||||
recipe_url = api_routes.recipes_recipe_slug(expected_slug)
|
|
||||||
response = api_client.get(recipe_url)
|
|
||||||
assert response.status_code == 200
|
|
||||||
|
|
||||||
|
|
||||||
def test_delete_chowdown_migration_data(api_client: TestClient, api_routes: AppRoutes, chowdown_zip: Path, token):
|
def test_delete_chowdown_migration_data(api_client: TestClient, api_routes: AppRoutes, chowdown_zip: Path, token):
|
||||||
|
@ -91,13 +86,9 @@ def test_import_nextcloud_directory(api_client: TestClient, api_routes: AppRoute
|
||||||
|
|
||||||
assert response.status_code == 200
|
assert response.status_code == 200
|
||||||
|
|
||||||
report = json.loads(response.content)
|
reports = json.loads(response.content)
|
||||||
assert report["failed"] == []
|
for report in reports:
|
||||||
|
assert report.get("status") is True
|
||||||
expected_slug = "air-fryer-shrimp"
|
|
||||||
recipe_url = api_routes.recipes_recipe_slug(expected_slug)
|
|
||||||
response = api_client.get(recipe_url)
|
|
||||||
assert response.status_code == 200
|
|
||||||
|
|
||||||
|
|
||||||
def test_delete__nextcloud_migration_data(api_client: TestClient, api_routes: AppRoutes, nextcloud_zip: Path, token):
|
def test_delete__nextcloud_migration_data(api_client: TestClient, api_routes: AppRoutes, nextcloud_zip: Path, token):
|
||||||
|
|
|
@ -1,40 +1,39 @@
|
||||||
import shutil
|
# import shutil
|
||||||
from pathlib import Path
|
# from pathlib import Path
|
||||||
|
|
||||||
import pytest
|
# import pytest
|
||||||
from mealie.core.config import app_dirs
|
# from mealie.core.config import app_dirs
|
||||||
from mealie.schema.recipe import Recipe
|
# from mealie.schema.recipe import Recipe
|
||||||
from mealie.services.migrations.nextcloud import cleanup, import_recipes, prep, process_selection
|
# from tests.test_config import TEST_NEXTCLOUD_DIR
|
||||||
from tests.test_config import TEST_NEXTCLOUD_DIR
|
|
||||||
|
|
||||||
CWD = Path(__file__).parent
|
# CWD = Path(__file__).parent
|
||||||
TEST_NEXTCLOUD_DIR
|
# TEST_NEXTCLOUD_DIR
|
||||||
TEMP_NEXTCLOUD = app_dirs.TEMP_DIR.joinpath("nextcloud")
|
# TEMP_NEXTCLOUD = app_dirs.TEMP_DIR.joinpath("nextcloud")
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.parametrize(
|
# @pytest.mark.parametrize(
|
||||||
"file_name,final_path",
|
# "file_name,final_path",
|
||||||
[("nextcloud.zip", TEMP_NEXTCLOUD)],
|
# [("nextcloud.zip", TEMP_NEXTCLOUD)],
|
||||||
)
|
# )
|
||||||
def test_zip_extraction(file_name: str, final_path: Path):
|
# def test_zip_extraction(file_name: str, final_path: Path):
|
||||||
prep()
|
# prep()
|
||||||
zip = TEST_NEXTCLOUD_DIR.joinpath(file_name)
|
# zip = TEST_NEXTCLOUD_DIR.joinpath(file_name)
|
||||||
dir = process_selection(zip)
|
# dir = process_selection(zip)
|
||||||
|
|
||||||
assert dir == final_path
|
# assert dir == final_path
|
||||||
cleanup()
|
# cleanup()
|
||||||
assert dir.exists() is False
|
# assert dir.exists() is False
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.parametrize(
|
# @pytest.mark.parametrize(
|
||||||
"recipe_dir",
|
# "recipe_dir",
|
||||||
[
|
# [
|
||||||
TEST_NEXTCLOUD_DIR.joinpath("Air Fryer Shrimp"),
|
# TEST_NEXTCLOUD_DIR.joinpath("Air Fryer Shrimp"),
|
||||||
TEST_NEXTCLOUD_DIR.joinpath("Chicken Parmigiana"),
|
# TEST_NEXTCLOUD_DIR.joinpath("Chicken Parmigiana"),
|
||||||
TEST_NEXTCLOUD_DIR.joinpath("Skillet Shepherd's Pie"),
|
# TEST_NEXTCLOUD_DIR.joinpath("Skillet Shepherd's Pie"),
|
||||||
],
|
# ],
|
||||||
)
|
# )
|
||||||
def test_nextcloud_migration(recipe_dir: Path):
|
# def test_nextcloud_migration(recipe_dir: Path):
|
||||||
recipe = import_recipes(recipe_dir)
|
# recipe = import_recipes(recipe_dir)
|
||||||
assert isinstance(recipe, Recipe)
|
# assert isinstance(recipe, Recipe)
|
||||||
shutil.rmtree(app_dirs.IMG_DIR.joinpath(recipe.image), ignore_errors=True)
|
# shutil.rmtree(app_dirs.IMG_DIR.joinpath(recipe.image), ignore_errors=True)
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue