[med-svn] [Git][med-team/sphinxcontrib-autoprogram][upstream] New upstream version 0.1.5
Michael R. Crusoe
gitlab at salsa.debian.org
Wed Jan 23 21:43:16 GMT 2019
Michael R. Crusoe pushed to branch upstream at Debian Med / sphinxcontrib-autoprogram
Commits:
25093ce1 by Michael R. Crusoe at 2019-01-23T20:56:14Z
New upstream version 0.1.5
- - - - -
7 changed files:
- .travis.yml
- doc/changelog.rst
- + doc/cli_with_groups.py
- doc/index.rst
- setup.cfg
- setup.py
- sphinxcontrib/autoprogram.py
Changes:
=====================================
.travis.yml
=====================================
@@ -17,7 +17,7 @@ script:
fi
deploy:
provider: pypi
- distributions: 'release sdist bdist_wheel'
+ distributions: 'sdist bdist_wheel'
on:
tags: true
python: 3.6
=====================================
doc/changelog.rst
=====================================
@@ -1,6 +1,14 @@
Changelog
=========
+Version 0.1.5
+-------------
+
+Released on May 15, 2018.
+
+- New ``:groups:`` option to render argument groups. [by Lukas Atkinson]
+
+
Version 0.1.4
-------------
=====================================
doc/cli_with_groups.py
=====================================
@@ -0,0 +1,18 @@
+import argparse
+
+parser = argparse.ArgumentParser(description='Process some integers.')
+parser.add_argument('integers', metavar='N', type=int, nargs='+',
+ help='An integer for the accumulator.')
+
+calculator_opts = parser.add_argument_group('Calculator Options')
+calculator_opts.add_argument(
+ '-i', '--identity', type=int, default=0,
+ help='the default result for no arguments ' '(default: 0)')
+calculator_opts.add_argument(
+ '--sum', dest='accumulate', action='store_const',
+ const=sum, default=max,
+ help='Sum the integers (default: find the max).')
+
+if __name__ == '__main__':
+ args = parser.parse_args()
+ print(args.accumulate(args.integers))
=====================================
doc/index.rst
=====================================
@@ -62,7 +62,7 @@ That's it. It will be rendered as:
:prog: cli.py
If there are subcommands (subparsers), they are rendered to subsections.
-For example, givem the following Python CLI program (say it's
+For example, given the following Python CLI program (say it's
:file:`subcmds.py`):
.. include:: subcmds.py
@@ -78,6 +78,25 @@ The above reStructuredText will render:
.. autoprogram:: subcmds:parser
:prog: subcmds.py
+If there are argument groups, they can optionally be rendered as subsections,
+just like subcommands.
+For example:
+
+.. include:: cli_with_groups.py
+ :code:
+
+.. code-block:: rst
+
+ .. autoprogram:: cli_with_groups:parser
+ :prog: cli_with_groups.py
+ :groups:
+
+The above reStructuredText Text will render:
+
+ .. autoprogram:: cli_with_groups:parser
+ :prog: cli_with_groups.py
+ :groups:
+
.. rst:directive:: .. autoprogram:: module:parser
It takes an import name of the parser object. For example, if ``xyz``
@@ -108,23 +127,34 @@ The above reStructuredText will render:
Additional Options for :rst:dir:`.. autoprogram::`
--------------------------------------------------
-.. versionadded:: 0.1.3
+``:groups:``
+ Render argument groups as subsections.
+
+ .. versionadded:: 0.1.5
``:maxdepth: ##``
Only show subcommands to a depth of ``##``.
+ .. versionadded:: 0.1.3
+
``:no_usage_codeblock:``
Don't put the usage text in a :rst:dir:`.. codeblock:: console` directive.
+ .. versionadded:: 0.1.3
+
``:start_command: subcommand``
Render document for the given subcommand. ``subcommand`` can be a space
separated list to render a sub-sub-...-command.
-
+
+ .. versionadded:: 0.1.3
+
``:strip_usage:``
Removes all but the last word in the usage string before the first option,
replaces it with '...', and removes an amount of whitespace to realign
subsequent lines.
+ .. versionadded:: 0.1.3
+
Author and license
------------------
=====================================
setup.cfg
=====================================
@@ -1,9 +1,2 @@
-[egg_info]
-tag_build = dev
-tag_date = true
-
[bdist_wheel]
universal = 1
-
-[aliases]
-release = egg_info -RDb ''
=====================================
setup.py
=====================================
@@ -7,7 +7,7 @@ from setuptools import setup, find_packages
# Do not change the variable name. It's parsed by doc/conf.py script.
-version = '0.1.4'
+version = '0.1.5'
requires = ['Sphinx >= 1.2', 'six']
=====================================
sphinxcontrib/autoprogram.py
=====================================
@@ -41,47 +41,19 @@ def get_subparser_action(parser):
return a
-def scan_programs(parser, command=[], maxdepth=0, depth=0):
+def scan_programs(parser, command=[], maxdepth=0, depth=0, groups=False):
if maxdepth and depth >= maxdepth:
return
- options = []
- for arg in parser._actions:
- if not (arg.option_strings or
- isinstance(arg, argparse._SubParsersAction)):
- name = (arg.metavar or arg.dest).lower()
- desc = (arg.help or '') % {'default': arg.default}
- options.append(([name], desc))
-
- for arg in parser._actions:
- if arg.option_strings and arg.help is not argparse.SUPPRESS:
- if isinstance(arg, (argparse._StoreAction,
- argparse._AppendAction)):
- if arg.choices is None:
- metavar = arg.metavar or arg.dest
-
- if isinstance(metavar, tuple):
- names = [
- '{0} <{1}>'.format(
- option_string, '> <'.join(metavar).lower()
- )
- for option_string in arg.option_strings
- ]
- else:
- names = [
- '{0} <{1}>'.format(option_string, metavar.lower())
- for option_string in arg.option_strings
- ]
- else:
- choices = '{0}'.format(','.join(arg.choices))
- names = ['{0} {{{1}}}'.format(option_string, choices)
- for option_string in arg.option_strings]
- else:
- names = list(arg.option_strings)
- desc = (arg.help or '') % {'default': arg.default}
- options.append((names, desc))
-
- yield command, options, parser
+ if groups:
+ yield command, [], parser
+ for group in parser._action_groups:
+ options = list(scan_options(group._group_actions))
+ if options:
+ yield command, options, group
+ else:
+ options = list(scan_options(parser._actions))
+ yield command, options, parser
if parser._subparsers:
choices = ()
@@ -103,6 +75,45 @@ def scan_programs(parser, command=[], maxdepth=0, depth=0):
yield program
+def scan_options(actions):
+ for arg in actions:
+ if not (arg.option_strings or
+ isinstance(arg, argparse._SubParsersAction)):
+ yield format_positional_argument(arg)
+
+ for arg in actions:
+ if arg.option_strings and arg.help is not argparse.SUPPRESS:
+ yield format_option(arg)
+
+
+def format_positional_argument(arg):
+ desc = (arg.help or '') % {'default': arg.default}
+ name = (arg.metavar or arg.dest).lower()
+ return [name], desc
+
+
+def format_option(arg):
+ desc = (arg.help or '') % {'default': arg.default}
+
+ if not isinstance(arg, (argparse._StoreAction, argparse._AppendAction)):
+ names = list(arg.option_strings)
+ return names, desc
+
+ if arg.choices is not None:
+ value = '{{{0}}}'.format(','.join(arg.choices))
+ else:
+ metavar = arg.metavar or arg.dest
+ if not isinstance(metavar, tuple):
+ metavar = metavar,
+ value = '<{0}>'.format('> <'.join(metavar).lower())
+
+ names = ['{0} {1}'.format(option_string, value)
+ for option_string in arg.option_strings]
+
+ return names, desc
+
+
+
def import_object(import_name):
module_name, expr = import_name.split(':', 1)
try:
@@ -148,6 +159,7 @@ class AutoprogramDirective(Directive):
'start_command': unchanged,
'strip_usage': unchanged,
'no_usage_codeblock': unchanged,
+ 'groups': unchanged,
}
def make_rst(self):
@@ -160,6 +172,8 @@ class AutoprogramDirective(Directive):
start_command = self.options.get('start_command', '').split(' ')
strip_usage = 'strip_usage' in self.options
usage_codeblock = 'no_usage_codeblock' not in self.options
+ maxdepth = int(self.options.get('maxdepth', 0))
+ groups = 'groups' in self.options
if start_command[0] == '':
start_command.pop(0)
@@ -183,54 +197,37 @@ class AutoprogramDirective(Directive):
if prog and parser.prog.startswith(original_prog):
parser.prog = parser.prog.replace(original_prog, prog, 1)
- for commands, options, cmd_parser in scan_programs(
- parser, maxdepth=int(self.options.get('maxdepth', 0))
+ for commands, options, group_or_parser in scan_programs(
+ parser, maxdepth=maxdepth, groups=groups
):
- if prog and cmd_parser.prog.startswith(original_prog):
- cmd_parser.prog = cmd_parser.prog.replace(
- original_prog, prog, 1)
- title = cmd_parser.prog.rstrip()
- usage = cmd_parser.format_usage()
-
- if strip_usage:
- to_strip = title.rsplit(' ', 1)[0]
- len_to_strip = len(to_strip) - 4
- usage_lines = usage.splitlines()
-
- usage = os.linesep.join([
- usage_lines[0].replace(to_strip, '...'),
- ] + [
- l[len_to_strip:] for l in usage_lines[1:]
- ])
-
- yield ''
- yield '.. program:: ' + title
- yield ''
- yield title
- yield ('!' if commands else '?') * len(title)
- yield ''
- for line in (cmd_parser.description or '').splitlines():
- yield line
- yield ''
-
- if usage_codeblock:
- yield '.. code-block:: console'
- yield ''
- for usage_line in usage.splitlines():
- yield ' ' + usage_line
+ if isinstance(group_or_parser, argparse._ArgumentGroup):
+ title = group_or_parser.title
+ description = group_or_parser.description
+ usage = None
+ epilog = None
+ is_subgroup = True
+ is_program = False
else:
- yield usage
-
- yield ''
-
- for option_strings, help_ in options:
- yield '.. option:: {0}'.format(', '.join(option_strings))
- yield ''
- yield ' ' + help_.replace('\n', ' \n')
- yield ''
- yield ''
- for line in (cmd_parser.epilog or '').splitlines():
- yield line or ''
+ cmd_parser = group_or_parser
+ if prog and cmd_parser.prog.startswith(original_prog):
+ cmd_parser.prog = cmd_parser.prog.replace(
+ original_prog, prog, 1)
+ title = cmd_parser.prog.rstrip()
+ description = cmd_parser.description
+ usage = cmd_parser.format_usage()
+ epilog = cmd_parser.epilog
+ is_subgroup = bool(commands)
+ is_program = True
+
+ for line in render_rst(title, options,
+ is_program=is_program,
+ is_subgroup=is_subgroup,
+ description=description,
+ usage=usage,
+ usage_strip=strip_usage,
+ usage_codeblock=usage_codeblock,
+ epilog=epilog):
+ yield line
def run(self):
node = nodes.section()
@@ -242,6 +239,55 @@ class AutoprogramDirective(Directive):
return node.children
+def render_rst(title, options, is_program, is_subgroup, description,
+ usage, usage_strip, usage_codeblock, epilog):
+ if usage_strip:
+ to_strip = title.rsplit(' ', 1)[0]
+ len_to_strip = len(to_strip) - 4
+ usage_lines = usage.splitlines()
+
+ usage = os.linesep.join([
+ usage_lines[0].replace(to_strip, '...'),
+ ] + [
+ l[len_to_strip:] for l in usage_lines[1:]
+ ])
+
+ yield ''
+
+ if is_program:
+ yield '.. program:: ' + title
+ yield ''
+
+ yield title
+ yield ('!' if is_subgroup else '?') * len(title)
+ yield ''
+
+ for line in (description or '').splitlines():
+ yield line
+ yield ''
+
+ if usage is None:
+ pass
+ elif usage_codeblock:
+ yield '.. code-block:: console'
+ yield ''
+ for usage_line in usage.splitlines():
+ yield ' ' + usage_line
+ else:
+ yield usage
+
+ yield ''
+
+ for option_strings, help_ in options:
+ yield '.. option:: {0}'.format(', '.join(option_strings))
+ yield ''
+ yield ' ' + help_.replace('\n', ' \n')
+ yield ''
+
+ for line in (epilog or '').splitlines():
+ yield line or ''
+
+
def patch_option_role_to_allow_argument_form():
"""Before Sphinx 1.2.2, :rst:dir:`.. option::` directive hadn't
allowed to not start with a dash or slash, so it hadn't been possible
@@ -350,6 +396,53 @@ class ScannerTestCase(unittest.TestCase):
self.assertEqual((['n'], 'An integer for the accumulator.'),
options[0])
+ def test_argument_groups(self):
+ parser = argparse.ArgumentParser(description='This is a program.')
+ parser.add_argument('-v', action='store_true',
+ help='A global argument')
+ plain_group = parser.add_argument_group('Plain Options',
+ description='This is a group.')
+ plain_group.add_argument('--plain', action='store_true',
+ help='A plain argument.')
+ fancy_group = parser.add_argument_group('Fancy Options',
+ description='Another group.')
+ fancy_group.add_argument('fancy', type=int, help='Set the fancyness')
+
+ sections = list(scan_programs(parser, groups=True))
+ self.assertEqual(4, len(sections))
+
+ # section: unnamed
+ program, options, cmd_parser = sections[0]
+ self.assertEqual([], program)
+ self.assertEqual('This is a program.', cmd_parser.description)
+ self.assertEqual(0, len(options))
+
+ # section: default optionals
+ program, options, group = sections[1]
+ self.assertEqual([], program)
+ self.assertEqual('optional arguments', group.title)
+ self.assertEqual(None, group.description)
+ self.assertEqual(2, len(options))
+ self.assertEqual((['-h', '--help'], 'show this help message and exit'),
+ options[0])
+ self.assertEqual((['-v'], 'A global argument'), options[1])
+
+ # section: Plain Options
+ program, options, group = sections[2]
+ self.assertEqual([], program)
+ self.assertEqual('Plain Options', group.title)
+ self.assertEqual('This is a group.', group.description)
+ self.assertEqual(1, len(options))
+ self.assertEqual((['--plain'], 'A plain argument.'), options[0])
+
+ # section: Fancy Options
+ program, options, group = sections[3]
+ self.assertEqual([], program)
+ self.assertEqual('Fancy Options', group.title)
+ self.assertEqual('Another group.', group.description)
+ self.assertEqual(1, len(options))
+ self.assertEqual((['fancy'], 'Set the fancyness'), options[0])
+
def test_choices(self):
parser = argparse.ArgumentParser()
parser.add_argument("--awesomeness", choices=["meh", "awesome"])
View it on GitLab: https://salsa.debian.org/med-team/sphinxcontrib-autoprogram/commit/25093ce1a926dbd84b1d0bb21a13618109aebe80
--
View it on GitLab: https://salsa.debian.org/med-team/sphinxcontrib-autoprogram/commit/25093ce1a926dbd84b1d0bb21a13618109aebe80
You're receiving this email because of your account on salsa.debian.org.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://alioth-lists.debian.net/pipermail/debian-med-commit/attachments/20190123/cf626d75/attachment-0001.html>
More information about the debian-med-commit
mailing list