database abstraction

This commit is contained in:
Hayden 2021-01-10 18:13:49 -09:00
commit 275ab47857
32 changed files with 494 additions and 216 deletions

View file

@ -21,7 +21,7 @@ new Vue({
}).$mount("#app");
// Truncate
let filter = function (text, length, clamp) {
let filter = function(text, length, clamp) {
clamp = clamp || "...";
let node = document.createElement("div");
node.innerHTML = text;
@ -32,5 +32,3 @@ let filter = function (text, length, clamp) {
Vue.filter("truncate", filter);
export { router };

View file

@ -1,10 +1,9 @@
from pathlib import Path
import uvicorn
from fastapi import FastAPI
from fastapi.staticfiles import StaticFiles
import startup
from global_scheduler import start_scheduler
from routes import (
backup_routes,
meal_routes,
@ -14,10 +13,12 @@ from routes import (
static_routes,
user_routes,
)
from services.settings_services import Colors, SiteTheme
from settings import PORT, PRODUCTION, WEB_PATH, docs_url, redoc_url
from utils.logger import logger
startup.pre_start()
# start_scheduler()
app = FastAPI(
title="Mealie",
@ -48,6 +49,10 @@ def invalid_api():
app.include_router(static_routes.router)
# Generate API Documentation
if not PRODUCTION:
startup.generate_api_docs(app)

View file

@ -0,0 +1,45 @@
{
"_default": {
"1": {
"name": "Chicken and Rice With Leeks and Salsa Verde",
"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",
"recipeYield": "4 Servings",
"recipeIngredient": [
"1\u00bd lb. skinless, boneless chicken thighs (4\u20138 depending on size)",
"Kosher salt, freshly ground pepper",
"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": "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": "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": "Drizzle remaining lemon juice over chicken and rice. Serve with salsa verde."
}
],
"totalTime": "None",
"slug": "chicken-and-rice-with-leeks-and-salsa-verde",
"categories": [],
"tags": [],
"dateAdded": null,
"notes": [],
"rating": null,
"orgURL": "https://www.bonappetit.com/recipe/chicken-and-rice-with-leeks-and-salsa-verde",
"extras": {}
}
}
}

View file

@ -1,18 +1,95 @@
{
"name": "Carottes Rapp\u00e9s with Rice and Sunflower Seeds \u2014 FEED THE SWIMMERS",
"description": " Carottes R\u00e2p\u00e9es with Rice and Sunflower Seeds thanks to @think_rice and @thefeedfeed. Carottes R\u00e2p\u00e9es is a classic French Salad found ready to go (think picnic) at every charcuterie and on most cafe menus. This is one of those insanely simple salads that explode with flavor! The carrots ar",
"image": "carottes-rappes-with-rice-and-sunflower-seeds-feed-the-swimmers.JPG?format=1500w",
"recipeYield": "",
"@context": "http://schema.org",
"@type": "Recipe",
"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",
"chicken recipes",
"kosher salt",
"black pepper",
"butter",
"leek",
"lemon zest",
"rice",
"chicken broth",
"anchovy",
"garlic",
"capers",
"herb",
"olive oil",
"healthyish",
"web"
],
"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",
"name": "Bon App\u00e9tit",
"logo": {
"@type": "ImageObject",
"url": "https://www.bonappetit.com/verso/static/bon-appetit/assets/logo-seo.328de564b950e3d5d1fbe3e42f065290ca1d3844.png",
"width": "479px",
"height": "100px"
},
"url": "https://www.bonappetit.com"
},
"isPartOf": {
"@type": [
"CreativeWork",
"Product"
],
"name": "Bon App\u00e9tit"
},
"isAccessibleForFree": true,
"author": [
{
"@type": "Person",
"name": "Deb Perelman",
"sameAs": "https://bon-appetit.com/contributor/deb-perelman/"
}
],
"aggregateRating": {
"@type": "AggregateRating",
"ratingValue": 4.02,
"ratingCount": 48
},
"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": [
"Could not detect ingredients"
"1\u00bd lb. skinless, boneless chicken thighs (4\u20138 depending on size)",
"Kosher salt, freshly ground pepper",
"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": "Could not detect instructions"
"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": "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": "Drizzle remaining lemon juice over chicken and rice. Serve with salsa verde."
}
],
"slug": "carottes-rappes-with-rice-and-sunflower-seeds-feed-the-swimmers",
"orgURL": "https://www.feedtheswimmers.com/blog/2019/6/5/carottes-rapps-with-rice-and-sunflower-seeds",
"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,

BIN
mealie/data/mealie.sqlite Normal file

Binary file not shown.

108
mealie/db/db_setup.py Normal file
View file

@ -0,0 +1,108 @@
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
"""
if USE_TINYDB:
from db.tinydb.tinydb_setup import TinyDatabase
tiny_db = TinyDatabase()
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
def get(self, match_value: str, match_key: str = None, limit=1) -> dict:
if USE_MONGO:
return self._document.objects.get(match_key=match_value).limit(limit)
elif USE_TINYDB:
return self.store.get(match_value, match_key)
def save_new(self, document: dict) -> str:
if USE_MONGO:
self._document = self._document(**document)
self._document.save()
return self._document.slug
elif USE_TINYDB:
return self.store.save(document)
def update(self) -> dict:
if USE_MONGO:
pass
elif USE_TINYDB:
pass
def delete(self) -> dict:
if USE_MONGO:
pass
elif USE_TINYDB:
pass
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
pass
class _Meals(BaseDocument):
def __init__(self) -> None:
self.primary_key = "uid"
if USE_TINYDB:
self.store = tiny_db.meals
self.document = MealPlanDocument
pass
class _Settings(BaseDocument):
def __init__(self) -> None:
self.primary_key = "name"
if USE_TINYDB:
self.store = tiny_db.settings
self.document = SiteSettingsDocument
pass
class _Themes(BaseDocument):
def __init__(self) -> None:
self.primary_key = "name"
if USE_TINYDB:
self.store = tiny_db.themes
self.document = SiteThemeDocument
pass
db = Database()

View file

@ -1,5 +1,4 @@
import datetime
import uuid
import mongoengine
@ -19,7 +18,7 @@ class RecipeDocument(mongoengine.Document):
slug = mongoengine.StringField(required=True, unique=True)
categories = mongoengine.ListField(default=[])
tags = mongoengine.ListField(default=[])
dateAdded = mongoengine.DateTimeField(binary=True, default=datetime.date.today())
dateAdded = mongoengine.DateTimeField(binary=True, default=datetime.date.today)
notes = mongoengine.ListField(default=[])
rating = mongoengine.IntField(required=True, default=0)
orgURL = mongoengine.URLField(required=False)

View file

@ -0,0 +1,6 @@
# import mongoengine
# class User(mongoengine.Document):
# username: mongoengine.EmailField()
# password: mongoengine.ReferenceField

View file

@ -1,26 +0,0 @@
from pathlib import Path
import sqlalchemy as sa
import sqlalchemy.orm as orm
from settings import SQLITE
factory = None
def global_init(db_file: Path):
if not SQLITE:
pass
global factory
if factory:
return
if not db_file or not db_file.strip:
raise Exception("You must Specif a db file")
conn_str = "sqlite:///" + db_file.absolute()
engine = sa.create_engine(conn_str, echo=False)
factory = orm.sessionmaker(bind=engine)

View file

@ -1,4 +0,0 @@
import sqlalchemy.ext.declarative as dec
SqlAlchemyBase = dec.declarative_base()

View file

@ -1,28 +0,0 @@
import mongoengine
import sqlalchemy as sa
from db.sql.model_base import SqlAlchemyBase
class RecipeSQLModel(SqlAlchemyBase):
__tablename__ = "recipes"
name = sa.Column(sa.String, primar_key=True)
description = sa.Column(sa.String)
image = sa.Column(sa.String)
recipeYield = sa.Column(sa.String)
recipeIngredient = mongoengine.ListField(required=True, default=[])
recipeInstructions = mongoengine.ListField(requiredd=True, default=[])
totalTime = sa.Column(sa.String)
# Mealie Specific
slug = sa.Column(sa.String)
categories = mongoengine.ListField(default=[])
tags = mongoengine.ListField(default=[])
dateAdded = mongoengine.DateTimeField(binary=True, default=datetime.date.today())
notes = mongoengine.ListField(default=[])
rating = sa.Column(sa.Integer)
orgURL = sa.Column(sa.String)
extras = mongoengine.DictField(required=False)
def __repr__(self):
return f"SQL Entry Recipe {self.name}"

View file

@ -0,0 +1,64 @@
from tinydb import Query, TinyDB, where
class StoreBase:
def __init__(self) -> None:
self.store: TinyDB
self.primary_key: str
def save(self, document: dict) -> str:
data = self.store.search(
Query()[self.primary_key] == document[self.primary_key]
)
if data != []:
raise Exception(
f"Cannot save document. Primary Key: {self.primary_key} already exists"
)
else:
return self.store.upsert(
document, Query()[self.primary_key] == document[self.primary_key]
)
def delete(self, document_primary_key: str):
self.store.remove(where(self.primary_key) == document_primary_key)
def get(self, value: str, key: str = None, limit: int = None) -> list or dict:
"""Retrieves an entry from the database matching the key/value provided.
If no key is provided the classes primary_key will be used instead
Args: \n
key (str, optional): Key to match against. Defaults to None. \n
value (str, optional): Value the key should contain. Defaults to None. \n
limit (int, optional): The limit of returned objects If 1 a single item is returned. If None all objects are returned. Defaults to None. \n
Returns:
list or dict: a List if limit is greater than 1
"""
if key == None:
key = self.primary_key
data = self.store.search(Query()[key] == value)
if limit == 1:
return data[0]
if limit:
return data[:limit]
else:
return data
def update_doc(self, id, document):
data: dict = self.get(self.primary_key, id, limit=1)
if data:
if data[self.primary_key] == document[self.primary_key]:
data.update(document)
else:
self.delete(id)
return self.save(document)
elif not data:
raise Exception(
f"Document'{document[self.primary_key]}' does not exists and cannot be updated. "
)

View file

@ -0,0 +1,32 @@
from db.tinydb.baseclass import StoreBase
from settings import TINYDB_DIR
from tinydb import TinyDB
class TinyDatabase:
def __init__(self) -> None:
self.recipes = self._Recipes()
self.meals = self._Meals()
self.settings = self._Settings()
self.themes = self._Themes()
class _Recipes(StoreBase):
def __init__(self) -> None:
self.primary_key = "slug"
self.store = TinyDB(TINYDB_DIR.joinpath("recipes.json"))
class _Meals(StoreBase):
def __init__(self) -> None:
self.primary_key = "uid"
self.store = TinyDB(TINYDB_DIR.joinpath("meals.json"))
class _Settings(StoreBase):
def __init__(self) -> None:
self.primary_key = "name"
self.store = TinyDB(TINYDB_DIR.joinpath("settings.json"))
class _Themes(StoreBase):
def __init__(self) -> None:
self.primary_key = "name"
self._store = TinyDB(TINYDB_DIR.joinpath("themes.json"))

View file

@ -1,6 +0,0 @@
import mongoengine
class User(mongoengine.Document):
username: mongoengine.EmailField()
# password: mongoengine.ReferenceField

View file

@ -0,0 +1,8 @@
from services.scheduler_services import Scheduler
scheduler = None
def start_scheduler():
global scheduler
scheduler = Scheduler()
scheduler.startup_scheduler()

View file

@ -1,7 +1,7 @@
from fastapi import APIRouter, HTTPException
from global_scheduler import scheduler
from services.scheduler_services import post_webhooks
from services.settings_services import SiteSettings, SiteTheme
from startup import scheduler
from utils.snackbar import SnackResponse
router = APIRouter()

14
mealie/scratch.py Normal file
View file

@ -0,0 +1,14 @@
from db.tinydb.tinydb_setup import TinyDatabase
db = TinyDatabase()
test_object = {"name": "dan", "job": "programmer"}
test_object_2 = {"name": "jennifer", "job": "programmer"}
test_object_3 = {"name": "steve", "job": "programmer"}
db.recipes.delete("jennifer")
db.recipes.delete("dan")
db.recipes.save(test_object)
db.recipes.save(test_object_2)
db.recipes.update_doc("dan", test_object_3)

View file

@ -4,7 +4,7 @@ import zipfile
from datetime import datetime
from pathlib import Path
from db.recipe_models import RecipeDocument
from db.mongo.recipe_models import RecipeDocument
from jinja2 import Template
from utils.logger import logger

View file

@ -3,7 +3,7 @@ from datetime import date, timedelta
from pathlib import Path
from typing import List, Optional
from db.meal_models import MealDocument, MealPlanDocument
from db.mongo.meal_models import MealDocument, MealPlanDocument
from pydantic import BaseModel
from services.recipe_services import Recipe

View file

@ -3,7 +3,8 @@ import json
from pathlib import Path
from typing import Any, List, Optional
from db.recipe_models import RecipeDocument
from db.db_setup import db
from db.mongo.recipe_models import RecipeDocument
from pydantic import BaseModel, validator
from slugify import slugify
@ -114,10 +115,9 @@ class Recipe(BaseModel):
except:
pass
recipeDoc = RecipeDocument(**recipe_dict)
recipeDoc.save()
recipe_slug = db.recipes.save_new(recipe_dict)
return recipeDoc.slug
return recipe_slug
@staticmethod
def delete(recipe_slug: str) -> str:

View file

@ -85,6 +85,12 @@ def process_recipe_data(new_recipe: dict, url=None) -> dict:
def extract_recipe_from_html(html: str, url: str) -> dict:
scraped_recipes: List[dict] = scrape_schema_recipe.loads(html, python_objects=True)
if not scraped_recipes:
scraped_recipes: List[dict] = scrape_schema_recipe.scrape_url(
url, python_objects=True
)
if scraped_recipes:
new_recipe: dict = scraped_recipes[0]
logger.info(f"Recipe Scraped From Web: {new_recipe}")

View file

@ -1,13 +1,11 @@
import json
from typing import List, Optional
from db.settings_models import (
SiteSettingsDocument,
SiteThemeDocument,
ThemeColorsDocument,
WebhooksDocument,
)
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):
@ -45,12 +43,15 @@ class SiteSettings(BaseModel):
@staticmethod
def get_site_settings():
try:
document = SiteSettingsDocument.objects.get(name="main")
except:
webhooks = WebhooksDocument()
document = SiteSettingsDocument(name="main", webhooks=webhooks)
document.save()
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()
return SiteSettings._unpack_doc(document)
@ -95,14 +96,23 @@ class SiteTheme(BaseModel):
@staticmethod
def get_by_name(theme_name):
document = SiteThemeDocument.objects.get(name=theme_name)
if USE_TINYDB:
theme = Query()
document = tinydb.themes.search(theme.name == theme_name)
else:
document = SiteThemeDocument.objects.get(name=theme_name)
return SiteTheme._unpack_doc(document)
@staticmethod
def _unpack_doc(document):
document = json.loads(document.to_json())
del document["_id"]
theme_colors = SiteTheme(**document)
if USE_TINYDB:
theme_colors = SiteTheme(**document)
else:
document = json.loads(document.to_json())
del document["_id"]
theme_colors = SiteTheme(**document)
return theme_colors
@staticmethod
@ -114,6 +124,15 @@ class SiteTheme(BaseModel):
return all_themes
def save_to_db(self):
if USE_TINYDB:
self._save_to_tinydb()
else:
self._save_to_mongo()
def _save_to_tinydb(self):
tinydb.themes.insert(self.dict())
def _save_to_mongo(self):
theme = self.dict()
theme["colors"] = ThemeColorsDocument(**theme["colors"])
@ -140,3 +159,37 @@ class SiteTheme(BaseModel):
if document:
document.delete()
return "Document Deleted"
def default_theme_init():
default_colors = {
"primary": "#E58325",
"accent": "#00457A",
"secondary": "#973542",
"success": "#5AB1BB",
"info": "#4990BA",
"warning": "#FF4081",
"error": "#EF5350",
}
if USE_TINYDB:
theme = Query()
item = tinydb.themes.search(theme.name == "default")
print(item)
if item == []:
logger.info("Generating Default Theme")
colors = Colors(**default_colors)
default_theme = SiteTheme(name="default", colors=colors)
default_theme.save_to_db()
else:
try:
SiteTheme.get_by_name("default")
return "default theme exists"
except:
logger.info("Generating Default Theme")
colors = Colors(**default_colors)
default_theme = SiteTheme(name="default", colors=colors)
default_theme.save_to_db()
# default_theme_init()

View file

@ -17,8 +17,19 @@ BACKUP_DIR = DATA_DIR.joinpath("backups")
DEBUG_DIR = DATA_DIR.joinpath("debug")
MIGRATION_DIR = DATA_DIR.joinpath("migration")
TEMPLATE_DIR = DATA_DIR.joinpath("templates")
TINYDB_DIR = DATA_DIR.joinpath("db")
TEMP_DIR = DATA_DIR.joinpath("temp")
REQUIRED_DIRS = [
DATA_DIR,
IMG_DIR,
BACKUP_DIR,
DEBUG_DIR,
MIGRATION_DIR,
TEMPLATE_DIR,
TINYDB_DIR,
]
# General
PRODUCTION = os.environ.get("ENV")
@ -34,14 +45,13 @@ else:
# DATABASE ENV
DATABASE_TYPE = os.getenv("db_type", "mongo") # mongo, sqlite
SQLITE = False
MONGO = False
if DATABASE_TYPE == "sqlite":
SQLITE = True
SQLITE_DB_FILE = DATA_DIR.joinpath("mealie.sqlite")
DATABASE_TYPE = os.getenv("db_type", "mongo") # mongo, tinydb
USE_TINYDB = False
USE_MONGO = False
if DATABASE_TYPE == "tinydb":
USE_TINYDB = True
elif DATABASE_TYPE == "mongo":
MONGO = True
USE_MONGO = True
else:
raise Exception(
"Unable to determine database type. Acceptible options are 'mongo' or 'sqlite' "

View file

@ -1,61 +1,23 @@
import json
from pathlib import Path
from db.mongo_setup import global_init as mongo_global_init
from db.sql.db_session import global_init as sql_global_init
from services.scheduler_services import Scheduler
from services.settings_services import Colors, SiteTheme
from settings import DATA_DIR, MONGO, SQLITE
from utils.logger import logger
from db.tinydb.tinydb_setup import TinyDatabase
from settings import REQUIRED_DIRS, USE_MONGO, USE_TINYDB
CWD = Path(__file__).parent
scheduler = None
def pre_start():
if SQLITE:
from settings import SQLITE_DB_FILE
sql_global_init(SQLITE_DB_FILE)
elif MONGO:
mongo_global_init()
global scheduler
scheduler = Scheduler()
scheduler.startup_scheduler()
ensure_dirs()
generate_default_theme()
def ensure_dirs():
DATA_DIR.mkdir(parents=True, exist_ok=True)
DATA_DIR.joinpath("img").mkdir(parents=True, exist_ok=True)
DATA_DIR.joinpath("backups").mkdir(parents=True, exist_ok=True)
DATA_DIR.joinpath("templates").mkdir(parents=True, exist_ok=True)
DATA_DIR.joinpath("debug").mkdir(parents=True, exist_ok=True)
def generate_default_theme():
default_colors = {
"primary": "#E58325",
"accent": "#00457A",
"secondary": "#973542",
"success": "#5AB1BB",
"info": "#4990BA",
"warning": "#FF4081",
"error": "#EF5350",
}
try:
SiteTheme.get_by_name("default")
return "default theme exists"
except:
logger.info("Generating Default Theme")
colors = Colors(**default_colors)
default_theme = SiteTheme(name="default", colors=colors)
default_theme.save_to_db()
for dir in REQUIRED_DIRS:
dir.mkdir(parents=True, exist_ok=True)
"""Script to export the ReDoc documentation page into a standalone HTML file."""

View file

@ -1,79 +1,25 @@
aiofiles==0.5.0
aniso8601==7.0.0
appdirs==1.4.4
APScheduler==3.6.3
astroid==2.4.2
apscheduler==3.6.3
async-exit-stack==1.0.1
async-generator==1.10
attrs==20.3.0
beautifulsoup4==4.9.1
black==20.8b1
certifi==2020.6.20
chardet==3.0.4
click==7.1.2
colorama==0.4.3
decorator==4.4.2
dnspython==2.0.0
email-validator==1.1.1
extruct==0.10.0
fastapi==0.61.1
fastapi-login==1.5.1
gitpython==3.1.11
graphene==2.1.8
graphql-core==2.3.2
graphql-relay==2.0.1
h11==0.9.0
html-text==0.5.2
html5lib==1.1
httptools==0.1.1
idna==2.10
iniconfig==1.1.1
isodate==0.6.0
isort==5.4.2
itsdangerous==1.1.0
Jinja2==2.11.2
jstyleson==0.0.2
lazy-object-proxy==1.4.3
lxml==4.5.2
MarkupSafe==1.1.1
mccabe==0.6.1
mf2py==1.1.2
mongoengine==0.21.0
mypy-extensions==0.4.3
packaging==20.8
pathspec==0.8.0
pluggy==0.13.1
promise==2.3
py==1.10.0
pydantic==1.6.1
nltk==3.5
pdfkit==0.6.1
pip-chill==1.0.0
pylint==2.6.0
pymongo==3.11.1
pyparsing==2.4.7
pytest==6.2.1
python-dateutil==2.8.1
python-dotenv==0.15.0
python-multipart==0.0.5
python-slugify==4.0.1
pytz==2020.4
PyYAML==5.3.1
rdflib==4.2.2
rdflib-jsonld==0.5.0
regex==2020.11.13
requests==2.24.0
Rx==1.6.1
scrape-schema-recipe==0.1.1
six==1.15.0
soupsieve==2.0.1
starlette==0.13.6
text-unidecode==1.3
toml==0.10.1
typed-ast==1.4.1
typing-extensions==3.7.4.3
tzlocal==2.1
sqlalchemy==1.3.22
ujson==3.1.0
urllib3==1.25.10
uvicorn==0.11.8
uvloop==0.14.0
validators==0.18.0
w3lib==1.22.0
webencodings==0.5.1
websockets==8.1
wrapt==1.12.1
uvicorn==0.11.8

View file

@ -5,6 +5,7 @@ APScheduler==3.6.3
astroid==2.4.2
async-exit-stack==1.0.1
async-generator==1.10
attrs==20.3.0
beautifulsoup4==4.9.1
black==20.8b1
certifi==2020.6.20
@ -16,6 +17,7 @@ dnspython==2.0.0
email-validator==1.1.1
extruct==0.10.0
fastapi==0.61.1
fastapi-login==1.5.1
future==0.18.2
gitdb==4.0.5
GitPython==3.1.11
@ -27,6 +29,7 @@ html-text==0.5.2
html5lib==1.1
httptools==0.1.1
idna==2.10
iniconfig==1.1.1
isodate==0.6.0
isort==5.4.2
itsdangerous==1.1.0
@ -36,7 +39,7 @@ jstyleson==0.0.2
lazy-object-proxy==1.4.3
livereload==2.6.3
lunr==0.5.8
lxml>=4.6.2
lxml==4.6.2
Markdown==3.3.3
MarkupSafe==1.1.1
mccabe==0.6.1
@ -47,10 +50,14 @@ mkdocs-material-extensions==1.0.1
mongoengine==0.21.0
mypy-extensions==0.4.3
nltk==3.5
packaging==20.8
passlib==1.7.4
pathspec==0.8.0
pdfkit==0.6.1
pip-chill==1.0.0
pluggy==0.13.1
promise==2.3
py==1.10.0
pydantic==1.6.1
Pygments==2.7.3
PyJWT==1.7.1
@ -58,6 +65,7 @@ pylint==2.6.0
pymdown-extensions==8.0.1
pymongo==3.11.1
pyparsing==2.4.7
pytest==6.2.1
python-dateutil==2.8.1
python-dotenv==0.15.0
python-multipart==0.0.5
@ -73,6 +81,7 @@ scrape-schema-recipe==0.1.1
six==1.15.0
smmap==3.0.4
soupsieve==2.0.1
SQLAlchemy==1.3.22
starlette==0.13.6
text-unidecode==1.3
toml==0.10.1