This commit is contained in:
Hayden 2023-08-13 17:45:23 -05:00
parent e55258c5be
commit be372dbc51
No known key found for this signature in database
GPG Key ID: 17CF79474E257545
54 changed files with 438 additions and 437 deletions

View File

@ -1,7 +1,8 @@
from abc import ABC, abstractmethod
from pathlib import Path
from pydantic import BaseModel, BaseSettings, PostgresDsn
from pydantic import BaseModel, PostgresDsn
from pydantic_settings import BaseSettings
class AbstractDBProvider(ABC):

View File

@ -1,7 +1,8 @@
import secrets
from pathlib import Path
from pydantic import BaseSettings, NoneStr, validator
from pydantic import field_validator
from pydantic_settings import BaseSettings, SettingsConfigDict
from .db_providers import AbstractDBProvider, db_provider_factory
@ -48,7 +49,8 @@ class AppSettings(BaseSettings):
SECURITY_USER_LOCKOUT_TIME: int = 24
"time in hours"
@validator("BASE_URL")
@field_validator("BASE_URL")
@classmethod
def remove_trailing_slash(cls, v: str) -> str:
if v and v[-1] == "/":
return v[:-1]
@ -127,15 +129,15 @@ class AppSettings(BaseSettings):
# LDAP Configuration
LDAP_AUTH_ENABLED: bool = False
LDAP_SERVER_URL: NoneStr = None
LDAP_SERVER_URL: None | str = None
LDAP_TLS_INSECURE: bool = False
LDAP_TLS_CACERTFILE: NoneStr = None
LDAP_TLS_CACERTFILE: None | str = None
LDAP_ENABLE_STARTTLS: bool = False
LDAP_BASE_DN: NoneStr = None
LDAP_QUERY_BIND: NoneStr = None
LDAP_QUERY_PASSWORD: NoneStr = None
LDAP_USER_FILTER: NoneStr = None
LDAP_ADMIN_FILTER: NoneStr = None
LDAP_BASE_DN: None | str = None
LDAP_QUERY_BIND: None | str = None
LDAP_QUERY_PASSWORD: None | str = None
LDAP_USER_FILTER: None | str = None
LDAP_ADMIN_FILTER: None | str = None
LDAP_ID_ATTRIBUTE: str = "uid"
LDAP_MAIL_ATTRIBUTE: str = "mail"
LDAP_NAME_ATTRIBUTE: str = "name"
@ -157,9 +159,7 @@ class AppSettings(BaseSettings):
# Testing Config
TESTING: bool = False
class Config:
arbitrary_types_allowed = True
model_config = SettingsConfigDict(arbitrary_types_allowed=True)
def app_settings_constructor(data_dir: Path, production: bool, env_file: Path, env_encoding="utf-8") -> AppSettings:

View File

@ -2,6 +2,7 @@ from typing import TYPE_CHECKING, Optional
import sqlalchemy as sa
import sqlalchemy.orm as orm
from pydantic import ConfigDict
from sqlalchemy import select
from sqlalchemy.orm import Mapped, mapped_column
from sqlalchemy.orm.session import Session
@ -78,18 +79,16 @@ class Group(SqlAlchemyBase, BaseMixins):
ingredient_foods: Mapped[list["IngredientFoodModel"]] = orm.relationship("IngredientFoodModel", **common_args)
tools: Mapped[list["Tool"]] = orm.relationship("Tool", **common_args)
tags: Mapped[list["Tag"]] = orm.relationship("Tag", **common_args)
class Config:
exclude = {
"users",
"webhooks",
"shopping_lists",
"cookbooks",
"preferences",
"invite_tokens",
"mealplans",
"data_exports",
}
model_config = ConfigDict(exclude={
"users",
"webhooks",
"shopping_lists",
"cookbooks",
"preferences",
"invite_tokens",
"mealplans",
"data_exports",
})
@auto_init()
def __init__(self, **_) -> None:

View File

@ -1,6 +1,7 @@
from datetime import datetime
from typing import TYPE_CHECKING
from pydantic import ConfigDict
from sqlalchemy import ForeignKey, orm
from sqlalchemy.orm import Mapped, mapped_column
from sqlalchemy.sql.sqltypes import Boolean, DateTime, String
@ -47,9 +48,7 @@ class ReportModel(SqlAlchemyBase, BaseMixins):
# Relationships
group_id: Mapped[GUID] = mapped_column(GUID, ForeignKey("groups.id"), nullable=False, index=True)
group: Mapped["Group"] = orm.relationship("Group", back_populates="group_reports", single_parent=True)
class Config:
exclude = ["entries"]
model_config = ConfigDict(exclude=["entries"])
@auto_init()
def __init__(self, **_) -> None:

View File

@ -1,5 +1,6 @@
from typing import TYPE_CHECKING, Optional
from pydantic import ConfigDict
from sqlalchemy import Boolean, Float, ForeignKey, Integer, String, orm
from sqlalchemy.ext.orderinglist import ordering_list
from sqlalchemy.orm import Mapped, mapped_column
@ -72,9 +73,7 @@ class ShoppingListItem(SqlAlchemyBase, BaseMixins):
recipe_references: Mapped[list[ShoppingListItemRecipeReference]] = orm.relationship(
ShoppingListItemRecipeReference, cascade="all, delete, delete-orphan"
)
class Config:
exclude = {"id", "label", "food", "unit"}
model_config = ConfigDict(exclude={"id", "label", "food", "unit"})
@api_extras
@auto_init()
@ -94,9 +93,7 @@ class ShoppingListRecipeReference(BaseMixins, SqlAlchemyBase):
)
recipe_quantity: Mapped[float] = mapped_column(Float, nullable=False)
class Config:
exclude = {"id", "recipe"}
model_config = ConfigDict(exclude={"id", "recipe"})
@auto_init()
def __init__(self, **_) -> None:
@ -114,9 +111,7 @@ class ShoppingListMultiPurposeLabel(SqlAlchemyBase, BaseMixins):
"MultiPurposeLabel", back_populates="shopping_lists_label_settings"
)
position: Mapped[int] = mapped_column(Integer, nullable=False, default=0)
class Config:
exclude = {"label"}
model_config = ConfigDict(exclude={"label"})
@auto_init()
def __init__(self, **_) -> None:
@ -148,9 +143,7 @@ class ShoppingList(SqlAlchemyBase, BaseMixins):
collection_class=ordering_list("position"),
)
extras: Mapped[list[ShoppingListExtras]] = orm.relationship("ShoppingListExtras", cascade="all, delete-orphan")
class Config:
exclude = {"id", "list_items"}
model_config = ConfigDict(exclude={"id", "list_items"})
@api_extras
@auto_init()

View File

@ -1,3 +1,4 @@
from pydantic import ConfigDict
from sqlalchemy import ForeignKey, Integer, String, orm
from sqlalchemy.orm import Mapped, mapped_column
@ -28,12 +29,10 @@ class RecipeInstruction(SqlAlchemyBase):
ingredient_references: Mapped[list[RecipeIngredientRefLink]] = orm.relationship(
RecipeIngredientRefLink, cascade="all, delete-orphan"
)
class Config:
exclude = {
"id",
"ingredient_references",
}
model_config = ConfigDict(exclude={
"id",
"ingredient_references",
})
@auto_init()
def __init__(self, ingredient_references, session, **_) -> None:

View File

@ -3,6 +3,7 @@ from typing import TYPE_CHECKING
import sqlalchemy as sa
import sqlalchemy.orm as orm
from pydantic import ConfigDict
from sqlalchemy import event
from sqlalchemy.ext.orderinglist import ordering_list
from sqlalchemy.orm import Mapped, mapped_column, validates
@ -135,19 +136,16 @@ class RecipeModel(SqlAlchemyBase, BaseMixins):
# Automatically updated by sqlalchemy event, do not write to this manually
name_normalized: Mapped[str] = mapped_column(sa.String, nullable=False, index=True)
description_normalized: Mapped[str | None] = mapped_column(sa.String, index=True)
class Config:
get_attr = "slug"
exclude = {
"assets",
"notes",
"nutrition",
"recipe_ingredient",
"recipe_instructions",
"settings",
"comments",
"timeline_events",
}
model_config = ConfigDict(get_attr="slug", exclude={
"assets",
"notes",
"nutrition",
"recipe_ingredient",
"recipe_instructions",
"settings",
"comments",
"timeline_events",
})
@validates("name")
def validate_name(self, _, name):

View File

@ -2,6 +2,7 @@ import enum
from datetime import datetime
from typing import TYPE_CHECKING, Optional
from pydantic import ConfigDict
from sqlalchemy import Boolean, DateTime, Enum, ForeignKey, Integer, String, orm
from sqlalchemy.orm import Mapped, mapped_column
@ -83,16 +84,14 @@ class User(SqlAlchemyBase, BaseMixins):
favorite_recipes: Mapped[list["RecipeModel"]] = orm.relationship(
"RecipeModel", secondary=users_to_favorites, back_populates="favorited_by"
)
class Config:
exclude = {
"password",
"admin",
"can_manage",
"can_invite",
"can_organize",
"group",
}
model_config = ConfigDict(exclude={
"password",
"admin",
"can_manage",
"can_invite",
"can_organize",
"group",
})
@auto_init()
def __init__(self, session, full_name, password, group: str | None = None, **kwargs) -> None:

View File

@ -60,7 +60,7 @@ class RepositoryRecipes(RepositoryGeneric[Recipe, RecipeModel]):
stmt = (
select(self.model)
.join(RecipeSettings)
.filter(RecipeSettings.public == True) # noqa: 711
.filter(RecipeSettings.public is True) # noqa: 711
.order_by(order_attr.desc())
.offset(start)
.limit(limit)
@ -70,7 +70,7 @@ class RepositoryRecipes(RepositoryGeneric[Recipe, RecipeModel]):
stmt = (
select(self.model)
.join(RecipeSettings)
.filter(RecipeSettings.public == True) # noqa: 711
.filter(RecipeSettings.public is True) # noqa: 711
.offset(start)
.limit(limit)
)

View File

@ -2,7 +2,7 @@ from abc import ABC
from logging import Logger
from fastapi import Depends
from pydantic import UUID4
from pydantic import UUID4, ConfigDict
from sqlalchemy.orm import Session
from mealie.core.config import get_app_dirs, get_app_settings
@ -57,9 +57,7 @@ class _BaseController(ABC):
if not self._folders:
self._folders = get_app_dirs()
return self._folders
class Config:
arbitrary_types_allowed = True
model_config = ConfigDict(arbitrary_types_allowed=True)
class BasePublicController(_BaseController):

View File

@ -1,7 +1,7 @@
from functools import cached_property
from fastapi import APIRouter, Depends
from pydantic import UUID4, BaseModel
from pydantic import UUID4, BaseModel, ConfigDict
from mealie.routes._base import BaseCrudController, controller
from mealie.routes._base.mixins import HttpRepo
@ -20,9 +20,7 @@ class CategorySummary(BaseModel):
id: UUID4
slug: str
name: str
class Config:
orm_mode = True
model_config = ConfigDict(from_attributes=True)
@controller(router)

View File

@ -4,16 +4,14 @@ from collections.abc import Sequence
from typing import Protocol, TypeVar
from humps.main import camelize
from pydantic import UUID4, BaseModel
from pydantic import UUID4, BaseModel, ConfigDict
from sqlalchemy.orm.interfaces import LoaderOption
T = TypeVar("T", bound=BaseModel)
class MealieModel(BaseModel):
class Config:
alias_generator = camelize
allow_population_by_field_name = True
model_config = ConfigDict(alias_generator=camelize, populate_by_name=True)
def cast(self, cls: type[T], **kwargs) -> T:
"""

View File

@ -19,9 +19,9 @@ class ImportJob(BackupOptions):
class CreateBackup(BaseModel):
tag: str | None
tag: str | None = None
options: BackupOptions
templates: list[str] | None
templates: list[str] | None = None
class BackupFile(BaseModel):

View File

@ -4,11 +4,11 @@ from pydantic.main import BaseModel
class ImportBase(BaseModel):
name: str
status: bool
exception: str | None
exception: str | None = None
class RecipeImport(ImportBase):
slug: str | None
slug: str | None = None
class CommentImport(ImportBase):

View File

@ -1,4 +1,4 @@
from pydantic import validator
from pydantic import ConfigDict, validator
from slugify import slugify
from mealie.schema._mealie import MealieModel
@ -11,10 +11,10 @@ class CustomPageBase(MealieModel):
slug: str | None
position: int
categories: list[RecipeCategoryResponse] = []
model_config = ConfigDict(from_attributes=True)
class Config:
orm_mode = True
# TODO[pydantic]: We couldn't refactor the `validator`, please replace it by `field_validator` manually.
# Check https://docs.pydantic.dev/dev-v2/migration/#changes-to-validators for more information.
@validator("slug", always=True, pre=True)
def validate_slug(slug: str, values):
name: str = values["name"]
@ -28,6 +28,4 @@ class CustomPageBase(MealieModel):
class CustomPageOut(CustomPageBase):
id: int
class Config:
orm_mode = True
model_config = ConfigDict(from_attributes=True)

View File

@ -1,4 +1,4 @@
from pydantic import UUID4, validator
from pydantic import UUID4, ConfigDict, validator
from slugify import slugify
from sqlalchemy.orm import joinedload
from sqlalchemy.orm.interfaces import LoaderOption
@ -24,10 +24,14 @@ class CreateCookBook(MealieModel):
require_all_tags: bool = True
require_all_tools: bool = True
# TODO[pydantic]: We couldn't refactor the `validator`, please replace it by `field_validator` manually.
# Check https://docs.pydantic.dev/dev-v2/migration/#changes-to-validators for more information.
@validator("public", always=True, pre=True)
def validate_public(public: bool | None, values: dict) -> bool: # type: ignore
return False if public is None else public
# TODO[pydantic]: We couldn't refactor the `validator`, please replace it by `field_validator` manually.
# Check https://docs.pydantic.dev/dev-v2/migration/#changes-to-validators for more information.
@validator("slug", always=True, pre=True)
def validate_slug(slug: str, values): # type: ignore
name: str = values["name"]
@ -50,9 +54,7 @@ class UpdateCookBook(SaveCookBook):
class ReadCookBook(UpdateCookBook):
group_id: UUID4
categories: list[CategoryBase] = []
class Config:
orm_mode = True
model_config = ConfigDict(from_attributes=True)
@classmethod
def loader_options(cls) -> list[LoaderOption]:
@ -66,6 +68,4 @@ class CookBookPagination(PaginationBase):
class RecipeCookBook(ReadCookBook):
group_id: UUID4
recipes: list[RecipeSummary]
class Config:
orm_mode = True
model_config = ConfigDict(from_attributes=True)

View File

@ -1,4 +1,4 @@
from pydantic import UUID4, NoneStr
from pydantic import UUID4, ConfigDict, NoneStr
from sqlalchemy.orm import joinedload
from sqlalchemy.orm.interfaces import LoaderOption
@ -54,9 +54,7 @@ class GroupEventNotifierOptionsSave(GroupEventNotifierOptions):
class GroupEventNotifierOptionsOut(GroupEventNotifierOptions):
id: UUID4
class Config:
orm_mode = True
model_config = ConfigDict(from_attributes=True)
# =======================================================================
@ -85,9 +83,7 @@ class GroupEventNotifierOut(MealieModel):
enabled: bool
group_id: UUID4
options: GroupEventNotifierOptionsOut
class Config:
orm_mode = True
model_config = ConfigDict(from_attributes=True)
@classmethod
def loader_options(cls) -> list[LoaderOption]:
@ -100,6 +96,4 @@ class GroupEventPagination(PaginationBase):
class GroupEventNotifierPrivate(GroupEventNotifierOut):
apprise_url: str
class Config:
orm_mode = True
model_config = ConfigDict(from_attributes=True)

View File

@ -1,6 +1,6 @@
from datetime import datetime
from pydantic import UUID4
from pydantic import UUID4, ConfigDict
from mealie.schema._mealie import MealieModel
@ -13,6 +13,4 @@ class GroupDataExport(MealieModel):
path: str
size: str
expires: datetime
class Config:
orm_mode = True
model_config = ConfigDict(from_attributes=True)

View File

@ -1,6 +1,6 @@
from uuid import UUID
from pydantic import UUID4
from pydantic import UUID4, ConfigDict
from mealie.schema._mealie import MealieModel
@ -24,6 +24,4 @@ class CreateGroupPreferences(UpdateGroupPreferences):
class ReadGroupPreferences(CreateGroupPreferences):
id: UUID4
class Config:
orm_mode = True
model_config = ConfigDict(from_attributes=True)

View File

@ -7,6 +7,8 @@ from mealie.schema._mealie.validators import validate_locale
class SeederConfig(MealieModel):
locale: str
# TODO[pydantic]: We couldn't refactor the `validator`, please replace it by `field_validator` manually.
# Check https://docs.pydantic.dev/dev-v2/migration/#changes-to-validators for more information.
@validator("locale")
def valid_locale(cls, v, values, **kwargs):
if not validate_locale(v):

View File

@ -2,7 +2,7 @@ from __future__ import annotations
from datetime import datetime
from pydantic import UUID4, validator
from pydantic import UUID4, ConfigDict, field_validator
from sqlalchemy.orm import joinedload, selectinload
from sqlalchemy.orm.interfaces import LoaderOption
@ -35,7 +35,8 @@ class ShoppingListItemRecipeRefCreate(MealieModel):
recipe_scale: NoneFloat = 1
"""the number of times this recipe has been added"""
@validator("recipe_quantity", pre=True)
@field_validator("recipe_quantity", mode="before")
@classmethod
def default_none_to_zero(cls, v):
return 0 if v is None else v
@ -46,8 +47,7 @@ class ShoppingListItemRecipeRefUpdate(ShoppingListItemRecipeRefCreate):
class ShoppingListItemRecipeRefOut(ShoppingListItemRecipeRefUpdate):
class Config:
orm_mode = True
model_config = ConfigDict(from_attributes=True)
class ShoppingListItemBase(RecipeIngredientBase):
@ -98,10 +98,9 @@ class ShoppingListItemOut(ShoppingListItemBase):
if (not self.label) and (self.food and self.food.label):
self.label = self.food.label
self.label_id = self.label.id
class Config:
orm_mode = True
getter_dict = ExtrasGetterDict
# TODO[pydantic]: The following keys were removed: `getter_dict`.
# Check https://docs.pydantic.dev/dev-v2/migration/#changes-to-config for more information.
model_config = ConfigDict(from_attributes=True, getter_dict=ExtrasGetterDict)
@classmethod
def loader_options(cls) -> list[LoaderOption]:
@ -135,9 +134,7 @@ class ShoppingListMultiPurposeLabelUpdate(ShoppingListMultiPurposeLabelCreate):
class ShoppingListMultiPurposeLabelOut(ShoppingListMultiPurposeLabelUpdate):
label: MultiPurposeLabelSummary
class Config:
orm_mode = True
model_config = ConfigDict(from_attributes=True)
@classmethod
def loader_options(cls) -> list[LoaderOption]:
@ -164,9 +161,7 @@ class ShoppingListRecipeRefOut(MealieModel):
"""the number of times this recipe has been added"""
recipe: RecipeSummary
class Config:
orm_mode = True
model_config = ConfigDict(from_attributes=True)
@classmethod
def loader_options(cls) -> list[LoaderOption]:
@ -185,10 +180,9 @@ class ShoppingListSummary(ShoppingListSave):
id: UUID4
recipe_references: list[ShoppingListRecipeRefOut]
label_settings: list[ShoppingListMultiPurposeLabelOut]
class Config:
orm_mode = True
getter_dict = ExtrasGetterDict
# TODO[pydantic]: The following keys were removed: `getter_dict`.
# Check https://docs.pydantic.dev/dev-v2/migration/#changes-to-config for more information.
model_config = ConfigDict(from_attributes=True, getter_dict=ExtrasGetterDict)
@classmethod
def loader_options(cls) -> list[LoaderOption]:
@ -219,10 +213,9 @@ class ShoppingListUpdate(ShoppingListSave):
class ShoppingListOut(ShoppingListUpdate):
recipe_references: list[ShoppingListRecipeRefOut]
label_settings: list[ShoppingListMultiPurposeLabelOut]
class Config:
orm_mode = True
getter_dict = ExtrasGetterDict
# TODO[pydantic]: The following keys were removed: `getter_dict`.
# Check https://docs.pydantic.dev/dev-v2/migration/#changes-to-config for more information.
model_config = ConfigDict(from_attributes=True, getter_dict=ExtrasGetterDict)
@classmethod
def loader_options(cls) -> list[LoaderOption]:

View File

@ -1,6 +1,6 @@
from uuid import UUID
from pydantic import NoneStr
from pydantic import ConfigDict, NoneStr
from mealie.schema._mealie import MealieModel
@ -19,9 +19,7 @@ class ReadInviteToken(MealieModel):
token: str
uses_left: int
group_id: UUID
class Config:
orm_mode = True
model_config = ConfigDict(from_attributes=True)
class EmailInvitation(MealieModel):

View File

@ -3,7 +3,7 @@ import enum
from uuid import UUID
from isodate import parse_time
from pydantic import UUID4, validator
from pydantic import UUID4, ConfigDict, field_validator
from pydantic.datetime_parse import parse_datetime
from mealie.schema._mealie import MealieModel
@ -22,7 +22,8 @@ class CreateWebhook(MealieModel):
webhook_type: WebhookType = WebhookType.mealplan
scheduled_time: datetime.time
@validator("scheduled_time", pre=True)
@field_validator("scheduled_time", mode="before")
@classmethod
@classmethod
def validate_scheduled_time(cls, v):
"""
@ -55,9 +56,7 @@ class SaveWebhook(CreateWebhook):
class ReadWebhook(SaveWebhook):
id: UUID4
class Config:
orm_mode = True
model_config = ConfigDict(from_attributes=True)
class WebhookPagination(PaginationBase):

View File

@ -1,6 +1,6 @@
from __future__ import annotations
from pydantic import UUID4
from pydantic import UUID4, ConfigDict
from mealie.schema._mealie import MealieModel
from mealie.schema.response.pagination import PaginationBase
@ -21,9 +21,7 @@ class MultiPurposeLabelUpdate(MultiPurposeLabelSave):
class MultiPurposeLabelSummary(MultiPurposeLabelUpdate):
pass
class Config:
orm_mode = True
model_config = ConfigDict(from_attributes=True)
class MultiPurposeLabelPagination(PaginationBase):
@ -31,11 +29,7 @@ class MultiPurposeLabelPagination(PaginationBase):
class MultiPurposeLabelOut(MultiPurposeLabelUpdate):
# shopping_list_items: list[ShoppingListItemOut] = []
# foods: list[IngredientFood] = []
class Config:
orm_mode = True
model_config = ConfigDict(from_attributes=True)
# from mealie.schema.recipe.recipe_ingredient import IngredientFood

View File

@ -1,6 +1,6 @@
from datetime import date
from pydantic import validator
from pydantic import ConfigDict, validator
from mealie.schema._mealie import MealieModel
@ -9,24 +9,18 @@ class MealIn(MealieModel):
slug: str | None
name: str | None
description: str | None
class Config:
orm_mode = True
model_config = ConfigDict(from_attributes=True)
class MealDayIn(MealieModel):
date: date | None
meals: list[MealIn]
class Config:
orm_mode = True
model_config = ConfigDict(from_attributes=True)
class MealDayOut(MealDayIn):
id: int
class Config:
orm_mode = True
model_config = ConfigDict(from_attributes=True)
class MealPlanIn(MealieModel):
@ -35,19 +29,17 @@ class MealPlanIn(MealieModel):
end_date: date
plan_days: list[MealDayIn]
# TODO[pydantic]: We couldn't refactor the `validator`, please replace it by `field_validator` manually.
# Check https://docs.pydantic.dev/dev-v2/migration/#changes-to-validators for more information.
@validator("end_date")
def end_date_after_start_date(v, values, config, field):
if "start_date" in values and v < values["start_date"]:
raise ValueError("EndDate should be greater than StartDate")
return v
class Config:
orm_mode = True
model_config = ConfigDict(from_attributes=True)
class MealPlanOut(MealPlanIn):
id: int
shopping_list: int | None
class Config:
orm_mode = True
model_config = ConfigDict(from_attributes=True)

View File

@ -2,7 +2,7 @@ from datetime import date
from enum import Enum
from uuid import UUID
from pydantic import validator
from pydantic import ConfigDict, validator
from sqlalchemy.orm import selectinload
from sqlalchemy.orm.interfaces import LoaderOption
@ -32,6 +32,8 @@ class CreatePlanEntry(MealieModel):
text: str = ""
recipe_id: UUID | None
# TODO[pydantic]: We couldn't refactor the `validator`, please replace it by `field_validator` manually.
# Check https://docs.pydantic.dev/dev-v2/migration/#changes-to-validators for more information.
@validator("recipe_id", always=True)
@classmethod
def id_or_title(cls, value, values):
@ -50,16 +52,12 @@ class UpdatePlanEntry(CreatePlanEntry):
class SavePlanEntry(CreatePlanEntry):
group_id: UUID
user_id: UUID | None
class Config:
orm_mode = True
model_config = ConfigDict(from_attributes=True)
class ReadPlanEntry(UpdatePlanEntry):
recipe: RecipeSummary | None
class Config:
orm_mode = True
model_config = ConfigDict(from_attributes=True)
@classmethod
def loader_options(cls) -> list[LoaderOption]:

View File

@ -1,7 +1,7 @@
import datetime
from enum import Enum
from pydantic import UUID4
from pydantic import UUID4, ConfigDict
from sqlalchemy.orm import joinedload
from sqlalchemy.orm.interfaces import LoaderOption
@ -14,14 +14,11 @@ class Category(MealieModel):
id: UUID4
name: str
slug: str
class Config:
orm_mode = True
model_config = ConfigDict(from_attributes=True)
class Tag(Category):
class Config:
orm_mode = True
model_config = ConfigDict(from_attributes=True)
class PlanRulesDay(str, Enum):
@ -64,9 +61,7 @@ class PlanRulesSave(PlanRulesCreate):
class PlanRulesOut(PlanRulesSave):
id: UUID4
class Config:
orm_mode = True
model_config = ConfigDict(from_attributes=True)
@classmethod
def loader_options(cls) -> list[LoaderOption]:

View File

@ -1,3 +1,5 @@
from pydantic import ConfigDict
from mealie.schema._mealie import MealieModel
from mealie.schema.getter_dict import GroupGetterDict
@ -7,9 +9,7 @@ class ListItem(MealieModel):
text: str = ""
quantity: int = 1
checked: bool = False
class Config:
orm_mode = True
model_config = ConfigDict(from_attributes=True)
class ShoppingListIn(MealieModel):
@ -20,7 +20,6 @@ class ShoppingListIn(MealieModel):
class ShoppingListOut(ShoppingListIn):
id: int
class Config:
orm_mode = True
getter_dict = GroupGetterDict
# TODO[pydantic]: The following keys were removed: `getter_dict`.
# Check https://docs.pydantic.dev/dev-v2/migration/#changes-to-config for more information.
model_config = ConfigDict(from_attributes=True, getter_dict=GroupGetterDict)

View File

@ -5,7 +5,7 @@ from pathlib import Path
from typing import Any
from uuid import uuid4
from pydantic import UUID4, BaseModel, Field, validator
from pydantic import UUID4, BaseModel, ConfigDict, Field, validator
from slugify import slugify
from sqlalchemy.orm import joinedload, selectinload
from sqlalchemy.orm.interfaces import LoaderOption
@ -36,9 +36,7 @@ class RecipeTag(MealieModel):
id: UUID4 | None = None
name: str
slug: str
class Config:
orm_mode = True
model_config = ConfigDict(from_attributes=True)
class RecipeTagPagination(PaginationBase):
@ -105,9 +103,7 @@ class RecipeSummary(MealieModel):
created_at: datetime.datetime | None
update_at: datetime.datetime | None
last_made: datetime.datetime | None
class Config:
orm_mode = True
model_config = ConfigDict(from_attributes=True)
class RecipePagination(PaginationBase):
@ -171,10 +167,9 @@ class Recipe(RecipeSummary):
raise ValueError("Recipe has no ID")
return self.image_dir_from_id(self.id)
class Config:
orm_mode = True
getter_dict = ExtrasGetterDict
# TODO[pydantic]: The following keys were removed: `getter_dict`.
# Check https://docs.pydantic.dev/dev-v2/migration/#changes-to-config for more information.
model_config = ConfigDict(from_attributes=True, getter_dict=ExtrasGetterDict)
@classmethod
def from_orm(cls, obj):
@ -195,6 +190,8 @@ class Recipe(RecipeSummary):
ingredient.is_food = not ingredient.disable_amount
ingredient.display = ingredient._format_display()
# TODO[pydantic]: We couldn't refactor the `validator`, please replace it by `field_validator` manually.
# Check https://docs.pydantic.dev/dev-v2/migration/#changes-to-validators for more information.
@validator("slug", always=True, pre=True, allow_reuse=True)
def validate_slug(slug: str, values): # type: ignore
if not values.get("name"):
@ -202,6 +199,8 @@ class Recipe(RecipeSummary):
return slugify(values["name"])
# TODO[pydantic]: We couldn't refactor the `validator`, please replace it by `field_validator` manually.
# Check https://docs.pydantic.dev/dev-v2/migration/#changes-to-validators for more information.
@validator("recipe_ingredient", always=True, pre=True, allow_reuse=True)
def validate_ingredients(recipe_ingredient, values):
if not recipe_ingredient or not isinstance(recipe_ingredient, list):
@ -212,24 +211,32 @@ class Recipe(RecipeSummary):
return recipe_ingredient
# TODO[pydantic]: We couldn't refactor the `validator`, please replace it by `field_validator` manually.
# Check https://docs.pydantic.dev/dev-v2/migration/#changes-to-validators for more information.
@validator("tags", always=True, pre=True, allow_reuse=True)
def validate_tags(cats: list[Any]): # type: ignore
if isinstance(cats, list) and cats and isinstance(cats[0], str):
return [RecipeTag(id=uuid4(), name=c, slug=slugify(c)) for c in cats]
return cats
# TODO[pydantic]: We couldn't refactor the `validator`, please replace it by `field_validator` manually.
# Check https://docs.pydantic.dev/dev-v2/migration/#changes-to-validators for more information.
@validator("recipe_category", always=True, pre=True, allow_reuse=True)
def validate_categories(cats: list[Any]): # type: ignore
if isinstance(cats, list) and cats and isinstance(cats[0], str):
return [RecipeCategory(id=uuid4(), name=c, slug=slugify(c)) for c in cats]
return cats
# TODO[pydantic]: We couldn't refactor the `validator`, please replace it by `field_validator` manually.
# Check https://docs.pydantic.dev/dev-v2/migration/#changes-to-validators for more information.
@validator("group_id", always=True, pre=True, allow_reuse=True)
def validate_group_id(group_id: Any):
if isinstance(group_id, int):
return uuid4()
return group_id
# TODO[pydantic]: We couldn't refactor the `validator`, please replace it by `field_validator` manually.
# Check https://docs.pydantic.dev/dev-v2/migration/#changes-to-validators for more information.
@validator("user_id", always=True, pre=True, allow_reuse=True)
def validate_user_id(user_id: Any):
if isinstance(user_id, int):

View File

@ -1,3 +1,5 @@
from pydantic import ConfigDict
from mealie.schema._mealie import MealieModel
@ -5,6 +7,4 @@ class RecipeAsset(MealieModel):
name: str
icon: str
file_name: str | None
class Config:
orm_mode = True
model_config = ConfigDict(from_attributes=True)

View File

@ -1,4 +1,4 @@
from pydantic import UUID4
from pydantic import UUID4, ConfigDict
from sqlalchemy.orm import selectinload
from sqlalchemy.orm.interfaces import LoaderOption
@ -17,24 +17,18 @@ class CategorySave(CategoryIn):
class CategoryBase(CategoryIn):
id: UUID4
slug: str
class Config:
orm_mode = True
model_config = ConfigDict(from_attributes=True)
class CategoryOut(CategoryBase):
slug: str
group_id: UUID4
class Config:
orm_mode = True
model_config = ConfigDict(from_attributes=True)
class RecipeCategoryResponse(CategoryBase):
recipes: "list[RecipeSummary]" = []
class Config:
orm_mode = True
model_config = ConfigDict(from_attributes=True)
class TagIn(CategoryIn):
@ -52,9 +46,7 @@ class TagBase(CategoryBase):
class TagOut(TagSave):
id: UUID4
slug: str
class Config:
orm_mode = True
model_config = ConfigDict(from_attributes=True)
class RecipeTagResponse(RecipeCategoryResponse):

View File

@ -1,6 +1,6 @@
from datetime import datetime
from pydantic import UUID4
from pydantic import UUID4, ConfigDict
from sqlalchemy.orm import joinedload
from sqlalchemy.orm.interfaces import LoaderOption
@ -13,9 +13,7 @@ class UserBase(MealieModel):
id: UUID4
username: str | None
admin: bool
class Config:
orm_mode = True
model_config = ConfigDict(from_attributes=True)
class RecipeCommentCreate(MealieModel):
@ -39,9 +37,7 @@ class RecipeCommentOut(RecipeCommentCreate):
update_at: datetime
user_id: UUID4
user: UserBase
class Config:
orm_mode = True
model_config = ConfigDict(from_attributes=True)
@classmethod
def loader_options(cls) -> list[LoaderOption]:

View File

@ -5,7 +5,7 @@ import enum
from fractions import Fraction
from uuid import UUID, uuid4
from pydantic import UUID4, Field, validator
from pydantic import UUID4, ConfigDict, Field, field_validator, validator
from sqlalchemy.orm import joinedload
from sqlalchemy.orm.interfaces import LoaderOption
@ -49,10 +49,9 @@ class IngredientFood(CreateIngredientFood):
label: MultiPurposeLabelSummary | None = None
created_at: datetime.datetime | None
update_at: datetime.datetime | None
class Config:
orm_mode = True
getter_dict = ExtrasGetterDict
# TODO[pydantic]: The following keys were removed: `getter_dict`.
# Check https://docs.pydantic.dev/dev-v2/migration/#changes-to-config for more information.
model_config = ConfigDict(from_attributes=True, getter_dict=ExtrasGetterDict)
@classmethod
def loader_options(cls) -> list[LoaderOption]:
@ -77,9 +76,7 @@ class IngredientUnit(CreateIngredientUnit):
id: UUID4
created_at: datetime.datetime | None
update_at: datetime.datetime | None
class Config:
orm_mode = True
model_config = ConfigDict(from_attributes=True)
class RecipeIngredientBase(MealieModel):
@ -114,14 +111,16 @@ class RecipeIngredientBase(MealieModel):
if not self.display:
self.display = self._format_display()
@validator("unit", pre=True)
@field_validator("unit", mode="before")
@classmethod
def validate_unit(cls, v):
if isinstance(v, str):
return CreateIngredientUnit(name=v)
else:
return v
@validator("food", pre=True)
@field_validator("food", mode="before")
@classmethod
def validate_food(cls, v):
if isinstance(v, str):
return CreateIngredientFood(name=v)
@ -200,11 +199,10 @@ class RecipeIngredient(RecipeIngredientBase):
# It is required for the reorder and section titles to function properly because of how
# Vue handles reactivity. ref may serve another purpose in the future.
reference_id: UUID = Field(default_factory=uuid4)
model_config = ConfigDict(from_attributes=True)
class Config:
orm_mode = True
@validator("quantity", pre=True)
@field_validator("quantity", mode="before")
@classmethod
def validate_quantity(cls, value) -> NoneFloat:
"""
Sometimes the frontend UI will provide an empty string as a "null" value because of the default
@ -226,6 +224,8 @@ class IngredientConfidence(MealieModel):
quantity: NoneFloat = None
food: NoneFloat = None
# TODO[pydantic]: We couldn't refactor the `validator`, please replace it by `field_validator` manually.
# Check https://docs.pydantic.dev/dev-v2/migration/#changes-to-validators for more information.
@validator("quantity", pre=True)
@classmethod
def validate_quantity(cls, value, values) -> NoneFloat:

View File

@ -1,9 +1,7 @@
from pydantic import BaseModel
from pydantic import BaseModel, ConfigDict
class RecipeNote(BaseModel):
title: str
text: str
class Config:
orm_mode = True
model_config = ConfigDict(from_attributes=True)

View File

@ -1,3 +1,5 @@
from pydantic import ConfigDict
from mealie.schema._mealie import MealieModel
@ -9,6 +11,4 @@ class Nutrition(MealieModel):
fiber_content: str | None
sodium_content: str | None
sugar_content: str | None
class Config:
orm_mode = True
model_config = ConfigDict(from_attributes=True)

View File

@ -1,3 +1,5 @@
from pydantic import ConfigDict
from mealie.schema._mealie.mealie_model import MealieModel
@ -8,11 +10,9 @@ class ScrapeRecipeTest(MealieModel):
class ScrapeRecipe(MealieModel):
url: str
include_tags: bool = False
class Config:
schema_extra = {
"example": {
"url": "https://myfavoriterecipes.com/recipes",
"includeTags": True,
},
}
model_config = ConfigDict(json_schema_extra={
"example": {
"url": "https://myfavoriterecipes.com/recipes",
"includeTags": True,
},
})

View File

@ -1,3 +1,5 @@
from pydantic import ConfigDict
from mealie.schema._mealie import MealieModel
@ -9,6 +11,4 @@ class RecipeSettings(MealieModel):
disable_comments: bool = True
disable_amount: bool = True
locked: bool = False
class Config:
orm_mode = True
model_config = ConfigDict(from_attributes=True)

View File

@ -1,6 +1,6 @@
from datetime import datetime, timedelta
from pydantic import UUID4, Field
from pydantic import UUID4, ConfigDict, Field
from sqlalchemy.orm import selectinload
from sqlalchemy.orm.interfaces import LoaderOption
@ -26,16 +26,12 @@ class RecipeShareTokenSave(RecipeShareTokenCreate):
class RecipeShareTokenSummary(RecipeShareTokenSave):
id: UUID4
created_at: datetime
class Config:
orm_mode = True
model_config = ConfigDict(from_attributes=True)
class RecipeShareToken(RecipeShareTokenSummary):
recipe: Recipe
class Config:
orm_mode = True
model_config = ConfigDict(from_attributes=True)
@classmethod
def loader_options(cls) -> list[LoaderOption]:

View File

@ -1,6 +1,6 @@
from uuid import UUID, uuid4
from pydantic import UUID4, Field
from pydantic import UUID4, ConfigDict, Field
from mealie.schema._mealie import MealieModel
@ -11,9 +11,7 @@ class IngredientReferences(MealieModel):
"""
reference_id: UUID4 | None
class Config:
orm_mode = True
model_config = ConfigDict(from_attributes=True)
class RecipeStep(MealieModel):
@ -21,6 +19,4 @@ class RecipeStep(MealieModel):
title: str | None = ""
text: str
ingredient_references: list[IngredientReferences] = []
class Config:
orm_mode = True
model_config = ConfigDict(from_attributes=True)

View File

@ -2,7 +2,7 @@ from datetime import datetime
from enum import Enum
from pathlib import Path
from pydantic import UUID4, Field
from pydantic import UUID4, ConfigDict, Field
from mealie.core.config import get_app_dirs
from mealie.schema._mealie.mealie_model import MealieModel
@ -35,9 +35,7 @@ class RecipeTimelineEventIn(MealieModel):
image: TimelineEventImage | None = TimelineEventImage.does_not_have_image
timestamp: datetime = datetime.now()
class Config:
use_enum_values = True
model_config = ConfigDict(use_enum_values=True)
class RecipeTimelineEventCreate(RecipeTimelineEventIn):
@ -48,18 +46,14 @@ class RecipeTimelineEventUpdate(MealieModel):
subject: str
message: str | None = Field(alias="eventMessage")
image: TimelineEventImage | None = None
class Config:
use_enum_values = True
model_config = ConfigDict(use_enum_values=True)
class RecipeTimelineEventOut(RecipeTimelineEventCreate):
id: UUID4
created_at: datetime
update_at: datetime
class Config:
orm_mode = True
model_config = ConfigDict(from_attributes=True)
@classmethod
def image_dir_from_id(cls, recipe_id: UUID4 | str, timeline_event_id: UUID4 | str) -> Path:

View File

@ -1,4 +1,4 @@
from pydantic import UUID4
from pydantic import UUID4, ConfigDict
from sqlalchemy.orm import selectinload
from sqlalchemy.orm.interfaces import LoaderOption
@ -19,16 +19,12 @@ class RecipeToolSave(RecipeToolCreate):
class RecipeToolOut(RecipeToolCreate):
id: UUID4
slug: str
class Config:
orm_mode = True
model_config = ConfigDict(from_attributes=True)
class RecipeToolResponse(RecipeToolOut):
recipes: list["RecipeSummary"] = []
class Config:
orm_mode = True
model_config = ConfigDict(from_attributes=True)
@classmethod
def loader_options(cls) -> list[LoaderOption]:

View File

@ -1,4 +1,4 @@
from pydantic import BaseModel
from pydantic import BaseModel, ConfigDict
from mealie.schema._mealie import MealieModel
@ -10,8 +10,7 @@ class RecipeSlug(MealieModel):
class SlugResponse(BaseModel):
class Config:
schema_extra = {"example": "adult-mac-and-cheese"}
model_config = ConfigDict(json_schema_extra={"example": "adult-mac-and-cheese"})
class UpdateImageResponse(BaseModel):
@ -23,4 +22,4 @@ class RecipeZipTokenResponse(BaseModel):
class RecipeDuplicate(BaseModel):
name: str | None
name: str | None = None

View File

@ -1,7 +1,7 @@
import datetime
import enum
from pydantic import Field
from pydantic import ConfigDict, Field
from pydantic.types import UUID4
from sqlalchemy.orm import joinedload
from sqlalchemy.orm.interfaces import LoaderOption
@ -34,9 +34,7 @@ class ReportEntryCreate(MealieModel):
class ReportEntryOut(ReportEntryCreate):
id: UUID4
class Config:
orm_mode = True
model_config = ConfigDict(from_attributes=True)
class ReportCreate(MealieModel):
@ -53,9 +51,7 @@ class ReportSummary(ReportCreate):
class ReportOut(ReportSummary):
entries: list[ReportEntryOut] = []
class Config:
orm_mode = True
model_config = ConfigDict(from_attributes=True)
@classmethod
def loader_options(cls) -> list[LoaderOption]:

View File

@ -4,7 +4,6 @@ from urllib.parse import parse_qs, urlencode, urlsplit, urlunsplit
from humps import camelize
from pydantic import UUID4, BaseModel, validator
from pydantic.generics import GenericModel
from mealie.schema._mealie import MealieModel
@ -34,6 +33,8 @@ class PaginationQuery(MealieModel):
query_filter: str | None = None
pagination_seed: str | None = None
# TODO[pydantic]: We couldn't refactor the `validator`, please replace it by `field_validator` manually.
# Check https://docs.pydantic.dev/dev-v2/migration/#changes-to-validators for more information.
@validator("pagination_seed", always=True, pre=True)
def validate_randseed(cls, pagination_seed, values):
if values.get("order_by") == "random" and not pagination_seed:
@ -41,7 +42,7 @@ class PaginationQuery(MealieModel):
return pagination_seed
class PaginationBase(GenericModel, Generic[DataT]):
class PaginationBase(BaseModel, Generic[DataT]):
page: int = 1
per_page: int = 10
total: int = 0

View File

@ -2,7 +2,7 @@ import datetime
import enum
from uuid import UUID
from pydantic import Field
from pydantic import ConfigDict, Field
from mealie.schema._mealie import MealieModel
from mealie.schema.response.pagination import PaginationBase
@ -43,9 +43,7 @@ class ServerTaskCreate(MealieModel):
class ServerTask(ServerTaskCreate):
id: int
class Config:
orm_mode = True
model_config = ConfigDict(from_attributes=True)
class ServerTaskPagination(PaginationBase):

View File

@ -1,5 +1,6 @@
from pydantic import UUID4, BaseModel
from pydantic.types import constr
from typing import Annotated
from pydantic import UUID4, BaseModel, StringConstraints
from mealie.schema._mealie.mealie_model import MealieModel
@ -10,8 +11,8 @@ class Token(BaseModel):
class TokenData(BaseModel):
user_id: UUID4 | None
username: constr(to_lower=True, strip_whitespace=True) | None = None # type: ignore
user_id: UUID4 | None = None
username: Annotated[str, StringConstraints(to_lower=True, strip_whitespace=True)] | None = None # type: ignore
class UnlockResults(MealieModel):

View File

@ -1,5 +1,7 @@
from pydantic import validator
from pydantic.types import NoneStr, constr
from typing import Annotated
from pydantic import StringConstraints, validator
from pydantic.types import NoneStr
from mealie.schema._mealie import MealieModel
from mealie.schema._mealie.validators import validate_locale
@ -8,8 +10,8 @@ from mealie.schema._mealie.validators import validate_locale
class CreateUserRegistration(MealieModel):
group: NoneStr = None
group_token: NoneStr = None
email: constr(to_lower=True, strip_whitespace=True) # type: ignore
username: constr(to_lower=True, strip_whitespace=True) # type: ignore
email: Annotated[str, StringConstraints(to_lower=True, strip_whitespace=True)] # type: ignore
username: Annotated[str, StringConstraints(to_lower=True, strip_whitespace=True)] # type: ignore
password: str
password_confirm: str
advanced: bool = False
@ -18,12 +20,16 @@ class CreateUserRegistration(MealieModel):
seed_data: bool = False
locale: str = "en-US"
# TODO[pydantic]: We couldn't refactor the `validator`, please replace it by `field_validator` manually.
# Check https://docs.pydantic.dev/dev-v2/migration/#changes-to-validators for more information.
@validator("locale")
def valid_locale(cls, v, values, **kwargs):
if not validate_locale(v):
raise ValueError("invalid locale")
return v
# TODO[pydantic]: We couldn't refactor the `validator`, please replace it by `field_validator` manually.
# Check https://docs.pydantic.dev/dev-v2/migration/#changes-to-validators for more information.
@validator("password_confirm")
@classmethod
def passwords_match(cls, value, values):
@ -31,6 +37,8 @@ class CreateUserRegistration(MealieModel):
raise ValueError("passwords do not match")
return value
# TODO[pydantic]: We couldn't refactor the `validator`, please replace it by `field_validator` manually.
# Check https://docs.pydantic.dev/dev-v2/migration/#changes-to-validators for more information.
@validator("group_token", always=True)
@classmethod
def group_or_token(cls, value, values):

View File

@ -1,10 +1,9 @@
from datetime import datetime, timedelta
from pathlib import Path
from typing import Any
from typing import Annotated, Any
from uuid import UUID
from pydantic import UUID4, Field, validator
from pydantic.types import constr
from pydantic import UUID4, ConfigDict, Field, StringConstraints, field_validator
from sqlalchemy.orm import joinedload, selectinload
from sqlalchemy.orm.interfaces import LoaderOption
@ -35,24 +34,18 @@ class LongLiveTokenOut(MealieModel):
name: str
id: int
created_at: datetime | None
class Config:
orm_mode = True
model_config = ConfigDict(from_attributes=True)
class CreateToken(LongLiveTokenIn):
user_id: UUID4
token: str
class Config:
orm_mode = True
model_config = ConfigDict(from_attributes=True)
class DeleteTokenResponse(MealieModel):
token_delete: str
class Config:
orm_mode = True
model_config = ConfigDict(from_attributes=True)
class ChangePassword(MealieModel):
@ -62,15 +55,13 @@ class ChangePassword(MealieModel):
class GroupBase(MealieModel):
name: str
class Config:
orm_mode = True
model_config = ConfigDict(from_attributes=True)
class UserBase(MealieModel):
username: str | None
full_name: str | None = None
email: constr(to_lower=True, strip_whitespace=True) # type: ignore
email: Annotated[str, StringConstraints(to_lower=True, strip_whitespace=True)] # type: ignore
auth_method: AuthMethod = AuthMethod.MEALIE
admin: bool = False
group: str | None
@ -80,20 +71,17 @@ class UserBase(MealieModel):
can_invite: bool = False
can_manage: bool = False
can_organize: bool = False
class Config:
orm_mode = True
getter_dict = GroupGetterDict
schema_extra = {
"example": {
"username": "ChangeMe",
"fullName": "Change Me",
"email": "changeme@email.com",
"group": settings.DEFAULT_GROUP,
"admin": "false",
}
# TODO[pydantic]: The following keys were removed: `getter_dict`.
# Check https://docs.pydantic.dev/dev-v2/migration/#changes-to-config for more information.
model_config = ConfigDict(from_attributes=True, getter_dict=GroupGetterDict, json_schema_extra={
"example": {
"username": "ChangeMe",
"fullName": "Change Me",
"email": "changeme@email.com",
"group": settings.DEFAULT_GROUP,
"admin": "false",
}
})
class UserIn(UserBase):
@ -107,11 +95,9 @@ class UserOut(UserBase):
tokens: list[LongLiveTokenOut] | None
cache_key: str
favorite_recipes: list[str] | None = []
class Config:
orm_mode = True
getter_dict = UserGetterDict
# TODO[pydantic]: The following keys were removed: `getter_dict`.
# Check https://docs.pydantic.dev/dev-v2/migration/#changes-to-config for more information.
model_config = ConfigDict(from_attributes=True, getter_dict=UserGetterDict)
@property
def is_default_user(self) -> bool:
@ -128,10 +114,9 @@ class UserPagination(PaginationBase):
class UserFavorites(UserBase):
favorite_recipes: list[RecipeSummary] = [] # type: ignore
class Config:
orm_mode = True
getter_dict = GroupGetterDict
# TODO[pydantic]: The following keys were removed: `getter_dict`.
# Check https://docs.pydantic.dev/dev-v2/migration/#changes-to-config for more information.
model_config = ConfigDict(from_attributes=True, getter_dict=GroupGetterDict)
@classmethod
def loader_options(cls) -> list[LoaderOption]:
@ -148,11 +133,10 @@ class PrivateUser(UserOut):
group_id: UUID4
login_attemps: int = 0
locked_at: datetime | None = None
model_config = ConfigDict(from_attributes=True)
class Config:
orm_mode = True
@validator("login_attemps", pre=True)
@field_validator("login_attemps", mode="before")
@classmethod
def none_to_zero(cls, v):
return 0 if v is None else v
@ -189,9 +173,7 @@ class UpdateGroup(GroupBase):
class GroupInDB(UpdateGroup):
users: list[UserOut] | None
preferences: ReadGroupPreferences | None = None
class Config:
orm_mode = True
model_config = ConfigDict(from_attributes=True)
@staticmethod
def get_directory(id: UUID4) -> Path:
@ -232,6 +214,4 @@ class GroupPagination(PaginationBase):
class LongLiveTokenInDB(CreateToken):
id: int
user: PrivateUser
class Config:
orm_mode = True
model_config = ConfigDict(from_attributes=True)

View File

@ -1,4 +1,4 @@
from pydantic import UUID4
from pydantic import UUID4, ConfigDict
from sqlalchemy.orm import selectinload
from sqlalchemy.orm.interfaces import LoaderOption
@ -33,9 +33,7 @@ class SavePasswordResetToken(MealieModel):
class PrivatePasswordResetToken(SavePasswordResetToken):
user: PrivateUser
class Config:
orm_mode = True
model_config = ConfigDict(from_attributes=True)
@classmethod
def loader_options(cls) -> list[LoaderOption]:

View File

@ -177,8 +177,8 @@ class Event(MealieModel):
document_data: EventDocumentDataBase
# set at instantiation
event_id: UUID4 | None
timestamp: datetime | None
event_id: UUID4 | None = None
timestamp: datetime | None = None
def __init__(self, *args, **kwargs) -> None:
super().__init__(*args, **kwargs)

View File

@ -1,7 +1,7 @@
import string
import unicodedata
from pydantic import BaseModel
from pydantic import BaseModel, ConfigDict
from .._helpers import check_char, move_parens_to_end
@ -11,9 +11,7 @@ class BruteParsedIngredient(BaseModel):
note: str = ""
amount: float = 1.0
unit: str = ""
class Config:
anystr_strip_whitespace = True
model_config = ConfigDict(str_strip_whitespace=True)
def parse_fraction(x):

View File

@ -31,6 +31,8 @@ class CRFIngredient(BaseModel):
unit: str = ""
confidence: CRFConfidence
# TODO[pydantic]: We couldn't refactor the `validator`, please replace it by `field_validator` manually.
# Check https://docs.pydantic.dev/dev-v2/migration/#changes-to-validators for more information.
@validator("qty", always=True, pre=True)
def validate_qty(qty, values): # sourcery skip: merge-nested-ifs
if qty is None or qty == "":

218
poetry.lock generated
View File

@ -44,6 +44,17 @@ files = [
[package.extras]
dev = ["black", "coverage", "isort", "pre-commit", "pyenchant", "pylint"]
[[package]]
name = "annotated-types"
version = "0.5.0"
description = "Reusable constraint types to use with typing.Annotated"
optional = false
python-versions = ">=3.7"
files = [
{file = "annotated_types-0.5.0-py3-none-any.whl", hash = "sha256:58da39888f92c276ad970249761ebea80ba544b77acddaa1a4d6cf78287d45fd"},
{file = "annotated_types-0.5.0.tar.gz", hash = "sha256:47cdc3490d9ac1506ce92c7aaa76c579dc3509ff11e098fc867e5130ab7be802"},
]
[[package]]
name = "anyio"
version = "3.6.2"
@ -545,24 +556,22 @@ cli = ["requests"]
[[package]]
name = "fastapi"
version = "0.95.0"
version = "0.101.0"
description = "FastAPI framework, high performance, easy to learn, fast to code, ready for production"
optional = false
python-versions = ">=3.7"
files = [
{file = "fastapi-0.95.0-py3-none-any.whl", hash = "sha256:daf73bbe844180200be7966f68e8ec9fd8be57079dff1bacb366db32729e6eb5"},
{file = "fastapi-0.95.0.tar.gz", hash = "sha256:99d4fdb10e9dd9a24027ac1d0bd4b56702652056ca17a6c8721eec4ad2f14e18"},
{file = "fastapi-0.101.0-py3-none-any.whl", hash = "sha256:494eb3494d89e8079c20859d7ca695f66eaccc40f46fe8c75ab6186d15f05ffd"},
{file = "fastapi-0.101.0.tar.gz", hash = "sha256:ca2ae65fe42f6a34b5cf6c994337149154b1b400c39809d7b2dccdceb5ae77af"},
]
[package.dependencies]
pydantic = ">=1.6.2,<1.7 || >1.7,<1.7.1 || >1.7.1,<1.7.2 || >1.7.2,<1.7.3 || >1.7.3,<1.8 || >1.8,<1.8.1 || >1.8.1,<2.0.0"
starlette = ">=0.26.1,<0.27.0"
pydantic = ">=1.7.4,<1.8 || >1.8,<1.8.1 || >1.8.1,<2.0.0 || >2.0.0,<2.0.1 || >2.0.1,<2.1.0 || >2.1.0,<3.0.0"
starlette = ">=0.27.0,<0.28.0"
typing-extensions = ">=4.5.0"
[package.extras]
all = ["email-validator (>=1.1.1)", "httpx (>=0.23.0)", "itsdangerous (>=1.1.0)", "jinja2 (>=2.11.2)", "orjson (>=3.2.1)", "python-multipart (>=0.0.5)", "pyyaml (>=5.3.1)", "ujson (>=4.0.1,!=4.0.2,!=4.1.0,!=4.2.0,!=4.3.0,!=5.0.0,!=5.1.0)", "uvicorn[standard] (>=0.12.0)"]
dev = ["pre-commit (>=2.17.0,<3.0.0)", "ruff (==0.0.138)", "uvicorn[standard] (>=0.12.0,<0.21.0)"]
doc = ["mdx-include (>=1.4.1,<2.0.0)", "mkdocs (>=1.1.2,<2.0.0)", "mkdocs-markdownextradata-plugin (>=0.1.7,<0.3.0)", "mkdocs-material (>=8.1.4,<9.0.0)", "pyyaml (>=5.3.1,<7.0.0)", "typer-cli (>=0.0.13,<0.0.14)", "typer[all] (>=0.6.1,<0.8.0)"]
test = ["anyio[trio] (>=3.2.1,<4.0.0)", "black (==23.1.0)", "coverage[toml] (>=6.5.0,<8.0)", "databases[sqlite] (>=0.3.2,<0.7.0)", "email-validator (>=1.1.1,<2.0.0)", "flask (>=1.1.2,<3.0.0)", "httpx (>=0.23.0,<0.24.0)", "isort (>=5.0.6,<6.0.0)", "mypy (==0.982)", "orjson (>=3.2.1,<4.0.0)", "passlib[bcrypt] (>=1.7.2,<2.0.0)", "peewee (>=3.13.3,<4.0.0)", "pytest (>=7.1.3,<8.0.0)", "python-jose[cryptography] (>=3.3.0,<4.0.0)", "python-multipart (>=0.0.5,<0.0.7)", "pyyaml (>=5.3.1,<7.0.0)", "ruff (==0.0.138)", "sqlalchemy (>=1.3.18,<1.4.43)", "types-orjson (==3.6.2)", "types-ujson (==5.7.0.1)", "ujson (>=4.0.1,!=4.0.2,!=4.1.0,!=4.2.0,!=4.3.0,!=5.0.0,!=5.1.0,<6.0.0)"]
all = ["email-validator (>=2.0.0)", "httpx (>=0.23.0)", "itsdangerous (>=1.1.0)", "jinja2 (>=2.11.2)", "orjson (>=3.2.1)", "pydantic-extra-types (>=2.0.0)", "pydantic-settings (>=2.0.0)", "python-multipart (>=0.0.5)", "pyyaml (>=5.3.1)", "ujson (>=4.0.1,!=4.0.2,!=4.1.0,!=4.2.0,!=4.3.0,!=5.0.0,!=5.1.0)", "uvicorn[standard] (>=0.12.0)"]
[[package]]
name = "filelock"
@ -1696,55 +1705,150 @@ pyasn1 = ">=0.4.6,<0.5.0"
[[package]]
name = "pydantic"
version = "1.10.7"
description = "Data validation and settings management using python type hints"
version = "2.1.1"
description = "Data validation using Python type hints"
optional = false
python-versions = ">=3.7"
files = [
{file = "pydantic-1.10.7-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:e79e999e539872e903767c417c897e729e015872040e56b96e67968c3b918b2d"},
{file = "pydantic-1.10.7-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:01aea3a42c13f2602b7ecbbea484a98169fb568ebd9e247593ea05f01b884b2e"},
{file = "pydantic-1.10.7-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:516f1ed9bc2406a0467dd777afc636c7091d71f214d5e413d64fef45174cfc7a"},
{file = "pydantic-1.10.7-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ae150a63564929c675d7f2303008d88426a0add46efd76c3fc797cd71cb1b46f"},
{file = "pydantic-1.10.7-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:ecbbc51391248116c0a055899e6c3e7ffbb11fb5e2a4cd6f2d0b93272118a209"},
{file = "pydantic-1.10.7-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:f4a2b50e2b03d5776e7f21af73e2070e1b5c0d0df255a827e7c632962f8315af"},
{file = "pydantic-1.10.7-cp310-cp310-win_amd64.whl", hash = "sha256:a7cd2251439988b413cb0a985c4ed82b6c6aac382dbaff53ae03c4b23a70e80a"},
{file = "pydantic-1.10.7-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:68792151e174a4aa9e9fc1b4e653e65a354a2fa0fed169f7b3d09902ad2cb6f1"},
{file = "pydantic-1.10.7-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:dfe2507b8ef209da71b6fb5f4e597b50c5a34b78d7e857c4f8f3115effaef5fe"},
{file = "pydantic-1.10.7-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:10a86d8c8db68086f1e30a530f7d5f83eb0685e632e411dbbcf2d5c0150e8dcd"},
{file = "pydantic-1.10.7-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d75ae19d2a3dbb146b6f324031c24f8a3f52ff5d6a9f22f0683694b3afcb16fb"},
{file = "pydantic-1.10.7-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:464855a7ff7f2cc2cf537ecc421291b9132aa9c79aef44e917ad711b4a93163b"},
{file = "pydantic-1.10.7-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:193924c563fae6ddcb71d3f06fa153866423ac1b793a47936656e806b64e24ca"},
{file = "pydantic-1.10.7-cp311-cp311-win_amd64.whl", hash = "sha256:b4a849d10f211389502059c33332e91327bc154acc1845f375a99eca3afa802d"},
{file = "pydantic-1.10.7-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:cc1dde4e50a5fc1336ee0581c1612215bc64ed6d28d2c7c6f25d2fe3e7c3e918"},
{file = "pydantic-1.10.7-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e0cfe895a504c060e5d36b287ee696e2fdad02d89e0d895f83037245218a87fe"},
{file = "pydantic-1.10.7-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:670bb4683ad1e48b0ecb06f0cfe2178dcf74ff27921cdf1606e527d2617a81ee"},
{file = "pydantic-1.10.7-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:950ce33857841f9a337ce07ddf46bc84e1c4946d2a3bba18f8280297157a3fd1"},
{file = "pydantic-1.10.7-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:c15582f9055fbc1bfe50266a19771bbbef33dd28c45e78afbe1996fd70966c2a"},
{file = "pydantic-1.10.7-cp37-cp37m-win_amd64.whl", hash = "sha256:82dffb306dd20bd5268fd6379bc4bfe75242a9c2b79fec58e1041fbbdb1f7914"},
{file = "pydantic-1.10.7-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:8c7f51861d73e8b9ddcb9916ae7ac39fb52761d9ea0df41128e81e2ba42886cd"},
{file = "pydantic-1.10.7-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:6434b49c0b03a51021ade5c4daa7d70c98f7a79e95b551201fff682fc1661245"},
{file = "pydantic-1.10.7-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:64d34ab766fa056df49013bb6e79921a0265204c071984e75a09cbceacbbdd5d"},
{file = "pydantic-1.10.7-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:701daea9ffe9d26f97b52f1d157e0d4121644f0fcf80b443248434958fd03dc3"},
{file = "pydantic-1.10.7-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:cf135c46099ff3f919d2150a948ce94b9ce545598ef2c6c7bf55dca98a304b52"},
{file = "pydantic-1.10.7-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:b0f85904f73161817b80781cc150f8b906d521fa11e3cdabae19a581c3606209"},
{file = "pydantic-1.10.7-cp38-cp38-win_amd64.whl", hash = "sha256:9f6f0fd68d73257ad6685419478c5aece46432f4bdd8d32c7345f1986496171e"},
{file = "pydantic-1.10.7-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:c230c0d8a322276d6e7b88c3f7ce885f9ed16e0910354510e0bae84d54991143"},
{file = "pydantic-1.10.7-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:976cae77ba6a49d80f461fd8bba183ff7ba79f44aa5cfa82f1346b5626542f8e"},
{file = "pydantic-1.10.7-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7d45fc99d64af9aaf7e308054a0067fdcd87ffe974f2442312372dfa66e1001d"},
{file = "pydantic-1.10.7-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d2a5ebb48958754d386195fe9e9c5106f11275867051bf017a8059410e9abf1f"},
{file = "pydantic-1.10.7-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:abfb7d4a7cd5cc4e1d1887c43503a7c5dd608eadf8bc615413fc498d3e4645cd"},
{file = "pydantic-1.10.7-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:80b1fab4deb08a8292d15e43a6edccdffa5377a36a4597bb545b93e79c5ff0a5"},
{file = "pydantic-1.10.7-cp39-cp39-win_amd64.whl", hash = "sha256:d71e69699498b020ea198468e2480a2f1e7433e32a3a99760058c6520e2bea7e"},
{file = "pydantic-1.10.7-py3-none-any.whl", hash = "sha256:0cd181f1d0b1d00e2b705f1bf1ac7799a2d938cce3376b8007df62b29be3c2c6"},
{file = "pydantic-1.10.7.tar.gz", hash = "sha256:cfc83c0678b6ba51b0532bea66860617c4cd4251ecf76e9846fa5a9f3454e97e"},
{file = "pydantic-2.1.1-py3-none-any.whl", hash = "sha256:43bdbf359d6304c57afda15c2b95797295b702948082d4c23851ce752f21da70"},
{file = "pydantic-2.1.1.tar.gz", hash = "sha256:22d63db5ce4831afd16e7c58b3192d3faf8f79154980d9397d9867254310ba4b"},
]
[package.dependencies]
typing-extensions = ">=4.2.0"
annotated-types = ">=0.4.0"
pydantic-core = "2.4.0"
typing-extensions = ">=4.6.1"
[package.extras]
dotenv = ["python-dotenv (>=0.10.4)"]
email = ["email-validator (>=1.0.3)"]
email = ["email-validator (>=2.0.0)"]
[[package]]
name = "pydantic-core"
version = "2.4.0"
description = ""
optional = false
python-versions = ">=3.7"
files = [
{file = "pydantic_core-2.4.0-cp310-cp310-macosx_10_7_x86_64.whl", hash = "sha256:2ca4687dd996bde7f3c420def450797feeb20dcee2b9687023e3323c73fc14a2"},
{file = "pydantic_core-2.4.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:782fced7d61469fd1231b184a80e4f2fa7ad54cd7173834651a453f96f29d673"},
{file = "pydantic_core-2.4.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6213b471b68146af97b8551294e59e7392c2117e28ffad9c557c65087f4baee3"},
{file = "pydantic_core-2.4.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:63797499a219d8e81eb4e0c42222d0a4c8ec896f5c76751d4258af95de41fdf1"},
{file = "pydantic_core-2.4.0-cp310-cp310-manylinux_2_24_armv7l.whl", hash = "sha256:0455876d575a35defc4da7e0a199596d6c773e20d3d42fa1fc29f6aa640369ed"},
{file = "pydantic_core-2.4.0-cp310-cp310-manylinux_2_24_ppc64le.whl", hash = "sha256:8c938c96294d983dcf419b54dba2d21056959c22911d41788efbf949a29ae30d"},
{file = "pydantic_core-2.4.0-cp310-cp310-manylinux_2_24_s390x.whl", hash = "sha256:878a5017d93e776c379af4e7b20f173c82594d94fa073059bcc546789ad50bf8"},
{file = "pydantic_core-2.4.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:69159afc2f2dc43285725f16143bc5df3c853bc1cb7df6021fce7ef1c69e8171"},
{file = "pydantic_core-2.4.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:54df7df399b777c1fd144f541c95d351b3aa110535a6810a6a569905d106b6f3"},
{file = "pydantic_core-2.4.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:e412607ca89a0ced10758dfb8f9adcc365ce4c1c377e637c01989a75e9a9ec8a"},
{file = "pydantic_core-2.4.0-cp310-none-win32.whl", hash = "sha256:853f103e2b9a58832fdd08a587a51de8b552ae90e1a5d167f316b7eabf8d7dde"},
{file = "pydantic_core-2.4.0-cp310-none-win_amd64.whl", hash = "sha256:3ba2c9c94a9176f6321a879c8b864d7c5b12d34f549a4c216c72ce213d7d953c"},
{file = "pydantic_core-2.4.0-cp311-cp311-macosx_10_7_x86_64.whl", hash = "sha256:a8b7acd04896e8f161e1500dc5f218017db05c1d322f054e89cbd089ce5d0071"},
{file = "pydantic_core-2.4.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:16468bd074fa4567592d3255bf25528ed41e6b616d69bf07096bdb5b66f947d1"},
{file = "pydantic_core-2.4.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cba5ad5eef02c86a1f3da00544cbc59a510d596b27566479a7cd4d91c6187a11"},
{file = "pydantic_core-2.4.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b7206e41e04b443016e930e01685bab7a308113c0b251b3f906942c8d4b48fcb"},
{file = "pydantic_core-2.4.0-cp311-cp311-manylinux_2_24_armv7l.whl", hash = "sha256:c1375025f0bfc9155286ebae8eecc65e33e494c90025cda69e247c3ccd2bab00"},
{file = "pydantic_core-2.4.0-cp311-cp311-manylinux_2_24_ppc64le.whl", hash = "sha256:3534118289e33130ed3f1cc487002e8d09b9f359be48b02e9cd3de58ce58fba9"},
{file = "pydantic_core-2.4.0-cp311-cp311-manylinux_2_24_s390x.whl", hash = "sha256:94d2b36a74623caab262bf95f0e365c2c058396082bd9d6a9e825657d0c1e7fa"},
{file = "pydantic_core-2.4.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:af24ad4fbaa5e4a2000beae0c3b7fd1c78d7819ab90f9370a1cfd8998e3f8a3c"},
{file = "pydantic_core-2.4.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:bf10963d8aed8bbe0165b41797c9463d4c5c8788ae6a77c68427569be6bead41"},
{file = "pydantic_core-2.4.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:68199ada7c310ddb8c76efbb606a0de656b40899388a7498954f423e03fc38be"},
{file = "pydantic_core-2.4.0-cp311-none-win32.whl", hash = "sha256:6f855bcc96ed3dd56da7373cfcc9dcbabbc2073cac7f65c185772d08884790ce"},
{file = "pydantic_core-2.4.0-cp311-none-win_amd64.whl", hash = "sha256:de39eb3bab93a99ddda1ac1b9aa331b944d8bcc4aa9141148f7fd8ee0299dafc"},
{file = "pydantic_core-2.4.0-cp312-cp312-macosx_10_7_x86_64.whl", hash = "sha256:f773b39780323a0499b53ebd91a28ad11cde6705605d98d999dfa08624caf064"},
{file = "pydantic_core-2.4.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:a297c0d6c61963c5c3726840677b798ca5b7dfc71bc9c02b9a4af11d23236008"},
{file = "pydantic_core-2.4.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:546064c55264156b973b5e65e5fafbe5e62390902ce3cf6b4005765505e8ff56"},
{file = "pydantic_core-2.4.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:36ba9e728588588f0196deaf6751b9222492331b5552f865a8ff120869d372e0"},
{file = "pydantic_core-2.4.0-cp312-cp312-manylinux_2_24_armv7l.whl", hash = "sha256:57a53a75010c635b3ad6499e7721eaa3b450e03f6862afe2dbef9c8f66e46ec8"},
{file = "pydantic_core-2.4.0-cp312-cp312-manylinux_2_24_ppc64le.whl", hash = "sha256:4b262bbc13022f2097c48a21adcc360a81d83dc1d854c11b94953cd46d7d3c07"},
{file = "pydantic_core-2.4.0-cp312-cp312-manylinux_2_24_s390x.whl", hash = "sha256:01947ad728f426fa07fcb26457ebf90ce29320259938414bc0edd1476e75addb"},
{file = "pydantic_core-2.4.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:b2799c2eaf182769889761d4fb4d78b82bc47dae833799fedbf69fc7de306faa"},
{file = "pydantic_core-2.4.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:a08fd490ba36d1fbb2cd5dcdcfb9f3892deb93bd53456724389135712b5fc735"},
{file = "pydantic_core-2.4.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:1e8a7c62d15a5c4b307271e4252d76ebb981d6251c6ecea4daf203ef0179ea4f"},
{file = "pydantic_core-2.4.0-cp312-none-win32.whl", hash = "sha256:9206c14a67c38de7b916e486ae280017cf394fa4b1aa95cfe88621a4e1d79725"},
{file = "pydantic_core-2.4.0-cp312-none-win_amd64.whl", hash = "sha256:884235507549a6b2d3c4113fb1877ae263109e787d9e0eb25c35982ab28d0399"},
{file = "pydantic_core-2.4.0-cp37-cp37m-macosx_10_7_x86_64.whl", hash = "sha256:4cbe929efa77a806e8f1a97793f2dc3ea3475ae21a9ed0f37c21320fe93f6f50"},
{file = "pydantic_core-2.4.0-cp37-cp37m-macosx_11_0_arm64.whl", hash = "sha256:9137289de8fe845c246a8c3482dd0cb40338846ba683756d8f489a4bd8fddcae"},
{file = "pydantic_core-2.4.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c5d8e764b5646623e57575f624f8ebb8f7a9f7fd1fae682ef87869ca5fec8dcf"},
{file = "pydantic_core-2.4.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8fba0aff4c407d0274e43697e785bcac155ad962be57518d1c711f45e72da70f"},
{file = "pydantic_core-2.4.0-cp37-cp37m-manylinux_2_24_armv7l.whl", hash = "sha256:30527d173e826f2f7651f91c821e337073df1555e3b5a0b7b1e2c39e26e50678"},
{file = "pydantic_core-2.4.0-cp37-cp37m-manylinux_2_24_ppc64le.whl", hash = "sha256:bd7d1dde70ff3e09e4bc7a1cbb91a7a538add291bfd5b3e70ef1e7b45192440f"},
{file = "pydantic_core-2.4.0-cp37-cp37m-manylinux_2_24_s390x.whl", hash = "sha256:72f1216ca8cef7b8adacd4c4c6b89c3b0c4f97503197f5284c80f36d6e4edd30"},
{file = "pydantic_core-2.4.0-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:b013c7861a7c7bfcec48fd709513fea6f9f31727e7a0a93ca0dd12e056740717"},
{file = "pydantic_core-2.4.0-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:478f5f6d7e32bd4a04d102160efb2d389432ecf095fe87c555c0a6fc4adfc1a4"},
{file = "pydantic_core-2.4.0-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:d9610b47b5fe4aacbbba6a9cb5f12cbe864eec99dbfed5710bd32ef5dd8a5d5b"},
{file = "pydantic_core-2.4.0-cp37-none-win32.whl", hash = "sha256:ff246c0111076c8022f9ba325c294f2cb5983403506989253e04dbae565e019b"},
{file = "pydantic_core-2.4.0-cp37-none-win_amd64.whl", hash = "sha256:d0c2b713464a8e263a243ae7980d81ce2de5ac59a9f798a282e44350b42dc516"},
{file = "pydantic_core-2.4.0-cp38-cp38-macosx_10_7_x86_64.whl", hash = "sha256:12ef6838245569fd60a179fade81ca4b90ae2fa0ef355d616f519f7bb27582db"},
{file = "pydantic_core-2.4.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:49db206eb8fdc4b4f30e6e3e410584146d813c151928f94ec0db06c4f2595538"},
{file = "pydantic_core-2.4.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0a507d7fa44688bbac76af6521e488b3da93de155b9cba6f2c9b7833ce243d59"},
{file = "pydantic_core-2.4.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ffe18407a4d000c568182ce5388bbbedeb099896904e43fc14eee76cfae6dec5"},
{file = "pydantic_core-2.4.0-cp38-cp38-manylinux_2_24_armv7l.whl", hash = "sha256:fa8e48001b39d54d97d7b380a0669fa99fc0feeb972e35a2d677ba59164a9a22"},
{file = "pydantic_core-2.4.0-cp38-cp38-manylinux_2_24_ppc64le.whl", hash = "sha256:394f12a2671ff8c4dfa2e85be6c08be0651ad85bc1e6aa9c77c21671baaf28cd"},
{file = "pydantic_core-2.4.0-cp38-cp38-manylinux_2_24_s390x.whl", hash = "sha256:2f9ea0355f90db2a76af530245fa42f04d98f752a1236ed7c6809ec484560d5b"},
{file = "pydantic_core-2.4.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:61d4e713f467abcdd59b47665d488bb898ad3dd47ce7446522a50e0cbd8e8279"},
{file = "pydantic_core-2.4.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:453862ab268f6326b01f067ed89cb3a527d34dc46f6f4eeec46a15bbc706d0da"},
{file = "pydantic_core-2.4.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:56a85fa0dab1567bd0cac10f0c3837b03e8a0d939e6a8061a3a420acd97e9421"},
{file = "pydantic_core-2.4.0-cp38-none-win32.whl", hash = "sha256:0d726108c1c0380b88b6dd4db559f0280e0ceda9e077f46ff90bc85cd4d03e77"},
{file = "pydantic_core-2.4.0-cp38-none-win_amd64.whl", hash = "sha256:047580388644c473b934d27849f8ed8dbe45df0adb72104e78b543e13bf69762"},
{file = "pydantic_core-2.4.0-cp39-cp39-macosx_10_7_x86_64.whl", hash = "sha256:867d3eea954bea807cabba83cfc939c889a18576d66d197c60025b15269d7cc0"},
{file = "pydantic_core-2.4.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:664402ef0c238a7f8a46efb101789d5f2275600fb18114446efec83cfadb5b66"},
{file = "pydantic_core-2.4.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:64e8012ad60a5f0da09ed48725e6e923d1be25f2f091a640af6079f874663813"},
{file = "pydantic_core-2.4.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ac2b680de398f293b68183317432b3d67ab3faeba216aec18de0c395cb5e3060"},
{file = "pydantic_core-2.4.0-cp39-cp39-manylinux_2_24_armv7l.whl", hash = "sha256:8efc1be43b036c2b6bcfb1451df24ee0ddcf69c31351003daf2699ed93f5687b"},
{file = "pydantic_core-2.4.0-cp39-cp39-manylinux_2_24_ppc64le.whl", hash = "sha256:d93aedbc4614cc21b9ab0d0c4ccd7143354c1f7cffbbe96ae5216ad21d1b21b5"},
{file = "pydantic_core-2.4.0-cp39-cp39-manylinux_2_24_s390x.whl", hash = "sha256:af788b64e13d52fc3600a68b16d31fa8d8573e3ff2fc9a38f8a60b8d94d1f012"},
{file = "pydantic_core-2.4.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:97c6349c81cee2e69ef59eba6e6c08c5936e6b01c2d50b9e4ac152217845ae09"},
{file = "pydantic_core-2.4.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:cc086ddb6dc654a15deeed1d1f2bcb1cb924ebd70df9dca738af19f64229b06c"},
{file = "pydantic_core-2.4.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:e953353180bec330c3b830891d260b6f8e576e2d18db3c78d314e56bb2276066"},
{file = "pydantic_core-2.4.0-cp39-none-win32.whl", hash = "sha256:6feb4b64d11d5420e517910d60a907d08d846cacaf4e029668725cd21d16743c"},
{file = "pydantic_core-2.4.0-cp39-none-win_amd64.whl", hash = "sha256:153a61ac4030fa019b70b31fb7986461119230d3ba0ab661c757cfea652f4332"},
{file = "pydantic_core-2.4.0-pp310-pypy310_pp73-macosx_10_7_x86_64.whl", hash = "sha256:3fcf529382b282a30b466bd7af05be28e22aa620e016135ac414f14e1ee6b9e1"},
{file = "pydantic_core-2.4.0-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2edef05b63d82568b877002dc4cb5cc18f8929b59077120192df1e03e0c633f8"},
{file = "pydantic_core-2.4.0-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:da055a1b0bfa8041bb2ff586b2cb0353ed03944a3472186a02cc44a557a0e661"},
{file = "pydantic_core-2.4.0-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:77dadc764cf7c5405e04866181c5bd94a447372a9763e473abb63d1dfe9b7387"},
{file = "pydantic_core-2.4.0-pp310-pypy310_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:a4ea23b07f29487a7bef2a869f68c7ee0e05424d81375ce3d3de829314c6b5ec"},
{file = "pydantic_core-2.4.0-pp310-pypy310_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:382f0baa044d674ad59455a5eff83d7965572b745cc72df35c52c2ce8c731d37"},
{file = "pydantic_core-2.4.0-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:08f89697625e453421401c7f661b9d1eb4c9e4c0a12fd256eeb55b06994ac6af"},
{file = "pydantic_core-2.4.0-pp37-pypy37_pp73-macosx_10_7_x86_64.whl", hash = "sha256:43a405ce520b45941df9ff55d0cd09762017756a7b413bbad3a6e8178e64a2c2"},
{file = "pydantic_core-2.4.0-pp37-pypy37_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:584a7a818c84767af16ce8bda5d4f7fedb37d3d231fc89928a192f567e4ef685"},
{file = "pydantic_core-2.4.0-pp37-pypy37_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:04922fea7b13cd480586fa106345fe06e43220b8327358873c22d8dfa7a711c7"},
{file = "pydantic_core-2.4.0-pp37-pypy37_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:17156abac20a9feed10feec867fddd91a80819a485b0107fe61f09f2117fe5f3"},
{file = "pydantic_core-2.4.0-pp37-pypy37_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:4e562cc63b04636cde361fd47569162f1daa94c759220ff202a8129902229114"},
{file = "pydantic_core-2.4.0-pp37-pypy37_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:90f3785146f701e053bb6b9e8f53acce2c919aca91df88bd4975be0cb926eb41"},
{file = "pydantic_core-2.4.0-pp37-pypy37_pp73-win_amd64.whl", hash = "sha256:e40b1e97edd3dc127aa53d8a5e539a3d0c227d71574d3f9ac1af02d58218a122"},
{file = "pydantic_core-2.4.0-pp38-pypy38_pp73-macosx_10_7_x86_64.whl", hash = "sha256:b27f3e67f6e031f6620655741b7d0d6bebea8b25d415924b3e8bfef2dd7bd841"},
{file = "pydantic_core-2.4.0-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:be86c2eb12fb0f846262ace9d8f032dc6978b8cb26a058920ecb723dbcb87d05"},
{file = "pydantic_core-2.4.0-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4665f7ed345012a8d2eddf4203ef145f5f56a291d010382d235b94e91813f88a"},
{file = "pydantic_core-2.4.0-pp38-pypy38_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:79262be5a292d1df060f29b9a7cdd66934801f987a817632d7552534a172709a"},
{file = "pydantic_core-2.4.0-pp38-pypy38_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:5fd905a69ac74eaba5041e21a1e8b1a479dab2b41c93bdcc4c1cede3c12a8d86"},
{file = "pydantic_core-2.4.0-pp38-pypy38_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:2ad538b7e07343001934417cdc8584623b4d8823c5b8b258e75ec8d327cec969"},
{file = "pydantic_core-2.4.0-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:dd2429f7635ad4857b5881503f9c310be7761dc681c467a9d27787b674d1250a"},
{file = "pydantic_core-2.4.0-pp39-pypy39_pp73-macosx_10_7_x86_64.whl", hash = "sha256:efff8b6761a1f6e45cebd1b7a6406eb2723d2d5710ff0d1b624fe11313693989"},
{file = "pydantic_core-2.4.0-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:32a1e0352558cd7ccc014ffe818c7d87b15ec6145875e2cc5fa4bb7351a1033d"},
{file = "pydantic_core-2.4.0-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a027f41c5008571314861744d83aff75a34cf3a07022e0be32b214a5bc93f7f1"},
{file = "pydantic_core-2.4.0-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:1927f0e15d190f11f0b8344373731e28fd774c6d676d8a6cfadc95c77214a48b"},
{file = "pydantic_core-2.4.0-pp39-pypy39_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:7aa82d483d5fb867d4fb10a138ffd57b0f1644e99f2f4f336e48790ada9ada5e"},
{file = "pydantic_core-2.4.0-pp39-pypy39_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:b85778308bf945e9b33ac604e6793df9b07933108d20bdf53811bc7c2798a4af"},
{file = "pydantic_core-2.4.0-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:3ded19dcaefe2f6706d81e0db787b59095f4ad0fbadce1edffdf092294c8a23f"},
{file = "pydantic_core-2.4.0.tar.gz", hash = "sha256:ec3473c9789cc00c7260d840c3db2c16dbfc816ca70ec87a00cddfa3e1a1cdd5"},
]
[package.dependencies]
typing-extensions = ">=4.6.0,<4.7.0 || >4.7.0"
[[package]]
name = "pydantic-settings"
version = "2.0.2"
description = "Settings management using Pydantic"
optional = false
python-versions = ">=3.7"
files = [
{file = "pydantic_settings-2.0.2-py3-none-any.whl", hash = "sha256:6183a2abeab465d5a3ab69758e9a22d38b0cc2ba193f0b85f6971a252ea630f6"},
{file = "pydantic_settings-2.0.2.tar.gz", hash = "sha256:342337fff50b23585e807a86dec85037900972364435c55c2fc00d16ff080539"},
]
[package.dependencies]
pydantic = ">=2.0.1"
python-dotenv = ">=0.21.0"
[[package]]
name = "pydantic-to-typescript"
@ -2453,13 +2557,13 @@ sqlcipher = ["sqlcipher3-binary"]
[[package]]
name = "starlette"
version = "0.26.1"
version = "0.27.0"
description = "The little ASGI library that shines."
optional = false
python-versions = ">=3.7"
files = [
{file = "starlette-0.26.1-py3-none-any.whl", hash = "sha256:e87fce5d7cbdde34b76f0ac69013fd9d190d581d80681493016666e6f96c6d5e"},
{file = "starlette-0.26.1.tar.gz", hash = "sha256:41da799057ea8620e4667a3e69a5b1923ebd32b1819c8fa75634bbe8d8bea9bd"},
{file = "starlette-0.27.0-py3-none-any.whl", hash = "sha256:918416370e846586541235ccd38a474c08b80443ed31c578a418e2209b3eef91"},
{file = "starlette-0.27.0.tar.gz", hash = "sha256:6a6b0d042acb8d469a01eba54e9cda6cbd24ac602c4cd016723117d6a7e73b75"},
]
[package.dependencies]
@ -2561,13 +2665,13 @@ files = [
[[package]]
name = "typing-extensions"
version = "4.4.0"
version = "4.7.1"
description = "Backported and Experimental Type Hints for Python 3.7+"
optional = false
python-versions = ">=3.7"
files = [
{file = "typing_extensions-4.4.0-py3-none-any.whl", hash = "sha256:16fa4864408f655d35ec496218b85f79b3437c829e93320c7c9215ccfd92489e"},
{file = "typing_extensions-4.4.0.tar.gz", hash = "sha256:1511434bb92bf8dd198c12b1cc812e800d4181cfcb867674e0f8279cc93087aa"},
{file = "typing_extensions-4.7.1-py3-none-any.whl", hash = "sha256:440d5dd3af93b060174bf433bccd69b0babc3b15b1a8dca43789fd7f61514b36"},
{file = "typing_extensions-4.7.1.tar.gz", hash = "sha256:b75ddc264f0ba5615db7ba217daeb99701ad295353c45f9e95963337ceeeffb2"},
]
[[package]]
@ -2935,4 +3039,4 @@ pgsql = ["psycopg2-binary"]
[metadata]
lock-version = "2.0"
python-versions = "^3.10"
content-hash = "6ec46a82cad73c78013d1729df179a3fb5c4e12eb2a11ca04b2412d6b8e5b25f"
content-hash = "86c45be1f77b9a37fe0933536a5ca4dda9e8bfafd94ce008db9070e870c9cbd1"

View File

@ -20,14 +20,14 @@ appdirs = "1.4.4"
apprise = "^1.2.0"
bcrypt = "^4.0.1"
extruct = "^0.14.0"
fastapi = "^0.95.0"
fastapi = "^0.101.0"
gunicorn = "^20.1.0"
httpx = "^0.23.1"
lxml = "^4.7.1"
orjson = "^3.8.0"
passlib = "^1.7.4"
psycopg2-binary = {version = "^2.9.1", optional = true}
pydantic = "^1.10.4"
pydantic = "^2.1.1"
pyhumps = "^3.5.3"
pytesseract = "^0.3.9"
python = "^3.10"
@ -43,6 +43,7 @@ tzdata = "^2022.7"
uvicorn = {extras = ["standard"], version = "^0.21.0"}
beautifulsoup4 = "^4.11.2"
isodate = "^0.6.1"
pydantic-settings = "^2.0.2"
[tool.poetry.group.dev.dependencies]
black = "^23.1.0"