Coverage for opt/mealie/lib/python3.12/site-packages/mealie/services/migrations/utils/database_helpers.py: 49%

29 statements  

« prev     ^ index     » next       coverage.py v7.15.2, created at 2026-10-07 03:04 +0000

1from __future__ import annotations 

2 

3from collections.abc import Iterable 

4from typing import TYPE_CHECKING 

5 

6from pydantic import BaseModel 

7from slugify import slugify 

8from sqlalchemy.orm import Session 

9 

10from mealie.repos.all_repositories import AllRepositories 

11from mealie.schema.recipe import RecipeCategory 

12from mealie.schema.recipe.recipe import RecipeTag 

13from mealie.schema.recipe.recipe_category import CategoryOut, CategorySave, TagOut, TagSave 

14 

15if TYPE_CHECKING: 15 ↛ 16line 15 didn't jump to line 16 because the condition on line 15 was never true

16 from mealie.repos.repository_generic import RepositoryGeneric 

17 

18 

19class DatabaseMigrationHelpers: 

20 def __init__(self, db: AllRepositories, session: Session) -> None: 

21 self.session = session 

22 self.db = db 

23 

24 def _get_or_set_generic[T: BaseModel]( 

25 self, accessor: RepositoryGeneric, items: Iterable[str], create_model: type[T], out_model: type[T] 

26 ) -> list[T]: 

27 """ 

28 Utility model for getting or setting categories or tags. This will only work for those two cases. 

29 

30 This is probably a bad implementation of this pattern. 

31 """ 

32 items_out = [] 

33 

34 for item_name in items: 

35 slug_lookup = slugify(item_name) 

36 

37 item_model = accessor.get_one(value=slug_lookup, key="slug", override_schema=out_model) 

38 

39 if not item_model: 

40 item_model = accessor.create( 

41 create_model( 

42 group_id=self.db.group_id, 

43 name=item_name, 

44 slug=slug_lookup, 

45 ) 

46 ) 

47 

48 items_out.append(item_model.model_dump()) 

49 return items_out 

50 

51 def get_or_set_category(self, categories: Iterable[str]) -> list[RecipeCategory]: 

52 return self._get_or_set_generic( 

53 self.db.categories, 

54 categories, 

55 CategorySave, 

56 CategoryOut, 

57 ) 

58 

59 def get_or_set_tags(self, tags: Iterable[str]) -> list[RecipeTag]: 

60 return self._get_or_set_generic( 

61 self.db.tags, 

62 tags, 

63 TagSave, 

64 TagOut, 

65 )