79 lines
2.2 KiB
Python
79 lines
2.2 KiB
Python
import json
|
|
from typing import Any
|
|
|
|
import click
|
|
|
|
import dbyaml.cli
|
|
|
|
|
|
def generate_schema_from_click(ctx, additional_properties=False):
|
|
"""Command or Group (no nested Groups)"""
|
|
schema: dict[str, Any] = {
|
|
"$schema": "http://json-schema.org/draft-07/schema#",
|
|
"$id": ("./src/dbyaml/resources/dbyaml.schema.json"),
|
|
"$comment": "tool.dbyaml table in pyproject.toml",
|
|
}
|
|
schema_ctx = generate_node_from_click(ctx, additional_properties)
|
|
schema.update(schema_ctx)
|
|
if isinstance(ctx, click.Group):
|
|
for name, cmd in ctx.commands.items():
|
|
assert name
|
|
name = name.replace("_", "-")
|
|
schema_cmd = generate_node_from_click(cmd, additional_properties)
|
|
schema["properties"][name] = schema_cmd
|
|
return schema
|
|
|
|
|
|
def generate_node_from_click(ctx, additional_properties=False):
|
|
"""Ignores eager options"""
|
|
props = {}
|
|
for param in ctx.params:
|
|
if not isinstance(param, click.Option) or param.is_eager:
|
|
continue
|
|
|
|
assert param.name
|
|
name = param.name.replace("_", "-")
|
|
|
|
props[name] = {}
|
|
|
|
match param.type:
|
|
case click.types.IntParamType():
|
|
props[name]["type"] = "integer"
|
|
case click.types.StringParamType() | click.types.Path():
|
|
props[name]["type"] = "string"
|
|
case click.types.Choice(choices=choices):
|
|
props[name]["enum"] = choices
|
|
case click.types.BoolParamType():
|
|
props[name]["type"] = "boolean"
|
|
case _:
|
|
msg = f"{param.type!r} not a known type for {param}"
|
|
raise TypeError(msg)
|
|
|
|
if param.multiple:
|
|
props[name] = {"type": "array", "items": props[name]}
|
|
|
|
props[name]["description"] = param.help
|
|
|
|
default = param.to_info_dict()["default"]
|
|
if default is not None and not param.multiple:
|
|
props[name]["default"] = default
|
|
|
|
schema = {
|
|
"type": "object",
|
|
"additionalProperties": additional_properties,
|
|
"properties": props,
|
|
}
|
|
|
|
return schema
|
|
|
|
|
|
@click.command(context_settings={"help_option_names": ["-h", "--help"]})
|
|
@click.option("--outfile", type=click.File(mode="w"), help="Write to file")
|
|
def main(outfile):
|
|
schema = generate_schema_from_click(dbyaml.cli.main, False)
|
|
print(json.dumps(schema, indent=2), file=outfile)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|