sphinxext: Generate better usage examples
At the moment, the 'autoprogram-cliff' directive uses the default usage formatter in its output. This is functional but no more. Take, for example, the following output, generated for the python-openstackclient project: openstack server migrate [--live <hostname>] [--shared-migration | --block-migration] [--disk-overcommit | --no-disk-overcommit] [--wait] <server> What we actually want is something like the below, which is not only more legible but also avoids issues like optional argument flags and the corresponding values being on separate lines: openstack server migrate [--live <hostname>] [--shared-migration | --block-migration] [--disk-overcommit | --no-disk-overcommit] [--wait] <server> Do this by manually generating our own usage samples, harnessing a little of the internal argparse infrastructure. Change-Id: If4dff4991562da9892f1c06f854143b71111007a
This commit is contained in:
parent
ff0c10dbcb
commit
78f188023c
|
@ -14,6 +14,7 @@
|
|||
|
||||
import argparse
|
||||
import fnmatch
|
||||
import re
|
||||
|
||||
from docutils import nodes
|
||||
from docutils.parsers import rst
|
||||
|
@ -37,10 +38,30 @@ def _indent(text):
|
|||
def _format_usage(parser):
|
||||
"""Get usage without a prefix."""
|
||||
fmt = argparse.HelpFormatter(parser.prog)
|
||||
fmt.add_usage(parser.usage, parser._actions,
|
||||
parser._mutually_exclusive_groups, prefix='')
|
||||
|
||||
return fmt.format_help().strip().splitlines()
|
||||
optionals = parser._get_optional_actions()
|
||||
positionals = parser._get_positional_actions()
|
||||
groups = parser._mutually_exclusive_groups
|
||||
|
||||
# hacked variant of the regex used by the actual argparse module. Unlike
|
||||
# that version, this one attempts to group long and short opts with their
|
||||
# optional arguments ensuring that, for example, '---format <FORMAT>'
|
||||
# becomes ['--format <FORMAT>'] and not ['--format', '<FORMAT>'].
|
||||
# Yes, they really do use regexes to break apart and rewrap their help
|
||||
# string. Don't ask me why.
|
||||
part_regexp = r'\(.*?\)+|\[.*?\]+|(?:(?:-\w|--\w+)(?:\s+<\w+>)?)|\S+'
|
||||
|
||||
opt_usage = fmt._format_actions_usage(optionals, groups)
|
||||
pos_usage = fmt._format_actions_usage(positionals, groups)
|
||||
|
||||
opt_parts = re.findall(part_regexp, opt_usage)
|
||||
pos_parts = re.findall(part_regexp, pos_usage)
|
||||
parts = opt_parts + pos_parts
|
||||
|
||||
if len(' '.join([parser.prog] + parts)) < 72:
|
||||
return [' '.join([parser.prog] + parts)]
|
||||
|
||||
return [parser.prog] + [_indent(x) for x in parts]
|
||||
|
||||
|
||||
def _format_positional_action(action):
|
||||
|
|
|
@ -103,3 +103,57 @@ class TestSphinxExtension(base.TestBase):
|
|||
|
||||
user name
|
||||
""").lstrip(), output)
|
||||
|
||||
def test_multiple_opts(self):
|
||||
"""Correctly output multiple opts on separate lines."""
|
||||
parser = argparse.ArgumentParser(prog='hello-world', add_help=False)
|
||||
parser.add_argument('name', help='user name')
|
||||
parser.add_argument('--language', dest='lang',
|
||||
help='greeting language')
|
||||
parser.add_argument('--translate', action='store_true',
|
||||
help='translate to local language')
|
||||
parser.add_argument('--write-to-var-log-something-or-other',
|
||||
action='store_true',
|
||||
help='a long opt to force wrapping')
|
||||
style_group = parser.add_mutually_exclusive_group(required=True)
|
||||
style_group.add_argument('--polite', action='store_true',
|
||||
help='use a polite greeting')
|
||||
style_group.add_argument('--profane', action='store_true',
|
||||
help='use a less polite greeting')
|
||||
|
||||
output = '\n'.join(sphinxext._format_parser(parser))
|
||||
self.assertEqual(textwrap.dedent("""
|
||||
.. program:: hello-world
|
||||
.. code-block:: shell
|
||||
|
||||
hello-world
|
||||
[--language LANG]
|
||||
[--translate]
|
||||
[--write-to-var-log-something-or-other]
|
||||
(--polite | --profane)
|
||||
name
|
||||
|
||||
.. option:: --language <LANG>
|
||||
|
||||
greeting language
|
||||
|
||||
.. option:: --translate
|
||||
|
||||
translate to local language
|
||||
|
||||
.. option:: --write-to-var-log-something-or-other
|
||||
|
||||
a long opt to force wrapping
|
||||
|
||||
.. option:: --polite
|
||||
|
||||
use a polite greeting
|
||||
|
||||
.. option:: --profane
|
||||
|
||||
use a less polite greeting
|
||||
|
||||
.. option:: name
|
||||
|
||||
user name
|
||||
""").lstrip(), output)
|
||||
|
|
Loading…
Reference in New Issue