[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