pip_sphinxext.py 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109
  1. """pip sphinx extensions"""
  2. import optparse
  3. import sys
  4. from textwrap import dedent
  5. from docutils import nodes
  6. from docutils.parsers import rst
  7. from docutils.statemachine import ViewList
  8. from pip._internal.cli import cmdoptions
  9. from pip._internal.commands import commands_dict as commands
  10. class PipCommandUsage(rst.Directive):
  11. required_arguments = 1
  12. def run(self):
  13. cmd = commands[self.arguments[0]]
  14. usage = dedent(cmd.usage.replace('%prog', 'pip')).strip()
  15. node = nodes.literal_block(usage, usage)
  16. return [node]
  17. class PipCommandDescription(rst.Directive):
  18. required_arguments = 1
  19. def run(self):
  20. node = nodes.paragraph()
  21. node.document = self.state.document
  22. desc = ViewList()
  23. description = dedent(commands[self.arguments[0]].__doc__)
  24. for line in description.split('\n'):
  25. desc.append(line, "")
  26. self.state.nested_parse(desc, 0, node)
  27. return [node]
  28. class PipOptions(rst.Directive):
  29. def _format_option(self, option, cmd_name=None):
  30. if cmd_name:
  31. bookmark_line = ".. _`%s_%s`:" % (cmd_name, option._long_opts[0])
  32. else:
  33. bookmark_line = ".. _`%s`:" % option._long_opts[0]
  34. line = ".. option:: "
  35. if option._short_opts:
  36. line += option._short_opts[0]
  37. if option._short_opts and option._long_opts:
  38. line += ", %s" % option._long_opts[0]
  39. elif option._long_opts:
  40. line += option._long_opts[0]
  41. if option.takes_value():
  42. metavar = option.metavar or option.dest.lower()
  43. line += " <%s>" % metavar.lower()
  44. # fix defaults
  45. opt_help = option.help.replace('%default', str(option.default))
  46. # fix paths with sys.prefix
  47. opt_help = opt_help.replace(sys.prefix, "<sys.prefix>")
  48. return [bookmark_line, "", line, "", " %s" % opt_help, ""]
  49. def _format_options(self, options, cmd_name=None):
  50. for option in options:
  51. if option.help == optparse.SUPPRESS_HELP:
  52. continue
  53. for line in self._format_option(option, cmd_name):
  54. self.view_list.append(line, "")
  55. def run(self):
  56. node = nodes.paragraph()
  57. node.document = self.state.document
  58. self.view_list = ViewList()
  59. self.process_options()
  60. self.state.nested_parse(self.view_list, 0, node)
  61. return [node]
  62. class PipGeneralOptions(PipOptions):
  63. def process_options(self):
  64. self._format_options(
  65. [o() for o in cmdoptions.general_group['options']]
  66. )
  67. class PipIndexOptions(PipOptions):
  68. def process_options(self):
  69. self._format_options(
  70. [o() for o in cmdoptions.index_group['options']]
  71. )
  72. class PipCommandOptions(PipOptions):
  73. required_arguments = 1
  74. def process_options(self):
  75. cmd = commands[self.arguments[0]]()
  76. self._format_options(
  77. cmd.parser.option_groups[0].option_list,
  78. cmd_name=cmd.name,
  79. )
  80. def setup(app):
  81. app.add_directive('pip-command-usage', PipCommandUsage)
  82. app.add_directive('pip-command-description', PipCommandDescription)
  83. app.add_directive('pip-command-options', PipCommandOptions)
  84. app.add_directive('pip-general-options', PipGeneralOptions)
  85. app.add_directive('pip-index-options', PipIndexOptions)