Compare commits

...

6 Commits

Author SHA1 Message Date
Michael Genson
216ae8571c fix: Include unmade recipes when filtering by last made (#7130) 2026-02-23 18:34:16 -06:00
renovate[bot]
02d32c8905 fix(deps): update dependency openai to v2.22.0 (#7128)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-02-23 22:15:25 +00:00
Hayden
7e0d083e77 chore(l10n): New Crowdin updates (#7126) 2026-02-23 18:21:38 +00:00
mealie-actions[bot]
b3cea081fe chore(auto): Update pre-commit hooks (#7122)
Co-authored-by: boc-the-git <3479092+boc-the-git@users.noreply.github.com>
2026-02-23 14:07:02 +00:00
renovate[bot]
d79252752b fix(deps): update dependency fastapi to v0.131.0 (#7113)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-02-22 22:44:02 +00:00
Hayden
b3c214d102 chore(l10n): New Crowdin updates (#7119) 2026-02-22 22:43:45 +00:00
14 changed files with 196 additions and 150 deletions

View File

@@ -12,7 +12,7 @@ repos:
exclude: ^tests/data/
- repo: https://github.com/astral-sh/ruff-pre-commit
# Ruff version.
rev: v0.15.1
rev: v0.15.2
hooks:
- id: ruff
- id: ruff-format

View File

@@ -79,8 +79,8 @@ This filter will find all foods that are not named "carrot": <br>
##### Keyword Filters
The API supports many SQL keywords, such as `IS NULL` and `IN`, as well as their negations (e.g. `IS NOT NULL` and `NOT IN`).
Here is an example of a filter that returns all recipes where the "last made" value is not null: <br>
`lastMade IS NOT NULL`
Here is an example of a filter that returns all shopping list items without a food: <br>
`foodId IS NULL`
This filter will find all recipes that don't start with the word "Test": <br>
`name NOT LIKE "Test%"`

View File

@@ -1423,8 +1423,8 @@
"is-greater-than-or-equal-to": "jest większe lub równe",
"is-less-than": "jest mniejsze niż",
"is-less-than-or-equal-to": "jest mniejsze lub równe",
"is-older-than": "is older than",
"is-newer-than": "is newer than"
"is-older-than": "jest starsze niż",
"is-newer-than": "jest nowsze niż"
},
"relational-keywords": {
"is": "jest",
@@ -1436,7 +1436,7 @@
"is-not-like": "nie jest jak"
},
"dates": {
"days-ago": "days ago|day ago|days ago"
"days-ago": "dni temu|dzień temu|dni temu"
}
},
"validators": {

View File

@@ -212,8 +212,8 @@
"upload-file": "Enviar arquivo",
"created-on-date": "Criado em {0}",
"unsaved-changes": "Você possui alterações não salvas. Deseja salvar antes de sair? Ok para salvar, Cancelar para descartar alterações.",
"discard-changes": "Discard Changes",
"discard-changes-description": "You have unsaved changes. Are you sure you want to discard them?",
"discard-changes": "Descartar alterações",
"discard-changes-description": "Você tem alterações não salvas. Tem certeza de que deseja descartá-las?",
"clipboard-copy-failure": "Falha ao copiar para a área de transferência.",
"confirm-delete-generic-items": "Tem certeza que quer excluir os itens seguintes?",
"organizers": "Organizadores",
@@ -644,7 +644,7 @@
"scrape-recipe-website-being-blocked": "Site sendo bloqueado?",
"scrape-recipe-try-importing-raw-html-instead": "Tente importar o HTML ao invés disso.",
"import-original-keywords-as-tags": "Importar palavras-chave originais como marcadores",
"import-original-categories": "Import original categories",
"import-original-categories": "Importar categorias originais",
"stay-in-edit-mode": "Permanecer no modo de edição",
"parse-recipe-ingredients-after-import": "Interpretar os ingredientes da receita após importar",
"import-from-zip": "Importar do .zip",
@@ -1423,7 +1423,7 @@
"is-greater-than-or-equal-to": "é maior ou igual a",
"is-less-than": "é menor que",
"is-less-than-or-equal-to": "é menor ou igual a",
"is-older-than": "is older than",
"is-older-than": "Mais antigo que",
"is-newer-than": "is newer than"
},
"relational-keywords": {

View File

@@ -1,5 +1,6 @@
import re as re
from collections.abc import Iterable, Sequence
from datetime import UTC, datetime
from random import randint
from typing import Self, cast
from uuid import UUID
@@ -51,10 +52,13 @@ class RepositoryRecipes(HouseholdRepositoryGeneric[Recipe, RecipeModel]):
return self
def _get_last_made_col_alias(self) -> sa.ColumnElement | None:
"""Computed last_made which uses `HouseholdToRecipe.last_made` for the user's household, otherwise None"""
"""
Computed last_made which uses `HouseholdToRecipe.last_made` for the user's household,
otherwise an arbitrarily low date
"""
user_household_subquery = sa.select(User.household_id).where(User.id == self.user_id).scalar_subquery()
return (
last_made_subquery = (
sa.select(HouseholdToRecipe.last_made)
.where(
HouseholdToRecipe.recipe_id == self.model.id,
@@ -63,6 +67,7 @@ class RepositoryRecipes(HouseholdRepositoryGeneric[Recipe, RecipeModel]):
.correlate(self.model)
.scalar_subquery()
)
return sa.func.coalesce(last_made_subquery, datetime(year=1900, month=1, day=1, tzinfo=UTC))
def _get_rating_col_alias(self) -> sa.ColumnElement | None:
"""Computed rating which uses the user's rating if it exists, otherwise falling back to the recipe's rating"""

View File

@@ -2494,25 +2494,25 @@
"aliases": [],
"description": "",
"name": "Backstein Käse",
"plural_name": "brick cheese"
"plural_name": "Brick-Käse"
},
"quick-melt cheese": {
"aliases": [],
"description": "",
"name": "quick-melt cheese",
"plural_name": "quick-melt cheese"
"name": "schnellschmelzender Käse",
"plural_name": "schnellschmelzender Käse"
},
"farmer's cheese": {
"aliases": [],
"description": "",
"name": "farmer's cheese",
"plural_name": "farmer's cheese"
"name": "Bauernkäse",
"plural_name": "Bauernkäse"
},
"manouri cheese": {
"aliases": [],
"description": "",
"name": "manouri cheese",
"plural_name": "manouri cheese"
"plural_name": "Manouri se"
},
"mimolette cheese": {
"aliases": [],
@@ -7670,7 +7670,7 @@
"aliases": [],
"description": "",
"name": "Backpulver",
"plural_name": "baking powder"
"plural_name": "Backpulver"
},
"baking soda": {
"aliases": [],

View File

@@ -5,7 +5,7 @@
"aliases": [],
"description": "",
"name": "fokhagyma",
"plural_name": "garlic"
"plural_name": "fokhagyma"
},
"onion": {
"aliases": [],
@@ -59,13 +59,13 @@
"aliases": [],
"description": "",
"name": "zeller",
"plural_name": "celery"
"plural_name": "zeller"
},
"jalapeño": {
"aliases": [],
"description": "",
"name": "jalapeño",
"plural_name": "jalapeños"
"name": "jalapeno",
"plural_name": "jalapeno"
},
"avocado": {
"aliases": [],
@@ -95,13 +95,13 @@
"aliases": [],
"description": "",
"name": "spenót",
"plural_name": "spinach"
"plural_name": "spenót"
},
"sweet corn": {
"aliases": [],
"description": "",
"name": "csemegekukorica",
"plural_name": "sweet corn"
"plural_name": "csemegekukorica"
},
"chile pepper": {
"aliases": [
@@ -121,7 +121,7 @@
"aliases": [],
"description": "",
"name": "brokkoli",
"plural_name": "broccoli"
"plural_name": "brokkoli"
},
"heart of palm": {
"aliases": [],
@@ -132,8 +132,8 @@
"baby greens": {
"aliases": [],
"description": "",
"name": "baby greens",
"plural_name": "baby greens"
"name": "salátakeverék",
"plural_name": "salátakeverék"
},
"pumpkin": {
"aliases": [],
@@ -145,7 +145,7 @@
"aliases": [],
"description": "",
"name": "karfiol",
"plural_name": "cauliflower"
"plural_name": "karfiol"
},
"cabbage": {
"aliases": [],
@@ -156,20 +156,20 @@
"asparagus": {
"aliases": [],
"description": "",
"name": "asparagus",
"plural_name": "asparagus"
"name": "spárga",
"plural_name": "spárga"
},
"kale": {
"aliases": [],
"description": "",
"name": "kelkáposzta",
"plural_name": "kale"
"plural_name": "kelkáposzta"
},
"arugula": {
"aliases": [],
"description": "",
"name": "rukkola",
"plural_name": "arugula"
"plural_name": "rukkola"
},
"leek": {
"aliases": [],
@@ -187,7 +187,7 @@
"aliases": [],
"description": "",
"name": "saláta",
"plural_name": "lettuce"
"plural_name": "fejes saláta"
},
"butternut squash": {
"aliases": [],
@@ -198,8 +198,8 @@
"romaine lettuce": {
"aliases": [],
"description": "",
"name": "romaine lettuce",
"plural_name": "romaine lettuce"
"name": "római saláta",
"plural_name": "római saláta"
},
"beetroot": {
"aliases": [],
@@ -217,7 +217,7 @@
"aliases": [],
"description": "",
"name": "édeskömény",
"plural_name": "fennel"
"plural_name": "édeskömény"
},
"sun dried tomato": {
"aliases": [],
@@ -261,8 +261,8 @@
"mixed greens": {
"aliases": [],
"description": "",
"name": "mixed greens",
"plural_name": "mixed greens"
"name": "salátakeverék",
"plural_name": "salátakeverék"
},
"parsnip": {
"aliases": [],
@@ -279,8 +279,8 @@
"mixed vegetables": {
"aliases": [],
"description": "",
"name": "mixed vegetables",
"plural_name": "mixed vegetables"
"name": "zöldségkeverék",
"plural_name": "zöldségkeverék"
},
"poblano pepper": {
"aliases": [],
@@ -304,7 +304,7 @@
"aliases": [],
"description": "",
"name": "cayenne bors",
"plural_name": "cayenne pepper"
"plural_name": "cayenne bors"
},
"green tomato": {
"aliases": [],
@@ -321,8 +321,8 @@
"iceberg lettuce": {
"aliases": [],
"description": "",
"name": "iceberg lettuce",
"plural_name": "iceberg lettuce"
"name": "jégsaláta",
"plural_name": "jégsaláta"
},
"mashed potato": {
"aliases": [],
@@ -340,13 +340,13 @@
"aliases": [],
"description": "",
"name": "mángold",
"plural_name": "chard"
"plural_name": "mángold"
},
"pimiento": {
"aliases": [],
"description": "",
"name": "kápia paprika",
"plural_name": "pimientos"
"plural_name": "kápia paprika"
},
"spaghetti squash": {
"aliases": [],
@@ -358,7 +358,7 @@
"aliases": [],
"description": "",
"name": "fejes saláta",
"plural_name": "butter lettuce"
"plural_name": "kötözősaláta"
},
"hash brown": {
"aliases": [],
@@ -419,8 +419,8 @@
"corn on the cob": {
"aliases": [],
"description": "",
"name": "corn on the cob",
"plural_name": "corn on the cob"
"name": "csöves kukorica",
"plural_name": "csöves kukorica"
},
"radicchio": {
"aliases": [],
@@ -438,7 +438,7 @@
"aliases": [],
"description": "",
"name": "brokkolini",
"plural_name": "tenderstem broccoli"
"plural_name": "bébi brokkoli"
},
"plantain": {
"aliases": [],
@@ -450,7 +450,7 @@
"aliases": [],
"description": "",
"name": "saláta",
"plural_name": "leaf lettuce"
"plural_name": "saláta"
},
"pepperoncini": {
"aliases": [],
@@ -484,11 +484,11 @@
},
"maize": {
"aliases": [
"corn husk"
"kukoricacsuhé"
],
"description": "",
"name": "maize",
"plural_name": "maize"
"name": "csemegekukorica",
"plural_name": "csemegekukorica"
},
"collard greens": {
"aliases": [],
@@ -3140,13 +3140,13 @@
"aliases": [],
"description": "",
"name": "kókusztej",
"plural_name": "coconut milk"
"plural_name": "kókusztej"
},
"almond milk": {
"aliases": [],
"description": "",
"name": "mandulatej",
"plural_name": "almond milk"
"plural_name": "mandulatej"
},
"almond butter": {
"aliases": [],
@@ -3182,7 +3182,7 @@
"aliases": [],
"description": "",
"name": "szójatej",
"plural_name": "soy milk"
"plural_name": "szójatej"
},
"extra firm tofu": {
"aliases": [],

View File

@@ -487,8 +487,8 @@
"łuska kukurydzy"
],
"description": "",
"name": "maize",
"plural_name": "maize"
"name": "kukurydza",
"plural_name": "kukurydza"
},
"collard greens": {
"aliases": [],
@@ -554,7 +554,7 @@
"aliases": [],
"description": "",
"name": "sałata masłowa",
"plural_name": "boston lettuce"
"plural_name": "sałata masłowa"
},
"kohlrabi": {
"aliases": [],
@@ -598,7 +598,7 @@
"aliases": [],
"description": "",
"name": "surówka z brokułów",
"plural_name": "broccoli slaw"
"plural_name": "surówka z brokułów"
},
"arbol chile pepper": {
"aliases": [],
@@ -974,7 +974,7 @@
"aliases": [],
"description": "",
"name": "pomelo",
"plural_name": "pomelos"
"plural_name": "pomelo"
},
"chestnut purée": {
"aliases": [],

View File

@@ -5,7 +5,7 @@
"aliases": [],
"description": "",
"name": "alho",
"plural_name": "garlic"
"plural_name": "alho"
},
"onion": {
"aliases": [],
@@ -59,7 +59,7 @@
"aliases": [],
"description": "",
"name": "salsão",
"plural_name": "celery"
"plural_name": "aipo"
},
"jalapeño": {
"aliases": [],

View File

@@ -101,7 +101,7 @@
"aliases": [],
"description": "",
"name": "milho doce",
"plural_name": "sweet corn"
"plural_name": "milho doce"
},
"chile pepper": {
"aliases": [
@@ -280,7 +280,7 @@
"aliases": [],
"description": "",
"name": "mixed vegetables",
"plural_name": "mixed vegetables"
"plural_name": "mistura de vegetais"
},
"poblano pepper": {
"aliases": [],
@@ -1671,8 +1671,8 @@
"chokeberry": {
"aliases": [],
"description": "",
"name": "chokeberry",
"plural_name": "chokeberries"
"name": "arónia",
"plural_name": "arónias"
},
"loganberry": {
"aliases": [],
@@ -1717,7 +1717,7 @@
"walnut": {
"aliases": [],
"description": "",
"name": "walnut",
"name": "noz",
"plural_name": "walnuts"
},
"pecan": {
@@ -1783,8 +1783,8 @@
"pumpkin seed": {
"aliases": [],
"description": "",
"name": "pumpkin seed",
"plural_name": "pumpkin seeds"
"name": "semente de abóbora",
"plural_name": "sementes de abóbora"
},
"hazelnut": {
"aliases": [],
@@ -1801,8 +1801,8 @@
"sunflower seed": {
"aliases": [],
"description": "",
"name": "sunflower seed",
"plural_name": "sunflower seeds"
"name": "semente de girassol",
"plural_name": "sementes de girassol"
},
"macadamia": {
"aliases": [],
@@ -1813,8 +1813,8 @@
"roasted peanut": {
"aliases": [],
"description": "",
"name": "roasted peanut",
"plural_name": "roasted peanuts"
"name": "amendoim torrado",
"plural_name": "amendoins torrados"
},
"chopped nut": {
"aliases": [],
@@ -2003,22 +2003,22 @@
"parmesan cheese": {
"aliases": [],
"description": "",
"name": "parmesan cheese",
"name": "queijo parmesão",
"plural_name": "parmesan cheese"
},
"cheddar cheese": {
"aliases": [
"cheddar cheese"
"queijo cheddar"
],
"description": "",
"name": "cheddar cheese",
"plural_name": "cheddar cheese"
"name": "queijo cheddar",
"plural_name": "queijos cheddar"
},
"cream cheese": {
"aliases": [],
"description": "",
"name": "cream cheese",
"plural_name": "cream cheese"
"name": "queijo creme",
"plural_name": "queijo creme"
},
"sharp cheddar cheese": {
"aliases": [
@@ -2031,26 +2031,26 @@
"cheese": {
"aliases": [],
"description": "",
"name": "cheese",
"plural_name": "cheese"
"name": "queijo",
"plural_name": "queijos"
},
"mozzarella cheese": {
"aliases": [],
"description": "",
"name": "mozzarella cheese",
"plural_name": "mozzarella cheese"
"name": "queijo mozzarella",
"plural_name": "queijos mozzarella"
},
"feta cheese": {
"aliases": [],
"description": "",
"name": "feta cheese",
"plural_name": "feta cheese"
"name": "queijo feta",
"plural_name": "queijos feta"
},
"ricotta cheese": {
"aliases": [],
"description": "",
"name": "ricotta cheese",
"plural_name": "ricotta cheese"
"name": "queijo ricotta",
"plural_name": "queijos ricotta"
},
"cheddar-jack cheese": {
"aliases": [],
@@ -2139,8 +2139,8 @@
"brie cheese": {
"aliases": [],
"description": "",
"name": "brie cheese",
"plural_name": "brie cheese"
"name": "queijo brie",
"plural_name": "queijos brie"
},
"paneer cheese": {
"aliases": [],
@@ -2617,26 +2617,26 @@
"butter": {
"aliases": [],
"description": "",
"name": "butter",
"plural_name": "butter"
"name": "manteiga",
"plural_name": "manteigas"
},
"egg": {
"aliases": [],
"description": "",
"name": "egg",
"plural_name": "eggs"
"name": "ovo",
"plural_name": "ovos"
},
"milk": {
"aliases": [],
"description": "",
"name": "milk",
"plural_name": "milk"
"name": "leite",
"plural_name": "leites"
},
"heavy cream": {
"aliases": [],
"description": "",
"name": "heavy cream",
"plural_name": "heavy cream"
"name": "nata",
"plural_name": "natas"
},
"sour cream": {
"aliases": [],
@@ -2691,8 +2691,8 @@
"condensed milk": {
"aliases": [],
"description": "",
"name": "condensed milk",
"plural_name": "condensed milk"
"name": "leite condensado",
"plural_name": "leites condensados"
},
"half and half": {
"aliases": [],
@@ -2703,20 +2703,20 @@
"sweetened condensed milk": {
"aliases": [],
"description": "",
"name": "sweetened condensed milk",
"plural_name": "sweetened condensed milk"
"name": "leite condensado açucarado",
"plural_name": "leites condensados açucarados"
},
"ice cream": {
"aliases": [],
"description": "",
"name": "ice cream",
"plural_name": "ice cream"
"name": "gelado",
"plural_name": "gelados"
},
"margarine": {
"aliases": [],
"description": "",
"name": "margarine",
"plural_name": "margarines"
"name": "margarina",
"plural_name": "margarinas"
},
"creme fraiche": {
"aliases": [],
@@ -2757,8 +2757,8 @@
"dulce de leche": {
"aliases": [],
"description": "",
"name": "dulce de leche",
"plural_name": "dulce de leche"
"name": "doce de leite",
"plural_name": "doces de leite"
},
"custard": {
"aliases": [],
@@ -2787,8 +2787,8 @@
"chocolate milk": {
"aliases": [],
"description": "",
"name": "chocolate milk",
"plural_name": "chocolate milk"
"name": "leite achocolatado",
"plural_name": "leites achocolatados"
},
"liquid egg substitute": {
"aliases": [],
@@ -3325,8 +3325,8 @@
"vegan sausage": {
"aliases": [],
"description": "",
"name": "vegan sausage",
"plural_name": "vegan sausages"
"name": "salsicha vegan",
"plural_name": "salsichas vegan"
},
"coconut whipped cream": {
"aliases": [],
@@ -3373,8 +3373,8 @@
"nut milk": {
"aliases": [],
"description": "",
"name": "nut milk",
"plural_name": "nut milk"
"name": "leite de noz",
"plural_name": "leite de nozes"
},
"non-dairy cream": {
"aliases": [],
@@ -3744,37 +3744,37 @@
"aliases": [],
"description": "",
"name": "bacon",
"plural_name": "bacons"
"plural_name": "bacon"
},
"chopped bacon": {
"aliases": [],
"description": "",
"name": "chopped bacon",
"plural_name": "chopped bacons"
"name": "bacon",
"plural_name": "bacon"
},
"ground beef": {
"aliases": [],
"description": "",
"name": "ground beef",
"plural_name": "ground beefs"
"name": "carne picada",
"plural_name": "carne picada"
},
"beef steak": {
"aliases": [],
"description": "",
"name": "beef steak",
"plural_name": "beef steaks"
"name": "bife de vaca",
"plural_name": "bifes de vaca"
},
"ham": {
"aliases": [],
"description": "",
"name": "ham",
"plural_name": "hams"
"name": "fiambre",
"plural_name": "fiambres"
},
"pork chop": {
"aliases": [],
"description": "",
"name": "pork chop",
"plural_name": "pork chops"
"name": "costoleta",
"plural_name": "costoletas"
},
"sweet italian sausage": {
"aliases": [],
@@ -3827,8 +3827,8 @@
"chorizo": {
"aliases": [],
"description": "",
"name": "chorizo",
"plural_name": "chorizoes"
"name": "chouriço",
"plural_name": "chouriços"
},
"pancetta": {
"aliases": [],
@@ -3899,8 +3899,8 @@
"deli ham": {
"aliases": [],
"description": "",
"name": "deli ham",
"plural_name": "deli hams"
"name": "fiambre",
"plural_name": "fiambres"
},
"leg of lamb": {
"aliases": [],
@@ -10638,8 +10638,8 @@
"olive oil": {
"aliases": [],
"description": "",
"name": "olive oil",
"plural_name": "olive oil"
"name": "azeite",
"plural_name": "azeite"
},
"vegetable oil": {
"aliases": [],
@@ -10650,8 +10650,8 @@
"extra virgin olive oil": {
"aliases": [],
"description": "",
"name": "extra virgin olive oil",
"plural_name": "extra virgin olive oil"
"name": "azeite extra virgem",
"plural_name": "azeite extra virgem"
},
"canola oil": {
"aliases": [],
@@ -10916,8 +10916,8 @@
"herb-infused olive oil": {
"aliases": [],
"description": "",
"name": "herb-infused olive oil",
"plural_name": "herb-infused olive oil"
"name": "azeite de ervas",
"plural_name": "azeite de ervas"
},
"roasted peanut oil": {
"aliases": [],

View File

@@ -9,7 +9,7 @@
"name": "colher de sopa",
"plural_name": "colheres de sopa",
"description": "",
"abbreviation": "csp"
"abbreviation": "c. sopa"
},
"cup": {
"name": "chávena",
@@ -25,7 +25,7 @@
},
"pint": {
"name": "pint",
"plural_name": "pintas",
"plural_name": "pints",
"description": "",
"abbreviation": "pt"
},
@@ -139,8 +139,8 @@
"abbreviation": ""
},
"sprig": {
"name": "sprig",
"plural_name": "sprigs",
"name": "ramo",
"plural_name": "ramos",
"description": "",
"abbreviation": ""
}

View File

@@ -17,7 +17,7 @@ dependencies = [
"apprise==1.9.7",
"bcrypt==5.0.0",
"extruct==0.18.0",
"fastapi==0.129.1",
"fastapi==0.131.0",
"httpx==0.28.1",
"lxml==6.0.2",
"orjson==3.11.7",
@@ -42,7 +42,7 @@ dependencies = [
"pydantic-settings==2.13.1",
"pillow-heif==1.2.1",
"pyjwt==2.11.0",
"openai==2.21.0",
"openai==2.22.0",
"typing-extensions==4.15.0",
"itsdangerous==2.2.0",
"ingredient-parser-nlp==2.5.0",

View File

@@ -647,6 +647,47 @@ def test_order_by_last_made(unique_user: TestUser, h2_user: TestUser):
assert [item.id for item in h2_query.items] == [recipe_2.id, recipe_1.id]
def test_coalesce_last_made(unique_user: TestUser):
dt = datetime.now(UTC)
made_recipe, unmade_recipe = (
unique_user.repos.recipes.create(
Recipe(user_id=unique_user.user_id, group_id=unique_user.group_id, name=random_string())
)
for _ in range(2)
)
unique_user.repos.household_recipes.create(
HouseholdRecipeCreate(recipe_id=made_recipe.id, household_id=unique_user.household_id, last_made=dt)
)
repos = get_repositories(
unique_user.repos.session, group_id=unique_user.group_id, household_id=None
).recipes.by_user(unique_user.user_id)
r = repos.page_all(
PaginationQuery(
page=1,
per_page=-1,
order_by="last_made",
order_direction=OrderDirection.asc,
query_filter=f"id IN [{made_recipe.id}, {unmade_recipe.id}] AND lastMade <= {dt.isoformat()}",
)
)
assert len(r.items) == 2
assert [item.id for item in r.items] == [unmade_recipe.id, made_recipe.id]
r = repos.page_all(
PaginationQuery(
page=1,
per_page=-1,
order_by="last_made",
order_direction=OrderDirection.desc,
query_filter=f"id IN [{made_recipe.id}, {unmade_recipe.id}]",
)
)
assert len(r.items) == 2
assert [item.id for item in r.items] == [made_recipe.id, unmade_recipe.id]
def test_order_by_rating(user_tuple: tuple[TestUser, TestUser]):
user_1, user_2 = user_tuple
database = user_1.repos

16
uv.lock generated
View File

@@ -399,7 +399,7 @@ wheels = [
[[package]]
name = "fastapi"
version = "0.129.1"
version = "0.131.0"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "annotated-doc" },
@@ -408,9 +408,9 @@ dependencies = [
{ name = "typing-extensions" },
{ name = "typing-inspection" },
]
sdist = { url = "https://files.pythonhosted.org/packages/f6/37/4aa7f6ce92745458b6ce0acd706dde2ac23a3bf341266b5311c904109f67/fastapi-0.129.1.tar.gz", hash = "sha256:6ccf0eca9644e0d6280115b4fc8281bf55ec5878d4d95572f7b2034ab15708ba", size = 369852, upload-time = "2026-02-21T13:10:03.335Z" }
sdist = { url = "https://files.pythonhosted.org/packages/91/32/158cbf685b7d5a26f87131069da286bf10fc9fbf7fc968d169d48a45d689/fastapi-0.131.0.tar.gz", hash = "sha256:6531155e52bee2899a932c746c9a8250f210e3c3303a5f7b9f8a808bfe0548ff", size = 369612, upload-time = "2026-02-22T16:38:11.252Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/01/f9/f15d92bd6035d4f83be8b82dc527a3e7abc87648fda62cf8d1df344410a7/fastapi-0.129.1-py3-none-any.whl", hash = "sha256:022462403bc385b791df418d8f088eb0e8f1fe7cb8f625d682f5e9da6157cc83", size = 103226, upload-time = "2026-02-21T13:10:05.058Z" },
{ url = "https://files.pythonhosted.org/packages/ff/94/b58ec24c321acc2ad1327f69b033cadc005e0f26df9a73828c9e9c7db7ce/fastapi-0.131.0-py3-none-any.whl", hash = "sha256:ed0e53decccf4459de78837ce1b867cd04fa9ce4579497b842579755d20b405a", size = 103854, upload-time = "2026-02-22T16:38:09.814Z" },
]
[[package]]
@@ -910,7 +910,7 @@ requires-dist = [
{ name = "bcrypt", specifier = "==5.0.0" },
{ name = "beautifulsoup4", specifier = "==4.14.3" },
{ name = "extruct", specifier = "==0.18.0" },
{ name = "fastapi", specifier = "==0.129.1" },
{ name = "fastapi", specifier = "==0.131.0" },
{ name = "html2text", specifier = "==2025.4.15" },
{ name = "httpx", specifier = "==0.28.1" },
{ name = "ingredient-parser-nlp", specifier = "==2.5.0" },
@@ -918,7 +918,7 @@ requires-dist = [
{ name = "itsdangerous", specifier = "==2.2.0" },
{ name = "jinja2", specifier = "==3.1.6" },
{ name = "lxml", specifier = "==6.0.2" },
{ name = "openai", specifier = "==2.21.0" },
{ name = "openai", specifier = "==2.22.0" },
{ name = "orjson", specifier = "==3.11.7" },
{ name = "paho-mqtt", specifier = "==1.6.1" },
{ name = "pillow", specifier = "==12.1.1" },
@@ -1143,7 +1143,7 @@ wheels = [
[[package]]
name = "openai"
version = "2.21.0"
version = "2.22.0"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "anyio" },
@@ -1155,9 +1155,9 @@ dependencies = [
{ name = "tqdm" },
{ name = "typing-extensions" },
]
sdist = { url = "https://files.pythonhosted.org/packages/92/e5/3d197a0947a166649f566706d7a4c8f7fe38f1fa7b24c9bcffe4c7591d44/openai-2.21.0.tar.gz", hash = "sha256:81b48ce4b8bbb2cc3af02047ceb19561f7b1dc0d4e52d1de7f02abfd15aa59b7", size = 644374, upload-time = "2026-02-14T00:12:01.577Z" }
sdist = { url = "https://files.pythonhosted.org/packages/73/ed/0a004a42fea6b6f3dd4ab33235183e994a4c7ade214fba10d9494577ec04/openai-2.22.0.tar.gz", hash = "sha256:fc2ea71c79951ac3faf178ff72c766bb4b09c3e9aab277184c5260ab3e94294f", size = 657093, upload-time = "2026-02-23T20:14:31.017Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/cc/56/0a89092a453bb2c676d66abee44f863e742b2110d4dbb1dbcca3f7e5fc33/openai-2.21.0-py3-none-any.whl", hash = "sha256:0bc1c775e5b1536c294eded39ee08f8407656537ccc71b1004104fe1602e267c", size = 1103065, upload-time = "2026-02-14T00:11:59.603Z" },
{ url = "https://files.pythonhosted.org/packages/dc/9a/ac24d606ea7e729475100689a1fe8866fe6cbcd0fd9b93dc4b8324be353d/openai-2.22.0-py3-none-any.whl", hash = "sha256:df02cfb731fe312215d046bf1330030e0f4b70a7b880b96992b1517b0b6aced8", size = 1118913, upload-time = "2026-02-23T20:14:29.546Z" },
]
[[package]]