Coverage for opt/mealie/lib/python3.12/site-packages/mealie/schema/recipe/recipe_timeline_events.py: 98%

57 statements  

« prev     ^ index     » next       coverage.py v7.10.6, created at 2025-11-25 15:48 +0000

1from datetime import UTC, datetime 1a

2from enum import Enum 1a

3from pathlib import Path 1a

4from typing import Annotated 1a

5 

6from pydantic import UUID4, ConfigDict, Field 1a

7from sqlalchemy.orm import joinedload 1a

8from sqlalchemy.orm.interfaces import LoaderOption 1a

9 

10from mealie.core.config import get_app_dirs 1a

11from mealie.db.models.recipe.recipe_timeline import RecipeTimelineEvent 1a

12from mealie.db.models.users.users import User 1a

13from mealie.schema._mealie import MealieModel 1a

14from mealie.schema._mealie.mealie_model import UpdatedAtField 1a

15from mealie.schema.recipe.recipe import Recipe 1a

16from mealie.schema.response.pagination import PaginationBase 1a

17 

18app_dirs = get_app_dirs() 1a

19 

20 

21class TimelineEventType(Enum): 1a

22 system = "system" 1a

23 info = "info" 1a

24 comment = "comment" 1a

25 

26 

27class TimelineEventImage(Enum): 1a

28 has_image = "has image" 1a

29 does_not_have_image = "does not have image" 1a

30 

31 

32class RecipeTimelineEventIn(MealieModel): 1a

33 recipe_id: UUID4 1a

34 user_id: UUID4 | None = None 1a

35 """can be inferred in some contexts, so it's not required""" 1a

36 

37 subject: str 1a

38 event_type: TimelineEventType 1a

39 

40 message: str | None = Field(None, alias="eventMessage") 1a

41 image: Annotated[TimelineEventImage | None, Field(validate_default=True)] = TimelineEventImage.does_not_have_image 1a

42 

43 timestamp: datetime = datetime.now(UTC) 1a

44 model_config = ConfigDict(use_enum_values=True) 1a

45 

46 

47class RecipeTimelineEventCreate(RecipeTimelineEventIn): 1a

48 user_id: UUID4 1a

49 

50 

51class RecipeTimelineEventUpdate(MealieModel): 1a

52 subject: str 1a

53 message: str | None = Field(None, alias="eventMessage") 1a

54 image: TimelineEventImage | None = None 1a

55 model_config = ConfigDict(use_enum_values=True) 1a

56 

57 

58class RecipeTimelineEventOut(RecipeTimelineEventCreate): 1a

59 id: UUID4 1a

60 group_id: UUID4 1a

61 household_id: UUID4 1a

62 

63 created_at: datetime 1a

64 updated_at: datetime = UpdatedAtField(...) 1a

65 model_config = ConfigDict(from_attributes=True) 1a

66 

67 @classmethod 1a

68 def loader_options(cls) -> list[LoaderOption]: 1a

69 return [ 1bcdefghijklm

70 joinedload(RecipeTimelineEvent.recipe), 

71 joinedload(RecipeTimelineEvent.user).load_only(User.household_id, User.group_id), 

72 ] 

73 

74 @classmethod 1a

75 def image_dir_from_id(cls, recipe_id: UUID4 | str, timeline_event_id: UUID4 | str) -> Path: 1a

76 return Recipe.timeline_image_dir_from_id(recipe_id, timeline_event_id) 1n

77 

78 @property 1a

79 def image_dir(self) -> Path: 1a

80 return self.image_dir_from_id(self.recipe_id, self.id) 

81 

82 

83class RecipeTimelineEventPagination(PaginationBase): 1a

84 items: list[RecipeTimelineEventOut] 1a