clickusagemd/clickusagemd.py

72 lines
1.9 KiB
Python
Executable File

#!/usr/bin/env python
import importlib
from typing import Iterator
import click
import toml
def iter_commands(
module_name: str,
cmd_chain: list,
cliobj: click.Group | click.Command,
depth: int = 1,
) -> Iterator[str]:
assert isinstance(cliobj, click.Command) or isinstance(cliobj, click.Group)
if isinstance(cliobj, click.Group):
if depth > 1:
yield f"{'#'*depth} {cliobj.name}"
for name in cliobj.commands:
yield from iter_commands(
module_name, cmd_chain + [name], cliobj.commands[name], depth=depth + 1
)
else:
ctx = click.get_current_context()
cmd = f"{module_name} {' '.join(cmd_chain)}"
help_message = cliobj.get_help(ctx).replace(ctx.command_path, cmd)
if cliobj.name == "cli":
cmd_title = "Default Command Line"
else:
cmd_title = cliobj.name
yield f"{'#'*(depth)} {cmd_title}\n```\n{help_message}\n```\n"
def generate_usage_md(script: str):
assert ":" in script
module, cliobj = script.split(":")
if "." in module:
module_name = module.split(".")[0]
else:
module_name = module
mod = importlib.import_module(module)
cli = getattr(mod, cliobj)
with open("USAGE.md", "wt") as fd:
print(f"# {module_name.capitalize()} - Command Usage Overview", file=fd)
for command in iter_commands(module_name, [], cli):
print(command, file=fd)
@click.command()
@click.argument("poetry_project_file", type=click.File())
@click.pass_context
def cli(ctx, poetry_project_file):
contents = toml.loads(poetry_project_file.read())
try:
scripts = contents["tool"]["poetry"]["scripts"]
for script in scripts.values():
generate_usage_md(script)
except KeyError:
click.echo("[ERROR] File does not contain 'tool.poetry.scripts' definitions.")
ctx.exit(1)
if __name__ == "__main__":
cli()