clickusagemd/clickusagemd.py

106 lines
2.8 KiB
Python
Executable File

#!/usr/bin/env python3
import importlib
import os
from pathlib import Path
from typing import Iterator
import click
import git
import toml
from clickusagelib.githook import install_hook, uninstall_hook
def find_git_root(path) -> Path:
git_repo = git.Repo(path, search_parent_directories=True)
git_root = git_repo.git.rev_parse("--show-toplevel")
return Path(git_root)
def iter_commands(
tool_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} {tool_name} {cliobj.name}\n"
for name in sorted(cliobj.commands):
yield from iter_commands(
tool_name, cmd_chain + [name], cliobj.commands[name], depth=depth + 1
)
else:
ctx = click.get_current_context()
cmd = f"{tool_name} {' '.join(cmd_chain)}"
help_message = cliobj.get_help(ctx).replace(ctx.command_path, cmd)
yield f"{'#'*(depth)} {tool_name} {' '.join(cmd_chain)}\n```\n{help_message}\n```"
def generate_usage_md(script: str, version: str):
script_name, module = script
assert ":" in module
module_name, cliobj = module.split(":")
mod = importlib.import_module(module_name)
cli = getattr(mod, cliobj)
with open("USAGE.md", "wt") as fd:
if "." in module_name:
module_name = module_name.split(".")[0]
print(
f"# {module_name.capitalize()} v{version} - {script_name} - Command Usage Overview\n",
file=fd,
)
for command in iter_commands(script_name, [], cli):
print(command, file=fd)
@click.group()
def cli():
pass
@cli.command(help="Generate markdown usage description.")
@click.argument(
"poetry_project_file",
type=click.File(),
default=os.path.join(find_git_root(os.getcwd()), "pyproject.toml"),
)
@click.pass_context
def run(ctx, poetry_project_file):
contents = toml.loads(poetry_project_file.read())
try:
scripts = contents["tool"]["poetry"]["scripts"].items()
version = contents["tool"]["poetry"]["version"]
for script in scripts:
generate_usage_md(script, version)
except KeyError:
click.echo("[ERROR] File does not contain 'tool.poetry.scripts' definitions.")
ctx.exit(1)
@cli.command(help="Install clickusagemd as pre-push hook.")
def install():
install_hook(find_git_root(os.getcwd()))
@cli.command(help="Uninstall clickusagemd pre-push hook.")
def uninstall():
uninstall_hook(find_git_root(os.getcwd()))
cli.add_command(run)
cli.add_command(install)
cli.add_command(uninstall)
if __name__ == "__main__":
cli()