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()