Plain is headed towards 1.0! Subscribe for development updates →

 1import json
 2import sys
 3
 4import click
 5import requests
 6
 7from plain.cli import register_cli
 8from plain.runtime import settings
 9from plain.utils.module_loading import import_string
10
11from .openapi.generator import OpenAPISchemaGenerator
12
13
14@register_cli("api")
15@click.group()
16def cli():
17    """API commands."""
18    pass
19
20
21@cli.command()
22@click.option("--validate", is_flag=True, help="Validate the OpenAPI schema.")
23@click.option("--indent", default=2, help="Indentation level for JSON and YAML output.")
24@click.option(
25    "--format",
26    default="json",
27    help="Output format (json or yaml).",
28    type=click.Choice(["json", "yaml"]),
29)
30def generate_openapi(validate, indent, format):
31    if not settings.API_OPENAPI_ROUTER:
32        click.secho("No OpenAPI URL router configured.", fg="red", err=True)
33        sys.exit(1)
34
35    url_router_class = import_string(settings.API_OPENAPI_ROUTER)
36
37    schema = OpenAPISchemaGenerator(url_router_class)
38
39    if format == "json":
40        print(schema.as_json(indent=indent))
41    elif format == "yaml":
42        print(schema.as_yaml(indent=indent))
43
44    if validate:
45        click.secho("\nOpenAPI schema validation: ", err=True, nl=False)
46        response = requests.post(
47            "https://validator.swagger.io/validator/debug",
48            headers={"Content-Type": "application/json"},
49            json=schema.schema,
50        )
51        response.raise_for_status()
52        failed = response.json().get(
53            "schemaValidationMessages", []
54        ) or response.json().get("messages", [])
55        if failed:
56            click.secho("Failed", fg="red", err=True)
57            click.secho(
58                json.dumps(response.json(), indent=2, sort_keys=True),
59                fg="yellow",
60                err=True,
61            )
62            sys.exit(1)
63        else:
64            click.secho("Success", fg="green", err=True)