1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164
|
"""pip sphinx extensions"""
import optparse
import sys
from textwrap import dedent
from docutils import nodes
from docutils.parsers import rst
from docutils.statemachine import ViewList
from pip._internal.cli import cmdoptions
from pip._internal.commands import commands_dict, create_command
from pip._internal.req.req_file import SUPPORTED_OPTIONS
class PipCommandUsage(rst.Directive):
required_arguments = 1
optional_arguments = 3
def run(self):
cmd = create_command(self.arguments[0])
cmd_prefix = 'python -m pip'
if len(self.arguments) > 1:
cmd_prefix = " ".join(self.arguments[1:])
cmd_prefix = cmd_prefix.strip('"')
cmd_prefix = cmd_prefix.strip("'")
usage = dedent(
cmd.usage.replace('%prog', '{} {}'.format(cmd_prefix, cmd.name))
).strip()
node = nodes.literal_block(usage, usage)
return [node]
class PipCommandDescription(rst.Directive):
required_arguments = 1
def run(self):
node = nodes.paragraph()
node.document = self.state.document
desc = ViewList()
cmd = create_command(self.arguments[0])
description = dedent(cmd.__doc__)
for line in description.split('\n'):
desc.append(line, "")
self.state.nested_parse(desc, 0, node)
return [node]
class PipOptions(rst.Directive):
def _format_option(self, option, cmd_name=None):
bookmark_line = (
".. _`{cmd_name}_{option._long_opts[0]}`:"
if cmd_name else
".. _`{option._long_opts[0]}`:"
).format(**locals())
line = ".. option:: "
if option._short_opts:
line += option._short_opts[0]
if option._short_opts and option._long_opts:
line += ", " + option._long_opts[0]
elif option._long_opts:
line += option._long_opts[0]
if option.takes_value():
metavar = option.metavar or option.dest.lower()
line += " <{}>".format(metavar.lower())
# fix defaults
opt_help = option.help.replace('%default', str(option.default))
# fix paths with sys.prefix
opt_help = opt_help.replace(sys.prefix, "<sys.prefix>")
return [bookmark_line, "", line, "", " " + opt_help, ""]
def _format_options(self, options, cmd_name=None):
for option in options:
if option.help == optparse.SUPPRESS_HELP:
continue
for line in self._format_option(option, cmd_name):
self.view_list.append(line, "")
def run(self):
node = nodes.paragraph()
node.document = self.state.document
self.view_list = ViewList()
self.process_options()
self.state.nested_parse(self.view_list, 0, node)
return [node]
class PipGeneralOptions(PipOptions):
def process_options(self):
self._format_options(
[o() for o in cmdoptions.general_group['options']]
)
class PipIndexOptions(PipOptions):
required_arguments = 1
def process_options(self):
cmd_name = self.arguments[0]
self._format_options(
[o() for o in cmdoptions.index_group['options']],
cmd_name=cmd_name,
)
class PipCommandOptions(PipOptions):
required_arguments = 1
def process_options(self):
cmd = create_command(self.arguments[0])
self._format_options(
cmd.parser.option_groups[0].option_list,
cmd_name=cmd.name,
)
class PipReqFileOptionsReference(PipOptions):
def determine_opt_prefix(self, opt_name):
for command in commands_dict:
cmd = create_command(command)
if cmd.cmd_opts.has_option(opt_name):
return command
raise KeyError('Could not identify prefix of opt {}'.format(opt_name))
def process_options(self):
for option in SUPPORTED_OPTIONS:
if getattr(option, 'deprecated', False):
continue
opt = option()
opt_name = opt._long_opts[0]
if opt._short_opts:
short_opt_name = '{}, '.format(opt._short_opts[0])
else:
short_opt_name = ''
if option in cmdoptions.general_group['options']:
prefix = ''
else:
prefix = '{}_'.format(self.determine_opt_prefix(opt_name))
self.view_list.append(
'* :ref:`{short}{long}<{prefix}{opt_name}>`'.format(
short=short_opt_name,
long=opt_name,
prefix=prefix,
opt_name=opt_name
),
"\n"
)
def setup(app):
app.add_directive('pip-command-usage', PipCommandUsage)
app.add_directive('pip-command-description', PipCommandDescription)
app.add_directive('pip-command-options', PipCommandOptions)
app.add_directive('pip-general-options', PipGeneralOptions)
app.add_directive('pip-index-options', PipIndexOptions)
app.add_directive(
'pip-requirements-file-options-ref-list', PipReqFileOptionsReference
)
|