docs, cli: enforce package-bound docs, add template scaffolding, and document CLI usage
- Restrict mkdocstrings generation to real Python packages (require __init__.py) - Add explicit documentation section for CLI scaffolding and templates - Generalize CLI to support multiple templates with dynamic discovery - Package templates correctly for importlib.resources access - Add fully documented health_app template (app entry point and handlers) - Fix setuptools package-data configuration for bundled templates These changes make documentation import-safe, clarify package boundaries, and provide a deterministic, OpenAPI-first scaffolding workflow via CLI.
This commit is contained in:
@@ -4,16 +4,8 @@ openapi_first.cli
|
||||
|
||||
Command-line interface for FastAPI OpenAPI-first scaffolding utilities.
|
||||
|
||||
This module provides a small, focused CLI intended to help developers
|
||||
quickly bootstrap OpenAPI-first FastAPI services using bundled project
|
||||
templates.
|
||||
|
||||
Currently supported scaffolds:
|
||||
- Health check service (minimal OpenAPI-first application)
|
||||
|
||||
The CLI copies versioned templates packaged with the library into a
|
||||
user-specified directory, allowing rapid local development without
|
||||
manual setup.
|
||||
This CLI bootstraps OpenAPI-first FastAPI applications from versioned,
|
||||
bundled templates packaged with the library.
|
||||
"""
|
||||
|
||||
import argparse
|
||||
@@ -22,68 +14,75 @@ from pathlib import Path
|
||||
from importlib import resources
|
||||
|
||||
|
||||
def copy_health_app_template(target_dir: Path) -> None:
|
||||
DEFAULT_TEMPLATE = "health_app"
|
||||
|
||||
|
||||
def available_templates() -> list[str]:
|
||||
"""
|
||||
Copy the bundled OpenAPI-first health app template into a directory.
|
||||
Return a list of available application templates.
|
||||
"""
|
||||
root = resources.files("openapi_first.templates")
|
||||
return sorted(
|
||||
item.name
|
||||
for item in root.iterdir()
|
||||
if item.is_dir() and not item.name.startswith("_")
|
||||
)
|
||||
|
||||
This function copies a fully working, minimal OpenAPI-first FastAPI
|
||||
health check application from the package's embedded templates into
|
||||
the specified target directory.
|
||||
|
||||
The target directory will be created if it does not already exist.
|
||||
Existing files may be overwritten.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
target_dir : pathlib.Path
|
||||
Destination directory into which the health app template
|
||||
should be copied.
|
||||
|
||||
Raises
|
||||
------
|
||||
FileNotFoundError
|
||||
If the bundled health app template cannot be located.
|
||||
def copy_template(template: str, target_dir: Path) -> None:
|
||||
"""
|
||||
Copy a bundled OpenAPI-first application template into a directory.
|
||||
"""
|
||||
target_dir = target_dir.resolve()
|
||||
target_dir.mkdir(parents=True, exist_ok=True)
|
||||
|
||||
with resources.files("openapi_first.templates").joinpath(
|
||||
"health_app"
|
||||
) as src:
|
||||
shutil.copytree(src, target_dir, dirs_exist_ok=True)
|
||||
root = resources.files("openapi_first.templates")
|
||||
src = root / template
|
||||
|
||||
if not src.exists():
|
||||
raise FileNotFoundError(
|
||||
f"Template '{template}' not found. "
|
||||
f"Available templates: {', '.join(available_templates())}"
|
||||
)
|
||||
|
||||
with resources.as_file(src) as path:
|
||||
shutil.copytree(path, target_dir, dirs_exist_ok=True)
|
||||
|
||||
|
||||
def main() -> None:
|
||||
"""
|
||||
Entry point for the FastAPI OpenAPI-first CLI.
|
||||
|
||||
Parses command-line arguments and initializes a new OpenAPI-first
|
||||
health check application by copying the bundled template into the
|
||||
specified directory.
|
||||
|
||||
If no target path is provided, the scaffold is created in a directory
|
||||
named ``health-app`` in the current working directory.
|
||||
|
||||
Example
|
||||
-------
|
||||
Create a health app in the default directory::
|
||||
|
||||
openapi-first
|
||||
|
||||
Create a health app in a custom directory::
|
||||
|
||||
openapi-first my-service
|
||||
"""
|
||||
parser = argparse.ArgumentParser(
|
||||
description="FastAPI OpenAPI-first scaffolding tools"
|
||||
)
|
||||
parser.add_argument(
|
||||
"template",
|
||||
nargs="?",
|
||||
default=DEFAULT_TEMPLATE,
|
||||
help=f"Template name (default: {DEFAULT_TEMPLATE})",
|
||||
)
|
||||
parser.add_argument(
|
||||
"path",
|
||||
nargs="?",
|
||||
default="health-app",
|
||||
help="Target directory for the health app",
|
||||
default=None,
|
||||
help="Target directory (defaults to template name)",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--list",
|
||||
action="store_true",
|
||||
help="List available templates and exit",
|
||||
)
|
||||
|
||||
args = parser.parse_args()
|
||||
copy_health_app_template(Path(args.path))
|
||||
print(f"Health app created at {args.path}")
|
||||
|
||||
if args.list:
|
||||
for name in available_templates():
|
||||
print(name)
|
||||
return
|
||||
|
||||
target = Path(args.path or args.template.replace("_", "-"))
|
||||
|
||||
try:
|
||||
copy_template(args.template, target)
|
||||
except Exception as exc:
|
||||
raise SystemExit(str(exc)) from exc
|
||||
|
||||
print(f"Template '{args.template}' created at {target}")
|
||||
|
||||
Reference in New Issue
Block a user