dump-command-help 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118
  1. #!/usr/bin/env python
  2. import os
  3. import click
  4. from click.formatting import join_options
  5. from sentry.runner import cli as root_command
  6. def get_opts(param):
  7. any_prefix_is_slash = []
  8. def _write(opts):
  9. rv, any_slashes = join_options(opts)
  10. if any_slashes:
  11. any_prefix_is_slash[:] = [True]
  12. if not param.is_flag and not param.count:
  13. rv += " " + param.make_metavar()
  14. return rv
  15. rv = [_write(param.opts)]
  16. if param.secondary_opts:
  17. rv.append(_write(param.secondary_opts))
  18. return (any_prefix_is_slash and "; " or " / ").join(rv)
  19. def write_page(out, data):
  20. path = data["path"]
  21. filename = os.path.join(out, *path[1:]) + "/index.rst"
  22. if len(path) == 1:
  23. filename += ".inc"
  24. dirname = os.path.dirname(filename)
  25. try:
  26. os.makedirs(dirname)
  27. except OSError:
  28. pass
  29. args = [x["metavar"] for x in data["arguments"]]
  30. title = "`%s`" % " ".join(data["path"] + args)
  31. body = [title, "-" * len(title), "", data["help"] or ""]
  32. body.append("")
  33. body.append("Options")
  34. body.append("```````")
  35. body.append("")
  36. for opt in data["options"]:
  37. prefix = "- ``%s``: " % opt["opt_string"]
  38. for line in click.wrap_text(opt["help"], 74, prefix, " ").splitlines() or [""]:
  39. body.append(line)
  40. body.append("- ``--help``: print this help page.")
  41. if data["subcommands"]:
  42. body.append("")
  43. body.append("Subcommands")
  44. body.append("```````````")
  45. body.append("")
  46. body.append(".. toctree::")
  47. body.append(" :maxdepth: 1")
  48. body.append("")
  49. for subcmd in data["subcommands"]:
  50. body.append(f" {subcmd} <{subcmd}/index>")
  51. body.append("")
  52. with open(filename, "w") as f:
  53. for line in body:
  54. f.write("%s\n" % line.encode("utf-8"))
  55. class NoHelp(Exception):
  56. pass
  57. def dump_command(out, cmd, path):
  58. if cmd.help is None:
  59. raise NoHelp
  60. data = {
  61. "path": path,
  62. "help": cmd.help.replace("\b", ""),
  63. "options": [],
  64. "arguments": [],
  65. "subcommands": [],
  66. }
  67. for param in cmd.params:
  68. if isinstance(param, click.Option):
  69. help_text = param.help or ""
  70. if param.show_default:
  71. help_text += " [default: %s]" % (
  72. ", ".join("%s" % d for d in param.default)
  73. if isinstance(param.default, (list, tuple))
  74. else (param.default,)
  75. )
  76. data["options"].append({"opt_string": get_opts(param), "help": help_text})
  77. else:
  78. data["arguments"].append({"metavar": param.make_metavar()})
  79. if isinstance(cmd, click.Group):
  80. for child_name, child_cmd in cmd.commands.items():
  81. try:
  82. dump_command(out, child_cmd, path + [child_name])
  83. except NoHelp:
  84. pass
  85. else:
  86. data["subcommands"].append(child_name)
  87. write_page(out, data)
  88. @click.command()
  89. @click.option("--output-path", "out", type=click.Path(), default="build/cli-help")
  90. def cli(out):
  91. dump_command(out, root_command, ["sentry"])
  92. if __name__ == "__main__":
  93. cli()