pax_global_header00006660000000000000000000000064132514341240014511gustar00rootroot0000000000000052 comment=6c9963ddf18b8133ddc1b6c55a8646e135911378 sphinx-argparse-0.2.2/000077500000000000000000000000001325143412400146255ustar00rootroot00000000000000sphinx-argparse-0.2.2/.gitignore000066400000000000000000000005211325143412400166130ustar00rootroot00000000000000*.py[cod] # C extensions *.so # Packages *.egg *.egg-info dist build eggs parts bin var sdist develop-eggs .installed.cfg lib lib64 # Installer logs pip-log.txt # Unit test / coverage reports .coverage .tox nosetests.xml # Translations *.mo # Mr Developer .mr.developer.cfg .project .idea .pydevproject .env/ docs/_build/ .cache/ sphinx-argparse-0.2.2/.travis.yml000066400000000000000000000003121325143412400167320ustar00rootroot00000000000000language: python python: - "2.7" - "3.3" - "3.4" - "3.5" - "3.6" install: - pip install . - pip install flake8 script: - py.test - flake8 . --ignore=E501,E722,E741 --exclude=docs/conf.py sphinx-argparse-0.2.2/LICENSE000066400000000000000000000020671325143412400156370ustar00rootroot00000000000000The MIT License (MIT) Copyright (c) 2013 Alex Rudakov Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. sphinx-argparse-0.2.2/README.md000066400000000000000000000016651325143412400161140ustar00rootroot00000000000000[![Build Status](https://travis-ci.org/ribozz/sphinx-argparse.svg?branch=master)](https://travis-ci.org/ribozz/sphinx-argparse) [![Documentation Status](https://readthedocs.org/projects/sphinx-argparse/badge/?version=stable)](http://sphinx-argparse.readthedocs.org/) [![PyPI version](https://badge.fury.io/py/sphinx-argparse.svg)](https://badge.fury.io/py/sphinx-argparse) [![Install with conda](https://anaconda.org/conda-forge/sphinx-argparse/badges/installer/conda.svg)](https://github.com/conda-forge/sphinx-argparse-feedstock) ![Conda downloads](https://anaconda.org/conda-forge/sphinx-argparse/badges/downloads.svg) sphinx-argparse =============== A sphinx extension that automatically documents argparse commands and options. For installation and usage details see the [documentation](http://sphinx-argparse.readthedocs.org/en/latest/). The changelog is also [found there](http://sphinx-argparse.readthedocs.org/en/latest/changelog.html). sphinx-argparse-0.2.2/docs/000077500000000000000000000000001325143412400155555ustar00rootroot00000000000000sphinx-argparse-0.2.2/docs/Makefile000066400000000000000000000127041325143412400172210ustar00rootroot00000000000000# Makefile for Sphinx documentation # # You can set these variables from the command line. SPHINXOPTS = SPHINXBUILD = sphinx-build PAPER = BUILDDIR = _build # Internal variables. PAPEROPT_a4 = -D latex_paper_size=a4 PAPEROPT_letter = -D latex_paper_size=letter ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) . # the i18n builder cannot share the environment and doctrees with the others I18NSPHINXOPTS = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) . .PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest gettext help: @echo "Please use \`make ' where is one of" @echo " html to make standalone HTML files" @echo " dirhtml to make HTML files named index.html in directories" @echo " singlehtml to make a single large HTML file" @echo " pickle to make pickle files" @echo " json to make JSON files" @echo " htmlhelp to make HTML files and a HTML help project" @echo " qthelp to make HTML files and a qthelp project" @echo " devhelp to make HTML files and a Devhelp project" @echo " epub to make an epub" @echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter" @echo " latexpdf to make LaTeX files and run them through pdflatex" @echo " text to make text files" @echo " man to make manual pages" @echo " texinfo to make Texinfo files" @echo " info to make Texinfo files and run them through makeinfo" @echo " gettext to make PO message catalogs" @echo " changes to make an overview of all changed/added/deprecated items" @echo " linkcheck to check all external links for integrity" @echo " doctest to run all doctests embedded in the documentation (if enabled)" clean: -rm -rf $(BUILDDIR)/* html: $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html @echo @echo "Build finished. The HTML pages are in $(BUILDDIR)/html." dirhtml: $(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml @echo @echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml." singlehtml: $(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml @echo @echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml." pickle: $(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle @echo @echo "Build finished; now you can process the pickle files." json: $(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json @echo @echo "Build finished; now you can process the JSON files." htmlhelp: $(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp @echo @echo "Build finished; now you can run HTML Help Workshop with the" \ ".hhp project file in $(BUILDDIR)/htmlhelp." qthelp: $(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp @echo @echo "Build finished; now you can run "qcollectiongenerator" with the" \ ".qhcp project file in $(BUILDDIR)/qthelp, like this:" @echo "# qcollectiongenerator $(BUILDDIR)/qthelp/pywizard.qhcp" @echo "To view the help file:" @echo "# assistant -collectionFile $(BUILDDIR)/qthelp/pywizard.qhc" devhelp: $(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp @echo @echo "Build finished." @echo "To view the help file:" @echo "# mkdir -p $$HOME/.local/share/devhelp/pywizard" @echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/pywizard" @echo "# devhelp" epub: $(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub @echo @echo "Build finished. The epub file is in $(BUILDDIR)/epub." latex: $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex @echo @echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex." @echo "Run \`make' in that directory to run these through (pdf)latex" \ "(use \`make latexpdf' here to do that automatically)." latexpdf: $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex @echo "Running LaTeX files through pdflatex..." $(MAKE) -C $(BUILDDIR)/latex all-pdf @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex." text: $(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text @echo @echo "Build finished. The text files are in $(BUILDDIR)/text." man: $(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man @echo @echo "Build finished. The manual pages are in $(BUILDDIR)/man." texinfo: $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo @echo @echo "Build finished. The Texinfo files are in $(BUILDDIR)/texinfo." @echo "Run \`make' in that directory to run these through makeinfo" \ "(use \`make info' here to do that automatically)." info: $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo @echo "Running Texinfo files through makeinfo..." make -C $(BUILDDIR)/texinfo info @echo "makeinfo finished; the Info files are in $(BUILDDIR)/texinfo." gettext: $(SPHINXBUILD) -b gettext $(I18NSPHINXOPTS) $(BUILDDIR)/locale @echo @echo "Build finished. The message catalogs are in $(BUILDDIR)/locale." changes: $(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes @echo @echo "The overview file is in $(BUILDDIR)/changes." linkcheck: $(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck @echo @echo "Link check complete; look for any errors in the above output " \ "or in $(BUILDDIR)/linkcheck/output.txt." doctest: $(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest @echo "Testing of doctests in the sources finished, look at the " \ "results in $(BUILDDIR)/doctest/output.txt." sphinx-argparse-0.2.2/docs/changelog.rst000066400000000000000000000075631325143412400202510ustar00rootroot00000000000000********** Change log ********** 0.2.2 ##### * CommonMark is now only imported if absolutely required. This should fix failures on read the docs. Thanks to @Chilipp for fixing this! 0.2.1 ##### * Stopped importing `sphinx.util.compat`, which was causing issues like that seen in `#65 `_ 0.2.0 ##### * Section titles can now be used in tables of contents and linked to. The title itself is also used as the anchor. In the case of repeated names `_replicateX`, where `X` is a number, is prepended to ensure that all titles are uniquely linkable. This was bug `#46 `_. * The positional (aka required) and named (aka optional) option sections are now named "Positional Arguments" and "Named Arguments", for the sake of clarity (e.g., named arguments can be required). This was issue `#58 `_. * Fixed quoting of default strings (issue `#59 `_). * Added the `:noepilogue:` and `:nodescription:` options, thanks to @arewm. * Added the `:nosubcommand:` option, thanks to @arewm. 0.1.17 ###### * Fixed handling of argument groups (this was bug `#49 `_). Thanks to @croth1 for reporting this bug. Note that now position arguments (also known as required arguments) within argument groups are now also handled correctly. 0.1.16 ###### * Added a `:nodefaultconst:` directive, which is similar to the `:nodefault:` directive, but applies only to `store_true`, `store_false`, and `store_const` (e.g., it will hide the "=True" part in the output, since that can be misleading to users). * Fixed various typos (thanks to users mikeantonacci, brondsem, and tony) * Format specifiers (e.g., `%(prog)s` and `%(default)s`) are now filled in (if possible) in help sections. If there's a missing keyword, then nothing will be filled in. This was issue #27. * The package is now a bit more robust to incorrectly spelling module names (#39, courtesy of Gabriel Falcão) * Added support for argparse groups (thanks to Fidel Ramirez) 0.1.15 ###### * Fixed malformed docutils DOM in manpages (Matt Boyer) 0.1.14 ###### * Support for aliasing arguments #22 (Campbell Barton) * Support for nested arguments #23 (Campbell Barton) * Support for subcommand descriptions #24 (Campbell Barton) * Improved parsing of content of `epilog` and `description` #25 (Louis - https://github.com/paternal) * Added 'passparser' option (David Hoese) 0.1.13 ###### * Bugfix: Choices are not always strings (Robert Langlois) * Polished small mistakes in usage documentation (Dean Malmgren) * Started to improve man-pages support (Zygmunt Krynicki) 0.1.12 ###### * Improved error reporting (James Anderson) 0.1.11 ###### * Fixed stupid bug, prevented things working on py3 (Alex Rudakov) * added tox configuration for tests 0.1.10 ###### * Remove the ugly new line in the end of usage string (Vadim Markovtsev) * Issue #9 Display argument choises (Proposed by Felix-neko, done by Alex Rudakov) * :ref: syntax for specifying path to parser instance. Issue #7 (Proposed by David Cottrell, Implemented by Alex Rudakov) * Updated docs to read the docs theme 0.1.9 ###### Fix problem with python version comparison, when python reports it as "2.7.5+" (Alex Rudakov) 0.1.8 ##### Argparse is not required anymore separate module as of python 2.7 (Mike Gleen) 0.1.7 ##### -- Nothing -- Created by accident. 0.1.6 ##### Adding :nodefault: directive that skips default values for options (Stephen Tridgell) 0.1.5 ##### Fix issue: epilog is ignored (James Anderson - https://github.com/jamesra) 0.1.4 ##### Fix issue #3: ==SUPPRESS== in option list with no default value 0.1.2 ##### Fix issue with subcommands (by Tony Narlock - https://github.com/tony) 0.1.1 ##### Initial version sphinx-argparse-0.2.2/docs/conf.py000066400000000000000000000202321325143412400170530ustar00rootroot00000000000000# -*- coding: utf-8 -*- # # sphinx-argparse documentation build configuration file, created by # sphinx-quickstart on Thu Jan 31 15:13:43 2013. # # This file is execfile()d with the current directory set to its containing dir. # # Note that not all possible configuration values are present in this # autogenerated file. # # All configuration values have a default; values that are commented out # serve to show the default. import sys, os # If extensions (or extra_modules to document with autodoc) are in another directory, # add these directories to sys.path here. If the directory is relative to the # documentation root, use os.path.abspath to make it absolute, like shown here. #sys.path.insert(0, os.path.abspath('..')) # -- General configuration ----------------------------------------------------- # If your documentation needs a minimal Sphinx version, state it here. #needs_sphinx = '1.0' # Add any Sphinx extension module names here, as strings. They can be extensions # coming with Sphinx (named 'sphinx.ext.*') or your custom ones. extensions = ['sphinx.ext.autodoc', 'sphinx.ext.todo', 'sphinx.ext.coverage', 'sphinx.ext.viewcode', 'sphinxarg.ext'] on_rtd = os.environ.get('READTHEDOCS', None) == 'True' if not on_rtd: # only import and set the theme if we're building docs locally import sphinx_rtd_theme html_theme = 'sphinx_rtd_theme' html_theme_path = [sphinx_rtd_theme.get_html_theme_path()] # Add any paths that contain templates here, relative to this directory. templates_path = ['_templates'] # The suffix of source filenames. source_suffix = '.rst' # The encoding of source files. #source_encoding = 'utf-8-sig' # The master toctree document. master_doc = 'index' # General information about the project. project = u'sphinx-argparse' copyright = u'2017, Alex Rudakov, Devon Ryan and contributors' # The version info for the project you're documenting, acts as replacement for # |version| and |release|, also used in various other places throughout the # built documents. # # The short X.Y version. import pkg_resources # part of setuptools version = pkg_resources.require("sphinx-argparse")[0].version # The full version, including alpha/beta/rc tags. release = version # The language for content autogenerated by Sphinx. Refer to documentation # for a list of supported languages. #language = None # There are two options for replacing |today|: either, you set today to some # non-false value, then it is used: #today = '' # Else, today_fmt is used as the format for a strftime call. #today_fmt = '%B %d, %Y' # List of patterns, relative to source directory, that match files and # directories to ignore when looking for source files. exclude_patterns = ['_build'] # The reST default role (used for this markup: `text`) to use for all documents. #default_role = None # If true, '()' will be appended to :func: etc. cross-reference text. #add_function_parentheses = True # If true, the current module name will be prepended to all description # unit titles (such as .. function::). #add_module_names = True # If true, sectionauthor and moduleauthor directives will be shown in the # output. They are ignored by default. #show_authors = False # The name of the Pygments (syntax highlighting) style to use. pygments_style = 'sphinx' # A list of ignored prefixes for module index sorting. #modindex_common_prefix = [] # -- Options for HTML output --------------------------------------------------- # The theme to use for HTML and HTML Help pages. See the documentation for # a list of builtin themes. #html_theme = 'default' # Theme options are theme-specific and customize the look and feel of a theme # further. For a list of options available for each theme, see the # documentation. #html_theme_options = {} # Add any paths that contain custom themes here, relative to this directory. #html_theme_path = [] # The name for this set of Sphinx documents. If None, it defaults to # " v documentation". #html_title = None # A shorter title for the navigation bar. Default is the same as html_title. #html_short_title = None # The name of an image file (relative to this directory) to place at the top # of the sidebar. #html_logo = None # The name of an image file (within the static path) to use as favicon of the # docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32 # pixels large. #html_favicon = None # Add any paths that contain custom static files (such as style sheets) here, # relative to this directory. They are copied after the builtin static files, # so a file named "default.css" will overwrite the builtin "default.css". #html_static_path = ['_static'] # If not '', a 'Last updated on:' timestamp is inserted at every page bottom, # using the given strftime format. #html_last_updated_fmt = '%b %d, %Y' # If true, SmartyPants will be used to convert quotes and dashes to # typographically correct entities. #html_use_smartypants = True # Custom sidebar templates, maps document names to template names. #html_sidebars = {} # Additional templates that should be rendered to pages, maps page names to # template names. #html_additional_pages = {} # If false, no module index is generated. #html_domain_indices = True # If false, no index is generated. #html_use_index = True # If true, the index is split into individual pages for each letter. #html_split_index = False # If true, links to the reST sources are added to the pages. #html_show_sourcelink = True # If true, "Created using Sphinx" is shown in the HTML footer. Default is True. #html_show_sphinx = True # If true, "(C) Copyright ..." is shown in the HTML footer. Default is True. #html_show_copyright = True # If true, an OpenSearch description file will be output, and all pages will # contain a tag referring to it. The value of this option must be the # base URL from which the finished HTML is served. #html_use_opensearch = '' # This is the file name suffix for HTML files (e.g. ".xhtml"). #html_file_suffix = None # Output file base name for HTML help builder. htmlhelp_basename = 'sphinxargparsedoc' # -- Options for LaTeX output -------------------------------------------------- latex_elements = { # The paper size ('letterpaper' or 'a4paper'). #'papersize': 'letterpaper', # The font size ('10pt', '11pt' or '12pt'). #'pointsize': '10pt', # Additional stuff for the LaTeX preamble. #'preamble': '', } # Grouping the document tree into LaTeX files. List of tuples # (source start file, target name, title, author, documentclass [howto/manual]). latex_documents = [ ('index', 'sphinx-argparse.tex', u'sphinx-argparse Documentation', u'Alex Rudakov and Devon Ryan', 'manual'), ] # The name of an image file (relative to this directory) to place at the top of # the title page. #latex_logo = None # For "manual" documents, if this is true, then toplevel headings are parts, # not chapters. #latex_use_parts = False # If true, show page references after internal links. #latex_show_pagerefs = False # If true, show URL addresses after external links. #latex_show_urls = False # Documents to append as an appendix to all manuals. #latex_appendices = [] # If false, no module index is generated. #latex_domain_indices = True # -- Options for manual page output -------------------------------------------- # One entry per manual page. List of tuples # (source start file, name, description, authors, manual section). man_pages = [ ('index', 'sphinx-argparse', u'sphinx-argparse Documentation', [u'Alex Rudakov', u'Devon Ryan'], 1) ] # If true, show URL addresses after external links. #man_show_urls = False # -- Options for Texinfo output ------------------------------------------------ # Grouping the document tree into Texinfo files. List of tuples # (source start file, target name, title, author, # dir menu entry, description, category) texinfo_documents = [ ('index', 'sphinx-argparse', u'sphinx-argparse Documentation', u'Alex Rudakov and Devon Ryan', 'sphinx-argparse', 'One line description of project.', 'Miscellaneous'), ] # Documents to append as an appendix to all manuals. #texinfo_appendices = [] # If false, no module index is generated. #texinfo_domain_indices = True # How to display URL addresses: 'footnote', 'no', or 'inline'. #texinfo_show_urls = 'footnote' sphinx-argparse-0.2.2/docs/contrib.rst000066400000000000000000000005021325143412400177440ustar00rootroot00000000000000Contribute ========== Any help is welcome! Most wanted: * Additional features * Bug fixes * Examples Contributions are gratefully accepted through `github `_ pull-request. Please report bugs as issues on github. Don't forget to run tests before committing:: py.test sphinx-argparse-0.2.2/docs/extend.rst000066400000000000000000000055131325143412400176020ustar00rootroot00000000000000Extending results of `argparse` directives ========================================== You can add extra content or even replace some parts of the documentation generated by the `argparse` directive. For example, any content you put inside directives (you must follow ReStructuredText identation rules) will be inserted just before the argument and option list:: .. argparse:: :module: my.module :func: my_func_that_return_parser :prog: fancytool My content here that will be inserted right before the argument list. Also any valid markup... ************************* ... may `be` *applied* here including:: any directives you usually use. Also, there is an option to insert custom content into a specific argument/option/subcommand/argument-group description. Just create a name:definition pair, where the name is an argument/option/subcommand/argument-group name and the definition is any reStructured markup. Changes to options/arguments appearing in multiple action groups can either be targeted (i.e., only one instance of the argument is changed) or general (i.e., all instances are modified).:: .. argparse:: :module: my.module :func: my_func_that_return_parser :prog: fancytool My content here that will be inserted right before the argument list. foo This text will go right after the "foo" positional argument help. install This text will go right after the "install" subcommand help and before its arguments. --upgrade -u This text will go after the upgrade option of the install subcommand. Nesting is unlimited. Note the space between --upgrade and -u, which differs from the comma that would normally be used. --output -o Content appended to the --output option, regardless of the argument group. You can also add classifiers, which will change how these definitions are incorporated:: .. argparse:: :module: my.module :func: my_func_that_return_parser :prog: fancytool My content that will be inserted right before the argument list. foo : @before This text will go before the "foo" positional argument help. install : @replace This text will replace the "install" subcommand help/description. --upgrade : @after The after directive is the default, so you needn't specify it. @before Insert content before the parsed help/description message of the argument/option/subcommand/argument-group. @after Insert content after the parsed help/description message of argument/option/subcommand/argument-group. This is the default. @replace Replace content of help/description message of argument/option/subcommand/argument-group. sphinx-argparse-0.2.2/docs/index.rst000066400000000000000000000007631325143412400174240ustar00rootroot00000000000000`sphinx-argparse` ================= `sphinx-argparse` is an extension for sphinx that allows for easy generation of documentation for command line tools using the python argparse library. .. toctree:: :maxdepth: 2 install usage extend sample misc markdown changelog contrib References ========== Similar projects ------------------- * https://pythonhosted.org/sphinxcontrib-autoprogram/ (See for comparison: https://github.com/ribozz/sphinx-argparse/issues/16) sphinx-argparse-0.2.2/docs/install.rst000066400000000000000000000003701325143412400177550ustar00rootroot00000000000000Installation ============ This extension is tested on python 2.7 and 3.3+. The package is available in the Python Package Index:: pip install sphinx-argparse Enable the extension in your sphinx config:: extensions += ['sphinxarg.ext'] sphinx-argparse-0.2.2/docs/make.bat000066400000000000000000000117541325143412400171720ustar00rootroot00000000000000@ECHO OFF REM Command file for Sphinx documentation if "%SPHINXBUILD%" == "" ( set SPHINXBUILD=sphinx-build ) set BUILDDIR=_build set ALLSPHINXOPTS=-d %BUILDDIR%/doctrees %SPHINXOPTS% . set I18NSPHINXOPTS=%SPHINXOPTS% . if NOT "%PAPER%" == "" ( set ALLSPHINXOPTS=-D latex_paper_size=%PAPER% %ALLSPHINXOPTS% set I18NSPHINXOPTS=-D latex_paper_size=%PAPER% %I18NSPHINXOPTS% ) if "%1" == "" goto help if "%1" == "help" ( :help echo.Please use `make ^` where ^ is one of echo. html to make standalone HTML files echo. dirhtml to make HTML files named index.html in directories echo. singlehtml to make a single large HTML file echo. pickle to make pickle files echo. json to make JSON files echo. htmlhelp to make HTML files and a HTML help project echo. qthelp to make HTML files and a qthelp project echo. devhelp to make HTML files and a Devhelp project echo. epub to make an epub echo. latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter echo. text to make text files echo. man to make manual pages echo. texinfo to make Texinfo files echo. gettext to make PO message catalogs echo. changes to make an overview over all changed/added/deprecated items echo. linkcheck to check all external links for integrity echo. doctest to run all doctests embedded in the documentation if enabled goto end ) if "%1" == "clean" ( for /d %%i in (%BUILDDIR%\*) do rmdir /q /s %%i del /q /s %BUILDDIR%\* goto end ) if "%1" == "html" ( %SPHINXBUILD% -b html %ALLSPHINXOPTS% %BUILDDIR%/html if errorlevel 1 exit /b 1 echo. echo.Build finished. The HTML pages are in %BUILDDIR%/html. goto end ) if "%1" == "dirhtml" ( %SPHINXBUILD% -b dirhtml %ALLSPHINXOPTS% %BUILDDIR%/dirhtml if errorlevel 1 exit /b 1 echo. echo.Build finished. The HTML pages are in %BUILDDIR%/dirhtml. goto end ) if "%1" == "singlehtml" ( %SPHINXBUILD% -b singlehtml %ALLSPHINXOPTS% %BUILDDIR%/singlehtml if errorlevel 1 exit /b 1 echo. echo.Build finished. The HTML pages are in %BUILDDIR%/singlehtml. goto end ) if "%1" == "pickle" ( %SPHINXBUILD% -b pickle %ALLSPHINXOPTS% %BUILDDIR%/pickle if errorlevel 1 exit /b 1 echo. echo.Build finished; now you can process the pickle files. goto end ) if "%1" == "json" ( %SPHINXBUILD% -b json %ALLSPHINXOPTS% %BUILDDIR%/json if errorlevel 1 exit /b 1 echo. echo.Build finished; now you can process the JSON files. goto end ) if "%1" == "htmlhelp" ( %SPHINXBUILD% -b htmlhelp %ALLSPHINXOPTS% %BUILDDIR%/htmlhelp if errorlevel 1 exit /b 1 echo. echo.Build finished; now you can run HTML Help Workshop with the ^ .hhp project file in %BUILDDIR%/htmlhelp. goto end ) if "%1" == "qthelp" ( %SPHINXBUILD% -b qthelp %ALLSPHINXOPTS% %BUILDDIR%/qthelp if errorlevel 1 exit /b 1 echo. echo.Build finished; now you can run "qcollectiongenerator" with the ^ .qhcp project file in %BUILDDIR%/qthelp, like this: echo.^> qcollectiongenerator %BUILDDIR%\qthelp\pywizard.qhcp echo.To view the help file: echo.^> assistant -collectionFile %BUILDDIR%\qthelp\pywizard.ghc goto end ) if "%1" == "devhelp" ( %SPHINXBUILD% -b devhelp %ALLSPHINXOPTS% %BUILDDIR%/devhelp if errorlevel 1 exit /b 1 echo. echo.Build finished. goto end ) if "%1" == "epub" ( %SPHINXBUILD% -b epub %ALLSPHINXOPTS% %BUILDDIR%/epub if errorlevel 1 exit /b 1 echo. echo.Build finished. The epub file is in %BUILDDIR%/epub. goto end ) if "%1" == "latex" ( %SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex if errorlevel 1 exit /b 1 echo. echo.Build finished; the LaTeX files are in %BUILDDIR%/latex. goto end ) if "%1" == "text" ( %SPHINXBUILD% -b text %ALLSPHINXOPTS% %BUILDDIR%/text if errorlevel 1 exit /b 1 echo. echo.Build finished. The text files are in %BUILDDIR%/text. goto end ) if "%1" == "man" ( %SPHINXBUILD% -b man %ALLSPHINXOPTS% %BUILDDIR%/man if errorlevel 1 exit /b 1 echo. echo.Build finished. The manual pages are in %BUILDDIR%/man. goto end ) if "%1" == "texinfo" ( %SPHINXBUILD% -b texinfo %ALLSPHINXOPTS% %BUILDDIR%/texinfo if errorlevel 1 exit /b 1 echo. echo.Build finished. The Texinfo files are in %BUILDDIR%/texinfo. goto end ) if "%1" == "gettext" ( %SPHINXBUILD% -b gettext %I18NSPHINXOPTS% %BUILDDIR%/locale if errorlevel 1 exit /b 1 echo. echo.Build finished. The message catalogs are in %BUILDDIR%/locale. goto end ) if "%1" == "changes" ( %SPHINXBUILD% -b changes %ALLSPHINXOPTS% %BUILDDIR%/changes if errorlevel 1 exit /b 1 echo. echo.The overview file is in %BUILDDIR%/changes. goto end ) if "%1" == "linkcheck" ( %SPHINXBUILD% -b linkcheck %ALLSPHINXOPTS% %BUILDDIR%/linkcheck if errorlevel 1 exit /b 1 echo. echo.Link check complete; look for any errors in the above output ^ or in %BUILDDIR%/linkcheck/output.txt. goto end ) if "%1" == "doctest" ( %SPHINXBUILD% -b doctest %ALLSPHINXOPTS% %BUILDDIR%/doctest if errorlevel 1 exit /b 1 echo. echo.Testing of doctests in the sources finished, look at the ^ results in %BUILDDIR%/doctest/output.txt. goto end ) :end sphinx-argparse-0.2.2/docs/markdown.rst000066400000000000000000000054231325143412400201350ustar00rootroot00000000000000Markdown ======== As of version 0.2.0, markdown (rather than only reStructuredText) can be included inside directives as nested content. While markdown is much easier to write, please note that it is also less powerful. An example is below:: .. argparse:: :filename: ../test/sample.py :func: parser :prog: sample :markdown: Header 1 ======== [I'm a link to google](http://www.google.com) ## Sub-heading ``` This is a fenced code block ``` The above example renders as follows: .. argparse:: :filename: ../test/sample.py :func: parser :prog: sample :markdown: A random paragraph Heading 1 ========= [I'm a link to google](http://www.google.com) ## Sub heading ``` This is a fenced code block ``` The `CommonMark-py `__ is used internally to parse Markdown. Consequently, only Markdown supported by CommonMark-py will be rendered. You must explicitly use the `:markdown:` flag, otherwise all content inside directives will be parsed as reStructuredText. A note on headers ----------------- If the Markdown you nest includes headings, then the first one **MUST** be level 1. Subsequent headings can be at `lower levels `__ and then rendered correctly. Hard line breaks ---------------- Sphinx strips white-space from the end of lines prior to handing it to this package. Because of that, hard line breaks can not currently be rendered. Replacing/appending/prepending content -------------------------------------- When markdown is used as nested content, it's not possible to create dictionary entries like in reStructuredText to `modify program option descriptions `__. This is because CommonMark-py does not support dictionary entries. MarkDown in program descriptions and option help ------------------------------------------------ In addition to using MarkDown in nested content, one can also use MarkDown directly in program descriptions and option help messages. For example:: import argparse def blah(): parser = argparse.ArgumentParser(description=""" ### Example of MarkDown inside programs [I'm a link](http://www.google.com) """) parser.add_argument('cmd', help='execute a `command`') return parser To render this as MarkDown rather than reStructuredText, use the `markdownhelp` option:: .. argparse:: :filename: ../test/sample2.py :func: blah :prog: sample :markdownhelp: This will then be rendered as: .. argparse:: :filename: ../test/sample2.py :func: blah :prog: sample :markdownhelp: sphinx-argparse-0.2.2/docs/misc.rst000066400000000000000000000026541325143412400172510ustar00rootroot00000000000000Miscellaneous ============= Text wrapping in argument tables -------------------------------- A common issue with the default html output is that the table within which options are displayed is designed such that the option descriptions are each held on one line. Any even remotely lengthy description then causes the viewer to need to scroll left/right to view the entire text. This is typically undesirable and the fix is described fully `here `_. The short synopsis is below: 1. Create a new CSS file (likely under `_static`) and point to it in `html_static_path` and `html_context` (or a template in the `templates_path`) in `conf.py`. 2. In that CSS file, add the following code: .. code:: CSS .wy-table-responsive table td { white-space: normal !important; } .wy-table-responsive { overflow: visible !important; } Linking to action groups ------------------------ As of version 0.2.0, action groups (e.g., "Optional arguments", "Required arguments", and subcommands) can be included in tables of contents and external links. The anchor name is the same as the title name (e.g., "Optional arguments"). In cases where titles are duplicated, as is often the case when subcommands are used, `_repeatX`, where `X` is a number, is prepended to duplicate anchor names to ensure that they can all be uniquely linked. sphinx-argparse-0.2.2/docs/sample.rst000066400000000000000000000034021325143412400175670ustar00rootroot00000000000000Examples ======== Example documentation structure ------------------------------- Here is an example structure for the documentation of a complex command with many subcommands. You are free to use any structure, but this may be a good starting point. File "index.rst":: .. toctree:: :maxdepth: 2 cmd File "cmd.rst":: Command line utilities ********************** .. toctree:: :maxdepth: 1 cmd_main cmd_subcommand File "cmd_main.rst":: Fancytool command *********************** .. argparse:: :module: my.module :func: my_func_that_returns_a_parser :prog: fancytool subcommand Here we add a reference to subcommand, to simplify navigation. See :doc:`cmd_subcommand` File "cmd_subcommand.rst":: Subcommand command *********************** .. argparse:: :module: my.module :func: my_func_that_return_parser :prog: fancytool :path: subcommand Source of example file ---------------------- This file will be used in all generated examples. .. literalinclude:: ../test/sample.py Generated sample 1 - command with subcommands --------------------------------------------- Directive ~~~~~~~~~ Source:: .. argparse:: :filename: ../test/sample.py :func: parser :prog: sample Output ~~~~~~ .. argparse:: :filename: ../test/sample.py :func: parser :prog: sample Generated sample 2 - subcommand ------------------------------- Directive ~~~~~~~~~ Source:: .. argparse:: :filename../test/sample.py :func: parser :prog: sample :path: game Output ~~~~~~ .. argparse:: :filename: ../test/sample.py :func: parser :prog: sample :path: game sphinx-argparse-0.2.2/docs/usage.rst000066400000000000000000000057501325143412400174220ustar00rootroot00000000000000Basic usage =========== This extension adds the "argparse" directive:: .. argparse:: :module: my.module :func: my_func_that_returns_a_parser :prog: fancytool The `module`, `func` and `prog` options are required. `func` is a function that returns an instance of the `argparse.ArgumentParser` class. Alternatively, one can use :ref: like this:: .. argparse:: :ref: my.module.my_func_that_returns_a_parser :prog: fancytool In this case :ref: points directly to argument parser instance. For this directive to work, you should point it to the function that will return a pre-filled `ArgumentParser`. Something like:: def my_func_that_return_parser(): parser = argparse.ArgumentParser() parser.add_argument('foo', default=False, help='foo help') parser.add_argument('bar', default=False) subparsers = parser.add_subparsers() subparser = subparsers.add_parser('install', help='install help') subparser.add_argument('ref', type=str, help='foo1 help') subparser.add_argument('--upgrade', action='store_true', default=False, help='foo2 help') return parser .. note:: We will use this example as a reference for every example in this document. To document a file that is not part of a module, use :filename:: .. argparse:: :filename: script.py :func: my_func_that_returns_a_parser :prog: script.py The 'filename' option could be absolute path or a relative path under current working dir. \:module\: Module name, where the function is located \:func\: Function name \:ref\: A combination of :module: and :func: \:filename\: A file name, in cases where the file to be documented is not part of a module. \:prog\: The name of your tool (or how it should appear in the documentation). For example, if you run your script as `./boo --some args` then \:prog\: will be "boo" That's it. Directives will render positional arguments, options and sub-commands. Sub-commands are limited to one level. But, you can always output help for subcommands separately:: .. argparse:: :module: my.module :func: my_func_that_return_parser :prog: fancytool :path: install This will render same doc for "install" subcommand. Nesting level is unlimited:: .. argparse:: :module: my.module :func: my_func_that_return_parser :prog: fancytool :path: install subcomand1 subcommand2 subcommand3 Other useful directives ----------------------- :nodefault: Do not show any default values. :nodefaultconst: Like nodefault:, except it applies only to arguments of types `store_const`, `store_true` and `store_false`. :nosubcommands: Do not show subcommands. :noepilogue: Do not parse the epilogue, which can be useful if it contains text that could be incorrectly parse as reStructuredText. :nodescription: Do not parse the description, which can be useful if it contains text that could be incorrectly parse as reStructuredText. sphinx-argparse-0.2.2/requirements_dev.txt000066400000000000000000000000701325143412400207440ustar00rootroot00000000000000pytest sphinx_rtd_theme sphinx>=1.2.0 CommonMark>=0.5.6 sphinx-argparse-0.2.2/requirements_rtd.txt000066400000000000000000000000471325143412400207630ustar00rootroot00000000000000pytest sphinx>=1.2.0 CommonMark>=0.5.6 sphinx-argparse-0.2.2/setup.py000066400000000000000000000027101325143412400163370ustar00rootroot00000000000000from setuptools import setup def getVersion(): f = open("sphinxarg/__init__.py") _ = f.read() ver = _.split("'")[1] f.close() return ver setup( name='sphinx-argparse', version=getVersion(), packages=[ 'sphinxarg', ], url='https://github.com/ribozz/sphinx-argparse', license='MIT', author='Aleksandr Rudakov and Devon Ryan', author_email='ribozz@gmail.com', description='A sphinx extension that automatically documents argparse commands and options', long_description="""A sphinx extension that automatically documents argparse commands and options. For installation and usage details, see the `documentation `_.""", classifiers=[ 'Development Status :: 5 - Production/Stable', 'Intended Audience :: Developers', 'License :: OSI Approved :: MIT License', 'Programming Language :: Python :: 2.7', 'Programming Language :: Python :: 3.2', 'Programming Language :: Python :: 3.3', 'Programming Language :: Python :: 3.4', 'Programming Language :: Python :: 3.5', 'Programming Language :: Python :: 3.6', 'Topic :: Documentation :: Sphinx', 'Topic :: Software Development :: Documentation' ], install_requires=[ 'sphinx>=1.2.0' ], extras_require={ 'dev': ['pytest', 'sphinx_rtd_theme'], 'markdown': ['CommonMark>=0.5.6'] } ) sphinx-argparse-0.2.2/sphinxarg/000077500000000000000000000000001325143412400166305ustar00rootroot00000000000000sphinx-argparse-0.2.2/sphinxarg/__init__.py000066400000000000000000000000261325143412400207370ustar00rootroot00000000000000__version__ = '0.2.2' sphinx-argparse-0.2.2/sphinxarg/ext.py000066400000000000000000000507201325143412400200060ustar00rootroot00000000000000from argparse import ArgumentParser import os from docutils import nodes from docutils.statemachine import StringList from docutils.parsers.rst.directives import flag, unchanged from docutils.parsers.rst import Parser, Directive from docutils.utils import new_document from docutils.frontend import OptionParser from sphinx.util.nodes import nested_parse_with_titles from sphinxarg.parser import parse_parser, parser_navigate def map_nested_definitions(nested_content): if nested_content is None: raise Exception('Nested content should be iterable, not null') # build definition dictionary definitions = {} for item in nested_content: if not isinstance(item, nodes.definition_list): continue for subitem in item: if not isinstance(subitem, nodes.definition_list_item): continue if not len(subitem.children) > 0: continue classifier = '@after' idx = subitem.first_child_matching_class(nodes.classifier) if idx is not None: ci = subitem[idx] if len(ci.children) > 0: classifier = ci.children[0].astext() if classifier is not None and classifier not in ( '@replace', '@before', '@after'): raise Exception('Unknown classifier: %s' % classifier) idx = subitem.first_child_matching_class(nodes.term) if idx is not None: term = subitem[idx] if len(term.children) > 0: term = term.children[0].astext() idx = subitem.first_child_matching_class(nodes.definition) if idx is not None: subContent = [] for _ in subitem[idx]: if isinstance(_, nodes.definition_list): subContent.append(_) definitions[term] = (classifier, subitem[idx].astext(), subContent) return definitions def renderList(l, markDownHelp, settings=None): """ Given a list of reStructuredText or MarkDown sections, return a docutils node list """ if len(l) == 0: return [] if markDownHelp: from sphinxarg.markdown import parseMarkDownBlock return parseMarkDownBlock('\n\n'.join(l) + '\n') else: if settings is None: settings = OptionParser(components=(Parser,)).get_default_values() document = new_document(None, settings) Parser().parse('\n\n'.join(l) + '\n', document) return document.children def print_action_groups(data, nested_content, markDownHelp=False, settings=None): """ Process all 'action groups', which are also include 'Options' and 'Required arguments'. A list of nodes is returned. """ definitions = map_nested_definitions(nested_content) nodes_list = [] if 'action_groups' in data: for action_group in data['action_groups']: # Every action group is comprised of a section, holding a title, the description, and the option group (members) section = nodes.section(ids=[action_group['title']]) section += nodes.title(action_group['title'], action_group['title']) desc = [] if action_group['description']: desc.append(action_group['description']) # Replace/append/prepend content to the description according to nested content subContent = [] if action_group['title'] in definitions: classifier, s, subContent = definitions[action_group['title']] if classifier == '@replace': desc = [s] elif classifier == '@after': desc.append(s) elif classifier == '@before': desc.insert(0, s) for k, v in subContent.items(): definitions[k] = v # Render appropriately for element in renderList(desc, markDownHelp): section += element localDefinitions = definitions if len(subContent) > 0: localDefinitions = {k: v for k, v in definitions.items()} for k, v in map_nested_definitions(subContent): localDefinitions[k] = v items = [] # Iterate over action group members for entry in action_group['options']: """ Members will include: default The default value. This may be ==SUPPRESS== name A list of option names (e.g., ['-h', '--help'] help The help message string There may also be a 'choices' member. """ # Build the help text arg = [] if 'choices' in entry: arg.append('Possible choices: {}\n'.format(", ".join([str(c) for c in entry['choices']]))) if 'help' in entry: arg.append(entry['help']) if entry['default'] is not None and entry['default'] not in ['"==SUPPRESS=="', '==SUPPRESS==']: if entry['default'] == '': arg.append('Default: ""') else: arg.append('Default: {}'.format(entry['default'])) # Handle nested content, the term used in the dict has the comma removed for simplicity desc = arg term = ' '.join(entry['name']) if term in localDefinitions: classifier, s, subContent = localDefinitions[term] if classifier == '@replace': desc = [s] elif classifier == '@after': desc.append(s) elif classifier == '@before': desc.insert(0, s) term = ', '.join(entry['name']) n = nodes.option_list_item('', nodes.option_group('', nodes.option_string(text=term)), nodes.description('', *renderList(desc, markDownHelp, settings))) items.append(n) section += nodes.option_list('', *items) nodes_list.append(section) return nodes_list def print_subcommands(data, nested_content, markDownHelp=False, settings=None): """ Each subcommand is a dictionary with the following keys: ['usage', 'action_groups', 'bare_usage', 'name', 'help'] In essence, this is all tossed in a new section with the title 'name'. Apparently there can also be a 'description' entry. """ definitions = map_nested_definitions(nested_content) items = [] if 'children' in data: subCommands = nodes.section(ids=["Sub-commands:"]) subCommands += nodes.title('Sub-commands:', 'Sub-commands:') for child in data['children']: sec = nodes.section(ids=[child['name']]) sec += nodes.title(child['name'], child['name']) if 'description' in child and child['description']: desc = [child['description']] elif child['help']: desc = [child['help']] else: desc = ['Undocumented'] # Handle nested content subContent = [] if child['name'] in definitions: classifier, s, subContent = definitions[child['name']] if classifier == '@replace': desc = [s] elif classifier == '@after': desc.append(s) elif classifier == '@before': desc.insert(0, s) for element in renderList(desc, markDownHelp): sec += element sec += nodes.literal_block(text=child['bare_usage']) for x in print_action_groups(child, nested_content + subContent, markDownHelp, settings=settings): sec += x for x in print_subcommands(child, nested_content + subContent, markDownHelp, settings=settings): sec += x subCommands += sec items.append(subCommands) return items def ensureUniqueIDs(items): """ If action groups are repeated, then links in the table of contents will just go to the first of the repeats. This may not be desirable, particularly in the case of subcommands where the option groups have different members. This function updates the title IDs by adding _repeatX, where X is a number so that the links are then unique. """ s = set() for item in items: for n in item.traverse(descend=True, siblings=True, ascend=False): if isinstance(n, nodes.section): ids = n['ids'] for idx, id in enumerate(ids): if id not in s: s.add(id) else: i = 1 while "{}_repeat{}".format(id, i) in s: i += 1 ids[idx] = "{}_repeat{}".format(id, i) s.add(ids[idx]) n['ids'] = ids class ArgParseDirective(Directive): has_content = True option_spec = dict(module=unchanged, func=unchanged, ref=unchanged, prog=unchanged, path=unchanged, nodefault=flag, nodefaultconst=flag, filename=unchanged, manpage=unchanged, nosubcommands=unchanged, passparser=flag, noepilog=unchanged, nodescription=unchanged, markdown=flag, markdownhelp=flag) def _construct_manpage_specific_structure(self, parser_info): """ Construct a typical man page consisting of the following elements: NAME (automatically generated, out of our control) SYNOPSIS DESCRIPTION OPTIONS FILES SEE ALSO BUGS """ items = [] # SYNOPSIS section synopsis_section = nodes.section( '', nodes.title(text='Synopsis'), nodes.literal_block(text=parser_info["bare_usage"]), ids=['synopsis-section']) items.append(synopsis_section) # DESCRIPTION section if 'nodescription' not in self.options: description_section = nodes.section( '', nodes.title(text='Description'), nodes.paragraph(text=parser_info.get( 'description', parser_info.get( 'help', "undocumented").capitalize())), ids=['description-section']) nested_parse_with_titles( self.state, self.content, description_section) items.append(description_section) if parser_info.get('epilog') and 'noepilog' not in self.options: # TODO: do whatever sphinx does to understand ReST inside # docstrings magically imported from other places. The nested # parse method invoked above seem to be able to do this but # I haven't found a way to do it for arbitrary text if description_section: description_section += nodes.paragraph( text=parser_info['epilog']) else: description_section = nodes.paragraph( text=parser_info['epilog']) items.append(description_section) # OPTIONS section options_section = nodes.section( '', nodes.title(text='Options'), ids=['options-section']) if 'args' in parser_info: options_section += nodes.paragraph() options_section += nodes.subtitle(text='Positional arguments:') options_section += self._format_positional_arguments(parser_info) for action_group in parser_info['action_groups']: if 'options' in parser_info: options_section += nodes.paragraph() options_section += nodes.subtitle(text=action_group['title']) options_section += self._format_optional_arguments(action_group) # NOTE: we cannot generate NAME ourselves. It is generated by # docutils.writers.manpage # TODO: items.append(files) # TODO: items.append(see also) # TODO: items.append(bugs) if len(options_section.children) > 1: items.append(options_section) if 'nosubcommands' not in self.options: # SUBCOMMANDS section (non-standard) subcommands_section = nodes.section( '', nodes.title(text='Sub-Commands'), ids=['subcommands-section']) if 'children' in parser_info: subcommands_section += self._format_subcommands(parser_info) if len(subcommands_section) > 1: items.append(subcommands_section) if os.getenv("INCLUDE_DEBUG_SECTION"): import json # DEBUG section (non-standard) debug_section = nodes.section( '', nodes.title(text="Argparse + Sphinx Debugging"), nodes.literal_block(text=json.dumps(parser_info, indent=' ')), ids=['debug-section']) items.append(debug_section) return items def _format_positional_arguments(self, parser_info): assert 'args' in parser_info items = [] for arg in parser_info['args']: arg_items = [] if arg['help']: arg_items.append(nodes.paragraph(text=arg['help'])) elif 'choices' not in arg: arg_items.append(nodes.paragraph(text='Undocumented')) if 'choices' in arg: arg_items.append( nodes.paragraph( text='Possible choices: ' + ', '.join(arg['choices']))) items.append( nodes.option_list_item( '', nodes.option_group( '', nodes.option( '', nodes.option_string(text=arg['metavar']) ) ), nodes.description('', *arg_items))) return nodes.option_list('', *items) def _format_optional_arguments(self, parser_info): assert 'options' in parser_info items = [] for opt in parser_info['options']: names = [] opt_items = [] for name in opt['name']: option_declaration = [nodes.option_string(text=name)] if opt['default'] is not None \ and opt['default'] not in ['"==SUPPRESS=="', '==SUPPRESS==']: option_declaration += nodes.option_argument( '', text='=' + str(opt['default'])) names.append(nodes.option('', *option_declaration)) if opt['help']: opt_items.append(nodes.paragraph(text=opt['help'])) elif 'choices' not in opt: opt_items.append(nodes.paragraph(text='Undocumented')) if 'choices' in opt: opt_items.append( nodes.paragraph( text='Possible choices: ' + ', '.join(opt['choices']))) items.append( nodes.option_list_item( '', nodes.option_group('', *names), nodes.description('', *opt_items))) return nodes.option_list('', *items) def _format_subcommands(self, parser_info): assert 'children' in parser_info items = [] for subcmd in parser_info['children']: subcmd_items = [] if subcmd['help']: subcmd_items.append(nodes.paragraph(text=subcmd['help'])) else: subcmd_items.append(nodes.paragraph(text='Undocumented')) items.append( nodes.definition_list_item( '', nodes.term('', '', nodes.strong( text=subcmd['bare_usage'])), nodes.definition('', *subcmd_items))) return nodes.definition_list('', *items) def _nested_parse_paragraph(self, text): content = nodes.paragraph() self.state.nested_parse(StringList(text.split("\n")), 0, content) return content def run(self): if 'module' in self.options and 'func' in self.options: module_name = self.options['module'] attr_name = self.options['func'] elif 'ref' in self.options: _parts = self.options['ref'].split('.') module_name = '.'.join(_parts[0:-1]) attr_name = _parts[-1] elif 'filename' in self.options and 'func' in self.options: mod = {} try: f = open(self.options['filename']) except IOError: # try open with abspath f = open(os.path.abspath(self.options['filename'])) code = compile(f.read(), self.options['filename'], 'exec') exec(code, mod) attr_name = self.options['func'] func = mod[attr_name] else: raise self.error( ':module: and :func: should be specified, or :ref:, or :filename: and :func:') # Skip this if we're dealing with a local file, since it obviously can't be imported if 'filename' not in self.options: try: mod = __import__(module_name, globals(), locals(), [attr_name]) except: raise self.error('Failed to import "%s" from "%s"' % (attr_name, module_name)) if not hasattr(mod, attr_name): raise self.error(( 'Module "%s" has no attribute "%s"\n' 'Incorrect argparse :module: or :func: values?' ) % (module_name, attr_name)) func = getattr(mod, attr_name) if isinstance(func, ArgumentParser): parser = func elif 'passparser' in self.options: parser = ArgumentParser() func(parser) else: parser = func() if 'path' not in self.options: self.options['path'] = '' path = str(self.options['path']) if 'prog' in self.options: parser.prog = self.options['prog'] result = parse_parser( parser, skip_default_values='nodefault' in self.options, skip_default_const_values='nodefaultconst' in self.options) result = parser_navigate(result, path) if 'manpage' in self.options: return self._construct_manpage_specific_structure(result) # Handle nested content, where markdown needs to be preprocessed items = [] nested_content = nodes.paragraph() if 'markdown' in self.options: from sphinxarg.markdown import parseMarkDownBlock items.extend(parseMarkDownBlock('\n'.join(self.content) + '\n')) else: self.state.nested_parse( self.content, self.content_offset, nested_content) nested_content = nested_content.children # add common content between for item in nested_content: if not isinstance(item, nodes.definition_list): items.append(item) markDownHelp = False if 'markdownhelp' in self.options: markDownHelp = True if 'description' in result and 'nodescription' not in self.options: if markDownHelp: items.extend(renderList([result['description']], True)) else: items.append(self._nested_parse_paragraph(result['description'])) items.append(nodes.literal_block(text=result['usage'])) items.extend(print_action_groups(result, nested_content, markDownHelp, settings=self.state.document.settings)) if 'nosubcommands' not in self.options: items.extend(print_subcommands(result, nested_content, markDownHelp, settings=self.state.document.settings)) if 'epilog' in result and 'noepilog' not in self.options: items.append(self._nested_parse_paragraph(result['epilog'])) # Traverse the returned nodes, modifying the title IDs as necessary to avoid repeats ensureUniqueIDs(items) return items def setup(app): app.add_directive('argparse', ArgParseDirective) sphinx-argparse-0.2.2/sphinxarg/markdown.py000066400000000000000000000234311325143412400210270ustar00rootroot00000000000000from CommonMark import Parser # >= 0.5.6 from CommonMark.node import Node from docutils import nodes from docutils.utils.code_analyzer import Lexer def customWalker(node, space=''): """ A convenience function to ease debugging. It will print the node structure that's returned from CommonMark The usage would be something like: >>> content = Parser().parse('Some big text block\n===================\n\nwith content\n') >>> customWalker(content) document heading text Some big text block paragraph text with content Spaces are used to convey nesting """ txt = '' try: txt = node.literal except: pass if txt is None or txt == '': print('{}{}'.format(space, node.t)) else: print('{}{}\t{}'.format(space, node.t, txt)) cur = node.first_child if cur: while cur is not None: customWalker(cur, space + ' ') cur = cur.nxt def paragraph(node): """ Process a paragraph, which includes all content under it """ text = '' if node.string_content is not None: text = node.string_content o = nodes.paragraph('', ' '.join(text)) o.line = node.sourcepos[0][0] for n in MarkDown(node): o.append(n) return o def text(node): """ Text in a paragraph """ return nodes.Text(node.literal) def hardbreak(node): """ A
in html or "\n" in ascii """ return nodes.Text('\n') def softbreak(node): """ A line ending or space. """ return nodes.Text('\n') def reference(node): """ A hyperlink. Note that alt text doesn't work, since there's no apparent way to do that in docutils """ o = nodes.reference() o['refuri'] = node.destination if node.title: o['name'] = node.title for n in MarkDown(node): o += n return o def emphasis(node): """ An italicized section """ o = nodes.emphasis() for n in MarkDown(node): o += n return o def strong(node): """ A bolded section """ o = nodes.strong() for n in MarkDown(node): o += n return o def literal(node): """ Inline code """ rendered = [] try: if node.info is not None: l = Lexer(node.literal, node.info, tokennames="long") for _ in l: rendered.append(node.inline(classes=_[0], text=_[1])) except: pass classes = ['code'] if node.info is not None: classes.append(node.info) if len(rendered) > 0: o = nodes.literal(classes=classes) for element in rendered: o += element else: o = nodes.literal(text=node.literal, classes=classes) for n in MarkDown(node): o += n return o def literal_block(node): """ A block of code """ rendered = [] try: if node.info is not None: l = Lexer(node.literal, node.info, tokennames="long") for _ in l: rendered.append(node.inline(classes=_[0], text=_[1])) except: pass classes = ['code'] if node.info is not None: classes.append(node.info) if len(rendered) > 0: o = nodes.literal_block(classes=classes) for element in rendered: o += element else: o = nodes.literal_block(text=node.literal, classes=classes) o.line = node.sourcepos[0][0] for n in MarkDown(node): o += n return o def raw(node): """ Add some raw html (possibly as a block) """ o = nodes.raw(node.literal, node.literal, format='html') if node.sourcepos is not None: o.line = node.sourcepos[0][0] for n in MarkDown(node): o += n return o def transition(node): """ An
tag in html. This has no children """ return nodes.transition() def title(node): """ A title node. It has no children """ return nodes.title(node.first_child.literal, node.first_child.literal) def section(node): """ A section in reStructuredText, which needs a title (the first child) This is a custom type """ title = '' # All sections need an id if node.first_child is not None: if node.first_child.t == u'heading': title = node.first_child.first_child.literal o = nodes.section(ids=[title], names=[title]) for n in MarkDown(node): o += n return o def block_quote(node): """ A block quote """ o = nodes.block_quote() o.line = node.sourcepos[0][0] for n in MarkDown(node): o += n return o def image(node): """ An image element The first child is the alt text. reStructuredText can't handle titles """ o = nodes.image(uri=node.destination) if node.first_child is not None: o['alt'] = node.first_child.literal return o def listItem(node): """ An item in a list """ o = nodes.list_item() for n in MarkDown(node): o += n return o def listNode(node): """ A list (numbered or not) For numbered lists, the suffix is only rendered as . in html """ if node.list_data['type'] == u'bullet': o = nodes.bullet_list(bullet=node.list_data['bullet_char']) else: o = nodes.enumerated_list(suffix=node.list_data['delimiter'], enumtype='arabic', start=node.list_data['start']) for n in MarkDown(node): o += n return o def MarkDown(node): """ Returns a list of nodes, containing CommonMark nodes converted to docutils nodes """ cur = node.first_child # Go into each child, in turn output = [] while cur is not None: t = cur.t if t == 'paragraph': output.append(paragraph(cur)) elif t == 'text': output.append(text(cur)) elif t == 'softbreak': output.append(softbreak(cur)) elif t == 'linebreak': output.append(hardbreak(cur)) elif t == 'link': output.append(reference(cur)) elif t == 'heading': output.append(title(cur)) elif t == 'emph': output.append(emphasis(cur)) elif t == 'strong': output.append(strong(cur)) elif t == 'code': output.append(literal(cur)) elif t == 'code_block': output.append(literal_block(cur)) elif t == 'html_inline' or t == 'html_block': output.append(raw(cur)) elif t == 'block_quote': output.append(block_quote(cur)) elif t == 'thematic_break': output.append(transition(cur)) elif t == 'image': output.append(image(cur)) elif t == 'list': output.append(listNode(cur)) elif t == 'item': output.append(listItem(cur)) elif t == 'MDsection': output.append(section(cur)) else: print('Received unhandled type: {}. Full print of node:'.format(t)) cur.pretty() cur = cur.nxt return output def finalizeSection(section): """ Correct the nxt and parent for each child """ cur = section.first_child last = section.last_child if last is not None: last.nxt = None while cur is not None: cur.parent = section cur = cur.nxt def nestSections(block, level=1): """ Sections aren't handled by CommonMark at the moment. This function adds sections to a block of nodes. 'title' nodes with an assigned level below 'level' will be put in a child section. If there are no child nodes with titles of level 'level' then nothing is done """ cur = block.first_child if cur is not None: children = [] # Do we need to do anything? nest = False while cur is not None: if cur.t == 'heading' and cur.level == level: nest = True break cur = cur.nxt if not nest: return section = Node('MDsection', 0) section.parent = block cur = block.first_child while cur is not None: if cur.t == 'heading' and cur.level == level: # Found a split point, flush the last section if needed if section.first_child is not None: finalizeSection(section) children.append(section) section = Node('MDsection', 0) nxt = cur.nxt # Avoid adding sections without titles at the start if section.first_child is None: if cur.t == 'heading' and cur.level == level: section.append_child(cur) else: children.append(cur) else: section.append_child(cur) cur = nxt # If there's only 1 child then don't bother if section.first_child is not None: finalizeSection(section) children.append(section) block.first_child = None block.last_child = None nextLevel = level + 1 for child in children: # Handle nesting if child.t == 'MDsection': nestSections(child, level=nextLevel) # Append if block.first_child is None: block.first_child = child else: block.last_child.nxt = child child.parent = block child.nxt = None child.prev = block.last_child block.last_child = child def parseMarkDownBlock(text): """ Parses a block of text, returning a list of docutils nodes >>> parseMarkdownBlock("Some\n====\n\nblock of text\n\nHeader\n======\n\nblah\n") [] """ block = Parser().parse(text) # CommonMark can't nest sections, so do it manually nestSections(block) return MarkDown(block) sphinx-argparse-0.2.2/sphinxarg/parser.py000066400000000000000000000144051325143412400205020ustar00rootroot00000000000000from argparse import _HelpAction, _SubParsersAction, _StoreConstAction import re class NavigationException(Exception): pass def parser_navigate(parser_result, path, current_path=None): if isinstance(path, str): if path == '': return parser_result path = re.split('\s+', path) current_path = current_path or [] if len(path) == 0: return parser_result if 'children' not in parser_result: raise NavigationException( 'Current parser has no child elements. (path: %s)' % ' '.join(current_path)) next_hop = path.pop(0) for child in parser_result['children']: if child['name'] == next_hop: current_path.append(next_hop) return parser_navigate(child, path, current_path) raise NavigationException( 'Current parser has no child element with name: %s (path: %s)' % ( next_hop, ' '.join(current_path))) def _try_add_parser_attribute(data, parser, attribname): attribval = getattr(parser, attribname, None) if attribval is None: return if not isinstance(attribval, str): return if len(attribval) > 0: data[attribname] = attribval def _format_usage_without_prefix(parser): """ Use private argparse APIs to get the usage string without the 'usage: ' prefix. """ fmt = parser._get_formatter() fmt.add_usage(parser.usage, parser._actions, parser._mutually_exclusive_groups, prefix='') return fmt.format_help().strip() def parse_parser(parser, data=None, **kwargs): if data is None: data = { 'name': '', 'usage': parser.format_usage().strip(), 'bare_usage': _format_usage_without_prefix(parser), 'prog': parser.prog, } _try_add_parser_attribute(data, parser, 'description') _try_add_parser_attribute(data, parser, 'epilog') for action in parser._get_positional_actions(): if not isinstance(action, _SubParsersAction): continue helps = {} for item in action._choices_actions: helps[item.dest] = item.help # commands which share an existing parser are an alias, # don't duplicate docs subsection_alias = {} subsection_alias_names = set() for name, subaction in action._name_parser_map.items(): if subaction not in subsection_alias: subsection_alias[subaction] = [] else: subsection_alias[subaction].append(name) subsection_alias_names.add(name) for name, subaction in action._name_parser_map.items(): if name in subsection_alias_names: continue subalias = subsection_alias[subaction] subaction.prog = '%s %s' % (parser.prog, name) subdata = { 'name': name if not subalias else '%s (%s)' % (name, ', '.join(subalias)), 'help': helps.get(name, ''), 'usage': subaction.format_usage().strip(), 'bare_usage': _format_usage_without_prefix(subaction), } parse_parser(subaction, subdata, **kwargs) data.setdefault('children', []).append(subdata) show_defaults = True if 'skip_default_values' in kwargs and kwargs['skip_default_values'] is True: show_defaults = False show_defaults_const = show_defaults if 'skip_default_const_values' in kwargs and kwargs['skip_default_const_values'] is True: show_defaults_const = False # argparse stores the different groups as a list in parser._action_groups # the first element of the list holds the positional arguments, the # second the option arguments not in groups, and subsequent elements # argument groups with positional and optional parameters action_groups = [] for action_group in parser._action_groups: options_list = [] for action in action_group._group_actions: if isinstance(action, _HelpAction): continue # Quote default values for string/None types default = action.default if action.default not in ['', None, True, False] and action.type in [None, str] and isinstance(action.default, str): default = '"%s"' % default # fill in any formatters, like %(default)s formatDict = dict(vars(action), prog=data.get('prog', ''), default=default) formatDict['default'] = default helpStr = action.help or '' # Ensure we don't print None try: helpStr = helpStr % formatDict except: pass # Options have the option_strings set, positional arguments don't name = action.option_strings if name == []: if action.metavar is None: name = [action.dest] else: name = [action.metavar] # Skip lines for subcommands if name == ['==SUPPRESS==']: continue if isinstance(action, _StoreConstAction): option = { 'name': name, 'default': default if show_defaults_const else '==SUPPRESS==', 'help': helpStr } else: option = { 'name': name, 'default': default if show_defaults else '==SUPPRESS==', 'help': helpStr } if action.choices: option['choices'] = action.choices if "==SUPPRESS==" not in option['help']: options_list.append(option) if len(options_list) == 0: continue # Upper case "Positional Arguments" and "Optional Arguments" titles if action_group.title == 'optional arguments': action_group.title = 'Named Arguments' if action_group.title == 'positional arguments': action_group.title = 'Positional Arguments' group = {'title': action_group.title, 'description': action_group.description, 'options': options_list} action_groups.append(group) if len(action_groups) > 0: data['action_groups'] = action_groups return data sphinx-argparse-0.2.2/test/000077500000000000000000000000001325143412400156045ustar00rootroot00000000000000sphinx-argparse-0.2.2/test/__init__.py000066400000000000000000000000001325143412400177030ustar00rootroot00000000000000sphinx-argparse-0.2.2/test/sample.py000066400000000000000000000042341325143412400174420ustar00rootroot00000000000000import argparse parser = argparse.ArgumentParser() subparsers = parser.add_subparsers() my_command1 = subparsers.add_parser('apply', help='Execute provision script, collect all resources and apply them.') my_command1.add_argument('path', help='Specify path to provision script. provision.py in current' 'directory by default. Also may include url.', default='provision.py') my_command1.add_argument('-r', '--rollback', action='store_true', default=False, help='If specified will rollback all' 'resources applied.') my_command1.add_argument('--tree', action='store_true', default=False, help='Print resource tree') my_command1.add_argument('--dry', action='store_true', default=False, help='Just print changes list') my_command1.add_argument('--force', action='store_true', default=False, help='Apply without confirmation') my_command1.add_argument('default_string', default='I am a default', help='Ensure variables are filled in %(prog)s (default %(default)s)') my_command2 = subparsers.add_parser('game', help='Decision games') my_command2.add_argument('move', choices=['rock', 'paper', 'scissors'], help='Choices for argument example') my_command2.add_argument('--opt', choices=['rock', 'paper', 'scissors'], help='Choices for option example') optional = my_command2.add_argument_group('Group 1') optional.add_argument('--addition', choices=['Spock', 'lizard'], help='Extra choices for additional group.') optional.add_argument('--lorem_ipsum', help='Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod ' 'tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, ' 'quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo ' 'consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse ' 'cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat ' 'non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.') sphinx-argparse-0.2.2/test/sample2.py000066400000000000000000000003621325143412400175220ustar00rootroot00000000000000import argparse def blah(): parser = argparse.ArgumentParser(description=""" ### Example of MarkDown inside programs [I'm a link](http://www.google.com) """) parser.add_argument('cmd', help='execute a `command`') return parser sphinx-argparse-0.2.2/test/test_parser.py000077500000000000000000000257071325143412400205270ustar00rootroot00000000000000import argparse from sphinxarg.parser import parse_parser, parser_navigate def test_parse_options(): parser = argparse.ArgumentParser() parser.add_argument('--foo', action='store_true', default=False, help='foo help') parser.add_argument('--bar', action='store_true', default=False) data = parse_parser(parser) assert data['action_groups'][0]['options'] == [ { 'name': ['--foo'], 'default': False, 'help': 'foo help' }, { 'name': ['--bar'], 'default': False, 'help': '' } ] def test_parse_default(): parser = argparse.ArgumentParser() parser.add_argument('--foo', default='123') data = parse_parser(parser) assert data['action_groups'][0]['options'] == [ { 'name': ['--foo'], 'default': '"123"', 'help': '' } ] def test_parse_arg_choices(): parser = argparse.ArgumentParser() parser.add_argument('move', choices=['rock', 'paper', 'scissors']) data = parse_parser(parser) assert data['action_groups'][0]['options'] == [ { 'name': ['move'], 'help': '', 'choices': ['rock', 'paper', 'scissors'], 'default': None } ] def test_parse_opt_choices(): parser = argparse.ArgumentParser() parser.add_argument('--move', choices=['rock', 'paper', 'scissors']) data = parse_parser(parser) assert data['action_groups'][0]['options'] == [ { 'name': ['--move'], 'default': None, 'help': '', 'choices': ['rock', 'paper', 'scissors'] } ] def test_parse_default_skip_default(): parser = argparse.ArgumentParser() parser.add_argument('--foo', default='123') data = parse_parser(parser, skip_default_values=True) assert data['action_groups'][0]['options'] == [ { 'name': ['--foo'], 'default': '==SUPPRESS==', 'help': '' } ] def test_parse_positional(): parser = argparse.ArgumentParser() parser.add_argument('foo', default=False, help='foo help') parser.add_argument('bar', default=False) data = parse_parser(parser) assert data['action_groups'][0]['options'] == [ { 'name': ['foo'], 'help': 'foo help', 'default': False }, { 'name': ['bar'], 'help': '', 'default': False } ] def test_parse_description(): parser = argparse.ArgumentParser(description='described', epilog='epilogged') parser.add_argument('foo', default=False, help='foo help') parser.add_argument('bar', default=False) data = parse_parser(parser) assert data['description'] == 'described' assert data['epilog'] == 'epilogged' assert data['action_groups'][0]['options'] == [ { 'name': ['foo'], 'help': 'foo help', 'default': False }, { 'name': ['bar'], 'help': '', 'default': False } ] def test_parse_nested(): parser = argparse.ArgumentParser() parser.add_argument('foo', default=False, help='foo help') parser.add_argument('bar', default=False) subparsers = parser.add_subparsers() subparser = subparsers.add_parser('install', help='install help') subparser.add_argument('ref', type=str, help='foo1 help') subparser.add_argument('--upgrade', action='store_true', default=False, help='foo2 help') data = parse_parser(parser) assert data['action_groups'][0]['options'] == [ { 'name': ['foo'], 'help': 'foo help', 'default': False }, { 'name': ['bar'], 'help': '', 'default': False } ] assert data['children'] == [ { 'name': 'install', 'help': 'install help', 'usage': 'usage: py.test install [-h] [--upgrade] ref', 'bare_usage': 'py.test install [-h] [--upgrade] ref', 'action_groups': [ { 'title': 'Positional Arguments', 'description': None, 'options': [ { 'name': ['ref'], 'help': 'foo1 help', 'default': None } ] }, { 'description': None, 'title': 'Named Arguments', 'options': [ { 'name': ['--upgrade'], 'default': False, 'help': 'foo2 help' } ] } ] } ] def test_parse_nested_traversal(): parser = argparse.ArgumentParser() subparsers1 = parser.add_subparsers() subparser1 = subparsers1.add_parser('level1') subparsers2 = subparser1.add_subparsers() subparser2 = subparsers2.add_parser('level2') subparsers3 = subparser2.add_subparsers() subparser3 = subparsers3.add_parser('level3') subparser3.add_argument('foo', help='foo help') subparser3.add_argument('bar') data = parse_parser(parser) data3 = parser_navigate(data, 'level1 level2 level3') assert data3['action_groups'][0]['options'] == [ { 'name': ['foo'], 'help': 'foo help', 'default': None }, { 'name': ['bar'], 'help': '', 'default': None } ] data2 = parser_navigate(data, 'level1 level2') assert data2['children'] == [ { 'name': 'level3', 'help': '', 'usage': 'usage: py.test level1 level2 level3 [-h] foo bar', 'bare_usage': 'py.test level1 level2 level3 [-h] foo bar', 'action_groups': [ { 'title': 'Positional Arguments', 'description': None, 'options': [ { 'default': None, 'name': ['foo'], 'help': 'foo help' }, { 'name': ['bar'], 'help': '', 'default': None } ] } ] } ] assert data == parser_navigate(data, '') def test_fill_in_default_prog(): """ Ensure that %(default)s and %(prog)s are getting properly filled in inside help='' """ parser = argparse.ArgumentParser(prog='test_fill_in_default_prog') parser.add_argument('bar', default='foo', help='%(prog)s (default: %(default)s)') data = parse_parser(parser) assert data['action_groups'][0]['options'] == [ { 'default': '"foo"', 'name': ['bar'], 'help': 'test_fill_in_default_prog (default: "foo")' } ] def test_string_quoting(): """ If an optional argument has a string type and a default, then the default should be in quotes. This prevents things like '--optLSFConf=-q short' when '--optLSFConf="-q short"' is correct. """ parser = argparse.ArgumentParser(prog='test_string_quoting_prog') parser.add_argument('--bar', default='foo bar', help='%(prog)s (default: %(default)s)') data = parse_parser(parser) assert data['action_groups'][0]['options'] == [ { 'default': '"foo bar"', 'name': ['--bar'], 'help': 'test_string_quoting_prog (default: "foo bar")' } ] def test_parse_groups(): parser = argparse.ArgumentParser() parser.add_argument('--foo', action='store_true', default=False, help='foo help') parser.add_argument('--bar', action='store_true', default=False) optional = parser.add_argument_group('Group 1') optional.add_argument("--option1", help='option #1') optional.add_argument("--option2", help='option #2') data = parse_parser(parser) assert data['action_groups'] == [ { 'description': None, 'options': [ {'default': False, 'help': 'foo help', 'name': ['--foo']}, {'default': False, 'help': '', 'name': ['--bar']}], 'title': 'Named Arguments'}, { 'description': None, 'options': [ {'default': None, 'help': 'option #1', 'name': ['--option1']}, {'default': None, 'help': 'option #2', 'name': ['--option2']}], 'title': 'Group 1' } ] def test_action_groups_with_subcommands(): """ This is a somewhat overly complicated example incorporating both action groups (with optional AND positional arguments) and subcommands (again with both optional and positional arguments) """ parser = argparse.ArgumentParser('foo') subparsers = parser.add_subparsers() parserA = subparsers.add_parser('A', help='A subparser') parserA.add_argument('baz', type=int, help='An integer') parserB = subparsers.add_parser('B', help='B subparser') parserB.add_argument('--barg', choices='XYZ', help='A list of choices') parser.add_argument('--foo', help='foo help') parser.add_argument('foo2', metavar='foo2 metavar', help='foo2 help') grp1 = parser.add_argument_group('bar options') grp1.add_argument('--bar', help='bar help') grp1.add_argument('quux', help='quux help') grp2 = parser.add_argument_group('bla options') grp2.add_argument('--blah', help='blah help') grp2.add_argument('sniggly', help='sniggly help') data = parse_parser(parser) assert data['action_groups'] == [ {'options': [{'default': None, 'name': ['foo2 metavar'], 'help': 'foo2 help'}], 'description': None, 'title': 'Positional Arguments'}, {'options': [{'default': None, 'name': ['--foo'], 'help': 'foo help'}], 'description': None, 'title': 'Named Arguments'}, {'options': [{'default': None, 'name': ['--bar'], 'help': 'bar help'}, {'default': None, 'name': ['quux'], 'help': 'quux help'}], 'description': None, 'title': 'bar options'}, {'options': [{'default': None, 'name': ['--blah'], 'help': 'blah help'}, {'default': None, 'name': ['sniggly'], 'help': 'sniggly help'}], 'description': None, 'title': 'bla options'} ] assert data['children'] == [ {'usage': 'usage: foo A [-h] baz', 'action_groups': [{'options': [{'default': None, 'name': ['baz'], 'help': 'An integer'}], 'description': None, 'title': 'Positional Arguments'}], 'bare_usage': 'foo A [-h] baz', 'name': 'A', 'help': 'A subparser'}, {'usage': 'usage: foo B [-h] [--barg {X,Y,Z}]', 'action_groups': [{'options': [{'default': None, 'choices': 'XYZ', 'name': ['--barg'], 'help': 'A list of choices'}], 'description': None, 'title': 'Named Arguments'}], 'bare_usage': 'foo B [-h] [--barg {X,Y,Z}]', 'name': 'B', 'help': 'B subparser'} ] sphinx-argparse-0.2.2/tox.ini000066400000000000000000000002061325143412400161360ustar00rootroot00000000000000[tox] envlist = py26,py27,py33,py34 [testenv] deps=pytest # install pytest in the venvs commands=py.test # or 'nosetests' or .