Skip to content

Commit

Permalink
feat: add api blueprint generator
Browse files Browse the repository at this point in the history
  • Loading branch information
CheeseCake87 committed Aug 8, 2024
1 parent 26c621f commit 30475bb
Show file tree
Hide file tree
Showing 7 changed files with 153 additions and 66 deletions.
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[project]
name = "flask-imp"
version = "5.1.2"
version = "5.2.0"
description = 'A Flask auto importer that allows your Flask apps to grow big.'
authors = [{ name = "David Carmichael", email = "[email protected]" }]
readme = "README.md"
Expand Down
46 changes: 35 additions & 11 deletions src/flask_imp/_cli/__init__.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import click

from .blueprint import add_blueprint as _add_blueprint
from .blueprint import add_api_blueprint as _add_api_blueprint
from .helpers import Sprinkles as Sp
from .init import init_app as _init_app

Expand All @@ -15,38 +16,61 @@ def cli() -> None:
"-n",
"--name",
nargs=1,
default="my_new_blueprint",
prompt="Name of the blueprint to create",
help="The name of the blueprint to create",
default="new_blueprint",
prompt="Name",
help="The name of the blueprint to create.",
)
@click.option(
"-f",
"--folder",
nargs=1,
default=".",
prompt=(
f"\n{Sp.WARNING}(Creation is relative to the current working directory){Sp.END}\n"
f"Folder to create blueprint in"
f"Folder {Sp.WARNING}(relative to CWD){Sp.END}"
),
help="The from_folder to create the blueprint in, defaults to the current working directory",
help="The folder to create the blueprint in, creation is relative to the current working directory.",
)
def add_blueprint(name: str, folder: str) -> None:
_add_blueprint(name=name, folder=folder)


@cli.command("init", help="Create a new flask-imp app")

@cli.command("api-blueprint", help="Create a flask-imp api blueprint")
@click.option(
"-n",
"--name",
nargs=1,
default="new_api_blueprint",
prompt="Name",
help="The name of the api blueprint to create.",
)
@click.option(
"-f",
"--folder",
nargs=1,
default=".",
prompt=(
f"Folder {Sp.WARNING}(relative to CWD){Sp.END}"
),
help="The folder to create the api blueprint in, creation is relative to the current working directory.",
)
def add_api_blueprint(name: str, folder: str) -> None:
_add_api_blueprint(name=name, folder=folder)


@cli.command("init", help="Create a new flask-imp app.")
@click.option(
"-n",
"--name",
nargs=1,
default=None,
help="The name of the app folder that will be created",
help="The name of the app folder that will be created.",
)
@click.option("-s", "--slim", is_flag=True, default=False, help="Create a slim app")
@click.option("-s", "--slim", is_flag=True, default=False, help="Create a slim app.")
@click.option(
"-m", "--minimal", is_flag=True, default=False, help="Create a minimal app"
"-m", "--minimal", is_flag=True, default=False, help="Create a minimal app."
)
@click.option("-f", "--full", is_flag=True, default=False, help="Create a full app")
@click.option("-f", "--full", is_flag=True, default=False, help="Create a full app.")
def init_new_app(name: str, full: bool, slim: bool, minimal: bool) -> None:
if not full and not slim and not minimal:
choice = click.prompt(
Expand Down
77 changes: 51 additions & 26 deletions src/flask_imp/_cli/blueprint.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,56 @@
from .filelib.water_css import water_css
from .helpers import Sprinkles as Sp
from .helpers import to_snake_case
from .helpers import build


def add_api_blueprint(
name: str = "new_api_blueprint",
folder: str = ".",
_init_app: bool = False,
_cwd: t.Optional[Path] = None,
_url_prefix: t.Optional[str] = None,
) -> None:
from .filelib.api_blueprint import api_blueprint_init_py
from .filelib.api_blueprint import api_blueprint_routes_index_py

click.echo(f"{Sp.OKGREEN}Creating API Blueprint: {name}")

if _cwd:
cwd = _cwd
else:
cwd = Path.cwd()

if not cwd.exists():
click.echo(f"{Sp.FAIL}{folder} does not exist.{Sp.END}")
return

name = to_snake_case(name)

if folder == ".":
root_folder = cwd / name
else:
root_folder = cwd / folder / name

folders: t.Dict[str, Path] = {
"root": root_folder,
"routes": root_folder / "routes",
}

files: t.Dict[str, t.Tuple[Path, t.Any]] = {
"root/__init__.py": (
folders["root"] / "__init__.py",
api_blueprint_init_py(
url_prefix=name if not _url_prefix else _url_prefix, name=name
),
),
"routes/index.py": (
folders["routes"] / "index.py",
api_blueprint_routes_index_py(),
),
}

build(folders, files, building="API Blueprint")


def add_blueprint(
Expand Down Expand Up @@ -112,29 +162,4 @@ def add_blueprint(
),
}

for folder, path in folders.items():
if not path.exists():
path.mkdir(parents=True)
click.echo(f"{Sp.OKGREEN}Blueprint folder: {folder}, created{Sp.END}")
else:
click.echo(
f"{Sp.WARNING}Blueprint folder already exists: {folder}, skipping{Sp.END}"
)

for file, (path, content) in files.items():
if not path.exists():
if file == "static/img/flask-imp-logo.png":
path.write_bytes(bytes.fromhex(content))
continue

if not content:
print(path)
path.write_text(content, encoding="utf-8")

click.echo(f"{Sp.OKGREEN}Blueprint file: {file}, created{Sp.END}")
else:
click.echo(
f"{Sp.WARNING}Blueprint file already exists: {file}, skipping{Sp.END}"
)

click.echo(f"{Sp.OKGREEN}Blueprint created: {folders['root']}{Sp.END}")
build(folders, files, building="Blueprint")
24 changes: 24 additions & 0 deletions src/flask_imp/_cli/filelib/api_blueprint.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
def api_blueprint_init_py(url_prefix: str, name: str) -> str:
return f"""\
from flask_imp import ImpBlueprint
from flask_imp.config import ImpBlueprintConfig
bp = ImpBlueprint(__name__, ImpBlueprintConfig(
enabled=True,
url_prefix="/{url_prefix}",
init_session={{"{name}_session_loaded": True}},
))
bp.import_resources("routes")
"""


def api_blueprint_routes_index_py() -> str:
return """\
from .. import bp
@bp.route("/", methods=["GET"])
def index():
return {"message": "Hello, World!"}
"""
2 changes: 1 addition & 1 deletion src/flask_imp/_cli/filelib/blueprint.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ def blueprint_init_py(url_prefix: str, name: str) -> str:
bp = ImpBlueprint(__name__, ImpBlueprintConfig(
enabled=True,
url_prefix="/{url_prefix}",
init_session={{ "{name}_session_loaded": True }},
init_session={{"{name}_session_loaded": True}},
))
bp.import_resources("routes")
Expand Down
40 changes: 40 additions & 0 deletions src/flask_imp/_cli/helpers.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
import re
import typing as t

import click


def to_snake_case(string: str) -> str:
Expand All @@ -24,3 +27,40 @@ class Sprinkles:
BOLD = "\033[1m"
UNDERLINE = "\033[4m"
END = "\033[0m"


def build(
folders: t.Dict[str, t.Any], files: t.Dict[str, t.Any], building: str = "App"
) -> None:
write_bytes: t.List[str] = [
"resources/static/favicon.ico",
"resources/static/img/flask-imp-logo.png",
"static/img/flask-imp-logo.png",
]

for folder, path in folders.items():
if not path.exists():
path.mkdir(parents=True)
click.echo(
f"{Sprinkles.OKGREEN}{building} folder: {folder}, created{Sprinkles.END}"
)
else:
click.echo(
f"{Sprinkles.WARNING}{building} folder already exists: {folder}, skipping{Sprinkles.END}"
)

for file, (path, content) in files.items():
if not path.exists():
if file in write_bytes:
path.write_bytes(bytes.fromhex(content))
continue

path.write_text(content, encoding="utf-8")

click.echo(
f"{Sprinkles.OKGREEN}{building} file: {file}, created{Sprinkles.END}"
)
else:
click.echo(
f"{Sprinkles.WARNING}{building} file already exists: {file}, skipping{Sprinkles.END}"
)
28 changes: 1 addition & 27 deletions src/flask_imp/_cli/init.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import os
import typing as t
from pathlib import Path

import click
Expand All @@ -10,32 +9,7 @@
from .filelib.head_tag_generator import head_tag_generator
from .filelib.water_css import water_css
from .helpers import Sprinkles as Sp


def build(folders: t.Dict[str, t.Any], files: t.Dict[str, t.Any]) -> None:
for folder, path in folders.items():
if not path.exists():
path.mkdir(parents=True)
click.echo(f"{Sp.OKGREEN}App folder: {folder}, created{Sp.END}")
else:
click.echo(
f"{Sp.WARNING}App folder already exists: {folder}, skipping{Sp.END}"
)

for file, (path, content) in files.items():
if not path.exists():
if (
file == "resources/static/favicon.ico"
or file == "resources/static/img/flask-imp-logo.png"
):
path.write_bytes(bytes.fromhex(content))
continue

path.write_text(content, encoding="utf-8")

click.echo(f"{Sp.OKGREEN}App file: {file}, created{Sp.END}")
else:
click.echo(f"{Sp.WARNING}App file already exists: {file}, skipping{Sp.END}")
from .helpers import build


def minimal_app(app_folder: Path) -> None:
Expand Down

0 comments on commit 30475bb

Please sign in to comment.