From 65c86f5dc5a1206c47cde973df637a71fd9a656b Mon Sep 17 00:00:00 2001 From: hay-kot Date: Mon, 29 Mar 2021 10:20:29 -0800 Subject: [PATCH] code-gen scripts --- dev/scripts/api_docs_gen.py | 44 ++++++++++++++ dev/scripts/app_routes_gen.py | 83 +++++++++++++++++++++++++++ dev/scripts/output/app_routes.py | 98 ++++++++++++++++++++++++++++++++ 3 files changed, 225 insertions(+) create mode 100644 dev/scripts/api_docs_gen.py create mode 100644 dev/scripts/app_routes_gen.py create mode 100644 dev/scripts/output/app_routes.py diff --git a/dev/scripts/api_docs_gen.py b/dev/scripts/api_docs_gen.py new file mode 100644 index 000000000..fb5300306 --- /dev/null +++ b/dev/scripts/api_docs_gen.py @@ -0,0 +1,44 @@ +import json + +from mealie.app import app +from mealie.core.config import DATA_DIR + +"""Script to export the ReDoc documentation page into a standalone HTML file.""" + +HTML_TEMPLATE = """ +{% extends "main.html" %} +{% block tabs %} +{{ super() }} + + + + +
+ + + + +{% endblock %} +{% block content %}{% endblock %} +{% block footer %}{% endblock %} +""" + +HTML_PATH = DATA_DIR.parent.parent.joinpath("docs/docs/overrides/api.html") + + +def generate_api_docs(my_app): + with open(HTML_PATH, "w") as fd: + text = HTML_TEMPLATE.replace("MY_SPECIFIC_TEXT", json.dumps(my_app.openapi())) + fd.write(text) + + +if __name__ == "__main__": + generate_api_docs(app) diff --git a/dev/scripts/app_routes_gen.py b/dev/scripts/app_routes_gen.py new file mode 100644 index 000000000..c15267d90 --- /dev/null +++ b/dev/scripts/app_routes_gen.py @@ -0,0 +1,83 @@ +import json +import re +from pathlib import Path +from typing import Optional + +import slugify +from jinja2 import Template +from mealie.app import app +from pydantic import BaseModel + +CWD = Path(__file__).parent +OUT_FILE = CWD.joinpath("output", "app_routes.py") + +code_template = """ +class AppRoutes: + def __init__(self) -> None: + self.prefix = '{{paths.prefix}}' +{% for path in paths.static_paths %} + self.{{ path.router_slug }} = "{{path.prefix}}{{ path.route }}"{% endfor %} +{% for path in paths.function_paths %} + def {{path.router_slug}}(self, {{path.var|join(", ")}}): + return f"{self.prefix}{{ path.route }}" +{% endfor %} +""" + + +def get_variables(path): + path = path.replace("/", " ") + print(path) + var = re.findall(r" \{.*\}", path) + print(var) + if var: + return [v.replace("{", "").replace("}", "") for v in var] + else: + return None + + +class RouteObject: + def __init__(self, route_string) -> None: + self.prefix = "/" + route_string.split("/")[1] + self.route = route_string.replace(self.prefix, "") + self.parts = route_string.split("/")[1:] + self.var = re.findall(r"\{(.*?)\}", route_string) + self.is_function = "{" in self.route + self.router_slug = slugify.slugify("_".join(self.parts[1:]), separator="_") + + def __repr__(self) -> str: + return f"""Route: {self.route} +Parts: {self.parts} +Function: {self.is_function} +Var: {self.var} +Slug: {self.router_slug} +""" + + +def get_paths(app): + paths = [] + print(json.dumps(app.openapi())) + for key, value in app.openapi().items(): + if key == "paths": + for key, value in value.items(): + paths.append(key) + + return paths + + +def generate_template(app): + paths = get_paths(app) + new_paths = [RouteObject(path) for path in paths] + + static_paths = [p for p in new_paths if not p.is_function] + function_paths = [p for p in new_paths if p.is_function] + + template = Template(code_template) + + content = template.render(paths={"prefix": "/api", "static_paths": static_paths, "function_paths": function_paths}) + + with open(OUT_FILE, "w") as f: + f.write(content) + + +if __name__ == "__main__": + generate_template(app) diff --git a/dev/scripts/output/app_routes.py b/dev/scripts/output/app_routes.py new file mode 100644 index 000000000..0d8b15bb9 --- /dev/null +++ b/dev/scripts/output/app_routes.py @@ -0,0 +1,98 @@ + +class AppRoutes: + def __init__(self) -> None: + self.prefix = '/api' + + self.users_sign_ups = "/api/users/sign-ups" + self.auth_token = "/api/auth/token" + self.auth_token_long = "/api/auth/token/long" + self.auth_refresh = "/api/auth/refresh" + self.users = "/api/users" + self.users_self = "/api/users/self" + self.groups = "/api/groups" + self.groups_self = "/api/groups/self" + self.recipes = "/api/recipes" + self.recipes_category = "/api/recipes/category" + self.recipes_tag = "/api/recipes/tag" + self.categories = "/api/categories" + self.recipes_tags = "/api/recipes/tags/" + self.recipes_create = "/api/recipes/create" + self.recipes_create_url = "/api/recipes/create-url" + self.meal_plans_all = "/api/meal-plans/all" + self.meal_plans_create = "/api/meal-plans/create" + self.meal_plans_this_week = "/api/meal-plans/this-week" + self.meal_plans_today = "/api/meal-plans/today" + self.site_settings_custom_pages = "/api/site-settings/custom-pages" + self.site_settings = "/api/site-settings" + self.site_settings_webhooks_test = "/api/site-settings/webhooks/test" + self.themes = "/api/themes" + self.themes_create = "/api/themes/create" + self.backups_available = "/api/backups/available" + self.backups_export_database = "/api/backups/export/database" + self.backups_upload = "/api/backups/upload" + self.migrations = "/api/migrations" + self.debug_version = "/api/debug/version" + self.debug_last_recipe_json = "/api/debug/last-recipe-json" + + def users_sign_ups_token(self, token): + return f"{self.prefix}/users/sign-ups/{token}" + + def users_id(self, id): + return f"{self.prefix}/users/{id}" + + def users_id_reset_password(self, id): + return f"{self.prefix}/users/{id}/reset-password" + + def users_id_image(self, id): + return f"{self.prefix}/users/{id}/image" + + def users_id_password(self, id): + return f"{self.prefix}/users/{id}/password" + + def groups_id(self, id): + return f"{self.prefix}/groups/{id}" + + def categories_category(self, category): + return f"{self.prefix}/categories/{category}" + + def recipes_tags_tag(self, tag): + return f"{self.prefix}/recipes/tags/{tag}" + + def recipes_recipe_slug(self, recipe_slug): + return f"{self.prefix}/recipes/{recipe_slug}" + + def recipes_recipe_slug_image(self, recipe_slug): + return f"{self.prefix}/recipes/{recipe_slug}/image" + + def meal_plans_plan_id(self, plan_id): + return f"{self.prefix}/meal-plans/{plan_id}" + + def meal_plans_id_shopping_list(self, id): + return f"{self.prefix}/meal-plans/{id}/shopping-list" + + def site_settings_custom_pages_id(self, id): + return f"{self.prefix}/site-settings/custom-pages/{id}" + + def themes_theme_name(self, theme_name): + return f"{self.prefix}/themes/{theme_name}" + + def backups_file_name_download(self, file_name): + return f"{self.prefix}/backups/{file_name}/download" + + def backups_file_name_import(self, file_name): + return f"{self.prefix}/backups/{file_name}/import" + + def backups_file_name_delete(self, file_name): + return f"{self.prefix}/backups/{file_name}/delete" + + def migrations_type_file_name_import(self, type, file_name): + return f"{self.prefix}/migrations/{type}/{file_name}/import" + + def migrations_type_file_name_delete(self, type, file_name): + return f"{self.prefix}/migrations/{type}/{file_name}/delete" + + def migrations_type_upload(self, type): + return f"{self.prefix}/migrations/{type}/upload" + + def debug_log_num(self, num): + return f"{self.prefix}/debug/log/{num}"