mirror of
				https://github.com/mealie-recipes/mealie.git
				synced 2025-10-31 02:03:35 -04:00 
			
		
		
		
	chore(deps): update dependency ruff to ^0.12.0 (#5568)
Co-authored-by: Kuchenpirat <24235032+Kuchenpirat@users.noreply.github.com>
This commit is contained in:
		| @@ -1,6 +1,5 @@ | |||||||
| import abc | import abc | ||||||
| from datetime import UTC, datetime, timedelta | from datetime import UTC, datetime, timedelta | ||||||
| from typing import Generic, TypeVar |  | ||||||
|  |  | ||||||
| import jwt | import jwt | ||||||
| from sqlalchemy.orm.session import Session | from sqlalchemy.orm.session import Session | ||||||
| @@ -13,10 +12,8 @@ ALGORITHM = "HS256" | |||||||
| ISS = "mealie" | ISS = "mealie" | ||||||
| remember_me_duration = timedelta(days=14) | remember_me_duration = timedelta(days=14) | ||||||
|  |  | ||||||
| T = TypeVar("T") |  | ||||||
|  |  | ||||||
|  | class AuthProvider[T](metaclass=abc.ABCMeta): | ||||||
| class AuthProvider(Generic[T], metaclass=abc.ABCMeta): |  | ||||||
|     """Base Authentication Provider interface""" |     """Base Authentication Provider interface""" | ||||||
|  |  | ||||||
|     def __init__(self, session: Session, data: T) -> None: |     def __init__(self, session: Session, data: T) -> None: | ||||||
|   | |||||||
| @@ -4,7 +4,7 @@ import random | |||||||
| from collections.abc import Iterable | from collections.abc import Iterable | ||||||
| from datetime import UTC, datetime | from datetime import UTC, datetime | ||||||
| from math import ceil | from math import ceil | ||||||
| from typing import Any, Generic, TypeVar | from typing import Any | ||||||
|  |  | ||||||
| from fastapi import HTTPException | from fastapi import HTTPException | ||||||
| from pydantic import UUID4, BaseModel | from pydantic import UUID4, BaseModel | ||||||
| @@ -28,18 +28,13 @@ from mealie.schema.response.query_search import SearchFilter | |||||||
|  |  | ||||||
| from ._utils import NOT_SET, NotSet | from ._utils import NOT_SET, NotSet | ||||||
|  |  | ||||||
| Schema = TypeVar("Schema", bound=MealieModel) |  | ||||||
| Model = TypeVar("Model", bound=SqlAlchemyBase) |  | ||||||
|  |  | ||||||
| T = TypeVar("T", bound="RepositoryGeneric") | class RepositoryGeneric[Schema: MealieModel, Model: SqlAlchemyBase]: | ||||||
|  |  | ||||||
|  |  | ||||||
| class RepositoryGeneric(Generic[Schema, Model]): |  | ||||||
|     """A Generic BaseAccess Model method to perform common operations on the database |     """A Generic BaseAccess Model method to perform common operations on the database | ||||||
|  |  | ||||||
|     Args: |     Args: | ||||||
|         Generic ([Schema]): Represents the Pydantic Model |         Schema: Represents the Pydantic Model | ||||||
|         Generic ([Model]): Represents the SqlAlchemyModel Model |         Model: Represents the SqlAlchemyModel Model | ||||||
|     """ |     """ | ||||||
|  |  | ||||||
|     session: Session |     session: Session | ||||||
| @@ -467,7 +462,7 @@ class RepositoryGeneric(Generic[Schema, Model]): | |||||||
|         return search_filter.filter_query_by_search(query, schema, self.model) |         return search_filter.filter_query_by_search(query, schema, self.model) | ||||||
|  |  | ||||||
|  |  | ||||||
| class GroupRepositoryGeneric(RepositoryGeneric[Schema, Model]): | class GroupRepositoryGeneric[Schema: MealieModel, Model: SqlAlchemyBase](RepositoryGeneric[Schema, Model]): | ||||||
|     def __init__( |     def __init__( | ||||||
|         self, |         self, | ||||||
|         session: Session, |         session: Session, | ||||||
| @@ -483,7 +478,7 @@ class GroupRepositoryGeneric(RepositoryGeneric[Schema, Model]): | |||||||
|         self._group_id = group_id if group_id else None |         self._group_id = group_id if group_id else None | ||||||
|  |  | ||||||
|  |  | ||||||
| class HouseholdRepositoryGeneric(RepositoryGeneric[Schema, Model]): | class HouseholdRepositoryGeneric[Schema: MealieModel, Model: SqlAlchemyBase](RepositoryGeneric[Schema, Model]): | ||||||
|     def __init__( |     def __init__( | ||||||
|         self, |         self, | ||||||
|         session: Session, |         session: Session, | ||||||
|   | |||||||
| @@ -6,20 +6,18 @@ See their repository for details -> https://github.com/dmontagu/fastapi-utils | |||||||
|  |  | ||||||
| import inspect | import inspect | ||||||
| from collections.abc import Callable | from collections.abc import Callable | ||||||
| from typing import Any, ClassVar, ForwardRef, TypeVar, cast, get_origin, get_type_hints | from typing import Any, ClassVar, ForwardRef, cast, get_origin, get_type_hints | ||||||
|  |  | ||||||
| from fastapi import APIRouter, Depends | from fastapi import APIRouter, Depends | ||||||
| from fastapi.routing import APIRoute | from fastapi.routing import APIRoute | ||||||
| from starlette.routing import Route, WebSocketRoute | from starlette.routing import Route, WebSocketRoute | ||||||
|  |  | ||||||
| T = TypeVar("T") |  | ||||||
|  |  | ||||||
| CBV_CLASS_KEY = "__cbv_class__" | CBV_CLASS_KEY = "__cbv_class__" | ||||||
| INCLUDE_INIT_PARAMS_KEY = "__include_init_params__" | INCLUDE_INIT_PARAMS_KEY = "__include_init_params__" | ||||||
| RETURN_TYPES_FUNC_KEY = "__return_types_func__" | RETURN_TYPES_FUNC_KEY = "__return_types_func__" | ||||||
|  |  | ||||||
|  |  | ||||||
| def controller(router: APIRouter, *urls: str) -> Callable[[type[T]], type[T]]: | def controller[T](router: APIRouter, *urls: str) -> Callable[[type[T]], type[T]]: | ||||||
|     """ |     """ | ||||||
|     This function returns a decorator that converts the decorated into a class-based view for the provided router. |     This function returns a decorator that converts the decorated into a class-based view for the provided router. | ||||||
|     Any methods of the decorated class that are decorated as endpoints using the router provided to this function |     Any methods of the decorated class that are decorated as endpoints using the router provided to this function | ||||||
| @@ -36,7 +34,7 @@ def controller(router: APIRouter, *urls: str) -> Callable[[type[T]], type[T]]: | |||||||
|     return decorator |     return decorator | ||||||
|  |  | ||||||
|  |  | ||||||
| def _cbv(router: APIRouter, cls: type[T], *urls: str, instance: Any | None = None) -> type[T]: | def _cbv[T](router: APIRouter, cls: type[T], *urls: str, instance: Any | None = None) -> type[T]: | ||||||
|     """ |     """ | ||||||
|     Replaces any methods of the provided class `cls` that are endpoints of routes in `router` with updated |     Replaces any methods of the provided class `cls` that are endpoints of routes in `router` with updated | ||||||
|     function calls that will properly inject an instance of `cls`. |     function calls that will properly inject an instance of `cls`. | ||||||
|   | |||||||
| @@ -1,6 +1,5 @@ | |||||||
| from collections.abc import Callable | from collections.abc import Callable | ||||||
| from logging import Logger | from logging import Logger | ||||||
| from typing import Generic, TypeVar |  | ||||||
|  |  | ||||||
| import sqlalchemy.exc | import sqlalchemy.exc | ||||||
| from fastapi import HTTPException, status | from fastapi import HTTPException, status | ||||||
| @@ -9,12 +8,8 @@ from pydantic import UUID4, BaseModel | |||||||
| from mealie.repos.repository_generic import RepositoryGeneric | from mealie.repos.repository_generic import RepositoryGeneric | ||||||
| from mealie.schema.response import ErrorResponse | from mealie.schema.response import ErrorResponse | ||||||
|  |  | ||||||
| C = TypeVar("C", bound=BaseModel) |  | ||||||
| R = TypeVar("R", bound=BaseModel) |  | ||||||
| U = TypeVar("U", bound=BaseModel) |  | ||||||
|  |  | ||||||
|  | class HttpRepo[C: BaseModel, R: BaseModel, U: BaseModel]: | ||||||
| class HttpRepo(Generic[C, R, U]): |  | ||||||
|     """ |     """ | ||||||
|     The HttpRepo[C, R, U] class is a mixin class that provides a common set of methods for CRUD operations. |     The HttpRepo[C, R, U] class is a mixin class that provides a common set of methods for CRUD operations. | ||||||
|     This class is intended to be used in a composition pattern where a class has a mixin property. For example: |     This class is intended to be used in a composition pattern where a class has a mixin property. For example: | ||||||
|   | |||||||
| @@ -4,7 +4,7 @@ import re | |||||||
| from collections.abc import Sequence | from collections.abc import Sequence | ||||||
| from datetime import UTC, datetime | from datetime import UTC, datetime | ||||||
| from enum import Enum | from enum import Enum | ||||||
| from typing import ClassVar, Protocol, Self, TypeVar | from typing import ClassVar, Protocol, Self | ||||||
|  |  | ||||||
| from humps.main import camelize | from humps.main import camelize | ||||||
| from pydantic import UUID4, AliasChoices, BaseModel, ConfigDict, Field, model_validator | from pydantic import UUID4, AliasChoices, BaseModel, ConfigDict, Field, model_validator | ||||||
| @@ -14,8 +14,6 @@ from sqlalchemy.orm.interfaces import LoaderOption | |||||||
|  |  | ||||||
| from mealie.db.models._model_base import SqlAlchemyBase | from mealie.db.models._model_base import SqlAlchemyBase | ||||||
|  |  | ||||||
| T = TypeVar("T", bound=BaseModel) |  | ||||||
|  |  | ||||||
| HOUR_ONLY_TZ_PATTERN = re.compile(r"[+-]\d{2}$") | HOUR_ONLY_TZ_PATTERN = re.compile(r"[+-]\d{2}$") | ||||||
|  |  | ||||||
|  |  | ||||||
| @@ -56,7 +54,7 @@ class MealieModel(BaseModel): | |||||||
|  |  | ||||||
|     @model_validator(mode="before") |     @model_validator(mode="before") | ||||||
|     @classmethod |     @classmethod | ||||||
|     def fix_hour_only_tz(cls, data: T) -> T: |     def fix_hour_only_tz[T: BaseModel](cls, data: T) -> T: | ||||||
|         """ |         """ | ||||||
|         Fixes datetimes with timezones that only have the hour portion. |         Fixes datetimes with timezones that only have the hour portion. | ||||||
|  |  | ||||||
| @@ -82,7 +80,7 @@ class MealieModel(BaseModel): | |||||||
|         Adds UTC timezone information to all datetimes in the model. |         Adds UTC timezone information to all datetimes in the model. | ||||||
|         The server stores everything in UTC without timezone info. |         The server stores everything in UTC without timezone info. | ||||||
|         """ |         """ | ||||||
|         for field in self.model_fields: |         for field in self.__class__.model_fields: | ||||||
|             val = getattr(self, field) |             val = getattr(self, field) | ||||||
|             if not isinstance(val, datetime): |             if not isinstance(val, datetime): | ||||||
|                 continue |                 continue | ||||||
| @@ -91,23 +89,25 @@ class MealieModel(BaseModel): | |||||||
|  |  | ||||||
|         return self |         return self | ||||||
|  |  | ||||||
|     def cast(self, cls: type[T], **kwargs) -> T: |     def cast[T: BaseModel](self, cls: type[T], **kwargs) -> T: | ||||||
|         """ |         """ | ||||||
|         Cast the current model to another with additional arguments. Useful for |         Cast the current model to another with additional arguments. Useful for | ||||||
|         transforming DTOs into models that are saved to a database |         transforming DTOs into models that are saved to a database | ||||||
|         """ |         """ | ||||||
|         create_data = {field: getattr(self, field) for field in self.model_fields if field in cls.model_fields} |         create_data = { | ||||||
|  |             field: getattr(self, field) for field in self.__class__.model_fields if field in cls.model_fields | ||||||
|  |         } | ||||||
|         create_data.update(kwargs or {}) |         create_data.update(kwargs or {}) | ||||||
|         return cls(**create_data) |         return cls(**create_data) | ||||||
|  |  | ||||||
|     def map_to(self, dest: T) -> T: |     def map_to[T: BaseModel](self, dest: T) -> T: | ||||||
|         """ |         """ | ||||||
|         Map matching values from the current model to another model. Model returned |         Map matching values from the current model to another model. Model returned | ||||||
|         for method chaining. |         for method chaining. | ||||||
|         """ |         """ | ||||||
|  |  | ||||||
|         for field in self.model_fields: |         for field in self.__class__.model_fields: | ||||||
|             if field in dest.model_fields: |             if field in dest.__class__.model_fields: | ||||||
|                 setattr(dest, field, getattr(self, field)) |                 setattr(dest, field, getattr(self, field)) | ||||||
|  |  | ||||||
|         return dest |         return dest | ||||||
| @@ -117,18 +117,18 @@ class MealieModel(BaseModel): | |||||||
|         Map matching values from another model to the current model. |         Map matching values from another model to the current model. | ||||||
|         """ |         """ | ||||||
|  |  | ||||||
|         for field in src.model_fields: |         for field in src.__class__.model_fields: | ||||||
|             if field in self.model_fields: |             if field in self.__class__.model_fields: | ||||||
|                 setattr(self, field, getattr(src, field)) |                 setattr(self, field, getattr(src, field)) | ||||||
|  |  | ||||||
|     def merge(self, src: T, replace_null=False): |     def merge[T: BaseModel](self, src: T, replace_null=False): | ||||||
|         """ |         """ | ||||||
|         Replace matching values from another instance to the current instance. |         Replace matching values from another instance to the current instance. | ||||||
|         """ |         """ | ||||||
|  |  | ||||||
|         for field in src.model_fields: |         for field in src.__class__.model_fields: | ||||||
|             val = getattr(src, field) |             val = getattr(src, field) | ||||||
|             if field in self.model_fields and (val is not None or replace_null): |             if field in self.__class__.model_fields and (val is not None or replace_null): | ||||||
|                 setattr(self, field, val) |                 setattr(self, field, val) | ||||||
|  |  | ||||||
|     @classmethod |     @classmethod | ||||||
|   | |||||||
| @@ -1,24 +1,21 @@ | |||||||
| from typing import TypeVar |  | ||||||
|  |  | ||||||
| from pydantic import BaseModel | from pydantic import BaseModel | ||||||
|  |  | ||||||
| T = TypeVar("T", bound=BaseModel) |  | ||||||
| U = TypeVar("U", bound=BaseModel) |  | ||||||
|  |  | ||||||
|  | def mapper[U: BaseModel, T: BaseModel](source: U, dest: T, **_) -> T: | ||||||
| def mapper(source: U, dest: T, **_) -> T: |  | ||||||
|     """ |     """ | ||||||
|     Map a source model to a destination model. Only top-level fields are mapped. |     Map a source model to a destination model. Only top-level fields are mapped. | ||||||
|     """ |     """ | ||||||
|  |  | ||||||
|     for field in source.model_fields: |     for field in source.__class__.model_fields: | ||||||
|         if field in dest.model_fields: |         if field in dest.__class__.model_fields: | ||||||
|             setattr(dest, field, getattr(source, field)) |             setattr(dest, field, getattr(source, field)) | ||||||
|  |  | ||||||
|     return dest |     return dest | ||||||
|  |  | ||||||
|  |  | ||||||
| def cast(source: U, dest: type[T], **kwargs) -> T: | def cast[U: BaseModel, T: BaseModel](source: U, dest: type[T], **kwargs) -> T: | ||||||
|     create_data = {field: getattr(source, field) for field in source.model_fields if field in dest.model_fields} |     create_data = { | ||||||
|  |         field: getattr(source, field) for field in source.__class__.model_fields if field in dest.model_fields | ||||||
|  |     } | ||||||
|     create_data.update(kwargs or {}) |     create_data.update(kwargs or {}) | ||||||
|     return dest(**create_data) |     return dest(**create_data) | ||||||
|   | |||||||
| @@ -1,5 +1,5 @@ | |||||||
| import enum | import enum | ||||||
| from typing import Annotated, Any, Generic, TypeVar | from typing import Annotated, Any | ||||||
| from urllib.parse import parse_qs, urlencode, urlsplit, urlunsplit | from urllib.parse import parse_qs, urlencode, urlsplit, urlunsplit | ||||||
|  |  | ||||||
| from humps import camelize | from humps import camelize | ||||||
| @@ -8,8 +8,6 @@ from pydantic_core.core_schema import ValidationInfo | |||||||
|  |  | ||||||
| from mealie.schema._mealie import MealieModel | from mealie.schema._mealie import MealieModel | ||||||
|  |  | ||||||
| DataT = TypeVar("DataT", bound=BaseModel) |  | ||||||
|  |  | ||||||
|  |  | ||||||
| class OrderDirection(str, enum.Enum): | class OrderDirection(str, enum.Enum): | ||||||
|     asc = "asc" |     asc = "asc" | ||||||
| @@ -50,7 +48,7 @@ class PaginationQuery(RequestQuery): | |||||||
|     per_page: int = 50 |     per_page: int = 50 | ||||||
|  |  | ||||||
|  |  | ||||||
| class PaginationBase(BaseModel, Generic[DataT]): | class PaginationBase[DataT: BaseModel](BaseModel): | ||||||
|     page: int = 1 |     page: int = 1 | ||||||
|     per_page: int = 10 |     per_page: int = 10 | ||||||
|     total: int = 0 |     total: int = 0 | ||||||
|   | |||||||
| @@ -3,7 +3,7 @@ from __future__ import annotations | |||||||
| import re | import re | ||||||
| from collections import deque | from collections import deque | ||||||
| from enum import Enum | from enum import Enum | ||||||
| from typing import Any, TypeVar, cast | from typing import Any, cast | ||||||
| from uuid import UUID | from uuid import UUID | ||||||
|  |  | ||||||
| import sqlalchemy as sa | import sqlalchemy as sa | ||||||
| @@ -19,8 +19,6 @@ from mealie.db.models._model_utils.datetime import NaiveDateTime | |||||||
| from mealie.db.models._model_utils.guid import GUID | from mealie.db.models._model_utils.guid import GUID | ||||||
| from mealie.schema._mealie.mealie_model import MealieModel | from mealie.schema._mealie.mealie_model import MealieModel | ||||||
|  |  | ||||||
| Model = TypeVar("Model", bound=SqlAlchemyBase) |  | ||||||
|  |  | ||||||
|  |  | ||||||
| class RelationalKeyword(Enum): | class RelationalKeyword(Enum): | ||||||
|     IS = "IS" |     IS = "IS" | ||||||
| @@ -274,7 +272,7 @@ class QueryFilterBuilder: | |||||||
|                 return consolidated_group_builder.self_group() |                 return consolidated_group_builder.self_group() | ||||||
|  |  | ||||||
|     @classmethod |     @classmethod | ||||||
|     def get_model_and_model_attr_from_attr_string( |     def get_model_and_model_attr_from_attr_string[Model: SqlAlchemyBase]( | ||||||
|         cls, attr_string: str, model: type[Model], *, query: sa.Select | None = None |         cls, attr_string: str, model: type[Model], *, query: sa.Select | None = None | ||||||
|     ) -> tuple[SqlAlchemyBase, InstrumentedAttribute, sa.Select | None]: |     ) -> tuple[SqlAlchemyBase, InstrumentedAttribute, sa.Select | None]: | ||||||
|         """ |         """ | ||||||
| @@ -343,7 +341,7 @@ class QueryFilterBuilder: | |||||||
|         return model_attr |         return model_attr | ||||||
|  |  | ||||||
|     @classmethod |     @classmethod | ||||||
|     def _get_filter_element( |     def _get_filter_element[Model: SqlAlchemyBase]( | ||||||
|         cls, |         cls, | ||||||
|         query: sa.Select, |         query: sa.Select, | ||||||
|         component: QueryFilterBuilderComponent, |         component: QueryFilterBuilderComponent, | ||||||
| @@ -397,7 +395,7 @@ class QueryFilterBuilder: | |||||||
|  |  | ||||||
|         return element |         return element | ||||||
|  |  | ||||||
|     def filter_query( |     def filter_query[Model: SqlAlchemyBase]( | ||||||
|         self, query: sa.Select, model: type[Model], column_aliases: dict[str, sa.ColumnElement] | None = None |         self, query: sa.Select, model: type[Model], column_aliases: dict[str, sa.ColumnElement] | None = None | ||||||
|     ) -> sa.Select: |     ) -> sa.Select: | ||||||
|         """ |         """ | ||||||
|   | |||||||
| @@ -1,6 +1,6 @@ | |||||||
| from datetime import UTC, datetime, timedelta | from datetime import UTC, datetime, timedelta | ||||||
| from pathlib import Path | from pathlib import Path | ||||||
| from typing import Annotated, Any, Generic, TypeVar | from typing import Annotated, Any | ||||||
| from uuid import UUID | from uuid import UUID | ||||||
|  |  | ||||||
| from pydantic import UUID4, BaseModel, ConfigDict, Field, StringConstraints, field_validator | from pydantic import UUID4, BaseModel, ConfigDict, Field, StringConstraints, field_validator | ||||||
| @@ -20,7 +20,6 @@ from mealie.schema.response.pagination import PaginationBase | |||||||
| from ...db.models.group import Group | from ...db.models.group import Group | ||||||
| from ..recipe import CategoryBase | from ..recipe import CategoryBase | ||||||
|  |  | ||||||
| DataT = TypeVar("DataT", bound=BaseModel) |  | ||||||
| DEFAULT_INTEGRATION_ID = "generic" | DEFAULT_INTEGRATION_ID = "generic" | ||||||
| settings = get_app_settings() | settings = get_app_settings() | ||||||
|  |  | ||||||
| @@ -102,7 +101,7 @@ class UserRatingOut(UserRatingCreate): | |||||||
|         ] |         ] | ||||||
|  |  | ||||||
|  |  | ||||||
| class UserRatings(BaseModel, Generic[DataT]): | class UserRatings[DataT: BaseModel](BaseModel): | ||||||
|     ratings: list[DataT] |     ratings: list[DataT] | ||||||
|  |  | ||||||
|  |  | ||||||
|   | |||||||
| @@ -1,7 +1,7 @@ | |||||||
| from __future__ import annotations | from __future__ import annotations | ||||||
|  |  | ||||||
| from collections.abc import Iterable | from collections.abc import Iterable | ||||||
| from typing import TYPE_CHECKING, TypeVar | from typing import TYPE_CHECKING | ||||||
|  |  | ||||||
| from pydantic import BaseModel | from pydantic import BaseModel | ||||||
| from slugify import slugify | from slugify import slugify | ||||||
| @@ -12,8 +12,6 @@ from mealie.schema.recipe import RecipeCategory | |||||||
| from mealie.schema.recipe.recipe import RecipeTag | from mealie.schema.recipe.recipe import RecipeTag | ||||||
| from mealie.schema.recipe.recipe_category import CategoryOut, CategorySave, TagOut, TagSave | from mealie.schema.recipe.recipe_category import CategoryOut, CategorySave, TagOut, TagSave | ||||||
|  |  | ||||||
| T = TypeVar("T", bound=BaseModel) |  | ||||||
|  |  | ||||||
| if TYPE_CHECKING: | if TYPE_CHECKING: | ||||||
|     from mealie.repos.repository_generic import RepositoryGeneric |     from mealie.repos.repository_generic import RepositoryGeneric | ||||||
|  |  | ||||||
| @@ -23,7 +21,7 @@ class DatabaseMigrationHelpers: | |||||||
|         self.session = session |         self.session = session | ||||||
|         self.db = db |         self.db = db | ||||||
|  |  | ||||||
|     def _get_or_set_generic( |     def _get_or_set_generic[T: BaseModel]( | ||||||
|         self, accessor: RepositoryGeneric, items: Iterable[str], create_model: type[T], out_model: type[T] |         self, accessor: RepositoryGeneric, items: Iterable[str], create_model: type[T], out_model: type[T] | ||||||
|     ) -> list[T]: |     ) -> list[T]: | ||||||
|         """ |         """ | ||||||
|   | |||||||
| @@ -1,5 +1,4 @@ | |||||||
| from abc import ABC, abstractmethod | from abc import ABC, abstractmethod | ||||||
| from typing import TypeVar |  | ||||||
|  |  | ||||||
| from pydantic import UUID4, BaseModel | from pydantic import UUID4, BaseModel | ||||||
| from rapidfuzz import fuzz, process | from rapidfuzz import fuzz, process | ||||||
| @@ -17,8 +16,6 @@ from mealie.schema.recipe.recipe_ingredient import ( | |||||||
| ) | ) | ||||||
| from mealie.schema.response.pagination import PaginationQuery | from mealie.schema.response.pagination import PaginationQuery | ||||||
|  |  | ||||||
| T = TypeVar("T", bound=BaseModel) |  | ||||||
|  |  | ||||||
|  |  | ||||||
| class DataMatcher: | class DataMatcher: | ||||||
|     def __init__( |     def __init__( | ||||||
| @@ -83,7 +80,9 @@ class DataMatcher: | |||||||
|         return self._units_by_alias |         return self._units_by_alias | ||||||
|  |  | ||||||
|     @classmethod |     @classmethod | ||||||
|     def find_match(cls, match_value: str, *, store_map: dict[str, T], fuzzy_match_threshold: int = 0) -> T | None: |     def find_match[T: BaseModel]( | ||||||
|  |         cls, match_value: str, *, store_map: dict[str, T], fuzzy_match_threshold: int = 0 | ||||||
|  |     ) -> T | None: | ||||||
|         # check for literal matches |         # check for literal matches | ||||||
|         if match_value in store_map: |         if match_value in store_map: | ||||||
|             return store_map[match_value] |             return store_map[match_value] | ||||||
|   | |||||||
							
								
								
									
										40
									
								
								poetry.lock
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										40
									
								
								poetry.lock
									
									
									
										generated
									
									
									
								
							| @@ -3250,30 +3250,30 @@ jupyter = ["ipywidgets (>=7.5.1,<9)"] | |||||||
|  |  | ||||||
| [[package]] | [[package]] | ||||||
| name = "ruff" | name = "ruff" | ||||||
| version = "0.11.13" | version = "0.12.0" | ||||||
| description = "An extremely fast Python linter and code formatter, written in Rust." | description = "An extremely fast Python linter and code formatter, written in Rust." | ||||||
| optional = false | optional = false | ||||||
| python-versions = ">=3.7" | python-versions = ">=3.7" | ||||||
| groups = ["dev"] | groups = ["dev"] | ||||||
| files = [ | files = [ | ||||||
|     {file = "ruff-0.11.13-py3-none-linux_armv6l.whl", hash = "sha256:4bdfbf1240533f40042ec00c9e09a3aade6f8c10b6414cf11b519488d2635d46"}, |     {file = "ruff-0.12.0-py3-none-linux_armv6l.whl", hash = "sha256:5652a9ecdb308a1754d96a68827755f28d5dfb416b06f60fd9e13f26191a8848"}, | ||||||
|     {file = "ruff-0.11.13-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:aef9c9ed1b5ca28bb15c7eac83b8670cf3b20b478195bd49c8d756ba0a36cf48"}, |     {file = "ruff-0.12.0-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:05ed0c914fabc602fc1f3b42c53aa219e5736cb030cdd85640c32dbc73da74a6"}, | ||||||
|     {file = "ruff-0.11.13-py3-none-macosx_11_0_arm64.whl", hash = "sha256:53b15a9dfdce029c842e9a5aebc3855e9ab7771395979ff85b7c1dedb53ddc2b"}, |     {file = "ruff-0.12.0-py3-none-macosx_11_0_arm64.whl", hash = "sha256:07a7aa9b69ac3fcfda3c507916d5d1bca10821fe3797d46bad10f2c6de1edda0"}, | ||||||
|     {file = "ruff-0.11.13-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ab153241400789138d13f362c43f7edecc0edfffce2afa6a68434000ecd8f69a"}, |     {file = "ruff-0.12.0-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e7731c3eec50af71597243bace7ec6104616ca56dda2b99c89935fe926bdcd48"}, | ||||||
|     {file = "ruff-0.11.13-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:6c51f93029d54a910d3d24f7dd0bb909e31b6cd989a5e4ac513f4eb41629f0dc"}, |     {file = "ruff-0.12.0-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:952d0630eae628250ab1c70a7fffb641b03e6b4a2d3f3ec6c1d19b4ab6c6c807"}, | ||||||
|     {file = "ruff-0.11.13-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1808b3ed53e1a777c2ef733aca9051dc9bf7c99b26ece15cb59a0320fbdbd629"}, |     {file = "ruff-0.12.0-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c021f04ea06966b02614d442e94071781c424ab8e02ec7af2f037b4c1e01cc82"}, | ||||||
|     {file = "ruff-0.11.13-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:d28ce58b5ecf0f43c1b71edffabe6ed7f245d5336b17805803312ec9bc665933"}, |     {file = "ruff-0.12.0-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:7d235618283718ee2fe14db07f954f9b2423700919dc688eacf3f8797a11315c"}, | ||||||
|     {file = "ruff-0.11.13-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:55e4bc3a77842da33c16d55b32c6cac1ec5fb0fbec9c8c513bdce76c4f922165"}, |     {file = "ruff-0.12.0-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:0c0758038f81beec8cc52ca22de9685b8ae7f7cc18c013ec2050012862cc9165"}, | ||||||
|     {file = "ruff-0.11.13-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:633bf2c6f35678c56ec73189ba6fa19ff1c5e4807a78bf60ef487b9dd272cc71"}, |     {file = "ruff-0.12.0-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:139b3d28027987b78fc8d6cfb61165447bdf3740e650b7c480744873688808c2"}, | ||||||
|     {file = "ruff-0.11.13-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4ffbc82d70424b275b089166310448051afdc6e914fdab90e08df66c43bb5ca9"}, |     {file = "ruff-0.12.0-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:68853e8517b17bba004152aebd9dd77d5213e503a5f2789395b25f26acac0da4"}, | ||||||
|     {file = "ruff-0.11.13-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:4a9ddd3ec62a9a89578c85842b836e4ac832d4a2e0bfaad3b02243f930ceafcc"}, |     {file = "ruff-0.12.0-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:3a9512af224b9ac4757f7010843771da6b2b0935a9e5e76bb407caa901a1a514"}, | ||||||
|     {file = "ruff-0.11.13-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:d237a496e0778d719efb05058c64d28b757c77824e04ffe8796c7436e26712b7"}, |     {file = "ruff-0.12.0-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:b08df3d96db798e5beb488d4df03011874aff919a97dcc2dd8539bb2be5d6a88"}, | ||||||
|     {file = "ruff-0.11.13-py3-none-musllinux_1_2_i686.whl", hash = "sha256:26816a218ca6ef02142343fd24c70f7cd8c5aa6c203bca284407adf675984432"}, |     {file = "ruff-0.12.0-py3-none-musllinux_1_2_i686.whl", hash = "sha256:6a315992297a7435a66259073681bb0d8647a826b7a6de45c6934b2ca3a9ed51"}, | ||||||
|     {file = "ruff-0.11.13-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:51c3f95abd9331dc5b87c47ac7f376db5616041173826dfd556cfe3d4977f492"}, |     {file = "ruff-0.12.0-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:1e55e44e770e061f55a7dbc6e9aed47feea07731d809a3710feda2262d2d4d8a"}, | ||||||
|     {file = "ruff-0.11.13-py3-none-win32.whl", hash = "sha256:96c27935418e4e8e77a26bb05962817f28b8ef3843a6c6cc49d8783b5507f250"}, |     {file = "ruff-0.12.0-py3-none-win32.whl", hash = "sha256:7162a4c816f8d1555eb195c46ae0bd819834d2a3f18f98cc63819a7b46f474fb"}, | ||||||
|     {file = "ruff-0.11.13-py3-none-win_amd64.whl", hash = "sha256:29c3189895a8a6a657b7af4e97d330c8a3afd2c9c8f46c81e2fc5a31866517e3"}, |     {file = "ruff-0.12.0-py3-none-win_amd64.whl", hash = "sha256:d00b7a157b8fb6d3827b49d3324da34a1e3f93492c1f97b08e222ad7e9b291e0"}, | ||||||
|     {file = "ruff-0.11.13-py3-none-win_arm64.whl", hash = "sha256:b4385285e9179d608ff1d2fb9922062663c658605819a6876d8beef0c30b7f3b"}, |     {file = "ruff-0.12.0-py3-none-win_arm64.whl", hash = "sha256:8cd24580405ad8c1cc64d61725bca091d6b6da7eb3d36f72cc605467069d7e8b"}, | ||||||
|     {file = "ruff-0.11.13.tar.gz", hash = "sha256:26fa247dc68d1d4e72c179e08889a25ac0c7ba4d78aecfc835d49cbfd60bf514"}, |     {file = "ruff-0.12.0.tar.gz", hash = "sha256:4d047db3662418d4a848a3fdbfaf17488b34b62f527ed6f10cb8afd78135bc5c"}, | ||||||
| ] | ] | ||||||
|  |  | ||||||
| [[package]] | [[package]] | ||||||
| @@ -3885,4 +3885,4 @@ pgsql = ["psycopg2-binary"] | |||||||
| [metadata] | [metadata] | ||||||
| lock-version = "2.1" | lock-version = "2.1" | ||||||
| python-versions = ">=3.12,<3.13" | python-versions = ">=3.12,<3.13" | ||||||
| content-hash = "2b8479e18ef741f5254b8c9d64566bf42d597cfb6564c1aa622f6a1afb117402" | content-hash = "632cd8ef199c2668bc799a1cf4f370161dc13ff7dcf76ed40f3c94a0896e304f" | ||||||
|   | |||||||
| @@ -69,7 +69,7 @@ pylint = "^3.0.0" | |||||||
| pytest = "^8.0.0" | pytest = "^8.0.0" | ||||||
| pytest-asyncio = "^1.0.0" | pytest-asyncio = "^1.0.0" | ||||||
| rich = "^14.0.0" | rich = "^14.0.0" | ||||||
| ruff = "^0.11.0" | ruff = "^0.12.0" | ||||||
| types-PyYAML = "^6.0.4" | types-PyYAML = "^6.0.4" | ||||||
| types-python-dateutil = "^2.8.18" | types-python-dateutil = "^2.8.18" | ||||||
| types-python-slugify = "^6.0.0" | types-python-slugify = "^6.0.0" | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user