vtt/src/ttfrog/cli.py

95 lines
2.1 KiB
Python
Raw Normal View History

2025-09-21 13:44:59 -07:00
import io
import logging
from pathlib import Path
from typing import Optional
2025-09-21 22:11:56 -07:00
import click
2025-09-21 13:44:59 -07:00
import typer
from dotenv import load_dotenv
2025-09-21 22:11:56 -07:00
from flask.cli import FlaskGroup
2025-09-21 13:44:59 -07:00
from rich.logging import RichHandler
2025-09-21 22:11:56 -07:00
import ttfrog.app
2025-09-21 13:44:59 -07:00
CONFIG_DEFAULTS = """
# ttfrog Defaults
LOG_LEVEL=INFO
"""
2025-09-21 22:11:56 -07:00
main_app = typer.Typer()
_context = ttfrog.app.initialize()
flask_app = _context.flask
2025-09-21 13:44:59 -07:00
app_state = dict(
config_file=Path("~/.config/ttfrog.conf").expanduser(),
)
logger = logging.getLogger("ttfrog.cli")
2025-09-21 22:11:56 -07:00
@main_app.callback(invoke_without_command=True)
def callback(
2025-09-21 13:44:59 -07:00
context: typer.Context,
verbose: bool = typer.Option(False, help="Enable verbose output."),
log_level: str = typer.Option("error", help=" Set the log level."),
config_file: Optional[Path] = typer.Option(
app_state["config_file"],
help="Path to the ttfrog configuration file",
),
):
"""
Configure the execution environment with global parameters.
"""
app_state["config_file"] = config_file
load_dotenv(stream=io.StringIO(CONFIG_DEFAULTS))
load_dotenv(app_state["config_file"])
logging.basicConfig(
format="%(message)s",
level=getattr(logging, log_level.upper()),
handlers=[RichHandler(rich_tracebacks=True, tracebacks_suppress=[typer])],
)
app_state["verbose"] = verbose
if context.invoked_subcommand is None:
logger.debug("No command specified; invoking default handler.")
run(context)
def run(context: typer.Context):
"""
The default CLI entrypoint is ttfrog.cli.run().
"""
2025-09-21 22:11:56 -07:00
flask_app.run()
@flask_app.shell_context_processor
def make_shell_context():
return {"db": flask_app.db, "app": flask_app._app}
@flask_app.cli.command()
@click.option("--drop", is_flag=True, help="Create after drop.")
@click.pass_context
def setup(ctx, drop: bool):
"""
(Re)create the database.
"""
if drop:
ctx.db.drop_all()
ctx.db.create_all()
@click.group(cls=FlaskGroup, create_app=lambda: flask_app)
@click.pass_context
def app(ctx):
"""
Application management functions
"""
main = typer.main.get_command(main_app)
main.add_command(app, "app")