start settings migration

This commit is contained in:
Hayden 2021-01-11 17:39:37 -09:00
commit 7285c9ce06
43 changed files with 391 additions and 337 deletions

11
.vscode/settings.json vendored
View file

@ -8,13 +8,8 @@
"python.testing.unittestEnabled": false,
"python.testing.nosetestsEnabled": false,
"python.discoverTest": true,
"python.testing.cwd": "./mealie/tests",
"python.testing.pytestEnabled": true,
"cSpell.enableFiletypes": [
"!javascript",
"!python"
],
"python.testing.pytestArgs": [
"mealie"
]
"cSpell.enableFiletypes": ["!javascript", "!python"],
"python.testing.pytestArgs": ["mealie/test/"]
}

View file

@ -1,33 +1,29 @@
{
"@context": "http://schema.org",
"@type": "Recipe",
"articleBody": "With plenty of protein, a double punch of acid from citrus and vinegar, and a garlicky chili oil, this salad is made for dinner. While your chicken is getting toasty in the oven, make your chile crisp-inspired dressing with garlic, paprika, cracked coriander, and red pepper flakes. If you have leftovers (or want to make extra for a bit of meal prep), keep all of your ingredients separate in the fridge so that they stay fresher for longer. \u00a0This recipe is part of the 2021\u00a0Feel Good Food Plan, our eight-day dinner plan for starting the year off right.",
"alternativeHeadline": "With plenty of protein, a double punch of acid from citrus and vinegar, and a garlicky chili oil, this salad is made for dinner.",
"dateModified": "2021-01-11 11:51:19.699000",
"datePublished": "2021-01-01 06:00:00",
"articleBody": "\u201cAfter a draining day juggling work, homeschooling, and urging children to stop using their masks as slingshots, the ideal food for me isn\u2019t perfectly prepared food that\u2019s been tweezered into position, but a meal that\u2019s simply comforting,\u201d writes the Smitten Kitchen\u2019s Deb Perelman. Right now, it\u2019s this deeply cozy pot of tender chicken thighs, jammy leeks, and broth-soaked rice.",
"alternativeHeadline": "This one-skillet dinner gets deep oniony flavor from lots of leeks cooked down to jammy tenderness.",
"dateModified": "2021-01-10 15:20:51.422000",
"datePublished": "2020-08-18 04:00:00",
"keywords": [
"recipes",
"healthyish",
"salad",
"chicken recipes",
"kosher salt",
"pepper",
"olive oil",
"black pepper",
"butter",
"leek",
"lemon zest",
"rice",
"chicken broth",
"anchovy",
"garlic",
"paprika",
"coriander",
"endive",
"radicchio",
"blood orange",
"orange",
"vinegar",
"red wine vinegar",
"sesame seed",
"feel good food plan",
"feel good food plan 2021",
"capers",
"herb",
"olive oil",
"healthyish",
"web"
],
"thumbnailUrl": "https://assets.bonappetit.com/photos/5fdbe110607088d75a57bc54/1:1/w_3142,h_3142,c_limit/BA0221coverfinal01_rev.jpg",
"thumbnailUrl": "https://assets.bonappetit.com/photos/5f29796456f43685a49327fb/1:1/w_1125,h_1125,c_limit/Chicken-and-Rice-With-Leeks-Salsa-Verde-01.jpg",
"publisher": {
"@context": "https://schema.org",
"@type": "Organization",
@ -51,57 +47,49 @@
"author": [
{
"@type": "Person",
"name": "Devonn Francis",
"sameAs": "https://bon-appetit.com/contributor/devonn-francis/"
"name": "Deb Perelman",
"sameAs": "https://bon-appetit.com/contributor/deb-perelman/"
}
],
"aggregateRating": {
"@type": "AggregateRating",
"ratingValue": 4.89,
"ratingCount": 12
"ratingValue": 4.02,
"ratingCount": 48
},
"description": "With plenty of protein, a double punch of acid from citrus and vinegar, and a garlicky chili oil, this salad is made for dinner.",
"image": "chicken-salad-with-citrus-and-chile-oil.jpg",
"headline": "Chicken Salad With Citrus and Chile Oil",
"name": "Chicken Salad With Citrus and Chile Oil",
"description": "This one-skillet dinner gets deep oniony flavor from lots of leeks cooked down to jammy tenderness.",
"image": "chicken-and-rice-with-leeks-and-salsa-verde.jpg",
"headline": "Chicken and Rice With Leeks and Salsa Verde",
"name": "Chicken and Rice With Leeks and Salsa Verde",
"recipeIngredient": [
"3 skin-on, bone-in chicken breasts\u00a0 (about 1\u00bd lb. total)",
"1\u00bd lb. skinless, boneless chicken thighs (4\u20138 depending on size)",
"Kosher salt, freshly ground pepper",
"2 Tbsp. plus \u2153 cup extra-virgin olive oil",
"3 garlic cloves, thinly sliced",
"2 tsp. paprika",
"1 tsp. coriander seeds, coarsely\u00a0crushed",
"\u00bd tsp. crushed red pepper flakes",
"2 medium endive, leaves separated",
"1 large head of radicchio, leaves\u00a0 separated, torn if large",
"4 satsumas or blood oranges or 3 medium oranges, peeled, sliced into rounds, seeds removed",
"2 Tbsp. white wine vinegar or red wine vinegar",
"2 tsp. toasted sesame seeds, lightly crushed"
"3 Tbsp. unsalted butter, divided",
"2 large or 3 medium leeks, white and pale green parts only, halved lengthwise, thinly sliced",
"Zest and juice of 1 lemon, divided",
"1\u00bd cups long-grain white rice, rinsed until water runs clear",
"2\u00be cups low-sodium chicken broth",
"1 oil-packed anchovy fillet",
"2 garlic cloves",
"1 Tbsp. drained capers",
"Crushed red pepper flakes",
"1 cup tender herb leaves (such as parsley, cilantro, and/or mint)",
"4\u20135 Tbsp. extra-virgin olive oil"
],
"recipeInstructions": [
{
"text": "Preheat oven to 450\u00b0. Pat chicken breasts dry with paper towels; season on all sides with salt and pepper, then rub with 2 Tbsp. oil."
"text": "Season chicken with salt and pepper. Melt 2 Tbsp. butter in a large high-sided skillet over medium-high heat. Add leeks and half of lemon zest, season with salt and pepper, and mix to coat leeks in butter. Reduce heat to medium-low, cover, and cook, stirring occasionally, until leeks are somewhat tender, about 5 minutes. Remove lid, increase heat to medium-high, and cook, stirring occasionally, until tender and just starting to take on color, about 3 minutes. Add rice and cook, stirring often, 3 minutes, then add broth, scraping up any browned bits. Tuck short sides of each chicken thigh underneath so they are touching and nestle seam side down into rice mixture. Bring to a simmer. Cover, reduce heat to medium-low, and cook until rice is tender and chicken is cooked through, about 20 minutes. Remove from heat. Cut remaining 1 Tbsp. butter into small pieces and scatter over mixture. Re-cover and let sit 10 minutes."
},
{
"text": "Heat a large ovenproof skillet over medium-high. Arrange chicken, skin side down, in pan and cook, undisturbed, until skin is deep golden brown, about 3 minutes. Turn chicken over with tongs and transfer skillet to oven. Roast chicken until cooked all the way through, 15\u201317 minutes. Transfer to a cutting board and let cool 10 minutes."
"text": "Meanwhile, pulse anchovy, garlic, capers, a few pinches of red pepper flakes, and remaining lemon zest in a food processor until finely chopped. Add herbs; process until a paste forms. With motor running, gradually stream in oil until loosened to a thick sauce. Add half of lemon juice; season salsa verde with salt."
},
{
"text": "Meanwhile, cook garlic and remaining \u2153 cup oil in a small skillet over medium heat, stirring occasionally, until garlic is fragrant and pale golden, about 4 minutes. Immediately pour garlic oil into a small bowl and stir in paprika, coriander seeds, and red pepper flakes; season with salt."
},
{
"text": "Cut chicken off the bone, then slice\u00a0 \u00bd\" thick; discard bones."
},
{
"text": "Toss endive, radicchio, and satsumas with vinegar and half of spiced garlic oil in a large bowl to combine; season salad with salt and pepper."
},
{
"text": "Divide salad among plates or shallow bowls; top with chicken and drizzle with more spiced garlic oil. Sprinkle sesame seeds over."
"text": "Drizzle remaining lemon juice over chicken and rice. Serve with salsa verde."
}
],
"recipeYield": "4 servings",
"url": "https://www.bonappetit.com/recipe/chicken-salad-with-citrus-and-chile-oil",
"slug": "chicken-salad-with-citrus-and-chile-oil",
"orgURL": "https://www.bonappetit.com/recipe/chicken-salad-with-citrus-and-chile-oil",
"recipeYield": "4 Servings",
"url": "https://www.bonappetit.com/recipe/chicken-and-rice-with-leeks-and-salsa-verde",
"slug": "chicken-and-rice-with-leeks-and-salsa-verde",
"orgURL": "https://www.bonappetit.com/recipe/chicken-and-rice-with-leeks-and-salsa-verde",
"categories": [],
"tags": [],
"dateAdded": null,

Binary file not shown.

Before

Width:  |  Height:  |  Size: 519 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 371 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 259 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 794 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 572 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 528 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 452 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 212 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 393 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 556 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 317 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 309 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 650 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 889 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 294 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 602 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 184 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 788 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 664 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 985 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 154 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 413 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 184 KiB

36
mealie/db/database.py Normal file
View file

@ -0,0 +1,36 @@
from db.db_mealplan import _Meals
from db.db_recipes import _Recipes
from db.db_settings import _Settings
from db.db_themes import _Themes
"""
Common Actions:
- [ ] Create
- [ ] Read
- [ ] Update
- [ ] Delete
- [ ] Unpack Document Mongo Mostly.
- [ ] Query by Primary Key
Recipe Actions
- [ ] Query by Category
- [ ] Query by dateAdded
Progress:
- [x] Recipes
- [ ] MealPlans
- [ ] Site Settings
- [ ] Themes
"""
class Database:
def __init__(self) -> None:
self.recipes = _Recipes()
self.meals = _Meals()
self.settings = _Settings()
self.themes = _Themes()
db = Database()

109
mealie/db/db_base.py Normal file
View file

@ -0,0 +1,109 @@
import json
import mongoengine
from settings import USE_MONGO, USE_TINYDB
from db.tinydb.baseclass import StoreBase
class BaseDocument:
def __init__(self) -> None:
self.primary_key: str
self.store: StoreBase
self.document: mongoengine.Document
@staticmethod
def _unpack_mongo(document) -> dict: # TODO: Probably Put a version in each class to speed up reads?
document = json.loads(document.to_json())
del document["_id"]
# Recipe Cleanup
try:
document["dateAdded"] = document["dateAdded"]["$date"]
except:
pass
try:
document["uid"] = document["uid"]["$uuid"]
except:
pass
# Meal Plan
try:
document["startDate"] = document["startDate"]["$date"]
document["endDate"] = document["endDate"]["$date"]
meals = []
for meal in document["meals"]:
meal["date"] = meal["date"]["$date"]
meals.append(meal)
document["meals"] = meals
except:
pass
return document
def get_all(self, limit: int = None, order_by: str = "dateAdded"):
if USE_MONGO:
documents = self.document.objects.order_by(str(order_by)).limit(limit)
docs = []
for item in documents:
doc = BaseDocument._unpack_mongo(item)
docs.append(doc)
if limit == 1:
return docs[0]
return docs
elif USE_TINYDB:
return self.store.get_all()
def get(
self, match_value: str, match_key: str = None, limit=1
) -> dict or list[dict]:
"""Retrieves an entry from the database by matching a key/value pair. If no
key is provided the class objects primary key will be used to match against.
Args: \n
match_value (str): A value used to match against the key/value in the database \n
match_key (str, optional): They key to match the value against. Defaults to None. \n
limit (int, optional): A limit to returned responses. Defaults to 1. \n
Returns:
dict or list[dict]:
"""
if match_key == None:
match_key = self.primary_key
if USE_MONGO:
document = self.document.objects.get(**{str(match_key): match_value})
db_entry = BaseDocument._unpack_mongo(document)
elif USE_TINYDB:
db_entry = self.store.get(match_value, match_key, limit=limit)
else:
raise Exception("No database type established")
if limit == 1 and type(db_entry) == list:
return db_entry[0]
else:
return db_entry
def save_new(self, document: dict) -> str:
if USE_MONGO:
new_document = self.document(**document)
new_document.save()
return new_document
elif USE_TINYDB:
return self.store.save(document)
def delete(self, primary_key) -> dict:
if USE_MONGO:
document = self.document.objects.get(**{str(self.primary_key): primary_key})
if document:
document.delete()
elif USE_TINYDB:
self.store.delete(primary_key)

59
mealie/db/db_mealplan.py Normal file
View file

@ -0,0 +1,59 @@
from typing import List
from settings import USE_MONGO, USE_TINYDB
from db.db_base import BaseDocument
from db.db_setup import USE_MONGO, USE_TINYDB, tiny_db
from db.mongo.meal_models import MealDocument, MealPlanDocument
class _Meals(BaseDocument):
def __init__(self) -> None:
self.primary_key = "uid"
if USE_TINYDB:
self.store = tiny_db.meals
self.document = MealPlanDocument
@staticmethod
def _process_meals(meals: List[dict]) -> List[MealDocument]:
"""Turns a list of Meals in dictionary form into a list of
MealDocuments that can be attached to a MealPlanDocument
Args: \n
meals (List[dict]): From a Pydantic Class in meal_services.py \n
Returns:
a List of MealDocuments
"""
meal_docs = []
for meal in meals:
meal_doc = MealDocument(**meal)
meal_docs.append(meal_doc)
return meal_docs
def save_new(self, plan_data: dict) -> None:
"""Saves a new meal plan into the database
Args: \n
plan_data (dict): From a Pydantic Class in meal_services.py \n
"""
if USE_MONGO:
plan_data["meals"] = _Meals._process_meals(plan_data["meals"])
document = self.document(**plan_data)
document.save()
elif USE_TINYDB:
pass
def update(self, uid: str, plan_data: dict) -> dict:
if USE_MONGO:
document = self.document.objects.get(uid=uid)
if document:
new_meals = _Meals._process_meals(plan_data["meals"])
document.update(set__meals=new_meals)
document.save()
elif USE_TINYDB:
pass

51
mealie/db/db_recipes.py Normal file
View file

@ -0,0 +1,51 @@
from settings import USE_MONGO, USE_TINYDB
from db.db_base import BaseDocument
from db.db_setup import tiny_db
from db.mongo.recipe_models import RecipeDocument
class _Recipes(BaseDocument):
def __init__(self) -> None:
self.primary_key = "slug"
if USE_TINYDB:
self.store = tiny_db.recipes
self.document = RecipeDocument
def update(self, slug: str, new_data: dict) -> None:
if USE_MONGO:
document = self.document.objects.get(slug=slug)
if document:
document.update(set__name=new_data.get("name"))
document.update(set__description=new_data.get("description"))
document.update(set__image=new_data.get("image"))
document.update(set__recipeYield=new_data.get("recipeYield"))
document.update(set__recipeIngredient=new_data.get("recipeIngredient"))
document.update(
set__recipeInstructions=new_data.get("recipeInstructions")
)
document.update(set__totalTime=new_data.get("totalTime"))
document.update(set__slug=new_data.get("slug"))
document.update(set__categories=new_data.get("categories"))
document.update(set__tags=new_data.get("tags"))
document.update(set__notes=new_data.get("notes"))
document.update(set__orgURL=new_data.get("orgURL"))
document.update(set__rating=new_data.get("rating"))
document.update(set__extras=new_data.get("extras"))
document.save()
return new_data.get("slug")
elif USE_TINYDB:
self.store.update_doc(slug, new_data)
return new_data.get("slug")
def update_image(self, slug: str, extension: str) -> None:
if USE_MONGO:
document = self.document.objects.get(slug=slug)
if document:
document.update(set__image=f"{slug}.{extension}")
elif USE_TINYDB:
self.store.update_doc(slug, {"image": f"{slug}.{extension}"})

36
mealie/db/db_settings.py Normal file
View file

@ -0,0 +1,36 @@
from settings import USE_MONGO, USE_TINYDB
from db.db_base import BaseDocument
from db.db_setup import USE_MONGO, USE_TINYDB, tiny_db
from db.mongo.settings_models import SiteSettingsDocument, WebhooksDocument
class _Settings(BaseDocument):
def __init__(self) -> None:
self.primary_key = "name"
if USE_TINYDB:
self.store = tiny_db.settings
self.document = SiteSettingsDocument
def save_new(self, main: dict, webhooks: dict) -> str:
if USE_MONGO:
main["webhooks"] = WebhooksDocument(**webhooks)
new_doc = self.document(**main)
return new_doc.save()
elif USE_TINYDB:
main["webhooks"] = webhooks
return self.store.save(main)
def update(self, name: str, new_data: dict) -> dict:
if USE_MONGO:
document = self.document.objects.get(name=name)
if document:
document.update(set__webhooks=WebhooksDocument(**new_data["webhooks"]))
document.save()
elif USE_TINYDB:
pass

View file

@ -1,37 +1,9 @@
import json
from typing import List
import mongoengine
from settings import USE_MONGO, USE_TINYDB
from db.mongo.meal_models import MealDocument, MealPlanDocument
from db.mongo.recipe_models import RecipeDocument
from db.mongo.settings_models import SiteSettingsDocument, SiteThemeDocument
from db.tinydb.baseclass import StoreBase
"""
Common Actions:
- [ ] Create
- [ ] Read
- [ ] Update
- [ ] Delete
- [ ] Unpack Document Mongo Mostly.
- [ ] Query by Primary Key
Recipe Actions
- [ ] Query by Category
- [ ] Query by dateAdded
Progress:
- [x] Recipes
- [ ] MealPlans
- [ ] Site Settings
- [ ] Themes
"""
from db.tinydb.tinydb_setup import TinyDatabase
tiny_db: TinyDatabase = None
if USE_TINYDB:
from db.tinydb.tinydb_setup import TinyDatabase
tiny_db = TinyDatabase()
@ -39,194 +11,3 @@ elif USE_MONGO:
from db.mongo.mongo_setup import global_init as mongo_global_init
mongo_global_init()
class BaseDocument:
def __init__(self) -> None:
self.primary_key: str
self.store: StoreBase
self.document: mongoengine.Document
@staticmethod
def _unpack_mongo(document) -> dict:
document = json.loads(document.to_json())
del document["_id"]
# Recipe Cleanup
try:
document["dateAdded"] = document["dateAdded"]["$date"]
except:
pass
try:
document["uid"] = document["uid"]["$uuid"]
except:
pass
# Meal Plan
try:
document["startDate"] = document["startDate"]["$date"]
document["endDate"] = document["endDate"]["$date"]
meals = []
for meal in document["meals"]:
meal["date"] = meal["date"]["$date"]
meals.append(meal)
document["meals"] = meals
except:
pass
return document
def get_all(self, limit: int = None, order_by: str = "dateAdded") -> list[dict]:
if USE_MONGO:
documents = self.document.objects.order_by(str(order_by)).limit(limit)
docs = []
for item in documents:
doc = BaseDocument._unpack_mongo(item)
docs.append(doc)
if limit == 1:
return docs[0]
return docs
elif USE_TINYDB:
return self.store.get_all()
def get(self, match_value: str, match_key: str = None, limit=1) -> dict:
if USE_MONGO:
document = self.document.objects.get(**{str(match_key): match_value})
return BaseDocument._unpack_mongo(document)
elif USE_TINYDB:
return self.store.get(match_value, match_key, limit=limit)
def save_new(self, document: dict) -> str:
if USE_MONGO:
new_document = self.document(**document)
new_document.save()
return new_document
elif USE_TINYDB:
return self.store.save(document)
def delete(self, primary_key) -> dict:
if USE_MONGO:
document = self.document.objects.get(**{str(self.primary_key): primary_key})
if document:
document.delete()
return "Document Deleted"
elif USE_TINYDB:
self.store.delete(primary_key)
class Database:
def __init__(self) -> None:
self.recipes = self._Recipes()
self.meals = self._Meals()
self.settings = self._Settings()
self.themes = self._Themes()
class _Recipes(BaseDocument):
def __init__(self) -> None:
self.primary_key = "slug"
if USE_TINYDB:
self.store = tiny_db.recipes
self.document = RecipeDocument
def update(self, slug: str, new_data: dict) -> None:
if USE_MONGO:
document = self.document.objects.get(slug=slug)
if document:
document.update(set__name=new_data.get("name"))
document.update(set__description=new_data.get("description"))
document.update(set__image=new_data.get("image"))
document.update(set__recipeYield=new_data.get("recipeYield"))
document.update(
set__recipeIngredient=new_data.get("recipeIngredient")
)
document.update(
set__recipeInstructions=new_data.get("recipeInstructions")
)
document.update(set__totalTime=new_data.get("totalTime"))
document.update(set__slug=new_data.get("slug"))
document.update(set__categories=new_data.get("categories"))
document.update(set__tags=new_data.get("tags"))
document.update(set__notes=new_data.get("notes"))
document.update(set__orgURL=new_data.get("orgURL"))
document.update(set__rating=new_data.get("rating"))
document.update(set__extras=new_data.get("extras"))
document.save()
return new_data.get("slug")
elif USE_TINYDB:
self.store.update_doc(slug, new_data)
return new_data.get("slug")
def update_image(self, slug: str, extension: str) -> None:
if USE_MONGO:
document = self.document.objects.get(slug=slug)
if document:
document.update(set__image=f"{slug}.{extension}")
elif USE_TINYDB:
self.store.update_doc(slug, {"image": f"{slug}.{extension}"})
class _Meals(BaseDocument):
def __init__(self) -> None:
self.primary_key = "uid"
if USE_TINYDB:
self.store = tiny_db.meals
self.document = MealPlanDocument
def update(self, uid: str, new_meals: List[MealDocument]) -> dict:
if USE_MONGO:
document = self.document.objects.get(uid=uid)
if document:
document.update(set__meals=new_meals)
document.save()
elif USE_TINYDB:
pass
class _Settings(BaseDocument):
def __init__(self) -> None:
self.primary_key = "name"
if USE_TINYDB:
self.store = tiny_db.settings
self.document = SiteSettingsDocument
def save_new(self, main: dict, webhooks: dict) -> str:
if USE_MONGO:
new_doc = self.document(**main)
return new_doc.save()
elif USE_TINYDB:
main["webhooks"] = webhooks
return self.store.save(main)
def update(self, key: str, new_data: dict) -> dict:
if USE_MONGO:
pass
elif USE_TINYDB:
pass
class _Themes(BaseDocument):
def __init__(self) -> None:
self.primary_key = "name"
if USE_TINYDB:
self.store = tiny_db.themes
self.document = SiteThemeDocument
def update(self, key: str, new_data: dict) -> dict:
if USE_MONGO:
pass
elif USE_TINYDB:
pass
db = Database()

19
mealie/db/db_themes.py Normal file
View file

@ -0,0 +1,19 @@
from settings import USE_MONGO, USE_TINYDB
from db.db_base import BaseDocument
from db.db_setup import USE_MONGO, USE_TINYDB, tiny_db
from db.mongo.settings_models import SiteThemeDocument
class _Themes(BaseDocument):
def __init__(self) -> None:
self.primary_key = "name"
if USE_TINYDB:
self.store = tiny_db.themes
self.document = SiteThemeDocument
def update(self, key: str, new_data: dict) -> dict:
if USE_MONGO:
pass
elif USE_TINYDB:
pass

View file

@ -3,8 +3,7 @@ from datetime import date, timedelta
from pathlib import Path
from typing import List, Optional
from db.db_setup import db
from db.mongo.meal_models import MealDocument
from db.database import db
from pydantic import BaseModel
from services.recipe_services import Recipe
@ -81,14 +80,6 @@ class MealPlan(BaseModel):
self.meals = meals
def save_to_db(self):
meal_docs = []
for meal in self.meals:
meal = meal.dict()
meal_doc = MealDocument(**meal)
meal_docs.append(meal_doc)
self.meals = meal_docs
db.meals.save_new(self.dict())
@staticmethod
@ -99,14 +90,7 @@ class MealPlan(BaseModel):
return all_meals
def update(self, uid):
meal_docs = []
for meal in self.meals:
meal = meal.dict()
meal_doc = MealDocument(**meal)
meal_docs.append(meal_doc)
db.meals.update(uid, meal_docs)
db.meals.update(uid, self.dict())
@staticmethod
def delete(uid):
@ -117,11 +101,7 @@ class MealPlan(BaseModel):
""" Returns the meal slug for Today """
meal_plan = db.meals.get_all(limit=1, order_by="startDate")
meal_docs = []
for meal in meal_plan["meals"]:
print(meal)
meal_doc = Meal(**meal)
meal_docs.append(meal_doc)
meal_docs = [Meal(**meal) for meal in meal_plan["meals"]]
for meal in meal_docs:
if meal.date == date.today():

View file

@ -3,7 +3,7 @@ import json
from pathlib import Path
from typing import Any, List, Optional
from db.db_setup import db
from db.database import db
from pydantic import BaseModel, validator
from slugify import slugify

View file

@ -1,21 +1,22 @@
import json
from typing import List, Optional
from db.mongo.settings_models import (SiteSettingsDocument, SiteThemeDocument,
ThemeColorsDocument, WebhooksDocument)
from db.database import db
from db.mongo.settings_models import (
SiteSettingsDocument,
SiteThemeDocument,
ThemeColorsDocument,
WebhooksDocument,
)
from pydantic import BaseModel
from startup import USE_TINYDB
from utils.logger import logger
class Webhooks(BaseModel):
webhookTime: str
webhookURLs: Optional[List[str]]
enabled: bool
@staticmethod
def run():
pass
webhookTime: str = "00:00"
webhookURLs: Optional[List[str]] = []
enabled: bool = "false"
class SiteSettings(BaseModel):
@ -43,25 +44,18 @@ class SiteSettings(BaseModel):
@staticmethod
def get_site_settings():
if USE_TINYDB:
document = tinydb.settings.get("main")
else:
try:
document = SiteSettingsDocument.objects.get(name="main")
except:
webhooks = WebhooksDocument()
document = SiteSettingsDocument(name="main", webhooks=webhooks)
document.save()
try:
document = db.settings.get("main")
except:
webhooks = Webhooks()
default_entry = SiteSettings(name="main", webhooks=webhooks)
document = db.settings.save_new(default_entry.dict(), webhooks.dict())
return SiteSettings._unpack_doc(document)
return SiteSettings(**document)
def update(self):
document = SiteSettingsDocument.objects.get(name="main")
new_webhooks = WebhooksDocument(**self.webhooks.dict())
document.update(set__webhooks=new_webhooks)
document.save()
db.settings.update(name="main", new_data=self.dict())
class Colors(BaseModel):

2
mealie/test/conftest.py Normal file
View file

@ -0,0 +1,2 @@
from pytest import fixture

4
mealie/test/pytest.ini Normal file
View file

@ -0,0 +1,4 @@
[pytest]
python_files = test_*
python_classes = *Tests
python_functions = test_*

View file

View file

@ -11,8 +11,8 @@ from services.migrations.nextcloud import (
from services.recipe_services import Recipe
CWD = Path(__file__).parent
NEXTCLOUD_DIR = CWD.joinpath("data", "nextcloud_recipes")
TEMP_NEXTCLOUD = CWD.parent.joinpath("data", "temp", "nextcloud")
NEXTCLOUD_DIR = CWD.parent.joinpath("data", "nextcloud_recipes")
TEMP_NEXTCLOUD = CWD.parent.parent.joinpath("data", "temp", "nextcloud")
@pytest.mark.parametrize(
@ -39,5 +39,5 @@ def test_zip_extraction(file_name: str, final_path: Path):
)
def test_nextcloud_migration(recipe_dir: Path):
recipe = import_recipes(recipe_dir)
assert type(recipe) == Recipe
assert isinstance(recipe, Recipe)
IMG_DIR.joinpath(recipe.image).unlink(missing_ok=True)

View file

View file

@ -10,8 +10,8 @@ from services.scrape_services import (
)
CWD = Path(__file__).parent
RAW_RECIPE_DIR = CWD.joinpath("data", "recipes-raw")
RAW_HTML_DIR = CWD.joinpath("data", "html-raw")
RAW_RECIPE_DIR = CWD.parent.joinpath("data", "recipes-raw")
RAW_HTML_DIR = CWD.parent.joinpath("data", "html-raw")
# https://github.com/django/django/blob/stable/1.3.x/django/core/validators.py#L45
url_validation_regex = re.compile(