Sebastian Wiesner avatar Sebastian Wiesner committed 9be29ec

Initial import of the programoutput extension

Comments (0)

Files changed (13)

 
 ansi:
    Sebastian Wiesner <lunaryorn@googlemail.com>
+
+programoutput:
+   Sebastian Wiesner <lunaryorn@googlemail.com>
 - pyqt4: markup for PyQt4 signals
 - doxylink: Link to external Doxygen-generated HTML documentation
 - ansi: parse ANSI color sequences inside documents
+- programoutput: include output of programs into documentation
 
 .. _aafigure: http://docutils.sourceforge.net/sandbox/aafigure/
 

programoutput/CHANGES.rst

+0.4 (May 21, 2010)
+==================
+
+- Initial release

programoutput/MANIFEST.in

+include README
+include LICENSE
+include CHANGES.*
+recursive-include doc *.rst *.py Makefile
+prune doc/_build

programoutput/README

+###########################
+sphinxcontrib-programoutput
+###########################
+
+http://packages.python.org/sphinxcontrib-programoutput
+
+This Sphinx_ 1.0 extension executes programs during the build step and
+includes their output into the documentation.  It supports the
+`sphinxcontrib-ansi`_ extension to turn colored output of programs in
+pretty-formatted HTML.
+
+
+Installation
+------------
+
+This extension can be installed from the Python Package Index::
+
+   pip install sphinx-contrib.programoutput
+
+Alternatively, you can clone the sphinx-contrib_ repository from BitBucket,
+and install the extension directly from the repository::
+
+   hg clone http://bitbucket.org/birkenfeld/sphinx-contrib
+   cd sphinx-contrib/programoutput
+   python setup.py install
+
+
+Usage
+-----
+
+Please refer to the documentation_ for further information.
+
+
+.. _`Sphinx`: http://sphinx.pocoo.org/latest
+.. _`sphinxcontrib-ansi`: http://packages.python.org/sphinxcontrib-ansi
+.. _`sphinx-contrib`: http://bitbucket.org/birkenfeld/sphinx-contrib
+.. _documentation: http://packages.python.org/sphinxcontrib-programoutput

programoutput/doc/Makefile

+# 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) .
+
+.PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest
+
+help:
+	@echo "Please use \`make <target>' where <target> 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 "  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/sphinxcontrib-programoutput.qhcp"
+	@echo "To view the help file:"
+	@echo "# assistant -collectionFile $(BUILDDIR)/qthelp/sphinxcontrib-programoutput.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/sphinxcontrib-programoutput"
+	@echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/sphinxcontrib-programoutput"
+	@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."
+
+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."

programoutput/doc/changes.rst

+#########
+Changelog
+#########
+
+.. include:: ../CHANGES.rst

programoutput/doc/conf.py

+# -*- coding: utf-8 -*-
+
+import sys, os
+
+extensions = ['sphinx.ext.intersphinx',
+              'sphinxcontrib.programoutput']
+
+source_suffix = '.rst'
+master_doc = 'index'
+
+project = u'sphinxcontrib-programoutput'
+copyright = u'2010, Sebastian Wiesner'
+version = '0.4'
+release = '0.4'
+
+exclude_patterns = ['_build']
+
+html_theme = 'default'
+html_static_path = []
+
+intersphinx_mapping = {
+    'http://packages.python.org/sphinxcontrib-ansi': None}
+
+
+def setup(app):
+    app.add_description_unit('confval', 'confval',
+                             'pair: %s; configuration value')

programoutput/doc/index.rst

+.. default-domain:: rst
+.. highlight:: rest
+
+:py:mod:`sphinxcontrib.programoutput` -- Include program output
+==================================================================
+
+.. py:module:: sphinxcontrib.programoutput
+   :synopsis:  Include the output of programs into documents
+
+This extension for Sphinx_ 1.0 allows to run programs during the build
+process, including their output into the documentation.  It supports the
+:py:mod:`sphinxcontrib.ansi` extension to turn colored output of programs in
+pretty-formatted HTML.
+
+The extension is available under the terms of the BSD license, see LICENSE_
+for more information.
+
+
+Installation
+------------
+
+This extension can be installed from the Python Package Index::
+
+   pip install sphinx-contrib.programoutput
+
+Alternatively, you can clone the sphinx-contrib_ repository from BitBucket,
+and install the extension directly from the repository::
+
+   hg clone http://bitbucket.org/birkenfeld/sphinx-contrib
+   cd sphinx-contrib/programoutput
+   python setup.py install
+
+
+Usage
+-----
+
+The main directive is :dir:`program-output`:
+
+.. directive:: program-output
+
+   This directive accepts a single string as argument, which is the command
+   to execute.  By default, this command string is split using the
+   :py:mod:`shlex` modules, which mostly works like common Unix shells like
+   ``bash`` or ``zsh``::
+
+      .. program-output:: python -V
+
+   The above snippet would render like this:
+
+   .. program-output:: python -V
+
+   However, special shell features like parameter expansion are not
+   supported::
+
+      .. program-output:: echo "$USER"
+
+   .. program-output:: echo "$USER"
+
+   To enable such shell features, use option ``shell``.  If this option is
+   given, the command string is executed using ``/bin/sh -c``::
+
+      .. program-output:: echo "$USER"
+         :shell:
+
+   .. program-output:: echo "$USER"
+      :shell:
+
+   By default, both standard output *and* standard error are captured and
+   included in the document.  Use option ``nostderr`` to hide anything from
+   the standard error stream of the invoked program.
+
+   Using the option ``prompt`` you can include the command, that produced
+   the output.  The result will mimic input on a shell prompt with the
+   resulting output::
+
+      .. program-output:: python -V
+         :prompt:
+
+   .. program-output:: python -V
+      :prompt:
+
+   The prompt can be configured using
+   :confval:`programoutput_prompt_template`.  The directive
+   :dir:`command-output` provides a convenient shortcut to this directive
+   with ``prompt``.
+
+   Sometimes the program may require options, you may not want to include in
+   the prompt.  You can use the ``extraargs`` option for this purpose.  The
+   value of this options is parsed just like the command itself, and
+   afterwards appended to the command.  It will however never appear in the
+   output, if ``prompt`` is specified.
+
+   Lengthy output can be shortened using the ``ellipsis`` option.  This
+   option accepts at most two comma-separated integers, which refer to lines
+   in the output.  If the second integer is missing, it refers to the last
+   line.  Everything in between these lines is replaced by a single ellipsis
+   ``...``::
+
+      .. program-output::  python --help
+         :prompt:
+         :ellipsis: 2
+
+   .. program-output::  python --help
+      :prompt:
+      :ellipsis: 2
+
+   Negative line numbers are counted from the last-line.  Thus specifying
+   ``:ellipsis:  2, -2`` will remove anything except the first two and the
+   last two lines::
+
+      .. program-output::  python --help
+         :prompt:
+         :shell:
+         :ellipsis: 2, -2
+
+   .. program-output::  python --help
+      :prompt:
+      :shell:
+      :ellipsis: 2, -2
+
+
+.. directive:: command-output
+
+   Just like :dir:`program-output`, but with ``prompt`` enabled.
+
+
+Configuration
+^^^^^^^^^^^^^
+
+This extension understands the following configuration options:
+
+.. confval:: programoutput_prompt_template
+
+   This configuration value defines the looks of the output of
+   :dir:`command-output` and :dir:`program-output` with option ``prompt``.
+   The default value is ``$ %(command)s\n%(output)s``.  The key ``command``
+   is replaced with the command, the key ``output`` with the output of this
+   command.
+
+.. confval:: programoutput_use_ansi
+
+   Interpret ANSI colour sequences in program output.  The extension
+   :py:mod:`sphinxcontrib.ansi` must be enabled and configured to use this
+   feature!
+
+Contribution
+------------
+
+Please contact the author or create an issue in the `issue tracker`_ of the
+sphinx-contrib_ repository, if you have found any bugs or miss some
+functionality (e.g. integration of some other issue tracker).  Patches are
+welcome!
+
+
+.. toctree::
+   :maxdepth: 2
+   :hidden:
+
+   changes.rst
+
+
+.. _`Sphinx`: http://sphinx.pocoo.org/
+.. _`sphinx-contrib`: http://bitbucket.org/birkenfeld/sphinx-contrib
+.. _`issue tracker`: http://bitbucket.org/birkenfeld/sphinx-contrib/issues
+.. _LICENSE: http://bitbucket.org/birkenfeld/sphinx-contrib/src/tip/LICENSE

programoutput/setup.cfg

+[egg_info]
+tag_build = dev
+tag_date = true
+
+[aliases]
+release = egg_info -RDb ''

programoutput/setup.py

+# -*- coding: utf-8 -*-
+
+from setuptools import setup, find_packages
+
+
+with open('README') as stream:
+    long_desc = stream.read()
+
+
+requires = ['Sphinx>=1.0']
+
+setup(
+    name='sphinxcontrib-programoutput',
+    version='0.4',
+    url='http://packages.python.org/sphinxcontrib-programoutput',
+    download_url='http://pypi.python.org/pypi/sphinxcontrib-programoutput',
+    license='BSD',
+    author='Sebastian Wiesner',
+    author_email='lunaryorn@googlemail.com',
+    description='Sphinx extension to include program output',
+    long_description=long_desc,
+    zip_safe=False,
+    classifiers=[
+        'Development Status :: 4 - Beta',
+        'Environment :: Console',
+        'Environment :: Web Environment',
+        'Intended Audience :: Developers',
+        'License :: OSI Approved :: BSD License',
+        'Operating System :: OS Independent',
+        'Programming Language :: Python',
+        'Topic :: Documentation',
+        'Topic :: Utilities',
+    ],
+    platforms='any',
+    packages=find_packages(),
+    include_package_data=True,
+    install_requires=requires,
+    namespace_packages=['sphinxcontrib'],
+)

programoutput/sphinxcontrib/__init__.py

+# -*- coding: utf-8 -*-
+"""
+    sphinxcontrib
+    ~~~~~~~~~~~~~
+
+    This package is a namespace package that contains all extensions
+    distributed in the ``sphinx-contrib`` distribution.
+
+    :copyright: Copyright 2007-2009 by the Sphinx team, see AUTHORS.
+    :license: BSD, see LICENSE for details.
+"""
+
+__import__('pkg_resources').declare_namespace(__name__)
+

programoutput/sphinxcontrib/programoutput.py

+# -*- coding: utf-8 -*-
+# Copyright (c) 2010, Sebastian Wiesner <lunaryorn@googlemail.com>
+# All rights reserved.
+
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are met:
+
+# 1. Redistributions of source code must retain the above copyright notice,
+#    this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+#    notice, this list of conditions and the following disclaimer in the
+#    documentation and/or other materials provided with the distribution.
+
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.
+
+
+"""
+    sphinxcontrib.programoutput
+    ===========================
+
+    This extension provides a directive to include the output of commands as
+    literal block while building the docs.
+
+    .. moduleauthor::  Sebastian Wiesner  <lunaryorn@googlemail.com>
+"""
+
+
+import os
+import sys
+import shlex
+import cPickle as pickle
+from subprocess import Popen, CalledProcessError, PIPE, STDOUT
+from collections import defaultdict
+
+from docutils import nodes
+from docutils.parsers import rst
+from docutils.parsers.rst.directives import flag, unchanged
+from sphinx.util.console import bold
+
+
+class program_output(nodes.Element):
+    pass
+
+
+def _slice(value):
+    parts = [int(v.strip()) for v in value.split(',')]
+    if len(parts) > 2:
+        raise ValueError('Need excatly two arguments')
+    return (parts + [None]*2)[:2]
+
+
+class ProgramOutputDirective(rst.Directive):
+    has_content = False
+    final_argument_whitespace = True
+    required_arguments = 1
+
+    option_spec = dict(shell=flag, prompt=flag, nostderr=flag,
+                       ellipsis=_slice, extraargs=unchanged)
+
+    def run(self):
+        node = program_output()
+        node['command'] = self.arguments[0]
+
+        if self.name == 'command-output':
+            node['show_prompt'] = True
+        else:
+            node['show_prompt'] = 'prompt' in self.options
+
+        node['hide_standard_error'] = 'nostderr' in self.options
+        node['extraargs'] = self.options.get('extraargs', '')
+        node['use_shell'] = 'shell' in self.options
+        if 'ellipsis' in self.options:
+            node['strip_lines'] = self.options['ellipsis']
+        return [node]
+
+
+class ProgramOutputCache(defaultdict):
+    """
+    :class:`collections.defaultdict` sub-class, which caches program output.
+
+    If a program's output is not contained in this cache, the program is
+    executed, and its output is placed in the cache.
+    """
+
+    def __missing__(self, key):
+        """
+        Called, if a command was not found in the cache.
+
+        ``key`` is a triple of ``(cmd, shell, hide_stderr)``.  ``cmd`` is
+        the command tuple.  If ``shell`` is ``True``, the command is
+        executed in the shell, otherwise it is executed directly.  If
+        ``hide_stderr`` is ``True``, the standard error of the program is
+        discarded, otherwise it is included in the output.
+        """
+        cmd, shell, hide_stderr = key
+        proc = Popen(cmd, shell=shell, stdout=PIPE,
+                     stderr=PIPE if hide_stderr else STDOUT)
+        stdout = proc.communicate()[0].decode(
+            sys.getfilesystemencoding()).rstrip()
+        if proc.returncode != 0:
+            raise CalledProcessError(proc.returncode, cmd)
+        self[key] = stdout
+        return stdout
+
+
+def run_programs(app, doctree):
+    """
+    Execute all programs represented by ``program_output`` nodes in
+    ``doctree``.  Each ``program_output`` node in ``doctree`` is then
+    replaced with a node, that represents the output of this program.
+
+    The program output is retrieved from the cache in
+    ``app.env.programoutput_cache``.
+    """
+    if app.config.programoutput_use_ansi:
+        # enable ANSI support, if requested by config
+        from sphinxcontrib.ansi import ansi_literal_block
+        node_class = ansi_literal_block
+    else:
+        node_class = nodes.literal_block
+
+    cache = app.env.programoutput_cache
+
+    for node in doctree.traverse(program_output):
+        command = node['command']
+        cmd_bytes = command.encode(sys.getfilesystemencoding())
+
+        extra_args = node.get('extraargs', '').encode(
+            sys.getfilesystemencoding())
+        if node['use_shell']:
+            cmd = cmd_bytes + ' ' + extra_args
+        else:
+            cmd = shlex.split(cmd_bytes)
+            if extra_args:
+                cmd.extend(shlex.split(extra_args))
+            cmd = tuple(cmd)
+
+        cache_key = (cmd, node['use_shell'], node['hide_standard_error'])
+        output = cache[cache_key]
+
+        # replace lines with ..., if ellipsis is specified
+        if 'strip_lines' in node:
+            lines = output.splitlines()
+            start, stop = node['strip_lines']
+            lines[start:stop] = ['...']
+            output = '\n'.join(lines)
+
+        if node['show_prompt']:
+            tmpl = app.config.programoutput_prompt_template
+            output = tmpl % dict(command=command, output=output)
+
+        new_node = node_class(output, output)
+        new_node['language'] = 'text'
+        node.replace_self(new_node)
+
+
+def init_cache(app):
+    """
+    Initialize the cache for program output at
+    ``app.env.programoutput_cache``, if not already present (e.g. being
+    loaded from a pickled environment).
+
+    The cache is of type :class:`ProgramOutputCache`.
+    """
+    if not hasattr(app.env, 'programoutput_cache'):
+        app.env.programoutput_cache = ProgramOutputCache()
+
+
+def setup(app):
+    app.add_config_value('programoutput_use_ansi', False, 'env')
+    app.add_config_value('programoutput_prompt_template',
+                         '$ %(command)s\n%(output)s', 'env')
+    app.add_directive('program-output', ProgramOutputDirective)
+    app.add_directive('command-output', ProgramOutputDirective)
+    app.connect('builder-inited', init_cache)
+    app.connect('doctree-read', run_programs)
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.