[med-svn] [Git][med-team/sphinxcontrib-autoprogram][upstream] New upstream version 0.1.4

Andreas Tille gitlab at salsa.debian.org
Mon Mar 26 17:16:23 UTC 2018


Andreas Tille pushed to branch upstream at Debian Med / sphinxcontrib-autoprogram


Commits:
f5e20274 by Andreas Tille at 2018-03-26T19:09:27+02:00
New upstream version 0.1.4
- - - - -


7 changed files:

- PKG-INFO
- README.rst
- setup.cfg
- setup.py
- sphinxcontrib/autoprogram.py
- sphinxcontrib_autoprogram.egg-info/PKG-INFO
- sphinxcontrib_autoprogram.egg-info/requires.txt


Changes:

=====================================
PKG-INFO
=====================================
--- a/PKG-INFO
+++ b/PKG-INFO
@@ -1,13 +1,26 @@
 Metadata-Version: 1.1
 Name: sphinxcontrib-autoprogram
-Version: 0.1.2
+Version: 0.1.4
 Summary: Documenting CLI programs
-Home-page: https://bitbucket.org/birkenfeld/sphinx-contrib
+Home-page: https://github.com/sphinx-contrib/autoprogram
 Author: Hong Minhee
-Author-email: minhee at dahlia.kr
+Author-email: hong.minhee at gmail.com
 License: BSD
-Description: ``sphinxcontrib.autoprogram`` --- Documenting CLI programs
-        ==========================================================
+Description-Content-Type: UNKNOWN
+Description: ``sphinxcontrib.autoprogram``
+        =============================
+        
+        .. image:: https://badge.fury.io/py/sphinxcontrib-autoprogram.svg
+           :target: https://pypi.org/project/sphinxcontrib-autoprogram/
+           :alt: Latest PyPI version
+        
+        .. image:: https://readthedocs.org/projects/sphinxcontrib-autoprogram/badge/
+           :target: https://sphinxcontrib-autoprogram.readthedocs.io/
+           :alt: Documentation Status
+        
+        .. image:: https://travis-ci.org/sphinx-contrib/autoprogram.svg?branch=master
+           :alt: Build Status
+           :target: https://travis-ci.org/sphinx-contrib/autoprogram
         
         This contrib extension, ``sphinxcontrib.autoprogram``, provides an automated
         way to document CLI programs.  It scans ``arparser.ArgumentParser`` object,
@@ -22,10 +35,10 @@ Description: ``sphinxcontrib.autoprogram`` --- Documenting CLI programs
         
         You can find the documentation from the following URL:
         
-        https://pythonhosted.org/sphinxcontrib-autoprogram/
+        https://sphinxcontrib-autoprogram.readthedocs.io/
         
 Platform: any
-Classifier: Development Status :: 4 - Beta
+Classifier: Development Status :: 5 - Production/Stable
 Classifier: Environment :: Console
 Classifier: Environment :: Web Environment
 Classifier: Intended Audience :: Developers
@@ -35,6 +48,9 @@ Classifier: Programming Language :: Python
 Classifier: Programming Language :: Python :: 2.6
 Classifier: Programming Language :: Python :: 2.7
 Classifier: Programming Language :: Python :: 3.3
+Classifier: Programming Language :: Python :: 3.4
+Classifier: Programming Language :: Python :: 3.5
+Classifier: Programming Language :: Python :: 3.6
 Classifier: Programming Language :: Python :: Implementation :: CPython
 Classifier: Programming Language :: Python :: Implementation :: PyPy
 Classifier: Programming Language :: Python :: Implementation :: Stackless


=====================================
README.rst
=====================================
--- a/README.rst
+++ b/README.rst
@@ -1,5 +1,17 @@
-``sphinxcontrib.autoprogram`` --- Documenting CLI programs
-==========================================================
+``sphinxcontrib.autoprogram``
+=============================
+
+.. image:: https://badge.fury.io/py/sphinxcontrib-autoprogram.svg
+   :target: https://pypi.org/project/sphinxcontrib-autoprogram/
+   :alt: Latest PyPI version
+
+.. image:: https://readthedocs.org/projects/sphinxcontrib-autoprogram/badge/
+   :target: https://sphinxcontrib-autoprogram.readthedocs.io/
+   :alt: Documentation Status
+
+.. image:: https://travis-ci.org/sphinx-contrib/autoprogram.svg?branch=master
+   :alt: Build Status
+   :target: https://travis-ci.org/sphinx-contrib/autoprogram
 
 This contrib extension, ``sphinxcontrib.autoprogram``, provides an automated
 way to document CLI programs.  It scans ``arparser.ArgumentParser`` object,
@@ -14,4 +26,4 @@ Install using ``pip``:
 
 You can find the documentation from the following URL:
 
-https://pythonhosted.org/sphinxcontrib-autoprogram/
+https://sphinxcontrib-autoprogram.readthedocs.io/


=====================================
setup.cfg
=====================================
--- a/setup.cfg
+++ b/setup.cfg
@@ -1,7 +1,6 @@
 [egg_info]
 tag_build = 
 tag_date = 0
-tag_svn_revision = 0
 
 [bdist_wheel]
 universal = 1


=====================================
setup.py
=====================================
--- a/setup.py
+++ b/setup.py
@@ -7,11 +7,11 @@ from setuptools import setup, find_packages
 
 
 # Do not change the variable name.  It's parsed by doc/conf.py script.
-version = '0.1.2'
+version = '0.1.4'
 
 requires = ['Sphinx >= 1.2', 'six']
 
-if sys.version_info < (2, 7):
+if 'bdist_wheel' not in sys.argv and sys.version_info < (2, 7):
     requires.append('argparse')
 
 
@@ -23,15 +23,15 @@ def readme():
 setup(
     name='sphinxcontrib-autoprogram',
     version=version,
-    url='https://bitbucket.org/birkenfeld/sphinx-contrib',
+    url='https://github.com/sphinx-contrib/autoprogram',
     license='BSD',
     author='Hong Minhee',
-    author_email='minhee' '@' 'dahlia.kr',
+    author_email='\x68\x6f\x6e\x67.minhee' '@' '\x67\x6d\x61\x69\x6c.com',
     description='Documenting CLI programs',
     long_description=readme(),
     zip_safe=False,
     classifiers=[
-        'Development Status :: 4 - Beta',
+        'Development Status :: 5 - Production/Stable',
         'Environment :: Console',
         'Environment :: Web Environment',
         'Intended Audience :: Developers',
@@ -41,6 +41,9 @@ setup(
         'Programming Language :: Python :: 2.6',
         'Programming Language :: Python :: 2.7',
         'Programming Language :: Python :: 3.3',
+        'Programming Language :: Python :: 3.4',
+        'Programming Language :: Python :: 3.5',
+        'Programming Language :: Python :: 3.6',
         'Programming Language :: Python :: Implementation :: CPython',
         'Programming Language :: Python :: Implementation :: PyPy',
         'Programming Language :: Python :: Implementation :: Stackless',
@@ -52,6 +55,7 @@ setup(
     packages=find_packages(),
     namespace_packages=['sphinxcontrib'],
     include_package_data=True,
-    test_suite='sphinxcontrib.autoprogram.suite',
-    install_requires=requires
+    install_requires=requires,
+    extras_requires={":python_version=='2.6'": ['argparse']},
+    test_suite='sphinxcontrib.autoprogram.suite'
 )


=====================================
sphinxcontrib/autoprogram.py
=====================================
--- a/sphinxcontrib/autoprogram.py
+++ b/sphinxcontrib/autoprogram.py
@@ -11,27 +11,40 @@
 # pylint: disable=protected-access,missing-docstring
 import argparse
 import collections
-try:
-    import builtins
-except ImportError:
-    import __builtin__ as builtins
-import functools
+import os
 import re
+import sys
 import unittest
-import six
 
 from docutils import nodes
+from docutils.parsers.rst import Directive
 from docutils.parsers.rst.directives import unchanged
-from docutils.statemachine import ViewList
-from sphinx.util.compat import Directive
-from sphinx.util.nodes import nested_parse_with_titles
+from docutils.statemachine import StringList, ViewList
+from six import exec_
+from six.moves import builtins, reduce
 from sphinx.domains import std
+from sphinx.util.nodes import nested_parse_with_titles
 
-__all__ = ('BOOLEAN_OPTIONS', 'AutoprogramDirective', 'ScannerTestCase',
+__all__ = ('AutoprogramDirective',
+           'AutoprogramDirectiveTestCase', 'ScannerTestCase',
            'import_object', 'scan_programs', 'setup', 'suite')
 
 
-def scan_programs(parser, command=[]):
+def get_subparser_action(parser):
+    neg1_action = parser._actions[-1]
+
+    if isinstance(neg1_action, argparse._SubParsersAction):
+        return neg1_action
+
+    for a in parser._actions:
+        if isinstance(a, argparse._SubParsersAction):
+            return a
+
+
+def scan_programs(parser, command=[], maxdepth=0, depth=0):
+    if maxdepth and depth >= maxdepth:
+        return
+
     options = []
     for arg in parser._actions:
         if not (arg.option_strings or
@@ -39,14 +52,26 @@ def scan_programs(parser, command=[]):
             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:
+        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).lower()
-                    names = ['{0} <{1}>'.format(option_string, metavar)
-                             for option_string in arg.option_strings]
+                    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)
@@ -55,15 +80,26 @@ def scan_programs(parser, command=[]):
                 names = list(arg.option_strings)
             desc = (arg.help or '') % {'default': arg.default}
             options.append((names, desc))
-    yield command, options, parser.description, parser.epilog or ''
+
+    yield command, options, parser
+
     if parser._subparsers:
-        choices = parser._subparsers._actions[-1].choices.items()
+        choices = ()
+
+        subp_action = get_subparser_action(parser)
+
+        if subp_action:
+            choices = subp_action.choices.items()
+
         if not (hasattr(collections, 'OrderedDict') and
                 isinstance(choices, collections.OrderedDict)):
             choices = sorted(choices, key=lambda pair: pair[0])
+
         for cmd, sub in choices:
             if isinstance(sub, argparse.ArgumentParser):
-                for program in scan_programs(sub, command + [cmd]):
+                for program in scan_programs(
+                    sub, command + [cmd], maxdepth, depth + 1
+                ):
                     yield program
 
 
@@ -87,7 +123,7 @@ def import_object(import_name):
                 with open(f[0]) as fobj:
                     codestring = fobj.read()
                 foo = imp.new_module("foo")
-                six.exec_(codestring, foo.__dict__)
+                exec_(codestring, foo.__dict__)
 
                 sys.modules["foo"] = foo
                 mod = __import__("foo")
@@ -95,8 +131,7 @@ def import_object(import_name):
         else:
             raise ImportError("No module named {}".format(module_name))
 
-    reduce_ = getattr(functools, 'reduce', None) or reduce
-    mod = reduce_(getattr, module_name.split('.')[1:], mod)
+    mod = reduce(getattr, module_name.split('.')[1:], mod)
     globals_ = builtins
     if not isinstance(globals_, dict):
         globals_ = globals_.__dict__
@@ -107,32 +142,94 @@ class AutoprogramDirective(Directive):
 
     has_content = False
     required_arguments = 1
-    option_spec = {'prog': unchanged}
+    option_spec = {
+        'prog': unchanged,
+        'maxdepth': unchanged,
+        'start_command': unchanged,
+        'strip_usage': unchanged,
+        'no_usage_codeblock': unchanged,
+    }
 
     def make_rst(self):
         import_name, = self.arguments
         parser = import_object(import_name or '__undefined__')
-        parser.prog = self.options.get('prog', parser.prog)
-        for commands, options, desc, epilog in scan_programs(parser):
-            command = ' '.join(commands)
-            title = '{0} {1}'.format(parser.prog, command).rstrip()
+        prog = self.options.get('prog')
+        if prog:
+            original_prog = parser.prog
+            parser.prog = prog
+        start_command = self.options.get('start_command', '').split(' ')
+        strip_usage = 'strip_usage' in self.options
+        usage_codeblock = 'no_usage_codeblock' not in self.options
+
+        if start_command[0] == '':
+            start_command.pop(0)
+
+        if start_command:
+            def get_start_cmd_parser(p):
+                looking_for = start_command.pop(0)
+                action = get_subparser_action(p)
+
+                if not action:
+                    raise ValueError('No actions for command ' + looking_for)
+
+                subp = action.choices[looking_for]
+
+                if start_command:
+                    return get_start_cmd_parser(subp)
+
+                return subp
+
+            parser = get_start_cmd_parser(parser)
+            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))
+        ):
+            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 ''
-            yield desc or ''
+            for line in (cmd_parser.description or '').splitlines():
+                yield line
             yield ''
-            yield parser.format_usage()
+
+            if 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 ''
             yield ''
-            for line in epilog.splitlines():
+            for line in (cmd_parser.epilog or '').splitlines():
                 yield line or ''
 
     def run(self):
@@ -175,14 +272,17 @@ class ScannerTestCase(unittest.TestCase):
         parser.add_argument('--sum', dest='accumulate', action='store_const',
                             const=sum, default=max,
                             help='sum the integers (default: find the max)')
+        parser.add_argument('--key-value', metavar=('KEY', 'VALUE'), nargs=2)
+        parser.add_argument('--max', help=argparse.SUPPRESS)  # must be opt-out
+
         programs = scan_programs(parser)
         programs = list(programs)
         self.assertEqual(1, len(programs))
         parser_info, = programs
-        program, options, desc, _ = parser_info
+        program, options, cmd_parser = parser_info
         self.assertEqual([], program)
-        self.assertEqual('Process some integers.', desc)
-        self.assertEqual(4, len(options))
+        self.assertEqual('Process some integers.', cmd_parser.description)
+        self.assertEqual(5, len(options))
         self.assertEqual(
             (['n'], 'an integer for the accumulator'),
             options[0]
@@ -200,6 +300,10 @@ class ScannerTestCase(unittest.TestCase):
             (['--sum'], 'sum the integers (default: find the max)'),
             options[3]
         )
+        self.assertEqual(
+            (['--key-value <key> <value>', ], ''),
+            options[4]
+        )
 
     def test_subcommands(self):
         parser = argparse.ArgumentParser(description='Process some integers.')
@@ -217,9 +321,9 @@ class ScannerTestCase(unittest.TestCase):
         programs = list(programs)
         self.assertEqual(3, len(programs))
         # main
-        program, options, desc, _ = programs[0]
+        program, options, cmd_parser = programs[0]
         self.assertEqual([], program)
-        self.assertEqual('Process some integers.', desc)
+        self.assertEqual('Process some integers.', cmd_parser.description)
         self.assertEqual(1, len(options))
         self.assertEqual(
             (['-h', '--help'],
@@ -227,9 +331,9 @@ class ScannerTestCase(unittest.TestCase):
             options[0]
         )
         # max
-        program, options, desc, _ = programs[1]
+        program, options, cmd_parser = programs[1]
         self.assertEqual(['max'], program)
-        self.assertEqual('Find the max.', desc)
+        self.assertEqual('Find the max.', cmd_parser.description)
         self.assertEqual(2, len(options))
         self.assertEqual((['n'], 'An integer for the accumulator.'),
                          options[0])
@@ -239,9 +343,9 @@ class ScannerTestCase(unittest.TestCase):
             options[1]
         )
         # sum
-        program, options, desc, _ = programs[2]
+        program, options, cmd_parser = programs[2]
         self.assertEqual(['sum'], program)
-        self.assertEqual('Sum the integers.', desc)
+        self.assertEqual('Sum the integers.', cmd_parser.description)
         self.assertEqual(2, len(options))
         self.assertEqual((['n'], 'An integer for the accumulator.'),
                          options[0])
@@ -249,7 +353,7 @@ class ScannerTestCase(unittest.TestCase):
     def test_choices(self):
         parser = argparse.ArgumentParser()
         parser.add_argument("--awesomeness", choices=["meh", "awesome"])
-        program, options, desc, _ = list(scan_programs(parser))[0]
+        program, options, cmd_parser = list(scan_programs(parser))[0]
         log_option = options[1]
         self.assertEqual((["--awesomeness {meh,awesome}"], ''), log_option)
 
@@ -262,8 +366,29 @@ class ScannerTestCase(unittest.TestCase):
         programs = list(programs)
         self.assertEqual(1, len(programs))
         parser_data, = programs
-        program, options, desc, epilog = parser_data
-        self.assertEqual('The integers will be processed.', epilog)
+        program, options, cmd_parser = parser_data
+        self.assertEqual('The integers will be processed.', cmd_parser.epilog)
+
+
+class AutoprogramDirectiveTestCase(unittest.TestCase):
+
+    def setUp(self):
+        self.untouched_sys_path = sys.path[:]
+        sample_prog_path = os.path.join(os.path.dirname(__file__), '..', 'doc')
+        sys.path.insert(0, sample_prog_path)
+        self.directive = AutoprogramDirective(
+            'autoprogram', ['cli:parser'], {'prog': 'cli.py'},
+            StringList([], items=[]), 1, 0,
+            '.. autoprogram:: cli:parser\n   :prog: cli.py\n',
+            None, None
+        )
+
+    def tearDown(self):
+        sys.path[:] = self.untouched_sys_path
+
+    def test_make_rst(self):
+        """Alt least it shouldn't raise errors during making RST string."""
+        list(self.directive.make_rst())
 
 
 class UtilTestCase(unittest.TestCase):
@@ -284,7 +409,5 @@ class UtilTestCase(unittest.TestCase):
 
 
 suite = unittest.TestSuite()
-suite.addTests(
-    unittest.defaultTestLoader.loadTestsFromTestCase(ScannerTestCase)
-)
-suite.addTests(unittest.defaultTestLoader.loadTestsFromTestCase(UtilTestCase))
+for test_case in ScannerTestCase, AutoprogramDirectiveTestCase, UtilTestCase:
+    suite.addTests(unittest.defaultTestLoader.loadTestsFromTestCase(test_case))


=====================================
sphinxcontrib_autoprogram.egg-info/PKG-INFO
=====================================
--- a/sphinxcontrib_autoprogram.egg-info/PKG-INFO
+++ b/sphinxcontrib_autoprogram.egg-info/PKG-INFO
@@ -1,13 +1,26 @@
 Metadata-Version: 1.1
 Name: sphinxcontrib-autoprogram
-Version: 0.1.2
+Version: 0.1.4
 Summary: Documenting CLI programs
-Home-page: https://bitbucket.org/birkenfeld/sphinx-contrib
+Home-page: https://github.com/sphinx-contrib/autoprogram
 Author: Hong Minhee
-Author-email: minhee at dahlia.kr
+Author-email: hong.minhee at gmail.com
 License: BSD
-Description: ``sphinxcontrib.autoprogram`` --- Documenting CLI programs
-        ==========================================================
+Description-Content-Type: UNKNOWN
+Description: ``sphinxcontrib.autoprogram``
+        =============================
+        
+        .. image:: https://badge.fury.io/py/sphinxcontrib-autoprogram.svg
+           :target: https://pypi.org/project/sphinxcontrib-autoprogram/
+           :alt: Latest PyPI version
+        
+        .. image:: https://readthedocs.org/projects/sphinxcontrib-autoprogram/badge/
+           :target: https://sphinxcontrib-autoprogram.readthedocs.io/
+           :alt: Documentation Status
+        
+        .. image:: https://travis-ci.org/sphinx-contrib/autoprogram.svg?branch=master
+           :alt: Build Status
+           :target: https://travis-ci.org/sphinx-contrib/autoprogram
         
         This contrib extension, ``sphinxcontrib.autoprogram``, provides an automated
         way to document CLI programs.  It scans ``arparser.ArgumentParser`` object,
@@ -22,10 +35,10 @@ Description: ``sphinxcontrib.autoprogram`` --- Documenting CLI programs
         
         You can find the documentation from the following URL:
         
-        https://pythonhosted.org/sphinxcontrib-autoprogram/
+        https://sphinxcontrib-autoprogram.readthedocs.io/
         
 Platform: any
-Classifier: Development Status :: 4 - Beta
+Classifier: Development Status :: 5 - Production/Stable
 Classifier: Environment :: Console
 Classifier: Environment :: Web Environment
 Classifier: Intended Audience :: Developers
@@ -35,6 +48,9 @@ Classifier: Programming Language :: Python
 Classifier: Programming Language :: Python :: 2.6
 Classifier: Programming Language :: Python :: 2.7
 Classifier: Programming Language :: Python :: 3.3
+Classifier: Programming Language :: Python :: 3.4
+Classifier: Programming Language :: Python :: 3.5
+Classifier: Programming Language :: Python :: 3.6
 Classifier: Programming Language :: Python :: Implementation :: CPython
 Classifier: Programming Language :: Python :: Implementation :: PyPy
 Classifier: Programming Language :: Python :: Implementation :: Stackless


=====================================
sphinxcontrib_autoprogram.egg-info/requires.txt
=====================================
--- a/sphinxcontrib_autoprogram.egg-info/requires.txt
+++ b/sphinxcontrib_autoprogram.egg-info/requires.txt
@@ -1,2 +1,2 @@
-Sphinx >= 1.2
-six
\ No newline at end of file
+Sphinx>=1.2
+six



View it on GitLab: https://salsa.debian.org/med-team/sphinxcontrib-autoprogram/commit/f5e20274a3bc503833a7a976e1d4815e225432c8

---
View it on GitLab: https://salsa.debian.org/med-team/sphinxcontrib-autoprogram/commit/f5e20274a3bc503833a7a976e1d4815e225432c8
You're receiving this email because of your account on salsa.debian.org.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.alioth.debian.org/pipermail/debian-med-commit/attachments/20180326/0c43bcf8/attachment-0001.html>


More information about the debian-med-commit mailing list