[Python-checkins] r68313 - in doctools/trunk: AUTHORS CHANGES EXAMPLES LICENSE MANIFEST.in README TODO babel.cfg doc/Makefile doc/_templates/index.html doc/_templates/indexsidebar.html doc/builders.rst doc/concepts.rst doc/conf.py doc/config.rst doc/ext/appapi.rst doc/ext/builderapi.rst doc/ext/coverage.rst doc/ext/doctest.rst doc/ext/math.rst doc/ext/refcounting.rst doc/ext/todo.rst doc/ext/tutorial.rst doc/extensions.rst doc/glossary.rst doc/intro.rst doc/markup/code.rst doc/markup/desc.rst doc/markup/inline.rst doc/markup/para.rst doc/rest.rst doc/sphinx-build.1 doc/sphinx-quickstart.1 doc/templating.rst ez_setup.py setup.py sphinx-build.py sphinx-quickstart.py sphinx/__init__.py sphinx/__init__.pyc sphinx/_jinja.py sphinx/addnodes.py sphinx/application.py sphinx/builder.py sphinx/builders sphinx/builders/__init__.py sphinx/builders/changes.py sphinx/builders/html.py sphinx/builders/htmlhelp.py sphinx/builders/latex.py sphinx/builders/linkcheck.py sphinx/builders/qthelp.py sphinx/builders/text.py sphinx/cmdline.py sphinx/config.py sphinx/directives/__init__.py sphinx/directives/code.py sphinx/directives/desc.py sphinx/directives/other.py sphinx/environment.py sphinx/ext/__init__.py sphinx/ext/autodoc.py sphinx/ext/coverage.py sphinx/ext/doctest.py sphinx/ext/ifconfig.py sphinx/ext/intersphinx.py sphinx/ext/jsmath.py sphinx/ext/mathbase.py sphinx/ext/pngmath.py sphinx/ext/refcounting.py sphinx/ext/todo.py sphinx/highlighting.py sphinx/jinja2glue.py sphinx/locale/__init__.py sphinx/locale/cs/LC_MESSAGES/sphinx.js sphinx/locale/cs/LC_MESSAGES/sphinx.mo sphinx/locale/cs/LC_MESSAGES/sphinx.po sphinx/locale/de/LC_MESSAGES/sphinx.po sphinx/locale/es/LC_MESSAGES/sphinx.po sphinx/locale/fr/LC_MESSAGES/sphinx.po sphinx/locale/it sphinx/locale/it/LC_MESSAGES sphinx/locale/it/LC_MESSAGES/sphinx.js sphinx/locale/it/LC_MESSAGES/sphinx.mo sphinx/locale/it/LC_MESSAGES/sphinx.po sphinx/locale/ja/LC_MESSAGES/sphinx.po sphinx/locale/nl/LC_MESSAGES/sphinx.po sphinx/locale/pl/LC_MESSAGES/sphinx.po sphinx/locale/pt_BR/LC_MESSAGES/sphinx.po sphinx/locale/sl/LC_MESSAGES/sphinx.po sphinx/locale/sphinx.pot sphinx/locale/zh_TW/LC_MESSAGES/sphinx.po sphinx/pycode sphinx/pycode/Grammar.txt sphinx/pycode/__init__.py sphinx/pycode/nodes.py sphinx/pycode/pgen2 sphinx/pycode/pgen2/__init__.py sphinx/pycode/pgen2/driver.py sphinx/pycode/pgen2/grammar.py sphinx/pycode/pgen2/literals.py sphinx/pycode/pgen2/parse.c sphinx/pycode/pgen2/parse.py sphinx/pycode/pgen2/parse.pyx sphinx/pycode/pgen2/pgen.py sphinx/pycode/pgen2/token.py sphinx/pycode/pgen2/tokenize.py sphinx/quickstart.py sphinx/roles.py sphinx/search.py sphinx/setup_command.py sphinx/static/searchtools.js sphinx/templates/changes/versionchanges.html sphinx/templates/layout.html sphinx/templates/modindex.html sphinx/templates/page.html sphinx/texinputs/sphinx.sty sphinx/util/__init__.py sphinx/util/compat.py sphinx/util/console.py sphinx/util/docstrings.py sphinx/util/jsdump.py sphinx/util/png.py sphinx/util/stemmer.py sphinx/util/texescape.py sphinx/writers sphinx/writers/__init__.py sphinx/writers/html.py sphinx/writers/latex.py sphinx/writers/text.py tests/root/_static/README tests/root/_templates/layout.html tests/root/conf.py tests/root/contents.txt tests/root/ext.pyc tests/root/images.txt tests/root/includes.txt tests/root/literal.inc tests/root/markup.txt tests/root/subdir/images.txt tests/root/subdir/simg.png tests/run.py tests/test_application.py tests/test_autodoc.py tests/test_build.py tests/test_config.py tests/test_coverage.py tests/test_env.py tests/test_highlighting.py tests/test_i18n.py tests/test_markup.py tests/test_quickstart.py tests/util.py utils/check_sources.py

benjamin.peterson python-checkins at python.org
Sun Jan 4 21:39:00 CET 2009


Author: benjamin.peterson
Date: Sun Jan  4 21:38:57 2009
New Revision: 68313

Log:
update to sphinx hg:964

Added:
   doctools/trunk/MANIFEST.in   (contents, props changed)
   doctools/trunk/doc/ext/todo.rst   (contents, props changed)
   doctools/trunk/doc/ext/tutorial.rst   (contents, props changed)
   doctools/trunk/doc/sphinx-build.1   (contents, props changed)
   doctools/trunk/doc/sphinx-quickstart.1   (contents, props changed)
   doctools/trunk/sphinx/__init__.pyc   (contents, props changed)
   doctools/trunk/sphinx/builders/
   doctools/trunk/sphinx/builders/__init__.py   (contents, props changed)
   doctools/trunk/sphinx/builders/changes.py   (contents, props changed)
   doctools/trunk/sphinx/builders/html.py   (contents, props changed)
   doctools/trunk/sphinx/builders/htmlhelp.py   (contents, props changed)
   doctools/trunk/sphinx/builders/latex.py   (contents, props changed)
   doctools/trunk/sphinx/builders/linkcheck.py   (contents, props changed)
   doctools/trunk/sphinx/builders/qthelp.py   (contents, props changed)
   doctools/trunk/sphinx/builders/text.py   (contents, props changed)
   doctools/trunk/sphinx/jinja2glue.py   (contents, props changed)
   doctools/trunk/sphinx/locale/it/
   doctools/trunk/sphinx/locale/it/LC_MESSAGES/
   doctools/trunk/sphinx/locale/it/LC_MESSAGES/sphinx.js   (contents, props changed)
   doctools/trunk/sphinx/locale/it/LC_MESSAGES/sphinx.mo   (contents, props changed)
   doctools/trunk/sphinx/locale/it/LC_MESSAGES/sphinx.po   (contents, props changed)
   doctools/trunk/sphinx/pycode/
   doctools/trunk/sphinx/pycode/Grammar.txt   (contents, props changed)
   doctools/trunk/sphinx/pycode/__init__.py   (contents, props changed)
   doctools/trunk/sphinx/pycode/nodes.py   (contents, props changed)
   doctools/trunk/sphinx/pycode/pgen2/
   doctools/trunk/sphinx/pycode/pgen2/__init__.py   (contents, props changed)
   doctools/trunk/sphinx/pycode/pgen2/driver.py   (contents, props changed)
   doctools/trunk/sphinx/pycode/pgen2/grammar.py   (contents, props changed)
   doctools/trunk/sphinx/pycode/pgen2/literals.py   (contents, props changed)
   doctools/trunk/sphinx/pycode/pgen2/parse.c   (contents, props changed)
   doctools/trunk/sphinx/pycode/pgen2/parse.py   (contents, props changed)
   doctools/trunk/sphinx/pycode/pgen2/parse.pyx   (contents, props changed)
   doctools/trunk/sphinx/pycode/pgen2/pgen.py   (contents, props changed)
   doctools/trunk/sphinx/pycode/pgen2/token.py   (contents, props changed)
   doctools/trunk/sphinx/pycode/pgen2/tokenize.py   (contents, props changed)
   doctools/trunk/sphinx/util/docstrings.py   (contents, props changed)
   doctools/trunk/sphinx/util/png.py   (contents, props changed)
   doctools/trunk/sphinx/writers/
   doctools/trunk/sphinx/writers/__init__.py   (contents, props changed)
   doctools/trunk/sphinx/writers/html.py   (contents, props changed)
   doctools/trunk/sphinx/writers/latex.py   (contents, props changed)
   doctools/trunk/sphinx/writers/text.py   (contents, props changed)
   doctools/trunk/tests/root/_static/README   (contents, props changed)
   doctools/trunk/tests/root/_templates/layout.html   (contents, props changed)
   doctools/trunk/tests/root/ext.pyc   (contents, props changed)
   doctools/trunk/tests/root/subdir/images.txt   (contents, props changed)
   doctools/trunk/tests/root/subdir/simg.png   (contents, props changed)
   doctools/trunk/tests/test_highlighting.py   (contents, props changed)
Modified:
   doctools/trunk/AUTHORS
   doctools/trunk/CHANGES
   doctools/trunk/EXAMPLES
   doctools/trunk/LICENSE
   doctools/trunk/README
   doctools/trunk/TODO
   doctools/trunk/babel.cfg
   doctools/trunk/doc/Makefile
   doctools/trunk/doc/_templates/index.html
   doctools/trunk/doc/_templates/indexsidebar.html
   doctools/trunk/doc/builders.rst
   doctools/trunk/doc/concepts.rst
   doctools/trunk/doc/conf.py
   doctools/trunk/doc/config.rst
   doctools/trunk/doc/ext/appapi.rst
   doctools/trunk/doc/ext/builderapi.rst
   doctools/trunk/doc/ext/coverage.rst
   doctools/trunk/doc/ext/doctest.rst
   doctools/trunk/doc/ext/math.rst
   doctools/trunk/doc/ext/refcounting.rst
   doctools/trunk/doc/extensions.rst
   doctools/trunk/doc/glossary.rst
   doctools/trunk/doc/intro.rst
   doctools/trunk/doc/markup/code.rst
   doctools/trunk/doc/markup/desc.rst
   doctools/trunk/doc/markup/inline.rst
   doctools/trunk/doc/markup/para.rst
   doctools/trunk/doc/rest.rst
   doctools/trunk/doc/templating.rst
   doctools/trunk/ez_setup.py
   doctools/trunk/setup.py
   doctools/trunk/sphinx-build.py
   doctools/trunk/sphinx-quickstart.py
   doctools/trunk/sphinx/__init__.py
   doctools/trunk/sphinx/_jinja.py
   doctools/trunk/sphinx/addnodes.py
   doctools/trunk/sphinx/application.py
   doctools/trunk/sphinx/builder.py
   doctools/trunk/sphinx/cmdline.py
   doctools/trunk/sphinx/config.py
   doctools/trunk/sphinx/directives/__init__.py
   doctools/trunk/sphinx/directives/code.py
   doctools/trunk/sphinx/directives/desc.py
   doctools/trunk/sphinx/directives/other.py
   doctools/trunk/sphinx/environment.py
   doctools/trunk/sphinx/ext/__init__.py
   doctools/trunk/sphinx/ext/autodoc.py
   doctools/trunk/sphinx/ext/coverage.py
   doctools/trunk/sphinx/ext/doctest.py
   doctools/trunk/sphinx/ext/ifconfig.py
   doctools/trunk/sphinx/ext/intersphinx.py
   doctools/trunk/sphinx/ext/jsmath.py
   doctools/trunk/sphinx/ext/mathbase.py
   doctools/trunk/sphinx/ext/pngmath.py
   doctools/trunk/sphinx/ext/refcounting.py
   doctools/trunk/sphinx/ext/todo.py
   doctools/trunk/sphinx/highlighting.py
   doctools/trunk/sphinx/locale/__init__.py
   doctools/trunk/sphinx/locale/cs/LC_MESSAGES/sphinx.js
   doctools/trunk/sphinx/locale/cs/LC_MESSAGES/sphinx.mo
   doctools/trunk/sphinx/locale/cs/LC_MESSAGES/sphinx.po
   doctools/trunk/sphinx/locale/de/LC_MESSAGES/sphinx.po
   doctools/trunk/sphinx/locale/es/LC_MESSAGES/sphinx.po
   doctools/trunk/sphinx/locale/fr/LC_MESSAGES/sphinx.po
   doctools/trunk/sphinx/locale/ja/LC_MESSAGES/sphinx.po
   doctools/trunk/sphinx/locale/nl/LC_MESSAGES/sphinx.po
   doctools/trunk/sphinx/locale/pl/LC_MESSAGES/sphinx.po
   doctools/trunk/sphinx/locale/pt_BR/LC_MESSAGES/sphinx.po
   doctools/trunk/sphinx/locale/sl/LC_MESSAGES/sphinx.po
   doctools/trunk/sphinx/locale/sphinx.pot
   doctools/trunk/sphinx/locale/zh_TW/LC_MESSAGES/sphinx.po
   doctools/trunk/sphinx/quickstart.py
   doctools/trunk/sphinx/roles.py
   doctools/trunk/sphinx/search.py
   doctools/trunk/sphinx/setup_command.py
   doctools/trunk/sphinx/static/searchtools.js
   doctools/trunk/sphinx/templates/changes/versionchanges.html
   doctools/trunk/sphinx/templates/layout.html
   doctools/trunk/sphinx/templates/modindex.html
   doctools/trunk/sphinx/templates/page.html
   doctools/trunk/sphinx/texinputs/sphinx.sty
   doctools/trunk/sphinx/util/__init__.py
   doctools/trunk/sphinx/util/compat.py
   doctools/trunk/sphinx/util/console.py
   doctools/trunk/sphinx/util/jsdump.py
   doctools/trunk/sphinx/util/stemmer.py
   doctools/trunk/sphinx/util/texescape.py
   doctools/trunk/tests/root/conf.py
   doctools/trunk/tests/root/contents.txt
   doctools/trunk/tests/root/images.txt
   doctools/trunk/tests/root/includes.txt
   doctools/trunk/tests/root/literal.inc
   doctools/trunk/tests/root/markup.txt
   doctools/trunk/tests/run.py
   doctools/trunk/tests/test_application.py
   doctools/trunk/tests/test_autodoc.py
   doctools/trunk/tests/test_build.py
   doctools/trunk/tests/test_config.py
   doctools/trunk/tests/test_coverage.py
   doctools/trunk/tests/test_env.py
   doctools/trunk/tests/test_i18n.py
   doctools/trunk/tests/test_markup.py
   doctools/trunk/tests/test_quickstart.py
   doctools/trunk/tests/util.py
   doctools/trunk/utils/check_sources.py

Modified: doctools/trunk/AUTHORS
==============================================================================
--- doctools/trunk/AUTHORS	(original)
+++ doctools/trunk/AUTHORS	Sun Jan  4 21:38:57 2009
@@ -1,8 +1,27 @@
-The doctools are written and maintained by Georg Brandl <georg at python.org>.
-Substantial parts of the templates and the web application were written by
-Armin Ronacher <armin.ronacher at active-4.com>.
+Sphinx is written and maintained by Georg Brandl <georg at python.org>.
 
-Other contributors are noted in the :copyright: fields within the docstrings
-of the respective files.
+Substantial parts of the templates were written by Armin Ronacher
+<armin.ronacher at active-4.com>.
+
+Other contributors, listed alphabetically, are:
+
+* Daniel Bültmann -- todo extension
+* Josip Dzolonga -- coverage builder
+* Horst Gutmann -- internationalization support
+* Martin Hans -- autodoc improvements
+* Dave Kuhlman -- original LaTeX writer
+* Thomas Lamb -- linkcheck builder
+* Benjamin Peterson -- unittests
+* Antonio Valentino -- qthelp builder
+* Pauli Virtanen -- autodoc improvements
+* Sebastian Wiesner -- image handling, distutils support
 
 Many thanks for all contributions!
+
+There are also a few modules or functions incorporated from other
+authors and projects:
+
+* sphinx.util.jsdump uses the basestring encoding from simplejson,
+  written by Bob Ippolito, released under the MIT license
+* sphinx.util.stemmer was written by Vivake Gupta, placed in the
+  Public Domain

Modified: doctools/trunk/CHANGES
==============================================================================
--- doctools/trunk/CHANGES	(original)
+++ doctools/trunk/CHANGES	Sun Jan  4 21:38:57 2009
@@ -1,9 +1,152 @@
-Release 0.5 (in development)
+Release 0.6 (in development)
 ============================
 
 New features added
 ------------------
 
+* Incompatible changes:
+
+  - Templating now requires the Jinja2 library, which is an enhanced
+    version of the old Jinja1 engine.  Since the syntax and semantic
+    is largely the same, very few fixes should be necessary in
+    custom templates.
+
+  - The ``autodoc_skip_member`` event now also gets to decide
+    whether to skip members whose name starts with underscores.
+    Previously, these members were always automatically skipped.
+    Therefore, if you handle this event, add something like this
+    to your event handler to restore the old behavior::
+
+       if name.startswith('_'):
+           return True
+
+* Markup:
+
+  - Due to popular demand, added a ``:doc:`` role which directly
+    links to another document without the need of creating a
+    label to which a ``:ref:`` could link to.
+
+  - #4: Added a ``:download:`` role that marks a non-document file
+    for inclusion into the HTML output and links to it.
+
+  - The ``literalinclude`` directive now supports several more
+    options, to include only parts of a file.
+
+  - The ``toctree`` directive now supports a ``:hidden:`` flag,
+    which will prevent links from being generated in place of
+    the directive -- this allows you to define your document
+    structure, but place the links yourself.
+
+  - #77: If a description environment with info field list only
+    contains one ``:param:`` entry, no bullet list is generated.
+
+  - #6: Don't generate redundant ``<ul>`` for top-level TOC tree
+    items, which leads to a visual separation of TOC entries.
+
+  - #23: Added a ``classmethod`` directive along with ``method``
+    and ``staticmethod``.
+
+* Configuration:
+
+  - The new ``html_add_permalinks`` config value can be used to
+    switch off the generated "paragraph sign" permalinks for each
+    heading and definition environment.
+
+  - The new ``html_show_sourcelink`` config value can be used to
+    switch off the links to the reST sources in the sidebar.
+
+  - The default value for ``htmlhelp_basename`` is now the project
+    title, cleaned up as a filename.
+
+* Builders:
+
+  - New builder for Qt help collections, by Antonio Valentino.
+
+  - The new ``html_link_suffix`` config value can be used to select
+    the suffix of generated links between HTML files.
+
+* New translations:
+  
+  - Italian by Sandro Dentella.
+
+* Extensions and API:
+
+  - Autodoc now handles documented attributes.
+
+  - Autodoc now handles inner classes and their methods.
+
+  - There is now a ``Sphinx.add_lexer()`` method to be able to use
+    custom Pygments lexers easily.
+
+* Other changes:
+
+  - Config overrides for single dict keys can now be given on the
+    command line.
+
+  - There is now a ``doctest_global_setup`` config value that can
+    be used to give setup code for all doctests in the documentation.
+
+  - Source links in HTML are now generated with ``rel="nofollow"``.
+
+
+Release 0.5.2 (in development)
+==============================
+
+* #81: Write environment and search index in a manner that is safe
+  from exceptions that occur during dumping.
+
+* #80: Fix UnicodeErrors when a locale is set with setlocale().
+
+
+Release 0.5.1 (Dec 15, 2008)
+============================
+
+* #67: Output warnings about failed doctests in the doctest extension
+  even when running in quiet mode.
+
+* #72: In pngmath, make it possible to give a full path to LaTeX and
+  dvipng on Windows.  For that to work, the ``pngmath_latex`` and
+  ``pngmath_dvipng`` options are no longer split into command and
+  additional arguments; use ``pngmath_latex_args`` and
+  ``pngmath_dvipng_args`` to give additional arguments.
+
+* Don't crash on failing doctests with non-ASCII characters.
+
+* Don't crash on writing status messages and warnings containing
+  unencodable characters.
+
+* Warn if a doctest extension block doesn't contain any code.
+
+* Fix the handling of ``:param:`` and ``:type:`` doc fields when
+  they contain markup (especially cross-referencing roles).
+
+* #65: Fix storage of depth information for PNGs generated by the
+  pngmath extension.
+
+* Fix autodoc crash when automethod is used outside a class context.
+
+* #68: Fix LaTeX writer output for images with specified height.
+
+* #60: Fix wrong generated image path when including images in sources
+  in subdirectories.
+
+* Fix the JavaScript search when html_copy_source is off.
+
+* Fix an indentation problem in autodoc when documenting classes
+  with the option ``autoclass_content = "both"`` set.
+
+* Don't crash on empty index entries, only emit a warning.
+
+* Fix a typo in the search JavaScript code, leading to unusable
+  search function in some setups.
+
+
+Release 0.5 (Nov 23, 2008) -- Birthday release!
+===============================================
+
+New features added
+------------------
+
 * Markup features:
 
   - Citations are now global: all citation defined in any file can be
@@ -28,6 +171,12 @@
   - Lists enumerated by letters or roman numerals are now handled like in
     standard reST.
 
+  - The ``seealso`` directive can now also be given arguments, as a short
+    form.
+
+  - You can now document several programs and their options with the
+    new ``program`` directive.
+
 * HTML output and templates:
 
   - Incompatible change: The "root" relation link (top left in the
@@ -39,6 +188,12 @@
   - The JavaScript search now searches for objects before searching in
     the full text.
 
+  - TOC tree entries now have CSS classes that make it possible to
+    style them depending on their depth.
+
+  - Highlighted code blocks now have CSS classes that make it possible
+    to style them depending on their language.
+
   - HTML ``<meta>`` tags via the docutils ``meta`` directive are now
     supported.
 
@@ -58,6 +213,9 @@
     used to disable the anchor-link creation after headlines and
     definition links.
 
+  - Only generate a module index if there are some modules in the
+    documentation.
+
 * New and changed config values:
 
   - Added support for internationalization in generated text with the
@@ -70,6 +228,10 @@
     * Michał Kandulski -- Polish
     * Yasushi Masuda -- Japanese
     * Guillem Borrell -- Spanish
+    * Luc Saffre and Peter Bertels -- Dutch
+    * Fred Lin -- Traditional Chinese
+    * Roger Demetrescu -- Brazilian Portuguese
+    * Rok Garbas -- Slovenian
 
   - The new config value ``highlight_language`` set a global default for
     highlighting.  When ``'python3'`` is selected, console output blocks
@@ -94,6 +256,10 @@
     creates links to Sphinx documentation of Python objects in other
     projects.
 
+  - The new extension ``sphinx.ext.todo`` allows the insertion of
+    "To do" directives whose visibility in the output can be toggled.
+    It also adds a directive to compile a list of all todo items.
+
   - sphinx.ext.autodoc has a new event ``autodoc-process-signature``
     that allows tuning function signature introspection.
 
@@ -115,10 +281,18 @@
     default HTML template.
 
   - Added new events: ``source-read``, ``env-updated``,
-    ``missing-reference``, ``build-finished``.
+    ``env-purge-doc``, ``missing-reference``, ``build-finished``.
 
 * Other changes:
 
+  - Added a command-line switch ``-Q``: it will suppress warnings.
+
+  - Added a command-line switch ``-A``: it can be used to supply
+    additional values into the HTML templates.
+
+  - Added a command-line switch ``-C``: if it is given, no configuration
+    file ``conf.py`` is required.
+
   - Added a distutils command `build_sphinx`: When Sphinx is installed,
     you can call ``python setup.py build_sphinx`` for projects that have
     Sphinx documentation, which will build the docs and place them in
@@ -130,13 +304,33 @@
 Bugs fixed
 ----------
 
+* #51: Escape configuration values placed in HTML templates.
+
+* #44: Fix small problems in HTML help index generation.
+
+* Fix LaTeX output for line blocks in tables.
+
+* #38: Fix "illegal unit" error when using pixel image widths/heights.
+
+* Support table captions in LaTeX output.
+
+* #39: Work around a bug in Jinja that caused "<generator ...>" to be
+  emitted in HTML output.
+
+* Fix a problem with module links not being generated in LaTeX output.
+
+* Fix the handling of images in different directories.
+
+* #29: Support option lists in the text writer.  Make sure that dashes
+  introducing long option names are not contracted to en-dashes.
+
 * Support the "scale" option for images in HTML output.
 
-* Properly escape quotes in HTML help attribute values.
+* #25: Properly escape quotes in HTML help attribute values.
 
 * Fix LaTeX build for some description environments with ``:noindex:``.
 
-* Don't crash on weird casing of role names (like ``:Class:``).
+* #24: Don't crash on uncommon casing of role names (like ``:Class:``).
 
 * Only output ANSI colors on color terminals.
 

Modified: doctools/trunk/EXAMPLES
==============================================================================
--- doctools/trunk/EXAMPLES	(original)
+++ doctools/trunk/EXAMPLES	Sun Jan  4 21:38:57 2009
@@ -1,36 +1,47 @@
 Projects using Sphinx
 =====================
 
-This is an (incomplete) list of projects that use Sphinx or are
-experimenting with using it for their documentation.  If you like
-to be included, please mail to `the Google group
+This is an (incomplete) alphabetic list of projects that use Sphinx or are
+experimenting with using it for their documentation.  If you like to be
+included, please mail to `the Google group
 <http://groups.google.com/group/sphinx-dev>`_.
 
-* Sphinx: http://sphinx.pocoo.org/
-* Python: http://docs.python.org/dev/
-* NumPy: http://mentat.za.net/numpy/refguide/
-* Matplotlib: http://matplotlib.sourceforge.net/
-* Pylons: http://docs.pylonshq.com/
+* APSW: http://apsw.googlecode.com/svn/publish/index.html
+* Calibre: http://calibre.kovidgoyal.net/user_manual/
+* Chaco: http://code.enthought.com/projects/chaco/docs/html/
+* Cython: http://docs.cython.org/
+* Director: http://packages.python.org/director/
 * Django: http://docs.djangoproject.com/
+* F2py: http://www.f2py.org/html/
+* GeoDjango: http://geodjango.org/docs/
+* Glashammer: http://glashammer.org/
 * Grok: http://grok.zope.org/doc/current/
-* TurboGears: http://turbogears.org/2.0/docs/
+* IFM: http://fluffybunny.memebot.com/ifm-docs/index.html
 * Jinja: http://jinja.pocoo.org/2/documentation/
-* Cython: http://docs.cython.org/
-* F2py: http://www.f2py.org/html/
-* zc.async: http://packages.python.org/zc.async/1.5.0/
+* MapServer: http://mapserver.osgeo.org/
+* Matplotlib: http://matplotlib.sourceforge.net/
 * Mayavi: http://code.enthought.com/projects/mayavi/docs/development/html/mayavi
-* Chaco: http://code.enthought.com/projects/chaco/docs/html/
+* Mixin.com: http://dev.mixin.com/
+* mpmath: http://mpmath.googlecode.com/svn/trunk/doc/build/index.html
+* NetworkX: http://networkx.lanl.gov/
+* NumPy: http://docs.scipy.org/doc/numpy/reference/
+* ObjectListView: http://objectlistview.sourceforge.net/python
+* OpenLayers: http://docs.openlayers.org/
+* Paste: http://pythonpaste.org/script/
 * Paver: http://www.blueskyonmars.com/projects/paver/
-* Satchmo: http://www.satchmoproject.com/docs/svn/
+* Py on Windows: http://timgolden.me.uk/python-on-windows/
 * PyEphem: http://rhodesmill.org/pyephem/
-* Paste: http://pythonpaste.org/script/
-* Calibre: http://calibre.kovidgoyal.net/user_manual/
+* PyPubSub: http://pubsub.sourceforge.net/
 * PyUblas: http://tiker.net/doc/pyublas/
-* Py on Windows: http://timgolden.me.uk/python-on-windows/
-* mpmath: http://mpmath.googlecode.com/svn/trunk/doc/build/index.html
-* Zope 3: e.g. http://docs.carduner.net/z3c-tutorial/
-* Glashammer: http://glashammer.org/
+* Pylons: http://docs.pylonshq.com/
+* Pysparse: http://pysparse.sourceforge.net/
+* Python: http://docs.python.org/dev/
+* Satchmo: http://www.satchmoproject.com/docs/svn/
+* Sphinx: http://sphinx.pocoo.org/
+* SQLAlchemy: http://www.sqlalchemy.org/docs/
 * SymPy: http://docs.sympy.org/
-* GeoDjango: http://geodjango.org/docs/
-* Mixin.com: http://dev.mixin.com/
-* PyPubSub: http://pubsub.sourceforge.net/
+* tinyTiM: http://tinytim.sourceforge.net/docs/2.0/
+* TurboGears: http://turbogears.org/2.0/docs/
+* WFront: http://discorporate.us/projects/WFront/
+* Zope 3: e.g. http://docs.carduner.net/z3c-tutorial/
+* zc.async: http://packages.python.org/zc.async/1.5.0/

Modified: doctools/trunk/LICENSE
==============================================================================
--- doctools/trunk/LICENSE	(original)
+++ doctools/trunk/LICENSE	Sun Jan  4 21:38:57 2009
@@ -1,30 +1,188 @@
-Copyright (c) 2007-2008 by the respective authors (see AUTHORS file).
-All rights reserved.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are
-met:
-
-    * Redistributions of source code must retain the above copyright
-      notice, this list of conditions and the following disclaimer.
-
-    * 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.
-
-    * The names of the contributors may not be used to endorse or
-      promote products derived from this software without specific
-      prior written permission.
-
-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.
+Copyright (c) 2007-2009 by the Sphinx team (see AUTHORS file).
+All rights reserved.
+
+License for Sphinx
+==================
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+* Redistributions of source code must retain the above copyright
+  notice, this list of conditions and the following disclaimer.
+
+* 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.
+
+
+Licenses for incorporated software
+==================================
+
+The pgen2 package, included in this distribution under the name
+sphinx.pycode.pgen2, is available in the Python 2.6 distribution under
+the PSF license agreement for Python:
+
+----------------------------------------------------------------------
+1. This LICENSE AGREEMENT is between the Python Software Foundation
+   ("PSF"), and the Individual or Organization ("Licensee") accessing
+   and otherwise using Python 2.6 software in source or binary form
+   and its associated documentation.
+
+2. Subject to the terms and conditions of this License Agreement, PSF
+   hereby grants Licensee a nonexclusive, royalty-free, world-wide
+   license to reproduce, analyze, test, perform and/or display
+   publicly, prepare derivative works, distribute, and otherwise use
+   Python 2.6 alone or in any derivative version, provided, however,
+   that PSF's License Agreement and PSF's notice of copyright, i.e.,
+   "Copyright © 2001-2008 Python Software Foundation; All Rights
+   Reserved" are retained in Python 2.6 alone or in any derivative
+   version prepared by Licensee.
+
+3. In the event Licensee prepares a derivative work that is based on
+   or incorporates Python 2.6 or any part thereof, and wants to make
+   the derivative work available to others as provided herein, then
+   Licensee hereby agrees to include in any such work a brief summary
+   of the changes made to Python 2.6.
+
+4. PSF is making Python 2.6 available to Licensee on an "AS IS" basis.
+   PSF MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED.  BY
+   WAY OF EXAMPLE, BUT NOT LIMITATION, PSF MAKES NO AND DISCLAIMS ANY
+   REPRESENTATION OR WARRANTY OF MERCHANTABILITY OR FITNESS FOR ANY
+   PARTICULAR PURPOSE OR THAT THE USE OF PYTHON 2.6 WILL NOT INFRINGE
+   ANY THIRD PARTY RIGHTS.
+
+5. PSF SHALL NOT BE LIABLE TO LICENSEE OR ANY OTHER USERS OF PYTHON
+   2.6 FOR ANY INCIDENTAL, SPECIAL, OR CONSEQUENTIAL DAMAGES OR LOSS
+   AS A RESULT OF MODIFYING, DISTRIBUTING, OR OTHERWISE USING PYTHON
+   2.6, OR ANY DERIVATIVE THEREOF, EVEN IF ADVISED OF THE POSSIBILITY
+   THEREOF.
+
+6. This License Agreement will automatically terminate upon a material
+   breach of its terms and conditions.
+
+7. Nothing in this License Agreement shall be deemed to create any
+   relationship of agency, partnership, or joint venture between PSF
+   and Licensee.  This License Agreement does not grant permission to
+   use PSF trademarks or trade name in a trademark sense to endorse or
+   promote products or services of Licensee, or any third party.
+
+8. By copying, installing or otherwise using Python 2.6, Licensee
+   agrees to be bound by the terms and conditions of this License
+   Agreement.
+----------------------------------------------------------------------
+
+The included smartypants module, included as sphinx.util.smartypants,
+is available under the following license:
+
+----------------------------------------------------------------------
+SmartyPants_ license::
+
+    Copyright (c) 2003 John Gruber
+    (http://daringfireball.net/)
+    All rights reserved.
+
+    Redistribution and use in source and binary forms, with or without
+    modification, are permitted provided that the following conditions
+    are met:
+
+    *   Redistributions of source code must retain the above copyright
+        notice, this list of conditions and the following disclaimer.
+
+    *   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.
+
+    *   Neither the name "SmartyPants" nor the names of its
+        contributors may be used to endorse or promote products
+        derived from this software without specific prior written
+        permission.
+
+    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.
+
+
+smartypants.py license::
+
+    smartypants.py is a derivative work of SmartyPants.
+
+    Redistribution and use in source and binary forms, with or without
+    modification, are permitted provided that the following conditions
+    are met:
+
+    *   Redistributions of source code must retain the above copyright
+        notice, this list of conditions and the following disclaimer.
+
+    *   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.
+----------------------------------------------------------------------
+
+The ElementTree package, included in this distribution in
+test/etree13, is available under the following license:
+
+----------------------------------------------------------------------
+The ElementTree toolkit is
+
+Copyright (c) 1999-2007 by Fredrik Lundh
+
+By obtaining, using, and/or copying this software and/or its
+associated documentation, you agree that you have read, understood,
+and will comply with the following terms and conditions:
+
+Permission to use, copy, modify, and distribute this software and its
+associated documentation for any purpose and without fee is hereby
+granted, provided that the above copyright notice appears in all
+copies, and that both that copyright notice and this permission notice
+appear in supporting documentation, and that the name of Secret Labs
+AB or the author not be used in advertising or publicity pertaining to
+distribution of the software without specific, written prior
+permission.
+
+SECRET LABS AB AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO
+THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANT- ABILITY
+AND FITNESS.  IN NO EVENT SHALL SECRET LABS AB OR THE AUTHOR BE LIABLE
+FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+----------------------------------------------------------------------

Added: doctools/trunk/MANIFEST.in
==============================================================================
--- (empty file)
+++ doctools/trunk/MANIFEST.in	Sun Jan  4 21:38:57 2009
@@ -0,0 +1,22 @@
+include README
+include LICENSE
+include AUTHORS
+include CHANGES
+include EXAMPLES
+include TODO
+
+include babel.cfg
+include Makefile
+include ez_setup.py
+include sphinx-build.py
+include sphinx-quickstart.py
+
+recursive-include sphinx/texinputs *
+recursive-include sphinx/templates *.html *.xml
+recursive-include sphinx/static *
+recursive-include sphinx/locale *
+recursive-include tests *
+recursive-include utils *
+
+recursive-include doc *
+prune doc/_build

Modified: doctools/trunk/README
==============================================================================
--- doctools/trunk/README	(original)
+++ doctools/trunk/README	Sun Jan  4 21:38:57 2009
@@ -17,9 +17,9 @@
 After installing::
 
    cd doc
-   mkdir -p _build/html
    sphinx-build . _build/html
-   browser _build/index.html
+
+Then, direct your browser to ``_build/html/index.html``.
 
 Or read them online at <http://sphinx.pocoo.org/>.
 
@@ -27,4 +27,4 @@
 Contributing
 ============
 
-Send wishes, comments, patches, etc. to georg at python.org.
+Send wishes, comments, patches, etc. to sphinx-dev at googlegroups.com.

Modified: doctools/trunk/TODO
==============================================================================
--- doctools/trunk/TODO	(original)
+++ doctools/trunk/TODO	Sun Jan  4 21:38:57 2009
@@ -2,5 +2,5 @@
 ===========
 
 All todo items are now tracked as issues in the Sphinx issue tracker at
-<http://code.google.com/p/sphinx/issues/list>.
+<http://www.bitbucket.org/birkenfeld/sphinx/issues/>.
 

Modified: doctools/trunk/babel.cfg
==============================================================================
--- doctools/trunk/babel.cfg	(original)
+++ doctools/trunk/babel.cfg	Sun Jan  4 21:38:57 2009
@@ -1,6 +1,4 @@
-[extractors]
-jinja = sphinx._jinja.babel_extract
 [python: **.py]
-[jinja: **/templates/**.html]
-[jinja: **/templates/**.xml]
+[jinja2: **/templates/**.html]
+[jinja2: **/templates/**.xml]
 [javascript: **.js]

Modified: doctools/trunk/doc/Makefile
==============================================================================
--- doctools/trunk/doc/Makefile	(original)
+++ doctools/trunk/doc/Makefile	Sun Jan  4 21:38:57 2009
@@ -11,12 +11,12 @@
 ALLSPHINXOPTS = -d _build/doctrees $(PAPEROPT_$(PAPER)) \
                 $(SPHINXOPTS) .
 
-.PHONY: help clean html web htmlhelp latex changes linkcheck
+.PHONY: help clean html pickle htmlhelp qthelp latex changes linkcheck doctest
 
 help:
 	@echo "Please use \`make <target>' where <target> is one of"
 	@echo "  html      to make standalone HTML files"
-	@echo "  web       to make files usable by Sphinx.web"
+	@echo "  pickle    to make pickle files"
 	@echo "  htmlhelp  to make HTML files and a HTML help project"
 	@echo "  latex     to make LaTeX files, you can set PAPER=a4 or PAPER=letter"
 	@echo "  changes   to make an overview over all changed/added/deprecated items"
@@ -31,13 +31,15 @@
 	@echo
 	@echo "Build finished. The HTML pages are in _build/html."
 
+text:
+	mkdir -p _build/text _build/doctrees
+	$(SPHINXBUILD) -b text $(ALLSPHINXOPTS) _build/text
+	@echo
+	@echo "Build finished."
+
 pickle:
 	mkdir -p _build/pickle _build/doctrees
 	$(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) _build/pickle
-	@echo
-	@echo "Build finished; now you can run"
-	@echo "  python -m sphinx.web _build/pickle"
-	@echo "to start the server."
 
 htmlhelp:
 	mkdir -p _build/htmlhelp _build/doctrees
@@ -46,6 +48,16 @@
 	@echo "Build finished; now you can run HTML Help Workshop with the" \
 	      ".hhp project file in _build/htmlhelp."
 
+qthelp:
+	mkdir -p _build/qthelp _build/doctrees
+	$(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) _build/qthelp
+	@echo
+	@echo "Build finished; now you can run qcollectiongenerator with the" \
+	      ".qhcp project file in build/qthelp."
+	@echo "# qcollectiongenerator _build/qthelp/Sphinx.qhcp"
+	@echo "To view the help collection:"
+	@echo "# assistant -collectionFile _build/qthelp/Sphinx.qhc"
+
 latex:
 	mkdir -p _build/latex _build/doctrees
 	$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) _build/latex

Modified: doctools/trunk/doc/_templates/index.html
==============================================================================
--- doctools/trunk/doc/_templates/index.html	(original)
+++ doctools/trunk/doc/_templates/index.html	Sun Jan  4 21:38:57 2009
@@ -3,17 +3,22 @@
 {% block body %}
   <h1>Welcome</h1>
 
+  <div class="quotebar">
+    <p>What users say:</p>
+    <p>&ldquo;Cheers for a great tool that actually makes programmers <b>want</b>
+      to write documentation!&rdquo;</p>
+  </div>
+
   <p>
     Sphinx is a tool that makes it easy to create intelligent and beautiful
-    documentation for Python projects, written by Georg Brandl and licensed
-    under the BSD license.</p>
+    documentation, written by Georg Brandl and licensed under the BSD license.</p>
   <p>It was originally created to translate <a href="http://docs.python.org/dev/">the
-    new Python documentation</a>, but has now been cleaned up in the hope that
-    it will be useful to many other projects.  (Of course, this site is also
-    created from reStructuredText sources using Sphinx!)
+    new Python documentation</a>, and it has excellent support for the documentation
+    of Python projects, but other documents can be written with it too.  Of course,
+    this site is also created from reStructuredText sources using Sphinx!
   </p>
   <p>
-    Although it is still under constant development, the following features are
+    It is still under constant development, and the following features are
     already present, work fine and can be seen &#8220;in action&#8221; in the
     Python docs:
   </p>
@@ -74,7 +79,7 @@
     package on the <a href="http://pypi.python.org/pypi/Sphinx">Python Package
     Index</a>.
   </p>
-  <p>The code can be found on the Python SVN server, under
-    <tt>http://svn.python.org/projects/doctools</tt>.</p>
+  <p>The code can be found in a Mercurial repository, at
+    <tt>http://bitbucket.org/birkenfeld/sphinx/</tt>.</p>
   
 {% endblock %}

Modified: doctools/trunk/doc/_templates/indexsidebar.html
==============================================================================
--- doctools/trunk/doc/_templates/indexsidebar.html	(original)
+++ doctools/trunk/doc/_templates/indexsidebar.html	Sun Jan  4 21:38:57 2009
@@ -1,16 +1,16 @@
 <h3>Download</h3>
-{% if version.endswith('(SVN)') %}
+{% if version.endswith('(hg)') %}
 <p>This documentation is for version <b>{{ version }}</b>, which is
   not released yet.</p>
-<p>You can check it out from
-  <a href="http://svn.python.org/projects/doctools">Subversion</a> or look for
+<p>You can use it from the
+  <a href="http://bitbucket.org/birkenfeld/sphinx/">Mercurial repo</a> or look for
   released versions in the <a href="http://pypi.python.org/pypi/Sphinx">Python
     Package Index</a>.</p>
 {% else %}
 <p>Current version: <b>{{ version }}</b></p>
 <p>Get Sphinx from the <a href="http://pypi.python.org/pypi/Sphinx">Python Package
 Index</a>, or install it with:</p>
-<pre>easy_install Sphinx</pre>
+<pre>easy_install -U Sphinx</pre>
 {% endif %}
 
 <h3>Questions? Suggestions?</h3>
@@ -23,4 +23,4 @@
 </form>
 <p>or come to the <tt>#python-docs</tt> channel on FreeNode.</p>
 <p>You can also open an issue at the
-  <a href="http://code.google.com/p/sphinx/issues/list">tracker</a>.</p>
+  <a href="http://www.bitbucket.org/birkenfeld/sphinx/issues/">tracker</a>.</p>

Modified: doctools/trunk/doc/builders.rst
==============================================================================
--- doctools/trunk/doc/builders.rst	(original)
+++ doctools/trunk/doc/builders.rst	Sun Jan  4 21:38:57 2009
@@ -3,7 +3,7 @@
 Available builders
 ==================
 
-.. module:: sphinx.builder
+.. module:: sphinx.builders
    :synopsis: Available built-in builder classes.
 
 These are the built-in Sphinx builders.  More builders can be added by
@@ -13,6 +13,7 @@
 :program:`sphinx-build` to select a builder.
 
 
+.. module:: sphinx.builders.html
 .. class:: StandaloneHTMLBuilder
 
    This is the standard HTML builder.  Its output is a directory with HTML
@@ -30,34 +31,7 @@
 
    Its name is ``htmlhelp``. 
 
-.. class:: PickleHTMLBuilder
-
-   This builder produces a directory with pickle files containing mostly HTML
-   fragments and TOC information, for use of a web application (or custom
-   postprocessing tool) that doesn't use the standard HTML templates.
-
-   See :ref:`serialization-details` for details about the output format.
-
-   Its name is ``pickle``.  (The old name ``web`` still works as well.)
-
-   The file suffix is ``.fpickle``.  The global context is called
-   ``globalcontext.pickle``, the search index ``searchindex.pickle``.
-
-.. class:: JSONHTMLBuilder
-
-   This builder produces a directory with JSON files containing mostly HTML
-   fragments and TOC information, for use of a web application (or custom
-   postprocessing tool) that doesn't use the standard HTML templates.
-
-   See :ref:`serialization-details` for details about the output format.
-
-   Its name is ``json``.
-
-   The file suffix is ``.fjson``.  The global context is called
-   ``globalcontext.json``, the search index ``searchindex.json``.
-
-   .. versionadded:: 0.5
-
+.. module:: sphinx.builders.latex
 .. class:: LaTeXBuilder
 
    This builder produces a bunch of LaTeX files in the output directory.  You
@@ -66,8 +40,19 @@
    configuration values that customize the output of this builder, see the
    chapter :ref:`latex-options` for details.
 
+   .. note::
+
+      The produced LaTeX file uses several LaTeX packages that may not be
+      present in a "minimal" TeX distribution installation.  For TeXLive,
+      the following packages need to be installed:
+
+      * latex-recommended
+      * latex-extra
+      * fonts-recommended
+
    Its name is ``latex``.
 
+.. module:: sphinx.builders.text
 .. class:: TextBuilder
 
    This builder produces a text file for each reST file -- this is almost the
@@ -78,6 +63,7 @@
 
    .. versionadded:: 0.4
 
+.. currentmodule:: sphinx.builders.html
 .. class:: SerializingHTMLBuilder
 
    This builder uses a module that implements the Python serialization API
@@ -124,7 +110,36 @@
    See :ref:`serialization-details` for details about the output format.
 
    .. versionadded:: 0.5
-   
+
+.. class:: PickleHTMLBuilder
+
+   This builder produces a directory with pickle files containing mostly HTML
+   fragments and TOC information, for use of a web application (or custom
+   postprocessing tool) that doesn't use the standard HTML templates.
+
+   See :ref:`serialization-details` for details about the output format.
+
+   Its name is ``pickle``.  (The old name ``web`` still works as well.)
+
+   The file suffix is ``.fpickle``.  The global context is called
+   ``globalcontext.pickle``, the search index ``searchindex.pickle``.
+
+.. class:: JSONHTMLBuilder
+
+   This builder produces a directory with JSON files containing mostly HTML
+   fragments and TOC information, for use of a web application (or custom
+   postprocessing tool) that doesn't use the standard HTML templates.
+
+   See :ref:`serialization-details` for details about the output format.
+
+   Its name is ``json``.
+
+   The file suffix is ``.fjson``.  The global context is called
+   ``globalcontext.json``, the search index ``searchindex.json``.
+
+   .. versionadded:: 0.5
+
+.. module:: sphinx.builders.changes
 .. class:: ChangesBuilder
 
    This builder produces an HTML overview of all :dir:`versionadded`,
@@ -134,6 +149,7 @@
 
    Its name is ``changes``.
 
+.. module:: sphinx.builders.linkcheck
 .. class:: CheckExternalLinksBuilder
 
    This builder scans all documents for external links, tries to open them with

Modified: doctools/trunk/doc/concepts.rst
==============================================================================
--- doctools/trunk/doc/concepts.rst	(original)
+++ doctools/trunk/doc/concepts.rst	Sun Jan  4 21:38:57 2009
@@ -85,6 +85,18 @@
    This includes first all documents whose names start with ``intro``, then all
    documents in the ``recipe`` folder, then all remaining documents (except the
    one containing the directive, of course.) [#]_
+
+   You can also give a "hidden" option to the directive, like this::
+
+      .. toctree::
+         :hidden:
+
+         doc_1
+         doc_2
+
+   This will still notify Sphinx of the document hierarchy, but not insert links
+   into the document at the location of the directive -- this makes sense if you
+   intend to insert these links yourself, in a different style.
           
    In the end, all documents in the :term:`source directory` (or subdirectories)
    must occur in some ``toctree`` directive; Sphinx will emit a warning if it
@@ -100,6 +112,9 @@
    .. versionchanged:: 0.3
       Added "globbing" option.
 
+   .. versionchanged:: 0.6
+      Added "hidden" option.
+
 
 Special names
 -------------

Modified: doctools/trunk/doc/conf.py
==============================================================================
--- doctools/trunk/doc/conf.py	(original)
+++ doctools/trunk/doc/conf.py	Sun Jan  4 21:38:57 2009
@@ -19,9 +19,11 @@
 # General configuration
 # ---------------------
 
+language = 'en'
+
 # Add any Sphinx extension module names here, as strings. They can be extensions
 # coming with Sphinx (named 'sphinx.addons.*') or your custom ones.
-extensions = ['sphinx.ext.autodoc', 'sphinx.ext.doctest']
+extensions = ['sphinx.ext.autodoc', 'sphinx.ext.doctest', 'sphinx.ext.todo']
 
 # Add any paths that contain templates here, relative to this directory.
 templates_path = ['_templates']
@@ -34,7 +36,7 @@
 
 # General substitutions.
 project = 'Sphinx'
-copyright = '2008, Georg Brandl'
+copyright = '2007-2009, Georg Brandl'
 
 # The default replacements for |version| and |release|, also used in various
 # other places throughout the built documents.
@@ -134,6 +136,12 @@
 #latex_appendices = []
 
 
+# Extension options
+# -----------------
+
+todo_include_todos = True
+
+
 # Extension interface
 # -------------------
 

Modified: doctools/trunk/doc/config.rst
==============================================================================
--- doctools/trunk/doc/config.rst	(original)
+++ doctools/trunk/doc/config.rst	Sun Jan  4 21:38:57 2009
@@ -22,8 +22,8 @@
 
 * The term "fully-qualified name" refers to a string that names an importable
   Python object inside a module; for example, the FQN
-  ``"sphinx.builder.Builder"`` means the ``Builder`` class in the
-  ``sphinx.builder`` module.
+  ``"sphinx.builders.Builder"`` means the ``Builder`` class in the
+  ``sphinx.builders`` module.
 
 * Remember that document names use ``/`` as the path separator and don't contain
   the file name extension.
@@ -45,7 +45,7 @@
 .. confval:: extensions
 
    A list of strings that are module names of Sphinx extensions.  These can be
-   extensions coming with Sphinx (named ``sphinx.addons.*``) or custom ones.
+   extensions coming with Sphinx (named ``sphinx.ext.*``) or custom ones.
 
    Note that you can extend :data:`sys.path` within the conf file if your
    extensions live in another directory -- but make sure you use absolute paths.
@@ -203,8 +203,14 @@
    * ``cs`` -- Czech
    * ``de`` -- German
    * ``en`` -- English
+   * ``es`` -- Spanish
    * ``fr`` -- French
+   * ``it`` -- Italian
+   * ``nl`` -- Dutch
    * ``pl`` -- Polish
+   * ``pt_BR`` -- Brazilian Portuguese
+   * ``sl`` -- Slovenian
+   * ``zh_TW`` -- Traditional Chinese
 
 .. confval:: today
              today_fmt
@@ -327,6 +333,15 @@
    If true, *SmartyPants* will be used to convert quotes and dashes to
    typographically correct entities.  Default: ``True``.
 
+.. confval:: html_add_permalinks
+
+   If true, Sphinx will add "permalinks" for each heading and description
+   environment as paragraph signs that become visible when the mouse hovers over
+   them.  Default: ``True``.
+
+   .. versionadded:: 0.6
+      Previously, this was always activated.
+   
 .. confval:: html_sidebars
 
    Custom sidebar templates, must be a dictionary that maps document names to
@@ -388,6 +403,19 @@
    If true, the reST sources are included in the HTML build as
    :file:`_sources/{name}`.  The default is ``True``.
 
+   .. warning::
+
+      If this config value is set to ``False``, the JavaScript search function
+      will only display the titles of matching documents, and no excerpt from
+      the matching contents.
+
+.. confval:: html_show_sourcelink
+
+   If true (and :confval:`html_copy_source` is true as well), links to the
+   reST sources will be added to the sidebar.  The default is ``True``.
+
+   .. versionadded:: 0.6
+
 .. confval:: html_use_opensearch
 
    If nonempty, an `OpenSearch <http://opensearch.org>` description file will be
@@ -404,10 +432,18 @@
 
    .. versionadded:: 0.4
 
+.. confval:: html_link_suffix
+
+   Suffix for generated links to HTML files.  The default is whatever
+   :confval:`html_file_suffix` is set to; it can be set differently (e.g. to
+   support different web server setups).
+
+   .. versionadded:: 0.6
+   
 .. confval:: html_translator_class
 
    A string with the fully-qualified name of a HTML Translator class, that is, a
-   subclass of Sphinx' :class:`~sphinx.htmlwriter.HTMLTranslator`, that is used
+   subclass of Sphinx' :class:`~sphinx.writers.html.HTMLTranslator`, that is used
    to translate document trees to HTML.  Default is ``None`` (use the builtin
    translator).
 

Modified: doctools/trunk/doc/ext/appapi.rst
==============================================================================
--- doctools/trunk/doc/ext/appapi.rst	(original)
+++ doctools/trunk/doc/ext/appapi.rst	Sun Jan  4 21:38:57 2009
@@ -13,7 +13,7 @@
 .. method:: Sphinx.add_builder(builder)
 
    Register a new builder.  *builder* must be a class that inherits from
-   :class:`~sphinx.builder.Builder`.
+   :class:`~sphinx.builders.Builder`.
 
 .. method:: Sphinx.add_config_value(name, default, rebuild_env)
 
@@ -59,7 +59,7 @@
    .. versionchanged:: 0.5
       Added the support for keyword arguments giving visit functions.
 
-.. method:: Sphinx.add_directive(name, cls, content, arguments, **options)
+.. method:: Sphinx.add_directive(name, func, content, arguments, **options)
 
    Register a Docutils directive.  *name* must be the prospective directive
    name, *func* the directive function for details about the signature and
@@ -68,6 +68,16 @@
    options, respectively.  For their exact meaning, please consult the Docutils
    documentation.
 
+   For example, the (already existing) :dir:`literalinclude` directive would be
+   added like this::
+
+      from docutils.parsers.rst import directives
+      add_directive('literalinclude', literalinclude_directive,
+                    content = 0, arguments = (1, 0, 0),
+                    linenos = directives.flag,
+                    language = direcitves.unchanged,
+                    encoding = directives.encoding)
+
    .. XXX once we target docutils 0.5, update this
 
 .. method:: Sphinx.add_role(name, role)
@@ -157,6 +167,13 @@
    :confval:`the docs for the config value <html_static_path>`.
 
    .. versionadded:: 0.5
+
+.. method:: Sphinx.add_lexer(alias, lexer)
+
+   Use *lexer*, which must be an instance of a Pygments lexer class, to
+   highlight code blocks with the given language *alias*.
+
+   .. versionadded:: 0.6
    
 .. method:: Sphinx.connect(event, callback)
 
@@ -208,12 +225,29 @@
    Emitted when the builder object has been created.  It is available as
    ``app.builder``.
 
+.. event:: env-purge-doc (app, env, docname)
+
+   Emitted when all traces of a source file should be cleaned from the
+   environment, that is, if the source file is removed or before it is freshly
+   read.  This is for extensions that keep their own caches in attributes of the
+   environment.
+
+   For example, there is a cache of all modules on the environment.  When a
+   source file has been changed, the cache's entries for the file are cleared,
+   since the module declarations could have been removed from the file.
+
+   .. versionadded:: 0.5
+   
 .. event:: source-read (app, docname, source)
 
    Emitted when a source file has been read.  The *source* argument is a list
    whose single element is the contents of the source file.  You can process the
    contents and replace this item to implement source-level transformations.
 
+   For example, if you want to use ``$`` signs to delimit inline math, like in
+   LaTeX, you can use a regular expression to replace ``$...$`` by
+   ``:math:`...```.
+
    .. versionadded:: 0.5
    
 .. event:: doctree-read (app, doctree)
@@ -241,7 +275,11 @@
 .. event:: doctree-resolved (app, doctree, docname)
 
    Emitted when a doctree has been "resolved" by the environment, that is, all
-   references have been resolved and TOCs have been inserted.
+   references have been resolved and TOCs have been inserted.  The *doctree* can
+   be modified in place.
+
+   Here is the place to replace custom nodes that don't have visitor methods in
+   the writers, so that they don't cause errors when the writers encounter them.
 
 .. event:: env-updated (app, env)
 

Modified: doctools/trunk/doc/ext/builderapi.rst
==============================================================================
--- doctools/trunk/doc/ext/builderapi.rst	(original)
+++ doctools/trunk/doc/ext/builderapi.rst	Sun Jan  4 21:38:57 2009
@@ -3,9 +3,9 @@
 Writing new builders
 ====================
 
-XXX to be expanded.
+.. todo:: Expand this.
 
-.. currentmodule:: sphinx.builder
+.. currentmodule:: sphinx.builders
 
 .. class:: Builder
 
@@ -20,7 +20,7 @@
    .. automethod:: build_update
    .. automethod:: build
 
-   These methods must be overridden in concrete builder classes:
+   These methods can be overridden in concrete builder classes:
 
    .. automethod:: init
    .. automethod:: get_outdated_docs
@@ -28,3 +28,7 @@
    .. automethod:: prepare_writing
    .. automethod:: write_doc
    .. automethod:: finish
+
+   Useful helpers:
+
+   .. automethod:: init_templates

Modified: doctools/trunk/doc/ext/coverage.rst
==============================================================================
--- doctools/trunk/doc/ext/coverage.rst	(original)
+++ doctools/trunk/doc/ext/coverage.rst	Sun Jan  4 21:38:57 2009
@@ -12,7 +12,7 @@
    To use this builder, activate the coverage extension in your configuration
    file and give ``-b coverage`` on the command line.
 
-XXX to be expanded.
+.. todo:: Write this section.
 
 Several new configuration values can be used to specify what the builder
 should check:

Modified: doctools/trunk/doc/ext/doctest.rst
==============================================================================
--- doctools/trunk/doc/ext/doctest.rst	(original)
+++ doctools/trunk/doc/ext/doctest.rst	Sun Jan  4 21:38:57 2009
@@ -149,6 +149,14 @@
    A list of directories that will be added to :data:`sys.path` when the doctest
    builder is used.  (Make sure it contains absolute paths.)
 
+.. confval:: doctest_global_setup
+
+   Python code that is treated like it were put in a ``testsetup`` directive for
+   *every* file that is tested, and for every group.  You can use this to
+   e.g. import modules you will always need in your doctests.
+
+   .. versionadded:: 0.6
+   
 .. confval:: doctest_test_doctest_blocks
 
    If this is a nonempty string (the default is ``'default'``), standard reST

Modified: doctools/trunk/doc/ext/math.rst
==============================================================================
--- doctools/trunk/doc/ext/math.rst	(original)
+++ doctools/trunk/doc/ext/math.rst	Sun Jan  4 21:38:57 2009
@@ -12,8 +12,13 @@
 supports math in documentation with two extensions.
 
 The basic math support that is common to both extensions is contained in
-:mod:`sphinx.ext.mathbase`.  Other math support extensions should, if possible,
-reuse that support too.
+:mod:`sphinx.ext.mathbase`.  Other math support extensions should,
+if possible, reuse that support too.
+
+.. note::
+
+   :mod:`sphinx.ext.mathbase` does not need to be added to the
+   :confval:`extensions` config value.
 
 The input language for mathematics is LaTeX markup.  This is the de-facto
 standard for plain-text math notation and has the added advantage that no
@@ -105,9 +110,6 @@
    may need to set this to a full path if ``latex`` not in the executable search
    path.
 
-   This string is split into words with :func:`shlex.split`, so that you can
-   include arguments as well if needed.
-
    Since this setting is not portable from system to system, it is normally not
    useful to set it in ``conf.py``; rather, giving it on the
    :program:`sphinx-build` command line via the :option:`-D` option should be
@@ -115,12 +117,23 @@
 
       sphinx-build -b html -D pngmath_latex=C:\tex\latex.exe . _build/html
 
+   .. versionchanged:: 0.5.1
+      This value should only contain the path to the latex executable, not
+      further arguments; use :confval:`pngmath_latex_args` for that purpose.
+
 .. confval:: pngmath_dvipng
 
    The command name with which to invoke ``dvipng``.  The default is
    ``'dvipng'``; you may need to set this to a full path if ``dvipng`` is not in
    the executable search path.
 
+.. confval:: pngmath_latex_args
+
+   Additional arguments to give to latex, as a list.  The default is an empty
+   list.
+
+   .. versionadded:: 0.5.1
+   
 .. confval:: pngmath_latex_preamble
 
    Additional LaTeX code to put into the preamble of the short LaTeX files that
@@ -129,11 +142,21 @@
 
 .. confval:: pngmath_dvipng_args
 
-   Additional arguments to give to dvipng, as a list.  This is empty by default.
-   Arguments you might want to add here are e.g. ``['-bg', 'Transparent']``,
+   Additional arguments to give to dvipng, as a list.  The default value is
+   ``['-gamma 1.5', '-D 110']`` which makes the image a bit darker and larger
+   then it is by default.
+   
+   An arguments you might want to add here is e.g. ``'-bg Transparent'``,
    which produces PNGs with a transparent background.  This is not enabled by
    default because some Internet Explorer versions don't like transparent PNGs.
 
+   .. note::
+
+      When you "add" an argument, you need to reproduce the default arguments if
+      you want to keep them; that is, like this::
+
+         pngmath_dvipng_args = ['-gamma 1.5', '-D 110', '-bg Transparent']
+
 .. confval:: pngmath_use_preview
 
    ``dvipng`` has the ability to determine the "depth" of the rendered text: for

Modified: doctools/trunk/doc/ext/refcounting.rst
==============================================================================
--- doctools/trunk/doc/ext/refcounting.rst	(original)
+++ doctools/trunk/doc/ext/refcounting.rst	Sun Jan  4 21:38:57 2009
@@ -4,4 +4,4 @@
 .. module:: sphinx.ext.refcounting
    :synopsis: Keep track of reference counting behavior.
 
-XXX to be written.
+.. todo:: Write this section.

Added: doctools/trunk/doc/ext/todo.rst
==============================================================================
--- (empty file)
+++ doctools/trunk/doc/ext/todo.rst	Sun Jan  4 21:38:57 2009
@@ -0,0 +1,30 @@
+:mod:`sphinx.ext.todo` -- Support for todo items
+================================================
+
+.. module:: sphinx.ext.todo
+   :synopsis: Allow inserting todo items into documents.
+.. moduleauthor:: Daniel Bültmann
+
+.. versionadded:: 0.5
+
+There are two additional directives when using this extension:
+
+.. directive:: todo
+
+   Use this directive like, for example, :dir:`note`.
+
+   It will only show up in the output if :confval:`todo_include_todos` is true.
+
+
+.. directive:: todolist
+
+   This directive is replaced by a list of all todo directives in the whole
+   documentation, if :confval:`todo_include_todos` is true.
+
+   
+There is also an additional config value:
+   
+.. confval:: todo_include_todos
+
+   If this is ``True``, :dir:`todo` and :dir:`todolist` produce output, else
+   they produce nothing.  The default is ``False``.

Added: doctools/trunk/doc/ext/tutorial.rst
==============================================================================
--- (empty file)
+++ doctools/trunk/doc/ext/tutorial.rst	Sun Jan  4 21:38:57 2009
@@ -0,0 +1,316 @@
+.. _exttut:
+
+Tutorial: Writing a simple extension
+====================================
+
+This section is intended as a walkthrough for the creation of custom extensions.
+It covers the basics of writing and activating an extensions, as well as
+commonly used features of extensions.
+
+As an example, we will cover a "todo" extension that adds capabilities to
+include todo entries in the documentation, and collecting these in a central
+place.  (A similar "todo" extension is distributed with Sphinx.)
+
+
+Build Phases
+------------
+
+One thing that is vital in order to understand extension mechanisms is the way
+in which a Sphinx project is built: this works in several phases.
+
+**Phase 0: Initialization**
+
+   In this phase, almost nothing interesting for us happens.  The source
+   directory is searched for source files, and extensions are initialized.
+   Should a stored build environment exist, it is loaded, otherwise a new one is
+   created.
+
+**Phase 1: Reading**
+
+   In Phase 1, all source files (and on subsequent builds, those that are new or
+   changed) are read and parsed.  This is the phase where directives and roles
+   are encountered by the docutils, and the corresponding functions are called.
+   The output of this phase is a *doctree* for each source files, that is a tree
+   of docutils nodes.  For document elements that aren't fully known until all
+   existing files are read, temporary nodes are created.
+
+   During reading, the build environment is updated with all meta- and cross
+   reference data of the read documents, such as labels, the names of headings,
+   described Python objects and index entries.  This will later be used to
+   replace the temporary nodes.
+
+   The parsed doctrees are stored on the disk, because it is not possible to
+   hold all of them in memory.
+
+**Phase 2: Consistency checks**
+
+   Some checking is done to ensure no surprises in the built documents.
+
+**Phase 3: Resolving**
+
+   Now that the metadata and cross-reference data of all existing documents is
+   known, all temporary nodes are replaced by nodes that can be converted into
+   output.  For example, links are created for object references that exist, and
+   simple literal nodes are created for those that don't.
+
+**Phase 4: Writing**
+
+   This phase converts the resolved doctrees to the desired output format, such
+   as HTML or LaTeX.  This happens via a so-called docutils writer that visits
+   the individual nodes of each doctree and produces some output in the process.
+
+.. note::
+
+   Some builders deviate from this general build plan, for example, the builder
+   that checks external links does not need anything more than the parsed
+   doctrees and therefore does not have phases 2--4.
+
+
+Extension Design
+----------------
+
+We want the extension to add the following to Sphinx:
+
+* A "todo" directive, containing some content that is marked with "TODO", and
+  only shown in the output if a new config value is set.  (Todo entries should
+  not be in the output by default.)
+
+* A "todolist" directive that creates a list of all todo entries throughout the
+  documentation.
+
+For that, we will need to add the following elements to Sphinx:
+
+* New directives, called ``todo`` and ``todolist``.
+* New document tree nodes to represent these directives, conventionally also
+  called ``todo`` and ``todolist``.  We wouldn't need new nodes if the new
+  directives only produced some content representable by existing nodes.
+* A new config value ``todo_include_todos`` (config value names should start
+  with the extension name, in order to stay unique) that controls whether todo
+  entries make it into the output.
+* New event handlers: one for the :event:`doctree-resolved` event, to replace
+  the todo and todolist nodes, and one for :event:`env-purge-doc` (the reason
+  for that will be covered later).
+
+
+The Setup Function
+------------------
+
+.. currentmodule:: sphinx.application
+
+The new elements are added in the extension's setup function.  Let us create a
+new Python module called :file:`todo.py` and add the setup function::
+
+   def setup(app):
+       app.add_config_value('todo_include_todos', False, False)
+
+       app.add_node(todolist)
+       app.add_node(todo,
+                    html=(visit_todo_node, depart_todo_node),
+                    latex=(visit_todo_node, depart_todo_node),
+                    text=(visit_todo_node, depart_todo_node))
+
+       app.add_directive('todo', todo_directive, 1, (0, 0, 1))
+       app.add_directive('todolist', todolist_directive, 0, (0, 0, 0))
+       app.connect('doctree-resolved', process_todo_nodes)
+       app.connect('env-purge-doc', purge_todos)
+
+The calls in this function refer to classes and functions not yet written.  What
+the individual calls do is the following:
+
+* :meth:`~Sphinx.add_config_value` lets Sphinx know that it should recognize the
+  new *config value* ``todo_include_todos``, whose default value should be
+  ``False`` (this also tells Sphinx that it is a boolean value).
+
+  If the third argument was ``True``, all documents would be re-read if the
+  config value changed its value.  This is needed for config values that
+  influence reading (build phase 1).
+
+* :meth:`~Sphinx.add_node` adds a new *node class* to the build system.  It also
+  can specify visitor functions for each supported output format.  These visitor
+  functions are needed when the new nodes stay until phase 4 -- since the
+  ``todolist`` node is always replaced in phase 3, it doesn't need any.
+
+  We need to create the two node classes ``todo`` and ``todolist`` later.
+
+* :meth:`~Sphinx.add_directive` adds a new *directive*, given by name, handler
+  function and two arguments that specify if the directive has content and how
+  many arguments it accepts.
+
+  The handler functions are created later.
+
+* Finally, :meth:`~Sphinx.connect` adds an *event handler* to the event whose
+  name is given by the first argument.  The event handler function is called
+  with several arguments which are documented with the event.
+
+
+The Node Classes
+----------------
+
+Let's start with the node classes::
+
+   from docutils import nodes
+
+   class todo(nodes.Admonition, nodes.Element):
+       pass
+
+   class todolist(nodes.General, nodes.Element):
+       pass
+
+   def visit_todo_node(self, node):
+       self.visit_admonition(node)
+    
+   def depart_todo_node(self, node):
+       self.depart_admonition(node)
+
+Node classes usually don't have to do anything except inherit from the standard
+docutils classes defined in :mod:`docutils.nodes`.  ``todo`` inherits from
+``Admonition`` because it should be handled like a note or warning, ``todolist``
+is just a "general" node.
+
+
+The Directive Handlers
+----------------------
+
+A directive handler is a function with a host of arguments, covered in detail in
+the docutils documentation.  It must return a list of nodes.
+
+The ``todolist`` directive is quite simple::
+
+   def todolist_directive(name, arguments, options, content, lineno,
+                          content_offset, block_text, state, state_machine):
+       return [todolist('')]
+
+An instance of our ``todolist`` node class is created and returned.  The
+todolist directive has neither content nor arguments that need to be handled.
+
+The ``todo`` directive function looks like this::
+
+   from sphinx.util.compat import make_admonition
+
+   def todo_directive(name, arguments, options, content, lineno,
+                      content_offset, block_text, state, state_machine):
+       env = state.document.settings.env
+    
+       targetid = "todo-%s" % env.index_num
+       env.index_num += 1
+       targetnode = nodes.target('', '', ids=[targetid])
+    
+       ad = make_admonition(todo, name, [_('Todo')], options, content, lineno,
+                            content_offset, block_text, state, state_machine)
+    
+       if not hasattr(env, 'todo_all_todos'):
+           env.todo_all_todos = []
+       env.todo_all_todos.append({
+           'docname': env.docname,
+           'lineno': lineno,
+           'todo': ad[0].deepcopy(),
+           'target': targetnode,
+       })
+    
+       return [targetnode] + ad
+
+Several important things are covered here. First, as you can see, you can refer
+to the build environment instance using ``state.document.settings.env``.
+
+Then, to act as a link target (from the todolist), the todo directive needs to
+return a target node in addition to the todo node.  The target ID (in HTML, this
+will be the anchor name) is generated by using ``env.index_num`` which is
+persistent between directive calls and therefore leads to unique target names.
+The target node is instantiated without any text (the first two arguments).
+
+An admonition is created using a standard docutils function (wrapped in Sphinx
+for docutils cross-version compatibility).  The first argument gives the node
+class, in our case ``todo``.  The third argument gives the admonition title (use
+``arguments`` here to let the user specify the title).  A list of nodes is
+returned from ``make_admonition``.
+
+Then, the todo node is added to the environment.  This is needed to be able to
+create a list of all todo entries throughout the documentation, in the place
+where the author puts a ``todolist`` directive.  For this case, the environment
+attribute ``todo_all_todos`` is used (again, the name should be unique, so it is
+prefixed by the extension name).  It does not exist when a new environment is
+created, so the directive must check and create it if necessary.  Various
+information about the todo entry's location are stored along with a copy of the
+node.
+
+In the last line, the nodes that should be put into the doctree are returned:
+the target node and the admonition node.
+
+
+The Event Handlers
+------------------
+
+Finally, let's look at the event handlers.  First, the one for the
+:event:`env-purge-doc` event::
+
+   def purge_todos(app, env, docname):
+       if not hasattr(env, 'todo_all_todos'):
+           return
+       env.todo_all_todos = [todo for todo in env.todo_all_todos
+                             if todo['docname'] != docname]
+
+Since we store information from source files in the environment, which is
+persistent, it may become out of date when the source file changes.  Therefore,
+before each source file is read, the environment's records of it are cleared,
+and the :event:`env-purge-doc` event gives extensions a chance to do the same.
+Here we clear out all todos whose docname matches the given one from the
+``todo_all_todos`` list.  If there are todos left in the document, they will be
+added again during parsing.
+
+The other handler belongs to the :event:`doctree-resolved` event.  This event is
+emitted at the end of phase 3 and allows custom resolving to be done::
+
+   def process_todo_nodes(app, doctree, fromdocname):
+       if not app.config.todo_include_todos:
+           for node in doctree.traverse(todo_node):
+               node.parent.remove(node)
+    
+       # Replace all todolist nodes with a list of the collected todos.
+       # Augment each todo with a backlink to the original location.
+       env = app.builder.env
+    
+       for node in doctree.traverse(todolist):
+           if not app.config.todo_include_todos:
+               node.replace_self([])
+               continue
+    
+           content = []
+    
+           for todo_info in env.todo_all_todos:
+               para = nodes.paragraph()
+               filename = env.doc2path(todo_info['docname'], base=None)
+               description = (
+                   _('(The original entry is located in %s, line %d and can be found ') %
+                   (filename, todo_info['lineno']))
+               para += nodes.Text(description, description)
+    
+               # Create a reference
+               newnode = nodes.reference('', '')
+               innernode = nodes.emphasis(_('here'), _('here'))
+               newnode['refdocname'] = todo_info['docname']
+               newnode['refuri'] = app.builder.get_relative_uri(
+                   fromdocname, todo_info['docname'])
+               newnode['refuri'] += '#' + todo_info['target']['refid']
+               newnode.append(innernode)
+               para += newnode
+               para += nodes.Text('.)', '.)')
+    
+               # Insert into the todolist
+               content.append(todo_info['todo'])
+               content.append(para)
+    
+           node.replace_self(content)
+
+It is a bit more involved.  If our new "todo_include_todos" config value is
+false, all todo and todolist nodes are removed from the documents.
+
+If not, todo nodes just stay where and how they are.  Todolist nodes are
+replaced by a list of todo entries, complete with backlinks to the location
+where they come from.  The list items are composed of the nodes from the todo
+entry and docutils nodes created on the fly: a paragraph for each entry,
+containing text that gives the location, and a link (reference node containing
+an italic node) with the backreference.  The reference URI is built by
+``app.builder.get_relative_uri`` which creates a suitable URI depending on the
+used builder, and appending the todo node's (the target's) ID as the anchor
+name.
+

Modified: doctools/trunk/doc/extensions.rst
==============================================================================
--- doctools/trunk/doc/extensions.rst	(original)
+++ doctools/trunk/doc/extensions.rst	Sun Jan  4 21:38:57 2009
@@ -9,17 +9,25 @@
 Since many projects will need special features in their documentation, Sphinx is
 designed to be extensible on several levels.
 
-First, you can add new :term:`builder`\s to support new output formats or
-actions on the parsed documents.  Then, it is possible to register custom
-reStructuredText roles and directives, extending the markup.  And finally, there
-are so-called "hook points" at strategic places throughout the build process,
-where an extension can register a hook and run specialized code.
-
-The configuration file itself can be an extension, see the :confval:`extensions`
-configuration value docs.
+This is what you can do in an extension: First, you can add new
+:term:`builder`\s to support new output formats or actions on the parsed
+documents.  Then, it is possible to register custom reStructuredText roles and
+directives, extending the markup.  And finally, there are so-called "hook
+points" at strategic places throughout the build process, where an extension can
+register a hook and run specialized code.
+
+An extension is simply a Python module.  When an extension is loaded, Sphinx
+imports this module and executes its ``setup()`` function, which in turn
+notifies Sphinx of everything the extension offers -- see the extension tutorial
+for examples.
+
+The configuration file itself can be treated as an extension if it contains a
+``setup()`` function.  All other extensions to load must be listed in the
+:confval:`extensions` configuration value.
 
 .. toctree::
 
+   ext/tutorial
    ext/appapi
    ext/builderapi
 
@@ -39,3 +47,36 @@
    ext/refcounting
    ext/ifconfig
    ext/coverage
+   ext/todo
+
+
+Third-party extensions
+----------------------
+
+There are several extensions that are not (yet) maintained in the Sphinx
+distribution.  The `Wiki at BitBucket`_ maintains a list of those.
+
+If you write an extension that you think others will find useful, please write
+to the project mailing list (sphinx-dev at googlegroups.com) and we'll find the
+proper way of including or hosting it for the public.
+
+.. _Wiki at BitBucket: http://www.bitbucket.org/birkenfeld/sphinx/wiki/Home
+
+
+Where to put your own extensions?
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Extensions local to a project should be put within the project's directory
+structure.  Set Python's module search path, ``sys.path``, accordingly so that
+Sphinx can find them.
+E.g., if your extension ``foo.py`` lies in the ``exts`` subdirectory of the
+project root, put into :file:`conf.py`::
+
+   import sys, os
+
+   sys.path.append(os.path.abspath('exts'))
+
+   extensions = ['foo']
+
+You can also install extensions anywhere else on ``sys.path``, e.g. in the
+``site-packages`` directory.

Modified: doctools/trunk/doc/glossary.rst
==============================================================================
--- doctools/trunk/doc/glossary.rst	(original)
+++ doctools/trunk/doc/glossary.rst	Sun Jan  4 21:38:57 2009
@@ -6,7 +6,7 @@
 .. glossary::
 
    builder
-      A class (inheriting from :class:`~sphinx.builder.Builder`) that takes
+      A class (inheriting from :class:`~sphinx.builders.Builder`) that takes
       parsed documents and performs an action on them.  Normally, builders
       translate the documents to an output format, but it is also possible to
       use the builder builders that e.g. check for broken links in the

Modified: doctools/trunk/doc/intro.rst
==============================================================================
--- doctools/trunk/doc/intro.rst	(original)
+++ doctools/trunk/doc/intro.rst	Sun Jan  4 21:38:57 2009
@@ -105,17 +105,33 @@
 
    .. versionadded:: 0.3
 
+**-C**
+   Don't look for a configuration file; only take options via the ``-D`` option.
+
+   .. versionadded:: 0.5
+   
 **-D** *setting=value*
-   Override a configuration value set in the :file:`conf.py` file.  (The value
-   must be a string value.)
+   Override a configuration value set in the :file:`conf.py` file.  The value
+   must be a string or dictionary value.  For the latter, supply the setting
+   name and key like this: ``-D latex_elements.docclass=scrartcl``.
+
+   .. versionchanged:: 0.6
+      The value can now be a dictionary value.
+
+**-A** *name=value*
+   Make the *name* assigned to *value* in the HTML templates.
 
 **-N**
    Do not do colored output.  (On Windows, colored output is disabled in any
    case.)
 
 **-q**
-   Do not output anything on standard output, only write warnings to standard
-   error.
+   Do not output anything on standard output, only write warnings and errors to
+   standard error.
+
+**-Q**
+   Do not output anything on standard output, also suppress warnings.  Only
+   errors are written to standard error.
 
 **-P**
    (Useful for debugging only.)  Run the Python debugger, :mod:`pdb`, if an

Modified: doctools/trunk/doc/markup/code.rst
==============================================================================
--- doctools/trunk/doc/markup/code.rst	(original)
+++ doctools/trunk/doc/markup/code.rst	Sun Jan  4 21:38:57 2009
@@ -113,8 +113,35 @@
       .. literalinclude:: example.py
          :encoding: latin-1
 
+   The directive also supports including only parts of the file.  If it is a
+   Python module, you can select a class, function or method to include using
+   the ``pyobject`` option::
+
+      .. literalinclude:: example.py
+         :pyobject: Timer.start
+
+   This would only include the code lines belonging to the ``start()`` method in
+   the ``Timer`` class within the file.
+
+   Alternately, you can specify exactly which lines to include by giving a
+   ``lines`` option::
+
+      .. literalinclude:: example.py
+         :lines: 1,3,5-10,20-
+
+   This includes the lines 1, 3, 5 to 10 and lines 20 to the last line.
+
+   Another way to control which part of the file is included is to use the
+   ``start-after`` and ``end-before`` options (or only one of them).  If
+   ``start-after`` is given as a string option, only lines that follow the first
+   line containing that string are included.  If ``end-before`` is given as a
+   string option, only lines that precede the first lines containing that string
+   are included.
+
    .. versionadded:: 0.4.3
       The ``encoding`` option.
+   .. versionadded:: 0.6
+      The ``pyobject``, ``lines``, ``start-after`` and ``end-before`` options.
 
 
 .. rubric:: Footnotes

Modified: doctools/trunk/doc/markup/desc.rst
==============================================================================
--- doctools/trunk/doc/markup/desc.rst	(original)
+++ doctools/trunk/doc/markup/desc.rst	Sun Jan  4 21:38:57 2009
@@ -17,7 +17,7 @@
    .. moduleauthor:: John Idle <john at python.invalid>
 
 
-The directives you can use for module are:
+The directives you can use for module declarations are:
 
 .. directive:: .. module:: name
 
@@ -67,8 +67,8 @@
 
 .. _desc-units:
 
-Description units
------------------
+Object description units
+------------------------
 
 There are a number of directives used to describe specific features provided by
 modules.  Each directive requires one or more signatures to provide basic
@@ -204,39 +204,12 @@
    Like :dir:`method`, but indicates that the method is a static method.
 
    .. versionadded:: 0.4
-   
-.. directive:: .. cmdoption:: name args, name args, ...
-
-   Describes a command line option or switch.  Option argument names should be
-   enclosed in angle brackets.  Example::
-
-      .. cmdoption:: -m <module>, --module <module>
-
-         Run a module as a script.
-
-   The directive will create a cross-reference target named after the *first*
-   option, referencable by :role:`option` (in the example case, you'd use
-   something like ``:option:`-m```).
-
-.. directive:: .. envvar:: name
 
-   Describes an environment variable that the documented code uses or defines.
+.. directive:: .. classmethod:: name(signature)
 
+   Like :dir:`method`, but indicates that the method is a class method.
 
-There is also a generic version of these directives:
-
-.. directive:: .. describe:: text
-
-   This directive produces the same formatting as the specific ones explained
-   above but does not create index entries or cross-referencing targets.  It is
-   used, for example, to describe the directives in this document. Example::
-
-      .. describe:: opcode
-
-         Describes a Python bytecode instruction.
-
-Extensions may add more directives like that, using the
-:func:`~sphinx.application.Sphinx.add_description_unit` method.
+   .. versionadded:: 0.6
 
 
 .. _signatures:
@@ -288,7 +261,7 @@
 
       Format the exception with a traceback.
    
-      :param object: exception type
+      :param etype: exception type
       :param value: exception value
       :param tb: traceback object
       :param limit: maximum number of stack frames to show
@@ -302,9 +275,83 @@
 
       Format the exception with a traceback.
 
-      :param object: exception type
+      :param etype: exception type
       :param value: exception value
       :param tb: traceback object
       :param limit: maximum number of stack frames to show
       :type limit: integer or None
       :rtype: list of strings
+
+
+Command-line program markup
+~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+There is a set of directives allowing documenting command-line programs:
+
+.. directive:: .. cmdoption:: name args, name args, ...
+
+   Describes a command line option or switch.  Option argument names should be
+   enclosed in angle brackets.  Example::
+
+      .. cmdoption:: -m <module>, --module <module>
+
+         Run a module as a script.
+
+   The directive will create a cross-reference target named after the *first*
+   option, referencable by :role:`option` (in the example case, you'd use
+   something like ``:option:`-m```).
+
+.. directive:: .. envvar:: name
+
+   Describes an environment variable that the documented code or program uses or
+   defines.
+
+
+.. directive:: .. program:: name
+
+   Like :dir:`currentmodule`, this directive produces no output.  Instead, it
+   serves to notify Sphinx that all following :dir:`cmdoption` directives
+   document options for the program called *name*.
+
+   If you use :dir:`program`, you have to qualify the references in your
+   :role:`option` roles by the program name, so if you have the following
+   situation ::
+
+      .. program:: rm
+
+      .. cmdoption:: -r
+
+         Work recursively.
+
+      .. program:: svn
+
+      .. cmdoption:: -r revision
+
+         Specify the revision to work upon.
+
+   then ``:option:`rm -r``` would refer to the first option, while
+   ``:option:`svn -r``` would refer to the second one.
+
+   The program name may contain spaces (in case you want to document subcommands
+   like ``svn add`` and ``svn commit`` separately).
+
+   .. versionadded:: 0.5
+
+
+Custom description units
+~~~~~~~~~~~~~~~~~~~~~~~~
+
+There is also a generic version of these directives:
+
+.. directive:: .. describe:: text
+
+   This directive produces the same formatting as the specific ones explained
+   above but does not create index entries or cross-referencing targets.  It is
+   used, for example, to describe the directives in this document. Example::
+
+      .. describe:: opcode
+
+         Describes a Python bytecode instruction.
+
+Extensions may add more directives like that, using the
+:func:`~sphinx.application.Sphinx.add_description_unit` method.

Modified: doctools/trunk/doc/markup/inline.rst
==============================================================================
--- doctools/trunk/doc/markup/inline.rst	(original)
+++ doctools/trunk/doc/markup/inline.rst	Sun Jan  4 21:38:57 2009
@@ -12,7 +12,8 @@
 .. note::
 
    The default role (```content```) has no special meaning by default.  You are
-   free to use it for anything you like. 
+   free to use it for anything you like; use the :confval:`default_role` config
+   value to set it to a known role.
 
 
 .. _xref-syntax:
@@ -223,7 +224,50 @@
 Using :role:`ref` is advised over standard reStructuredText links to sections
 (like ```Section title`_``) because it works across files, when section headings
 are changed, and for all builders that support cross-references.
-  
+
+
+Cross-referencing documents
+---------------------------
+
+.. versionadded:: 0.6
+
+There is also a way to directly link to documents:
+
+.. role:: doc
+
+   Link to the specified document; the document name can be specified in
+   absolute or relative fashion.  For example, if the reference
+   ``:doc:`parrot``` occurs in the document ``sketches/index``, then the link
+   refers to ``sketches/parrot``.  If the reference is ``:doc:`/people``` or
+   ``:doc:`../people```, the link refers to ``people``.
+
+   If no explicit link text is given (like usual: ``:doc:`Monty Python members
+   </people>```), the link caption will be the title of the given document.
+
+
+Referencing downloadable files
+------------------------------
+
+.. versionadded:: 0.6
+
+.. role:: download
+
+   This role lets you link to files within your source tree that are not reST
+   documents that can be viewed, but files that can be downloaded.
+
+   When you use this role, the referenced file is automatically marked for
+   inclusion in the output when building (obviously, for HTML output only).
+   All downloadable files are put into the ``_downloads`` subdirectory of the
+   output directory; duplicate filenames are handled.
+
+   An example::
+
+      See :download:`this example script <../example.py>`.
+
+   The given filename is relative to the directory the current source file is
+   contained in.  The ``../example.py`` file will be copied to the output
+   directory, and a suitable link generated to it.
+
 
 Other semantic markup
 ---------------------
@@ -329,7 +373,7 @@
    curly braces to indicate a "variable" part, as in ``:file:``.
 
    If you don't need the "variable part" indication, use the standard
-   ````code```` instead.   
+   ````code```` instead.
 
 
 The following roles generate external links:
@@ -350,6 +394,7 @@
 Note that there are no special roles for including hyperlinks as you can use
 the standard reST markup for that purpose.
 
+
 .. _default-substitutions:
 
 Substitutions
@@ -372,6 +417,6 @@
 
 .. describe:: |today|
 
-   Replaced by either today's date, or the date set in the build configuration
-   file.  Normally has the format ``April 14, 2007``.  Set by
-   :confval:`today_fmt` and :confval:`today`.
+   Replaced by either today's date (the date on which the document is read), or
+   the date set in the build configuration file.  Normally has the format
+   ``April 14, 2007``.  Set by :confval:`today_fmt` and :confval:`today`.

Modified: doctools/trunk/doc/markup/para.rst
==============================================================================
--- doctools/trunk/doc/markup/para.rst	(original)
+++ doctools/trunk/doc/markup/para.rst	Sun Jan  4 21:38:57 2009
@@ -74,6 +74,13 @@
          `GNU tar manual, Basic Tar Format <http://link>`_
             Documentation for tar archive files, including GNU tar extensions.
 
+   There's also a "short form" allowed that looks like this::
+
+      .. seealso:: modules :mod:`zipfile`, :mod:`tarfile`
+
+   .. versionadded:: 0.5
+      The short form.
+
 .. directive:: .. rubric:: title
 
    This directive creates a paragraph heading that is not used to create a

Modified: doctools/trunk/doc/rest.rst
==============================================================================
--- doctools/trunk/doc/rest.rst	(original)
+++ doctools/trunk/doc/rest.rst	Sun Jan  4 21:38:57 2009
@@ -217,6 +217,11 @@
 subdirectory of the output directory on building (e.g. the ``_static`` directory
 for HTML output.)
 
+Interpretation of image size options (``width`` and ``height``) is as follows:
+if the size has no unit or the unit is pixels, the given size will only be
+respected for output channels that support pixels (i.e. not in LaTeX output).
+Other units (like ``pt`` for points) will be used for HTML and LaTeX output.
+
 Sphinx extends the standard docutils behavior by allowing an asterisk for the
 extension::
 
@@ -291,7 +296,17 @@
 --------
 
 Every explicit markup block which isn't a valid markup construct (like the
-footnotes above) is regarded as a comment.
+footnotes above) is regarded as a comment.  For example::
+
+   .. This is a comment.
+
+You can indent text after a comment start to form multiline comments::
+   
+   ..
+      This whole indented block
+      is a comment.
+
+      Still in the comment.
 
 
 Source encoding
@@ -312,4 +327,7 @@
   separated from the surrounding text by non-word characters, you have to use
   a backslash-escaped space to get around that.
 
+* **No nested inline markup:** Something like ``*see :func:`foo`*`` is not
+  possible.
+  
 .. XXX more?

Added: doctools/trunk/doc/sphinx-build.1
==============================================================================
--- (empty file)
+++ doctools/trunk/doc/sphinx-build.1	Sun Jan  4 21:38:57 2009
@@ -0,0 +1,96 @@
+.TH sphinx-build 1 "Jan 2009" "Sphinx 0.6" "User Commands"
+.SH NAME
+sphinx-build \- Sphinx documentation generator tool
+.SH SYNOPSIS
+.B sphinx-build
+[\fIoptions\fR] <\fIsourcedir\fR> <\fIoutdir\fR> [\fIfilenames\fR...]
+.SH DESCRIPTION
+sphinx-build generates documentation from the files in <sourcedir> and places it
+in the <outdir>.
+
+sphinx-build looks for <sourcedir>/conf.py for the configuration settings.
+.B sphinx-quickstart(1)
+may be used to generate template files, including conf.py.
+
+sphinx-build can create documentation in different formats.  A format is
+selected by specifying the builder name on the command line; it defaults to
+HTML.  Builders can also perform other tasks related to documentation
+processing.
+
+By default, everything that is outdated is built.  Output only for selected
+files can be built by specifying individual filenames.
+
+List of available builders:
+.TP
+\fBhtml\fR
+HTML files generation.  This is default builder.
+.TP
+\fBhtmlhelp\fR
+Generates files for CHM generation.
+.TP
+\fBqthelp\fR
+Generates files for Qt help collection generation.
+.TP
+\fBlatex\fR
+Generates a LaTeX version of the documentation.
+.TP
+\fBtext\fR
+Generates a plain-text version of the documentation.
+.TP
+\fBchanges\fR
+Generates HTML files listing changed/added/deprecated items for the
+current version.
+.TP
+\fBlinkcheck\fR
+Checks the integrity of all external links in the documentation.
+.TP
+\fBpickle / json\fR
+Generates serialized HTML files in the selected format.
+
+.SH OPTIONS
+.TP
+\fB-b\fR <builder>
+Builder to use; defaults to html. See the full list of builders above.
+.TP
+\fB-a\fR
+Generates output for all files; without this option only output for
+new and changed files is generated.
+.TP
+\fB-E\fR
+Ignores cached files, forces to re-read all source files from disk.
+.TP
+\fB-c\fR <path>
+Locates the conf.py file in the specified path instead of <sourcedir>.
+.TP
+\fB-C\fR
+Specifies that no conf.py file at all is to be used.  Configuration can
+only be set with the -D option.
+.TP
+\fB-D\fR <setting>=<value>
+Overrides a setting from the configuration file.
+.TP
+\fB-d\fR <path>
+Path to cached files; defaults to <outdir>/.doctrees.
+.TP
+\fB-A\fR <name>=<value>
+Passes a value into the HTML templates (only for html builders).
+.TP
+\fB-N\fR
+Prevents colored output.
+.TP
+\fB-q\fR
+Quiet operation, just prints warnings and errors on stderr.
+.TP
+\fB-Q\fR
+Very quiet operation, doesn't print anything except for errors.
+.TP
+\fB-P\fR
+Runs Pdb on exception.
+.SH "SEE ALSO"
+.BR sphinx-quickstart(1)
+.SH AUTHOR
+Georg Brandl <georg at python.org>, Armin Ronacher <armin.ronacher at active-4.com> et
+al.
+.PP
+This manual page was initially written by Mikhail Gusarov
+<dottedmag at dottedmag.net>, for the Debian project.

Added: doctools/trunk/doc/sphinx-quickstart.1
==============================================================================
--- (empty file)
+++ doctools/trunk/doc/sphinx-quickstart.1	Sun Jan  4 21:38:57 2009
@@ -0,0 +1,17 @@
+.TH sphinx-quickstart 1 "Jan 2009" "Sphinx 0.6" "User Commands"
+.SH NAME
+sphinx-quickstart \- Sphinx documentation template generator
+.SH SYNOPSIS
+.B sphinx-quickstart
+.SH DESCRIPTION
+sphinx-quickstart is an interactive tool that asks some questions about your
+project and then generates a complete documentation directory and sample
+Makefile to be used with \fBsphinx-build(1)\fR.
+.SH "SEE ALSO"
+.BR sphinx-build(1)
+.SH AUTHOR
+Georg Brandl <georg at python.org>, Armin Ronacher <armin.ronacher at active-4.com> et
+al.
+.PP
+This manual page was initially written by Mikhail Gusarov
+<dottedmag at dottedmag.net> for the Debian project.

Modified: doctools/trunk/doc/templating.rst
==============================================================================
--- doctools/trunk/doc/templating.rst	(original)
+++ doctools/trunk/doc/templating.rst	Sun Jan  4 21:38:57 2009
@@ -19,10 +19,10 @@
   configuration value accordingly.
 
 * You can :ref:`write a custom builder <writing-builders>` that derives from
-  :class:`~sphinx.builder.StandaloneHTMLBuilder` and calls your template engine
+  :class:`~sphinx.builders.StandaloneHTMLBuilder` and calls your template engine
   of choice.
 
-* You can use the :class:`~sphinx.builder.PickleHTMLBuilder` that produces
+* You can use the :class:`~sphinx.builders.PickleHTMLBuilder` that produces
   pickle files with the page contents, and postprocess them using a custom tool,
   or use them in your Web application.
 
@@ -135,6 +135,10 @@
 `sidebarrel`
     The relation links (previous, next document) within the sidebar.
 
+`sidebarsourcelink`
+    The "Show source" link within the sidebar (normally only shown if this is
+    enabled by :confval:`html_show_sourcelink`).
+
 `sidebarsearch`
     The search box within the sidebar.  Override this if you want to place some
     content at the bottom of the sidebar.

Modified: doctools/trunk/ez_setup.py
==============================================================================
--- doctools/trunk/ez_setup.py	(original)
+++ doctools/trunk/ez_setup.py	Sun Jan  4 21:38:57 2009
@@ -14,7 +14,7 @@
 This file can also be run as a script to install or upgrade setuptools.
 """
 import sys
-DEFAULT_VERSION = "0.6c8"
+DEFAULT_VERSION = "0.6c9"
 DEFAULT_URL     = "http://pypi.python.org/packages/%s/s/setuptools/" % sys.version[:3]
 
 md5_data = {
@@ -48,13 +48,18 @@
     'setuptools-0.6c8-py2.3.egg': '50759d29b349db8cfd807ba8303f1902',
     'setuptools-0.6c8-py2.4.egg': 'cba38d74f7d483c06e9daa6070cce6de',
     'setuptools-0.6c8-py2.5.egg': '1721747ee329dc150590a58b3e1ac95b',
+    'setuptools-0.6c9-py2.3.egg': 'a83c4020414807b496e4cfbe08507c03',
+    'setuptools-0.6c9-py2.4.egg': '260a2be2e5388d66bdaee06abec6342a',
+    'setuptools-0.6c9-py2.5.egg': 'fe67c3e5a17b12c0e7c541b7ea43a8e6',
+    'setuptools-0.6c9-py2.6.egg': 'ca37b1ff16fa2ede6e19383e7b59245a',
 }
 
 import sys, os
+try: from hashlib import md5
+except ImportError: from md5 import md5
 
 def _validate_md5(egg_name, data):
     if egg_name in md5_data:
-        from md5 import md5
         digest = md5(data).hexdigest()
         if digest != md5_data[egg_name]:
             print >>sys.stderr, (
@@ -64,7 +69,6 @@
             sys.exit(2)
     return data
 
-
 def use_setuptools(
     version=DEFAULT_VERSION, download_base=DEFAULT_URL, to_dir=os.curdir,
     download_delay=15
@@ -233,7 +237,6 @@
     """Update our built-in md5 registry"""
 
     import re
-    from md5 import md5
 
     for name in filenames:
         base = os.path.basename(name)
@@ -270,3 +273,4 @@
 
 
 
+

Modified: doctools/trunk/setup.py
==============================================================================
--- doctools/trunk/setup.py	(original)
+++ doctools/trunk/setup.py	Sun Jan  4 21:38:57 2009
@@ -4,7 +4,7 @@
 
 import os
 import sys
-from setuptools import setup
+from setuptools import setup, find_packages
 from distutils import log
 
 import sphinx
@@ -24,7 +24,7 @@
 Although it is still under constant development, the following features
 are already present, work fine and can be seen "in action" in the Python docs:
 
-* Output formats: HTML (including Windows HTML Help) and LaTeX,
+* Output formats: HTML (including Windows HTML Help), plain text and LaTeX,
   for printable PDF versions
 * Extensive cross-references: semantic markup and automatic links
   for functions, classes, glossary terms and similar pieces of information
@@ -36,7 +36,7 @@
   and inclusion of appropriately formatted docstrings.
 '''
 
-requires = ['Pygments>=0.8', 'Jinja>=1.1', 'docutils>=0.4']
+requires = ['Pygments>=0.8', 'Jinja2>=2.0', 'docutils>=0.4']
 
 if sys.version_info < (2, 4):
     print 'ERROR: Sphinx requires at least Python 2.4 to run.'
@@ -172,7 +172,7 @@
         'Topic :: Utilities',
     ],
     platforms='any',
-    packages=['sphinx'],
+    packages=find_packages(),
     include_package_data=True,
     entry_points={
         'console_scripts': [

Modified: doctools/trunk/sphinx-build.py
==============================================================================
--- doctools/trunk/sphinx-build.py	(original)
+++ doctools/trunk/sphinx-build.py	Sun Jan  4 21:38:57 2009
@@ -4,8 +4,8 @@
     Sphinx - Python documentation toolchain
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
-    :copyright: 2007-2008 by Georg Brandl.
-    :license: BSD.
+    :copyright: Copyright 2007-2009 by the Sphinx team, see AUTHORS.
+    :license: BSD, see LICENSE for details.
 """
 
 import sys

Modified: doctools/trunk/sphinx-quickstart.py
==============================================================================
--- doctools/trunk/sphinx-quickstart.py	(original)
+++ doctools/trunk/sphinx-quickstart.py	Sun Jan  4 21:38:57 2009
@@ -4,8 +4,8 @@
     Sphinx - Python documentation toolchain
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
-    :copyright: 2008 by Georg Brandl.
-    :license: BSD.
+    :copyright: Copyright 2007-2009 by the Sphinx team, see AUTHORS.
+    :license: BSD, see LICENSE for details.
 """
 
 import sys

Modified: doctools/trunk/sphinx/__init__.py
==============================================================================
--- doctools/trunk/sphinx/__init__.py	(original)
+++ doctools/trunk/sphinx/__init__.py	Sun Jan  4 21:38:57 2009
@@ -5,15 +5,18 @@
 
     The Sphinx documentation toolchain.
 
-    :copyright: 2007-2008 by Georg Brandl.
-    :license: BSD.
+    :copyright: Copyright 2007-2009 by the Sphinx team, see AUTHORS.
+    :license: BSD, see LICENSE for details.
 """
 
 import sys
+from os import path
 
 __revision__ = '$Revision$'
-__version__ = '0.5'
-__released__ = '0.5'
+__version__ = '0.6'
+__released__ = '0.6 (hg)'
+
+package_dir = path.abspath(path.dirname(__file__))
 
 
 def main(argv=sys.argv):
@@ -28,17 +31,23 @@
         errstr = str(err)
         if errstr.lower().startswith('no module named'):
             whichmod = errstr[16:]
+            hint = ''
             if whichmod.startswith('docutils'):
                 whichmod = 'Docutils library'
             elif whichmod.startswith('jinja'):
                 whichmod = 'Jinja library'
             elif whichmod == 'roman':
                 whichmod = 'roman module (which is distributed with Docutils)'
+                hint = ('This can happen if you upgraded docutils using\n'
+                        'easy_install without uninstalling the old version'
+                        'first.')
             else:
                 whichmod += ' module'
             print >>sys.stderr, \
                   'Error: The %s cannot be found. Did you install Sphinx '\
                   'and its dependencies correctly?' % whichmod
+            if hint:
+                print >> sys.stderr, hint
             return 1
         raise
     return cmdline.main(argv)

Added: doctools/trunk/sphinx/__init__.pyc
==============================================================================
Binary file. No diff available.

Modified: doctools/trunk/sphinx/_jinja.py
==============================================================================
--- doctools/trunk/sphinx/_jinja.py	(original)
+++ doctools/trunk/sphinx/_jinja.py	Sun Jan  4 21:38:57 2009
@@ -5,13 +5,14 @@
 
     Jinja glue.
 
-    :copyright: 2007-2008 by Georg Brandl, Horst Gutmann.
-    :license: BSD.
+    :copyright: Copyright 2007-2009 by the Sphinx team, see AUTHORS.
+    :license: BSD, see LICENSE for details.
 """
 
 import codecs
 from os import path
 
+from sphinx import package_dir
 from sphinx.util import mtimes_of_files
 from sphinx.application import TemplateBridge
 
@@ -88,7 +89,7 @@
 class BuiltinTemplates(TemplateBridge):
     def init(self, builder):
         self.templates = {}
-        base_templates_path = path.join(path.dirname(__file__), 'templates')
+        base_templates_path = path.join(package_dir, 'templates')
         ext_templates_path = [path.join(builder.confdir, dir)
                               for dir in builder.config.templates_path]
         self.templates_path = [base_templates_path] + ext_templates_path

Modified: doctools/trunk/sphinx/addnodes.py
==============================================================================
--- doctools/trunk/sphinx/addnodes.py	(original)
+++ doctools/trunk/sphinx/addnodes.py	Sun Jan  4 21:38:57 2009
@@ -5,8 +5,8 @@
 
     Additional docutils nodes.
 
-    :copyright: 2007-2008 by Georg Brandl.
-    :license: BSD.
+    :copyright: Copyright 2007-2009 by the Sphinx team, see AUTHORS.
+    :license: BSD, see LICENSE for details.
 """
 
 from docutils import nodes
@@ -23,8 +23,12 @@
 class desc_addname(nodes.Part, nodes.Inline, nodes.TextElement): pass
 # compatibility alias
 desc_classname = desc_addname
-# return type (C); object type, e.g. -> annotation (Python)
+# return type (C); object type
 class desc_type(nodes.Part, nodes.Inline, nodes.TextElement): pass
+# -> annotation (Python)
+class desc_returns(desc_type):
+    def astext(self):
+        return ' -> ' + nodes.TextElement.astext(self)
 # main name of object
 class desc_name(nodes.Part, nodes.Inline, nodes.TextElement): pass
 # argument list
@@ -64,6 +68,9 @@
 # compact paragraph -- never makes a <p>
 class compact_paragraph(nodes.paragraph): pass
 
+# reference to a file to download
+class download_reference(nodes.reference): pass
+
 # for the ACKS list
 class acks(nodes.Element): pass
 
@@ -90,8 +97,9 @@
 
 # make them known to docutils. this is needed, because the HTML writer
 # will choke at some point if these are not added
-nodes._add_node_class_names("""index desc desc_content desc_signature desc_type
-      desc_addname desc_name desc_parameterlist desc_parameter desc_optional
+nodes._add_node_class_names("""index desc desc_content desc_signature
+      desc_type desc_returns desc_addname desc_name desc_parameterlist
+      desc_parameter desc_optional download_reference
       centered versionmodified seealso productionlist production toctree
       pending_xref compact_paragraph highlightlang literal_emphasis
       glossary acks module start_of_file tabular_col_spec meta""".split())

Modified: doctools/trunk/sphinx/application.py
==============================================================================
--- doctools/trunk/sphinx/application.py	(original)
+++ doctools/trunk/sphinx/application.py	Sun Jan  4 21:38:57 2009
@@ -7,9 +7,8 @@
 
     Gracefully adapted from the TextPress system by Armin.
 
-
-    :copyright: 2008 by Georg Brandl, Armin Ronacher.
-    :license: BSD.
+    :copyright: Copyright 2007-2009 by the Sphinx team, see AUTHORS.
+    :license: BSD, see LICENSE for details.
 """
 
 import sys
@@ -22,7 +21,7 @@
 import sphinx
 from sphinx.roles import xfileref_role, innernodetypes
 from sphinx.config import Config
-from sphinx.builder import builtin_builders, StandaloneHTMLBuilder
+from sphinx.builders import BUILTIN_BUILDERS
 from sphinx.directives import desc_directive, target_directive, additional_xref_types
 from sphinx.environment import SphinxStandaloneReader
 from sphinx.util.console import bold
@@ -77,7 +76,7 @@
                  confoverrides, status, warning=sys.stderr, freshenv=False):
         self.next_listener_id = 0
         self._listeners = {}
-        self.builderclasses = builtin_builders.copy()
+        self.builderclasses = BUILTIN_BUILDERS.copy()
         self.builder = None
 
         self.srcdir = srcdir
@@ -125,6 +124,11 @@
                                                     buildername)))
 
         builderclass = self.builderclasses[buildername]
+        if isinstance(builderclass, tuple):
+            # builtin builder
+            mod, cls = builderclass
+            builderclass = getattr(
+                __import__('sphinx.builders.' + mod, None, None, [cls]), cls)
         self.builder = builderclass(self, freshenv=freshenv)
         self.emit('builder-inited')
 
@@ -144,13 +148,20 @@
 
     def warn(self, message):
         self._warncount += 1
-        self._warning.write('WARNING: %s\n' % message)
+        try:
+            self._warning.write('WARNING: %s\n' % message)
+        except UnicodeEncodeError:
+            encoding = getattr(self._warning, 'encoding', 'ascii')
+            self._warning.write(('WARNING: %s\n' % message).encode(encoding, 'replace'))
 
     def info(self, message='', nonl=False):
-        if nonl:
+        try:
             self._status.write(message)
-        else:
-            self._status.write(message + '\n')
+        except UnicodeEncodeError:
+            encoding = getattr(self._status, 'encoding', 'ascii')
+            self._status.write(message.encode(encoding, 'replace'))
+        if not nonl:
+            self._status.write('\n')
         self._status.flush()
 
     # general extensibility interface
@@ -220,8 +231,12 @@
         if not hasattr(builder, 'name'):
             raise ExtensionError('Builder class %s has no "name" attribute' % builder)
         if builder.name in self.builderclasses:
-            raise ExtensionError('Builder %r already exists (in module %s)' % (
-                builder.name, self.builderclasses[builder.name].__module__))
+            if isinstance(self.builderclasses[builder.name], tuple):
+                raise ExtensionError('Builder %r is a builtin builder' %
+                                     builder.name)
+            else:
+                raise ExtensionError('Builder %r already exists (in module %s)' % (
+                    builder.name, self.builderclasses[builder.name].__module__))
         self.builderclasses[builder.name] = builder
 
     def add_config_value(self, name, default, rebuild_env):
@@ -243,11 +258,11 @@
                 raise ExtensionError('Value for key %r must be a (visit, depart) '
                                      'function tuple' % key)
             if key == 'html':
-                from sphinx.htmlwriter import HTMLTranslator as translator
+                from sphinx.writers.html import HTMLTranslator as translator
             elif key == 'latex':
-                from sphinx.latexwriter import LaTeXTranslator as translator
+                from sphinx.writers.latex import LaTeXTranslator as translator
             elif key == 'text':
-                from sphinx.textwriter import TextTranslator as translator
+                from sphinx.writers.text import TextTranslator as translator
             else:
                 # ignore invalid keys for compatibility
                 continue
@@ -284,9 +299,16 @@
         SphinxStandaloneReader.transforms.append(transform)
 
     def add_javascript(self, filename):
+        from sphinx.builders.html import StandaloneHTMLBuilder
         StandaloneHTMLBuilder.script_files.append(
             posixpath.join('_static', filename))
 
+    def add_lexer(self, alias, lexer):
+        from sphinx.highlighting import lexers
+        if lexers is None:
+            return
+        lexers[alias] = lexer
+
 
 class TemplateBridge(object):
     """

Modified: doctools/trunk/sphinx/builder.py
==============================================================================
--- doctools/trunk/sphinx/builder.py	(original)
+++ doctools/trunk/sphinx/builder.py	Sun Jan  4 21:38:57 2009
@@ -3,1268 +3,26 @@
     sphinx.builder
     ~~~~~~~~~~~~~~
 
-    Builder classes for different output formats.
+    .. warning::
 
-    :copyright: 2007-2008 by Georg Brandl, Sebastian Wiesner, Horst Gutmann.
-    :license: BSD.
-"""
-
-import os
-import time
-import codecs
-import shutil
-import gettext
-import cPickle as pickle
-from os import path
-from cgi import escape
-
-from docutils import nodes
-from docutils.io import StringOutput, FileOutput, DocTreeInput
-from docutils.core import publish_parts
-from docutils.utils import new_document
-from docutils.frontend import OptionParser
-from docutils.readers.doctree import Reader as DoctreeReader
-
-from sphinx import addnodes, locale, __version__
-from sphinx.util import ensuredir, relative_uri, SEP, os_path, texescape, ustrftime
-from sphinx.htmlhelp import build_hhx
-from sphinx.htmlwriter import HTMLWriter, HTMLTranslator, SmartyPantsHTMLTranslator
-from sphinx.textwriter import TextWriter
-from sphinx.latexwriter import LaTeXWriter
-from sphinx.environment import BuildEnvironment, NoUri
-from sphinx.highlighting import PygmentsBridge
-from sphinx.util.console import bold, purple, darkgreen
-from sphinx.search import js_index
-
-try:
-    import json
-except ImportError:
-    try:
-        import simplejson as json
-    except ImportError:
-        json = None
-
-# side effect: registers roles and directives
-from sphinx import roles
-from sphinx import directives
-
-ENV_PICKLE_FILENAME = 'environment.pickle'
-LAST_BUILD_FILENAME = 'last_build'
-INVENTORY_FILENAME = 'objects.inv'
-
-
-class Builder(object):
-    """
-    Builds target formats from the reST sources.
-    """
-
-    # builder's name, for the -b command line options
-    name = ''
-
-    def __init__(self, app, env=None, freshenv=False):
-        self.srcdir = app.srcdir
-        self.confdir = app.confdir
-        self.outdir = app.outdir
-        self.doctreedir = app.doctreedir
-        if not path.isdir(self.doctreedir):
-            os.makedirs(self.doctreedir)
-
-        self.app = app
-        self.warn = app.warn
-        self.info = app.info
-        self.config = app.config
-
-        self.load_i18n()
-
-        # images that need to be copied over (source -> dest)
-        self.images = {}
-
-        # if None, this is set in load_env()
-        self.env = env
-        self.freshenv = freshenv
-
-        self.init()
-        self.load_env()
-
-    # helper methods
-
-    def init(self):
-        """Load necessary templates and perform initialization."""
-        raise NotImplementedError
-
-    def init_templates(self):
-        # Call this from init() if you need templates.
-        if self.config.template_bridge:
-            self.templates = self.app.import_object(
-                self.config.template_bridge, 'template_bridge setting')()
-        else:
-            from sphinx._jinja import BuiltinTemplates
-            self.templates = BuiltinTemplates()
-        self.templates.init(self)
-
-    def get_target_uri(self, docname, typ=None):
-        """
-        Return the target URI for a document name (typ can be used to qualify
-        the link characteristic for individual builders).
-        """
-        raise NotImplementedError
-
-    def get_relative_uri(self, from_, to, typ=None):
-        """
-        Return a relative URI between two source filenames. May raise environment.NoUri
-        if there's no way to return a sensible URI.
-        """
-        return relative_uri(self.get_target_uri(from_),
-                            self.get_target_uri(to, typ))
-
-    def get_outdated_docs(self):
-        """
-        Return an iterable of output files that are outdated, or a string describing
-        what an update build will build.
-        """
-        raise NotImplementedError
-
-    def status_iterator(self, iterable, summary, colorfunc=darkgreen):
-        l = -1
-        for item in iterable:
-            if l == -1:
-                self.info(bold(summary), nonl=1)
-                l = 0
-            self.info(colorfunc(item) + ' ', nonl=1)
-            yield item
-        if l == 0:
-            self.info()
-
-    supported_image_types = []
-
-    def post_process_images(self, doctree):
-        """
-        Pick the best candidate for all image URIs.
-        """
-        for node in doctree.traverse(nodes.image):
-            if '?' in node['candidates']:
-                # don't rewrite nonlocal image URIs
-                continue
-            if '*' not in node['candidates']:
-                for imgtype in self.supported_image_types:
-                    candidate = node['candidates'].get(imgtype, None)
-                    if candidate:
-                        break
-                else:
-                    self.warn('%s:%s: no matching candidate for image URI %r' %
-                              (node.source, getattr(node, 'lineno', ''), node['uri']))
-                    continue
-                node['uri'] = candidate
-            else:
-                candidate = node['uri']
-            if candidate not in self.env.images:
-                # non-existing URI; let it alone
-                continue
-            self.images[candidate] = self.env.images[candidate][1]
-
-    # build methods
-
-    def load_i18n(self):
-        """
-        Load translated strings from the configured localedirs if
-        enabled in the configuration.
-        """
-        self.translator = None
-        if self.config.language is not None:
-            self.info(bold('loading translations [%s]... ' % self.config.language),
-                      nonl=True)
-            locale_dirs = [path.join(path.dirname(__file__), 'locale')] + \
-                          [path.join(self.srcdir, x) for x in self.config.locale_dirs]
-            for dir_ in locale_dirs:
-                try:
-                    trans = gettext.translation('sphinx', localedir=dir_,
-                            languages=[self.config.language])
-                    if self.translator is None:
-                        self.translator = trans
-                    else:
-                        self.translator._catalog.update(trans.catalog)
-                except Exception:
-                    # Language couldn't be found in the specified path
-                    pass
-            if self.translator is not None:
-                self.info('done')
-            else:
-                self.info('locale not available')
-        if self.translator is None:
-            self.translator = gettext.NullTranslations()
-        self.translator.install(unicode=True)
-        locale.init()  # translate common labels
-
-    def load_env(self):
-        """Set up the build environment."""
-        if self.env:
-            return
-        if not self.freshenv:
-            try:
-                self.info(bold('loading pickled environment... '), nonl=True)
-                self.env = BuildEnvironment.frompickle(self.config,
-                    path.join(self.doctreedir, ENV_PICKLE_FILENAME))
-                self.info('done')
-            except Exception, err:
-                if type(err) is IOError and err.errno == 2:
-                    self.info('not found')
-                else:
-                    self.info('failed: %s' % err)
-                self.env = BuildEnvironment(self.srcdir, self.doctreedir, self.config)
-                self.env.find_files(self.config)
-        else:
-            self.env = BuildEnvironment(self.srcdir, self.doctreedir, self.config)
-            self.env.find_files(self.config)
-        self.env.set_warnfunc(self.warn)
-
-    def build_all(self):
-        """Build all source files."""
-        self.build(None, summary='all source files', method='all')
-
-    def build_specific(self, filenames):
-        """Only rebuild as much as needed for changes in the source_filenames."""
-        # bring the filenames to the canonical format, that is,
-        # relative to the source directory and without source_suffix.
-        dirlen = len(self.srcdir) + 1
-        to_write = []
-        suffix = self.config.source_suffix
-        for filename in filenames:
-            filename = path.abspath(filename)[dirlen:]
-            if filename.endswith(suffix):
-                filename = filename[:-len(suffix)]
-            filename = filename.replace(os.path.sep, SEP)
-            to_write.append(filename)
-        self.build(to_write, method='specific',
-                   summary='%d source files given on command '
-                   'line' % len(to_write))
-
-    def build_update(self):
-        """Only rebuild files changed or added since last build."""
-        to_build = self.get_outdated_docs()
-        if isinstance(to_build, str):
-            self.build(['__all__'], to_build)
-        else:
-            to_build = list(to_build)
-            self.build(to_build,
-                       summary='targets for %d source files that are '
-                       'out of date' % len(to_build))
-
-    def build(self, docnames, summary=None, method='update'):
-        if summary:
-            self.info(bold('building [%s]: ' % self.name), nonl=1)
-            self.info(summary)
-
-        updated_docnames = []
-        # while reading, collect all warnings from docutils
-        warnings = []
-        self.env.set_warnfunc(warnings.append)
-        self.info(bold('updating environment: '), nonl=1)
-        iterator = self.env.update(self.config, self.srcdir, self.doctreedir, self.app)
-        # the first item in the iterator is a summary message
-        self.info(iterator.next())
-        for docname in self.status_iterator(iterator, 'reading sources... ', purple):
-            updated_docnames.append(docname)
-            # nothing further to do, the environment has already done the reading
-        for warning in warnings:
-            if warning.strip():
-                self.warn(warning)
-        self.env.set_warnfunc(self.warn)
-
-        if updated_docnames:
-            # save the environment
-            self.info(bold('pickling environment... '), nonl=True)
-            self.env.topickle(path.join(self.doctreedir, ENV_PICKLE_FILENAME))
-            self.info('done')
-
-            # global actions
-            self.info(bold('checking consistency... '), nonl=True)
-            self.env.check_consistency()
-            self.info('done')
-        else:
-            if method == 'update' and not docnames:
-                self.info(bold('no targets are out of date.'))
-                return
-
-        # another indirection to support methods which don't build files
-        # individually
-        self.write(docnames, updated_docnames, method)
-
-        # finish (write static files etc.)
-        self.finish()
-        if self.app._warncount:
-            self.info(bold('build succeeded, %s warning%s.' %
-                           (self.app._warncount,
-                            self.app._warncount != 1 and 's' or '')))
-        else:
-            self.info(bold('build succeeded.'))
-
-    def write(self, build_docnames, updated_docnames, method='update'):
-        if build_docnames is None or build_docnames == ['__all__']:
-            # build_all
-            build_docnames = self.env.found_docs
-        if method == 'update':
-            # build updated ones as well
-            docnames = set(build_docnames) | set(updated_docnames)
-        else:
-            docnames = set(build_docnames)
-
-        # add all toctree-containing files that may have changed
-        for docname in list(docnames):
-            for tocdocname in self.env.files_to_rebuild.get(docname, []):
-                docnames.add(tocdocname)
-        docnames.add(self.config.master_doc)
-
-        self.info(bold('preparing documents... '), nonl=True)
-        self.prepare_writing(docnames)
-        self.info('done')
-
-        # write target files
-        warnings = []
-        self.env.set_warnfunc(warnings.append)
-        for docname in self.status_iterator(sorted(docnames),
-                                            'writing output... ', darkgreen):
-            doctree = self.env.get_and_resolve_doctree(docname, self)
-            self.write_doc(docname, doctree)
-        for warning in warnings:
-            if warning.strip():
-                self.warn(warning)
-        self.env.set_warnfunc(self.warn)
-
-    def prepare_writing(self, docnames):
-        raise NotImplementedError
-
-    def write_doc(self, docname, doctree):
-        raise NotImplementedError
-
-    def finish(self):
-        raise NotImplementedError
-
-
-class StandaloneHTMLBuilder(Builder):
-    """
-    Builds standalone HTML docs.
-    """
-    name = 'html'
-    copysource = True
-    out_suffix = '.html'
-    indexer_format = js_index
-    supported_image_types = ['image/svg+xml', 'image/png', 'image/gif',
-                             'image/jpeg']
-    searchindex_filename = 'searchindex.js'
-    add_header_links = True
-    add_definition_links = True
-
-    # This is a class attribute because it is mutated by Sphinx.add_javascript.
-    script_files = ['_static/jquery.js', '_static/doctools.js']
-
-    def init(self):
-        """Load templates."""
-        self.init_templates()
-        self.init_translator_class()
-        if self.config.html_file_suffix:
-            self.out_suffix = self.config.html_file_suffix
-
-        if self.config.language is not None:
-            jsfile = path.join(path.dirname(__file__), 'locale', self.config.language,
-                               'LC_MESSAGES', 'sphinx.js')
-            if path.isfile(jsfile):
-                self.script_files.append('_static/translations.js')
-
-    def init_translator_class(self):
-        if self.config.html_translator_class:
-            self.translator_class = self.app.import_object(
-                self.config.html_translator_class, 'html_translator_class setting')
-        elif self.config.html_use_smartypants:
-            self.translator_class = SmartyPantsHTMLTranslator
-        else:
-            self.translator_class = HTMLTranslator
-
-    def render_partial(self, node):
-        """Utility: Render a lone doctree node."""
-        doc = new_document('<partial node>')
-        doc.append(node)
-        return publish_parts(
-            doc,
-            source_class=DocTreeInput,
-            reader=DoctreeReader(),
-            writer=HTMLWriter(self),
-            settings_overrides={'output_encoding': 'unicode'}
-        )
-
-    def prepare_writing(self, docnames):
-        from sphinx.search import IndexBuilder
-
-        self.indexer = IndexBuilder(self.env)
-        self.load_indexer(docnames)
-        self.docwriter = HTMLWriter(self)
-        self.docsettings = OptionParser(
-            defaults=self.env.settings,
-            components=(self.docwriter,)).get_default_values()
-
-        # format the "last updated on" string, only once is enough since it
-        # typically doesn't include the time of day
-        lufmt = self.config.html_last_updated_fmt
-        if lufmt is not None:
-            self.last_updated = ustrftime(lufmt or _('%b %d, %Y'))
-        else:
-            self.last_updated = None
-
-        logo = self.config.html_logo and \
-               path.basename(self.config.html_logo) or ''
-
-        favicon = self.config.html_favicon and \
-                  path.basename(self.config.html_favicon) or ''
-        if favicon and os.path.splitext(favicon)[1] != '.ico':
-            self.warn('html_favicon is not an .ico file')
-
-        if not isinstance(self.config.html_use_opensearch, basestring):
-            self.warn('html_use_opensearch config value must now be a string')
-
-        self.relations = self.env.collect_relations()
-
-        rellinks = []
-        if self.config.html_use_index:
-            rellinks.append(('genindex', _('General Index'), 'I', _('index')))
-        if self.config.html_use_modindex and self.env.modules:
-            rellinks.append(('modindex', _('Global Module Index'), 'M', _('modules')))
-
-        self.globalcontext = dict(
-            project = self.config.project,
-            release = self.config.release,
-            version = self.config.version,
-            last_updated = self.last_updated,
-            copyright = self.config.copyright,
-            master_doc = self.config.master_doc,
-            style = self.config.html_style,
-            use_opensearch = self.config.html_use_opensearch,
-            docstitle = self.config.html_title,
-            shorttitle = self.config.html_short_title,
-            show_sphinx = self.config.html_show_sphinx,
-            file_suffix = self.out_suffix,
-            script_files = self.script_files,
-            sphinx_version = __version__,
-            rellinks = rellinks,
-            builder = self.name,
-            parents = [],
-            logo = logo,
-            favicon = favicon,
-        )
-        self.globalcontext.update(self.config.html_context)
-
-    def get_doc_context(self, docname, body, metatags):
-        """Collect items for the template context of a page."""
-        # find out relations
-        prev = next = None
-        parents = []
-        rellinks = self.globalcontext['rellinks'][:]
-        related = self.relations.get(docname)
-        titles = self.env.titles
-        if related and related[2]:
-            try:
-                next = {'link': self.get_relative_uri(docname, related[2]),
-                        'title': self.render_partial(titles[related[2]])['title']}
-                rellinks.append((related[2], next['title'], 'N', _('next')))
-            except KeyError:
-                next = None
-        if related and related[1]:
-            try:
-                prev = {'link': self.get_relative_uri(docname, related[1]),
-                        'title': self.render_partial(titles[related[1]])['title']}
-                rellinks.append((related[1], prev['title'], 'P', _('previous')))
-            except KeyError:
-                # the relation is (somehow) not in the TOC tree, handle that gracefully
-                prev = None
-        while related and related[0]:
-            try:
-                parents.append(
-                    {'link': self.get_relative_uri(docname, related[0]),
-                     'title': self.render_partial(titles[related[0]])['title']})
-            except KeyError:
-                pass
-            related = self.relations.get(related[0])
-        if parents:
-            parents.pop() # remove link to the master file; we have a generic
-                          # "back to index" link already
-        parents.reverse()
-
-        # title rendered as HTML
-        title = titles.get(docname)
-        title = title and self.render_partial(title)['title'] or ''
-        # the name for the copied source
-        sourcename = self.config.html_copy_source and docname + '.txt' or ''
-
-        # metadata for the document
-        meta = self.env.metadata.get(docname)
-
-        return dict(
-            parents = parents,
-            prev = prev,
-            next = next,
-            title = title,
-            meta = meta,
-            body = body,
-            metatags = metatags,
-            rellinks = rellinks,
-            sourcename = sourcename,
-            toc = self.render_partial(self.env.get_toc_for(docname))['fragment'],
-            # only display a TOC if there's more than one item to show
-            display_toc = (self.env.toc_num_entries[docname] > 1),
-        )
-
-    def write_doc(self, docname, doctree):
-        self.post_process_images(doctree)
-        destination = StringOutput(encoding='utf-8')
-        doctree.settings = self.docsettings
-
-        self.imgpath = relative_uri(self.get_target_uri(docname), '_images')
-        self.docwriter.write(doctree, destination)
-        self.docwriter.assemble_parts()
-        body = self.docwriter.parts['fragment']
-        metatags = self.docwriter.clean_meta
-
-        ctx = self.get_doc_context(docname, body, metatags)
-        self.index_page(docname, doctree, ctx.get('title', ''))
-        self.handle_page(docname, ctx, event_arg=doctree)
-
-    def finish(self):
-        self.info(bold('writing additional files...'), nonl=1)
-
-        # the global general index
-
-        if self.config.html_use_index:
-            # the total count of lines for each index letter, used to distribute
-            # the entries into two columns
-            genindex = self.env.create_index(self)
-            indexcounts = []
-            for _, entries in genindex:
-                indexcounts.append(sum(1 + len(subitems)
-                                       for _, (_, subitems) in entries))
-
-            genindexcontext = dict(
-                genindexentries = genindex,
-                genindexcounts = indexcounts,
-                split_index = self.config.html_split_index,
-            )
-            self.info(' genindex', nonl=1)
-
-            if self.config.html_split_index:
-                self.handle_page('genindex', genindexcontext, 'genindex-split.html')
-                self.handle_page('genindex-all', genindexcontext, 'genindex.html')
-                for (key, entries), count in zip(genindex, indexcounts):
-                    ctx = {'key': key, 'entries': entries, 'count': count,
-                           'genindexentries': genindex}
-                    self.handle_page('genindex-' + key, ctx, 'genindex-single.html')
-            else:
-                self.handle_page('genindex', genindexcontext, 'genindex.html')
-
-        # the global module index
-
-        if self.config.html_use_modindex and self.env.modules:
-            # the sorted list of all modules, for the global module index
-            modules = sorted(((mn, (self.get_relative_uri('modindex', fn) +
-                                    '#module-' + mn, sy, pl, dep))
-                              for (mn, (fn, sy, pl, dep)) in
-                              self.env.modules.iteritems()),
-                             key=lambda x: x[0].lower())
-            # collect all platforms
-            platforms = set()
-            # sort out collapsable modules
-            modindexentries = []
-            letters = []
-            pmn = ''
-            num_toplevels = 0
-            num_collapsables = 0
-            cg = 0 # collapse group
-            fl = '' # first letter
-            for mn, (fn, sy, pl, dep) in modules:
-                pl = pl and pl.split(', ') or []
-                platforms.update(pl)
-                if fl != mn[0].lower() and mn[0] != '_':
-                    # heading
-                    modindexentries.append(['', False, 0, False,
-                                            mn[0].upper(), '', [], False])
-                    letters.append(mn[0].upper())
-                tn = mn.split('.')[0]
-                if tn != mn:
-                    # submodule
-                    if pmn == tn:
-                        # first submodule - make parent collapsable
-                        modindexentries[-1][1] = True
-                        num_collapsables += 1
-                    elif not pmn.startswith(tn):
-                        # submodule without parent in list, add dummy entry
-                        cg += 1
-                        modindexentries.append([tn, True, cg, False, '', '', [], False])
-                else:
-                    num_toplevels += 1
-                    cg += 1
-                modindexentries.append([mn, False, cg, (tn != mn), fn, sy, pl, dep])
-                pmn = mn
-                fl = mn[0].lower()
-            platforms = sorted(platforms)
-
-            # apply heuristics when to collapse modindex at page load:
-            # only collapse if number of toplevel modules is larger than
-            # number of submodules
-            collapse = len(modules) - num_toplevels < num_toplevels
-
-            modindexcontext = dict(
-                modindexentries = modindexentries,
-                platforms = platforms,
-                letters = letters,
-                collapse_modindex = collapse,
-            )
-            self.info(' modindex', nonl=1)
-            self.handle_page('modindex', modindexcontext, 'modindex.html')
-
-        # the search page
-        if self.name != 'htmlhelp':
-            self.info(' search', nonl=1)
-            self.handle_page('search', {}, 'search.html')
-
-        # additional pages from conf.py
-        for pagename, template in self.config.html_additional_pages.items():
-            self.info(' '+pagename, nonl=1)
-            self.handle_page(pagename, {}, template)
-
-        if self.config.html_use_opensearch and self.name != 'htmlhelp':
-            self.info(' opensearch', nonl=1)
-            fn = path.join(self.outdir, '_static', 'opensearch.xml')
-            self.handle_page('opensearch', {}, 'opensearch.xml', outfilename=fn)
-
-        self.info()
-
-        # copy image files
-        if self.images:
-            self.info(bold('copying images...'), nonl=True)
-            ensuredir(path.join(self.outdir, '_images'))
-            for src, dest in self.images.iteritems():
-                self.info(' '+src, nonl=1)
-                shutil.copyfile(path.join(self.srcdir, src),
-                                path.join(self.outdir, '_images', dest))
-            self.info()
-
-        # copy static files
-        self.info(bold('copying static files... '), nonl=True)
-        ensuredir(path.join(self.outdir, '_static'))
-        # first, create pygments style file
-        f = open(path.join(self.outdir, '_static', 'pygments.css'), 'w')
-        f.write(PygmentsBridge('html', self.config.pygments_style).get_stylesheet())
-        f.close()
-        # then, copy translations JavaScript file
-        if self.config.language is not None:
-            jsfile = path.join(path.dirname(__file__), 'locale', self.config.language,
-                               'LC_MESSAGES', 'sphinx.js')
-            if path.isfile(jsfile):
-                shutil.copyfile(jsfile, path.join(self.outdir, '_static',
-                                                  'translations.js'))
-        # then, copy over all user-supplied static files
-        staticdirnames = [path.join(path.dirname(__file__), 'static')] + \
-                         [path.join(self.confdir, spath)
-                          for spath in self.config.html_static_path]
-        for staticdirname in staticdirnames:
-            for filename in os.listdir(staticdirname):
-                if filename.startswith('.'):
-                    continue
-                fullname = path.join(staticdirname, filename)
-                targetname = path.join(self.outdir, '_static', filename)
-                if path.isfile(fullname):
-                    shutil.copyfile(fullname, targetname)
-                elif path.isdir(fullname):
-                    if filename in self.config.exclude_dirnames:
-                        continue
-                    if path.exists(targetname):
-                        shutil.rmtree(targetname)
-                    shutil.copytree(fullname, targetname)
-        # last, copy logo file (handled differently)
-        if self.config.html_logo:
-            logobase = path.basename(self.config.html_logo)
-            shutil.copyfile(path.join(self.confdir, self.config.html_logo),
-                            path.join(self.outdir, '_static', logobase))
-        self.info('done')
-
-        # dump the search index
-        self.handle_finish()
-
-    def get_outdated_docs(self):
-        if self.templates:
-            template_mtime = self.templates.newest_template_mtime()
-        else:
-            template_mtime = 0
-        for docname in self.env.found_docs:
-            if docname not in self.env.all_docs:
-                yield docname
-                continue
-            targetname = self.env.doc2path(docname, self.outdir, self.out_suffix)
-            try:
-                targetmtime = path.getmtime(targetname)
-            except Exception:
-                targetmtime = 0
-            try:
-                srcmtime = max(path.getmtime(self.env.doc2path(docname)),
-                               template_mtime)
-                if srcmtime > targetmtime:
-                    yield docname
-            except EnvironmentError:
-                # source doesn't exist anymore
-                pass
-
-    def load_indexer(self, docnames):
-        keep = set(self.env.all_docs) - set(docnames)
-        try:
-            f = open(path.join(self.outdir, self.searchindex_filename), 'rb')
-            try:
-                self.indexer.load(f, self.indexer_format)
-            finally:
-                f.close()
-        except (IOError, OSError, ValueError):
-            if keep:
-                self.warn("search index couldn't be loaded, but not all documents "
-                          "will be built: the index will be incomplete.")
-        # delete all entries for files that will be rebuilt
-        self.indexer.prune(keep)
-
-    def index_page(self, pagename, doctree, title):
-        # only index pages with title
-        if self.indexer is not None and title:
-            self.indexer.feed(pagename, title, doctree)
-
-    # --------- these are overwritten by the serialization builder
-
-    def get_target_uri(self, docname, typ=None):
-        return docname + self.out_suffix
-
-    def handle_page(self, pagename, addctx, templatename='page.html',
-                    outfilename=None, event_arg=None):
-        ctx = self.globalcontext.copy()
-        # current_page_name is backwards compatibility
-        ctx['pagename'] = ctx['current_page_name'] = pagename
-
-        def pathto(otheruri, resource=False,
-                   baseuri=self.get_target_uri(pagename)):
-            if not resource:
-                otheruri = self.get_target_uri(otheruri)
-            return relative_uri(baseuri, otheruri)
-        ctx['pathto'] = pathto
-        ctx['hasdoc'] = lambda name: name in self.env.all_docs
-        ctx['customsidebar'] = self.config.html_sidebars.get(pagename)
-        ctx.update(addctx)
-
-        self.app.emit('html-page-context', pagename, templatename, ctx, event_arg)
-
-        output = self.templates.render(templatename, ctx)
-        if not outfilename:
-            outfilename = path.join(self.outdir, os_path(pagename) + self.out_suffix)
-        ensuredir(path.dirname(outfilename)) # normally different from self.outdir
-        try:
-            f = codecs.open(outfilename, 'w', 'utf-8')
-            try:
-                f.write(output)
-            finally:
-                f.close()
-        except (IOError, OSError), err:
-            self.warn("Error writing file %s: %s" % (outfilename, err))
-        if self.copysource and ctx.get('sourcename'):
-            # copy the source file for the "show source" link
-            source_name = path.join(self.outdir, '_sources', os_path(ctx['sourcename']))
-            ensuredir(path.dirname(source_name))
-            shutil.copyfile(self.env.doc2path(pagename), source_name)
-
-    def handle_finish(self):
-        self.info(bold('dumping search index... '), nonl=True)
-        self.indexer.prune(self.env.all_docs)
-        f = open(path.join(self.outdir, self.searchindex_filename), 'wb')
-        try:
-            self.indexer.dump(f, self.indexer_format)
-        finally:
-            f.close()
-        self.info('done')
-
-        self.info(bold('dumping object inventory... '), nonl=True)
-        f = open(path.join(self.outdir, INVENTORY_FILENAME), 'w')
-        try:
-            f.write('# Sphinx inventory version 1\n')
-            f.write('# Project: %s\n' % self.config.project.encode('utf-8'))
-            f.write('# Version: %s\n' % self.config.version)
-            for modname, info in self.env.modules.iteritems():
-                f.write('%s mod %s\n' % (modname, self.get_target_uri(info[0])))
-            for refname, (docname, desctype) in self.env.descrefs.iteritems():
-                f.write('%s %s %s\n' % (refname, desctype, self.get_target_uri(docname)))
-        finally:
-            f.close()
-        self.info('done')
-
-
-class SerializingHTMLBuilder(StandaloneHTMLBuilder):
-    """
-    An abstract builder that serializes the HTML generated.
-    """
-    #: the serializing implementation to use.  Set this to a module that
-    #: implements a `dump`, `load`, `dumps` and `loads` functions
-    #: (pickle, simplejson etc.)
-    implementation = None
-
-    #: the filename for the global context file
-    globalcontext_filename = None
-
-    supported_image_types = ('image/svg+xml', 'image/png', 'image/gif',
-                             'image/jpeg')
-
-    def init(self):
-        self.init_translator_class()
-        self.templates = None   # no template bridge necessary
-
-    def get_target_uri(self, docname, typ=None):
-        if docname == 'index':
-            return ''
-        if docname.endswith(SEP + 'index'):
-            return docname[:-5] # up to sep
-        return docname + SEP
-
-    def handle_page(self, pagename, ctx, templatename='page.html',
-                    outfilename=None, event_arg=None):
-        ctx['current_page_name'] = pagename
-        sidebarfile = self.config.html_sidebars.get(pagename)
-        if sidebarfile:
-            ctx['customsidebar'] = sidebarfile
-
-        if not outfilename:
-            outfilename = path.join(self.outdir, os_path(pagename) + self.out_suffix)
-
-        self.app.emit('html-page-context', pagename, templatename, ctx, event_arg)
-
-        ensuredir(path.dirname(outfilename))
-        f = open(outfilename, 'wb')
-        try:
-            self.implementation.dump(ctx, f, 2)
-        finally:
-            f.close()
-
-        # if there is a source file, copy the source file for the
-        # "show source" link
-        if ctx.get('sourcename'):
-            source_name = path.join(self.outdir, '_sources',
-                                    os_path(ctx['sourcename']))
-            ensuredir(path.dirname(source_name))
-            shutil.copyfile(self.env.doc2path(pagename), source_name)
-
-    def handle_finish(self):
-        # dump the global context
-        outfilename = path.join(self.outdir, self.globalcontext_filename)
-        f = open(outfilename, 'wb')
-        try:
-            self.implementation.dump(self.globalcontext, f, 2)
-        finally:
-            f.close()
-
-        # super here to dump the search index
-        StandaloneHTMLBuilder.handle_finish(self)
-
-        # copy the environment file from the doctree dir to the output dir
-        # as needed by the web app
-        shutil.copyfile(path.join(self.doctreedir, ENV_PICKLE_FILENAME),
-                        path.join(self.outdir, ENV_PICKLE_FILENAME))
-
-        # touch 'last build' file, used by the web application to determine
-        # when to reload its environment and clear the cache
-        open(path.join(self.outdir, LAST_BUILD_FILENAME), 'w').close()
-
-
-class PickleHTMLBuilder(SerializingHTMLBuilder):
-    """
-    A Builder that dumps the generated HTML into pickle files.
-    """
-    implementation = pickle
-    indexer_format = pickle
-    name = 'pickle'
-    out_suffix = '.fpickle'
-    globalcontext_filename = 'globalcontext.pickle'
-    searchindex_filename = 'searchindex.pickle'
-
-
-class JSONHTMLBuilder(SerializingHTMLBuilder):
-    """
-    A builder that dumps the generated HTML into JSON files.
-    """
-    implementation = json
-    indexer_format = json
-    name = 'json'
-    out_suffix = '.fjson'
-    globalcontext_filename = 'globalcontext.json'
-    searchindex_filename = 'searchindex.json'
-
-    def init(self):
-        if json is None:
-            from sphinx.application import SphinxError
-            raise SphinxError('The module simplejson (or json in Python >= 2.6) '
-                              'is not available. The JSONHTMLBuilder builder '
-                              'will not work.')
-        SerializingHTMLBuilder.init(self)
-
-
-class HTMLHelpBuilder(StandaloneHTMLBuilder):
-    """
-    Builder that also outputs Windows HTML help project, contents and index files.
-    Adapted from the original Doc/tools/prechm.py.
-    """
-    name = 'htmlhelp'
-
-    # don't copy the reST source
-    copysource = False
-    supported_image_types = ['image/png', 'image/gif', 'image/jpeg']
-
-    # don't add links
-    add_header_links = False
-    add_definition_links = False
-
-    def init(self):
-        StandaloneHTMLBuilder.init(self)
-        # the output files for HTML help must be .html only
-        self.out_suffix = '.html'
-
-    def handle_finish(self):
-        build_hhx(self, self.outdir, self.config.htmlhelp_basename)
-
-
-class LaTeXBuilder(Builder):
-    """
-    Builds LaTeX output to create PDF.
-    """
-    name = 'latex'
-    supported_image_types = ['application/pdf', 'image/png', 'image/gif',
-                             'image/jpeg']
-
-    def init(self):
-        self.docnames = []
-        self.document_data = []
-        texescape.init()
-
-    def get_outdated_docs(self):
-        return 'all documents' # for now
-
-    def get_target_uri(self, docname, typ=None):
-        if typ == 'token':
-            # token references are always inside production lists and must be
-            # replaced by \token{} in LaTeX
-            return '@token'
-        if docname not in self.docnames:
-            raise NoUri
-        else:
-            return ''
-
-    def init_document_data(self):
-        preliminary_document_data = map(list, self.config.latex_documents)
-        if not preliminary_document_data:
-            self.warn('No "latex_documents" config value found; no documents '
-                      'will be written.')
-            return
-        # assign subdirs to titles
-        self.titles = []
-        for entry in preliminary_document_data:
-            docname = entry[0]
-            if docname not in self.env.all_docs:
-                self.warn('"latex_documents" config value references unknown '
-                          'document %s' % docname)
-                continue
-            self.document_data.append(entry)
-            if docname.endswith(SEP+'index'):
-                docname = docname[:-5]
-            self.titles.append((docname, entry[2]))
-
-    def write(self, *ignored):
-        # first, assemble the "appendix" docs that are in every PDF
-        appendices = []
-        for fname in self.config.latex_appendices:
-            appendices.append(self.env.get_doctree(fname))
-
-        docwriter = LaTeXWriter(self)
-        docsettings = OptionParser(
-            defaults=self.env.settings,
-            components=(docwriter,)).get_default_values()
-
-        self.init_document_data()
-
-        for entry in self.document_data:
-            docname, targetname, title, author, docclass = entry[:5]
-            toctree_only = False
-            if len(entry) > 5:
-                toctree_only = entry[5]
-            destination = FileOutput(
-                destination_path=path.join(self.outdir, targetname),
-                encoding='utf-8')
-            self.info("processing " + targetname + "... ", nonl=1)
-            doctree = self.assemble_doctree(docname, toctree_only,
-                appendices=(docclass == 'manual') and appendices or [])
-            self.post_process_images(doctree)
-            self.info("writing... ", nonl=1)
-            doctree.settings = docsettings
-            doctree.settings.author = author
-            doctree.settings.title = title
-            doctree.settings.docname = docname
-            doctree.settings.docclass = docclass
-            docwriter.write(doctree, destination)
-            self.info("done")
-
-    def assemble_doctree(self, indexfile, toctree_only, appendices):
-        self.docnames = set([indexfile] + appendices)
-        self.info(darkgreen(indexfile) + " ", nonl=1)
-        def process_tree(docname, tree):
-            tree = tree.deepcopy()
-            for toctreenode in tree.traverse(addnodes.toctree):
-                newnodes = []
-                includefiles = map(str, toctreenode['includefiles'])
-                for includefile in includefiles:
-                    try:
-                        self.info(darkgreen(includefile) + " ", nonl=1)
-                        subtree = process_tree(includefile,
-                                               self.env.get_doctree(includefile))
-                        self.docnames.add(includefile)
-                    except Exception:
-                        self.warn('%s: toctree contains ref to nonexisting file %r' %
-                                  (docname, includefile))
-                    else:
-                        sof = addnodes.start_of_file()
-                        sof.children = subtree.children
-                        newnodes.append(sof)
-                toctreenode.parent.replace(toctreenode, newnodes)
-            return tree
-        tree = self.env.get_doctree(indexfile)
-        if toctree_only:
-            # extract toctree nodes from the tree and put them in a fresh document
-            new_tree = new_document('<latex output>')
-            new_sect = nodes.section()
-            new_sect += nodes.title(u'<Set title in conf.py>', u'<Set title in conf.py>')
-            new_tree += new_sect
-            for node in tree.traverse(addnodes.toctree):
-                new_sect += node
-            tree = new_tree
-        largetree = process_tree(indexfile, tree)
-        largetree.extend(appendices)
-        self.info()
-        self.info("resolving references...")
-        self.env.resolve_references(largetree, indexfile, self)
-        # resolve :ref:s to distant tex files -- we can't add a cross-reference,
-        # but append the document name
-        for pendingnode in largetree.traverse(addnodes.pending_xref):
-            docname = pendingnode['refdocname']
-            sectname = pendingnode['refsectname']
-            newnodes = [nodes.emphasis(sectname, sectname)]
-            for subdir, title in self.titles:
-                if docname.startswith(subdir):
-                    newnodes.append(nodes.Text(_(' (in '), _(' (in ')))
-                    newnodes.append(nodes.emphasis(title, title))
-                    newnodes.append(nodes.Text(')', ')'))
-                    break
-            else:
-                pass
-            pendingnode.replace_self(newnodes)
-        return largetree
-
-    def finish(self):
-        # copy image files
-        if self.images:
-            self.info(bold('copying images...'), nonl=1)
-            for src, dest in self.images.iteritems():
-                self.info(' '+src, nonl=1)
-                shutil.copyfile(path.join(self.srcdir, src),
-                                path.join(self.outdir, dest))
-            self.info()
-
-        # the logo is handled differently
-        if self.config.latex_logo:
-            logobase = path.basename(self.config.latex_logo)
-            shutil.copyfile(path.join(self.confdir, self.config.latex_logo),
-                            path.join(self.outdir, logobase))
-
-        self.info(bold('copying TeX support files... '), nonl=True)
-        staticdirname = path.join(path.dirname(__file__), 'texinputs')
-        for filename in os.listdir(staticdirname):
-            if not filename.startswith('.'):
-                shutil.copyfile(path.join(staticdirname, filename),
-                                path.join(self.outdir, filename))
-        self.info('done')
-
-
-class ChangesBuilder(Builder):
-    """
-    Write a summary with all versionadded/changed directives.
-    """
-    name = 'changes'
-
-    def init(self):
-        self.init_templates()
-
-    def get_outdated_docs(self):
-        return self.outdir
-
-    typemap = {
-        'versionadded': 'added',
-        'versionchanged': 'changed',
-        'deprecated': 'deprecated',
-    }
-
-    def write(self, *ignored):
-        version = self.config.version
-        libchanges = {}
-        apichanges = []
-        otherchanges = {}
-        if version not in self.env.versionchanges:
-            self.info(bold('no changes in this version.'))
-            return
-        self.info(bold('writing summary file...'))
-        for type, docname, lineno, module, descname, content in \
-                self.env.versionchanges[version]:
-            ttext = self.typemap[type]
-            context = content.replace('\n', ' ')
-            if descname and docname.startswith('c-api'):
-                if not descname:
-                    continue
-                if context:
-                    entry = '<b>%s</b>: <i>%s:</i> %s' % (descname, ttext, context)
-                else:
-                    entry = '<b>%s</b>: <i>%s</i>.' % (descname, ttext)
-                apichanges.append((entry, docname, lineno))
-            elif descname or module:
-                if not module:
-                    module = _('Builtins')
-                if not descname:
-                    descname = _('Module level')
-                if context:
-                    entry = '<b>%s</b>: <i>%s:</i> %s' % (descname, ttext, context)
-                else:
-                    entry = '<b>%s</b>: <i>%s</i>.' % (descname, ttext)
-                libchanges.setdefault(module, []).append((entry, docname, lineno))
-            else:
-                if not context:
-                    continue
-                entry = '<i>%s:</i> %s' % (ttext.capitalize(), context)
-                title = self.env.titles[docname].astext()
-                otherchanges.setdefault((docname, title), []).append(
-                    (entry, docname, lineno))
-
-        ctx = {
-            'project': self.config.project,
-            'version': version,
-            'docstitle': self.config.html_title,
-            'shorttitle': self.config.html_short_title,
-            'libchanges': sorted(libchanges.iteritems()),
-            'apichanges': sorted(apichanges),
-            'otherchanges': sorted(otherchanges.iteritems()),
-            'show_sphinx': self.config.html_show_sphinx,
-        }
-        f = open(path.join(self.outdir, 'index.html'), 'w')
-        try:
-            f.write(self.templates.render('changes/frameset.html', ctx))
-        finally:
-            f.close()
-        f = open(path.join(self.outdir, 'changes.html'), 'w')
-        try:
-            f.write(self.templates.render('changes/versionchanges.html', ctx))
-        finally:
-            f.close()
-
-        hltext = ['.. versionadded:: %s' % version,
-                  '.. versionchanged:: %s' % version,
-                  '.. deprecated:: %s' % version]
-
-        def hl(no, line):
-            line = '<a name="L%s"> </a>' % no + escape(line)
-            for x in hltext:
-                if x in line:
-                    line = '<span class="hl">%s</span>' % line
-                    break
-            return line
-
-        self.info(bold('copying source files...'))
-        for docname in self.env.all_docs:
-            f = open(self.env.doc2path(docname))
-            lines = f.readlines()
-            targetfn = path.join(self.outdir, 'rst', os_path(docname)) + '.html'
-            ensuredir(path.dirname(targetfn))
-            f = codecs.open(targetfn, 'w', 'utf8')
-            try:
-                text = ''.join(hl(i+1, line) for (i, line) in enumerate(lines))
-                ctx = {'filename': self.env.doc2path(docname, None), 'text': text}
-                f.write(self.templates.render('changes/rstsource.html', ctx))
-            finally:
-                f.close()
-        shutil.copyfile(path.join(path.dirname(__file__), 'static', 'default.css'),
-                        path.join(self.outdir, 'default.css'))
-
-    def hl(self, text, version):
-        text = escape(text)
-        for directive in ['versionchanged', 'versionadded', 'deprecated']:
-            text = text.replace('.. %s:: %s' % (directive, version),
-                                '<b>.. %s:: %s</b>' % (directive, version))
-        return text
-
-    def finish(self):
-        pass
-
-
-class TextBuilder(Builder):
-    name = 'text'
-    out_suffix = '.txt'
-
-    def init(self):
-        pass
-
-    def get_outdated_docs(self):
-        for docname in self.env.found_docs:
-            if docname not in self.env.all_docs:
-                yield docname
-                continue
-            targetname = self.env.doc2path(docname, self.outdir, self.out_suffix)
-            try:
-                targetmtime = path.getmtime(targetname)
-            except Exception:
-                targetmtime = 0
-            try:
-                srcmtime = path.getmtime(self.env.doc2path(docname))
-                if srcmtime > targetmtime:
-                    yield docname
-            except EnvironmentError:
-                # source doesn't exist anymore
-                pass
-
-    def get_target_uri(self, docname, typ=None):
-        return ''
-
-    def prepare_writing(self, docnames):
-        self.writer = TextWriter(self)
-
-    def write_doc(self, docname, doctree):
-        destination = StringOutput(encoding='utf-8')
-        self.writer.write(doctree, destination)
-        outfilename = path.join(self.outdir, os_path(docname) + self.out_suffix)
-        ensuredir(path.dirname(outfilename)) # normally different from self.outdir
-        try:
-            f = codecs.open(outfilename, 'w', 'utf-8')
-            try:
-                f.write(self.writer.output)
-            finally:
-                f.close()
-        except (IOError, OSError), err:
-            self.warn("Error writing file %s: %s" % (outfilename, err))
-
-    def finish(self):
-        pass
-
-
-# compatibility alias
-WebHTMLBuilder = PickleHTMLBuilder
+       This module is only kept for API compatibility; new code should
+       import these classes directly from the sphinx.builders package.
 
+    :copyright: Copyright 2007-2009 by the Sphinx team, see AUTHORS.
+    :license: BSD, see LICENSE for details.
+"""
 
-from sphinx.linkcheck import CheckExternalLinksBuilder
+import warnings
 
-builtin_builders = {
-    'html': StandaloneHTMLBuilder,
-    'pickle': PickleHTMLBuilder,
-    'json': JSONHTMLBuilder,
-    'web': PickleHTMLBuilder,
-    'htmlhelp': HTMLHelpBuilder,
-    'latex': LaTeXBuilder,
-    'text': TextBuilder,
-    'changes': ChangesBuilder,
-    'linkcheck': CheckExternalLinksBuilder,
-}
+from sphinx.builders import Builder
+from sphinx.builders.text import TextBuilder
+from sphinx.builders.html import StandaloneHTMLBuilder, WebHTMLBuilder, \
+     PickleHTMLBuilder, JSONHTMLBuilder
+from sphinx.builders.latex import LaTeXBuilder
+from sphinx.builders.changes import ChangesBuilder
+from sphinx.builders.htmlhelp import HTMLHelpBuilder
+from sphinx.builders.linkcheck import CheckExternalLinksBuilder
+
+warnings.warn('The sphinx.builder module is deprecated; please import '
+              'builders from the respective sphinx.builders submodules.',
+              DeprecationWarning, stacklevel=2)

Added: doctools/trunk/sphinx/builders/__init__.py
==============================================================================
--- (empty file)
+++ doctools/trunk/sphinx/builders/__init__.py	Sun Jan  4 21:38:57 2009
@@ -0,0 +1,346 @@
+# -*- coding: utf-8 -*-
+"""
+    sphinx.builders
+    ~~~~~~~~~~~~~~~
+
+    Builder superclass for all builders.
+
+    :copyright: Copyright 2007-2009 by the Sphinx team, see AUTHORS.
+    :license: BSD, see LICENSE for details.
+"""
+
+import os
+import gettext
+from os import path
+
+from docutils import nodes
+
+from sphinx import package_dir, locale
+from sphinx.util import SEP, relative_uri
+from sphinx.environment import BuildEnvironment
+from sphinx.util.console import bold, purple, darkgreen
+
+# side effect: registers roles and directives
+from sphinx import roles
+from sphinx import directives
+
+
+ENV_PICKLE_FILENAME = 'environment.pickle'
+
+
+class Builder(object):
+    """
+    Builds target formats from the reST sources.
+    """
+
+    # builder's name, for the -b command line options
+    name = ''
+
+    def __init__(self, app, env=None, freshenv=False):
+        self.srcdir = app.srcdir
+        self.confdir = app.confdir
+        self.outdir = app.outdir
+        self.doctreedir = app.doctreedir
+        if not path.isdir(self.doctreedir):
+            os.makedirs(self.doctreedir)
+
+        self.app = app
+        self.warn = app.warn
+        self.info = app.info
+        self.config = app.config
+
+        self.load_i18n()
+
+        # images that need to be copied over (source -> dest)
+        self.images = {}
+
+        # if None, this is set in load_env()
+        self.env = env
+        self.freshenv = freshenv
+
+        self.init()
+        self.load_env()
+
+    # helper methods
+
+    def init(self):
+        """
+        Load necessary templates and perform initialization.  The default
+        implementation does nothing.
+        """
+        pass
+
+    def init_templates(self):
+        """
+        Initialize the template system.
+
+        Call this method from init() if you need templates in your builder.
+        """
+        if self.config.template_bridge:
+            self.templates = self.app.import_object(
+                self.config.template_bridge, 'template_bridge setting')()
+        else:
+            from sphinx.jinja2glue import BuiltinTemplates
+            self.templates = BuiltinTemplates()
+        self.templates.init(self)
+
+    def get_target_uri(self, docname, typ=None):
+        """
+        Return the target URI for a document name (*typ* can be used to qualify
+        the link characteristic for individual builders).
+        """
+        raise NotImplementedError
+
+    def get_relative_uri(self, from_, to, typ=None):
+        """
+        Return a relative URI between two source filenames. May raise environment.NoUri
+        if there's no way to return a sensible URI.
+        """
+        return relative_uri(self.get_target_uri(from_),
+                            self.get_target_uri(to, typ))
+
+    def get_outdated_docs(self):
+        """
+        Return an iterable of output files that are outdated, or a string describing
+        what an update build will build.
+
+        If the builder does not output individual files corresponding to source files,
+        return a string here.  If it does, return an iterable of those files that need
+        to be written.
+        """
+        raise NotImplementedError
+
+    def status_iterator(self, iterable, summary, colorfunc=darkgreen):
+        l = -1
+        for item in iterable:
+            if l == -1:
+                self.info(bold(summary), nonl=1)
+                l = 0
+            self.info(colorfunc(item) + ' ', nonl=1)
+            yield item
+        if l == 0:
+            self.info()
+
+    supported_image_types = []
+
+    def post_process_images(self, doctree):
+        """
+        Pick the best candidate for all image URIs.
+        """
+        for node in doctree.traverse(nodes.image):
+            if '?' in node['candidates']:
+                # don't rewrite nonlocal image URIs
+                continue
+            if '*' not in node['candidates']:
+                for imgtype in self.supported_image_types:
+                    candidate = node['candidates'].get(imgtype, None)
+                    if candidate:
+                        break
+                else:
+                    self.warn('%s:%s: no matching candidate for image URI %r' %
+                              (node.source, getattr(node, 'lineno', ''), node['uri']))
+                    continue
+                node['uri'] = candidate
+            else:
+                candidate = node['uri']
+            if candidate not in self.env.images:
+                # non-existing URI; let it alone
+                continue
+            self.images[candidate] = self.env.images[candidate][1]
+
+    # build methods
+
+    def load_i18n(self):
+        """
+        Load translated strings from the configured localedirs if
+        enabled in the configuration.
+        """
+        self.translator = None
+        if self.config.language is not None:
+            self.info(bold('loading translations [%s]... ' % self.config.language),
+                      nonl=True)
+            locale_dirs = [path.join(package_dir, 'locale')] + \
+                          [path.join(self.srcdir, x) for x in self.config.locale_dirs]
+            for dir_ in locale_dirs:
+                try:
+                    trans = gettext.translation('sphinx', localedir=dir_,
+                            languages=[self.config.language])
+                    if self.translator is None:
+                        self.translator = trans
+                    else:
+                        self.translator._catalog.update(trans.catalog)
+                except Exception:
+                    # Language couldn't be found in the specified path
+                    pass
+            if self.translator is not None:
+                self.info('done')
+            else:
+                self.info('locale not available')
+        if self.translator is None:
+            self.translator = gettext.NullTranslations()
+        self.translator.install(unicode=True)
+        locale.init()  # translate common labels
+
+    def load_env(self):
+        """Set up the build environment."""
+        if self.env:
+            return
+        if not self.freshenv:
+            try:
+                self.info(bold('loading pickled environment... '), nonl=True)
+                self.env = BuildEnvironment.frompickle(self.config,
+                    path.join(self.doctreedir, ENV_PICKLE_FILENAME))
+                self.info('done')
+            except Exception, err:
+                if type(err) is IOError and err.errno == 2:
+                    self.info('not found')
+                else:
+                    self.info('failed: %s' % err)
+                self.env = BuildEnvironment(self.srcdir, self.doctreedir, self.config)
+                self.env.find_files(self.config)
+        else:
+            self.env = BuildEnvironment(self.srcdir, self.doctreedir, self.config)
+            self.env.find_files(self.config)
+        self.env.set_warnfunc(self.warn)
+
+    def build_all(self):
+        """Build all source files."""
+        self.build(None, summary='all source files', method='all')
+
+    def build_specific(self, filenames):
+        """Only rebuild as much as needed for changes in the *filenames*."""
+        # bring the filenames to the canonical format, that is,
+        # relative to the source directory and without source_suffix.
+        dirlen = len(self.srcdir) + 1
+        to_write = []
+        suffix = self.config.source_suffix
+        for filename in filenames:
+            filename = path.abspath(filename)[dirlen:]
+            if filename.endswith(suffix):
+                filename = filename[:-len(suffix)]
+            filename = filename.replace(os.path.sep, SEP)
+            to_write.append(filename)
+        self.build(to_write, method='specific',
+                   summary='%d source files given on command '
+                   'line' % len(to_write))
+
+    def build_update(self):
+        """Only rebuild what was changed or added since last build."""
+        to_build = self.get_outdated_docs()
+        if isinstance(to_build, str):
+            self.build(['__all__'], to_build)
+        else:
+            to_build = list(to_build)
+            self.build(to_build,
+                       summary='targets for %d source files that are '
+                       'out of date' % len(to_build))
+
+    def build(self, docnames, summary=None, method='update'):
+        """
+        Main build method.  First updates the environment, and then calls :meth:`write`.
+        """
+        if summary:
+            self.info(bold('building [%s]: ' % self.name), nonl=1)
+            self.info(summary)
+
+        updated_docnames = []
+        # while reading, collect all warnings from docutils
+        warnings = []
+        self.env.set_warnfunc(warnings.append)
+        self.info(bold('updating environment: '), nonl=1)
+        iterator = self.env.update(self.config, self.srcdir, self.doctreedir, self.app)
+        # the first item in the iterator is a summary message
+        self.info(iterator.next())
+        for docname in self.status_iterator(iterator, 'reading sources... ', purple):
+            updated_docnames.append(docname)
+            # nothing further to do, the environment has already done the reading
+        for warning in warnings:
+            if warning.strip():
+                self.warn(warning)
+        self.env.set_warnfunc(self.warn)
+
+        if updated_docnames:
+            # save the environment
+            self.info(bold('pickling environment... '), nonl=True)
+            self.env.topickle(path.join(self.doctreedir, ENV_PICKLE_FILENAME))
+            self.info('done')
+
+            # global actions
+            self.info(bold('checking consistency... '), nonl=True)
+            self.env.check_consistency()
+            self.info('done')
+        else:
+            if method == 'update' and not docnames:
+                self.info(bold('no targets are out of date.'))
+                return
+
+        # another indirection to support builders that don't build files individually
+        self.write(docnames, updated_docnames, method)
+
+        # finish (write static files etc.)
+        self.finish()
+        status = self.app.statuscode == 0 and 'succeeded' or 'finished with problems'
+        if self.app._warncount:
+            self.info(bold('build %s, %s warning%s.' %
+                           (status, self.app._warncount,
+                            self.app._warncount != 1 and 's' or '')))
+        else:
+            self.info(bold('build %s.' % status))
+
+    def write(self, build_docnames, updated_docnames, method='update'):
+        if build_docnames is None or build_docnames == ['__all__']:
+            # build_all
+            build_docnames = self.env.found_docs
+        if method == 'update':
+            # build updated ones as well
+            docnames = set(build_docnames) | set(updated_docnames)
+        else:
+            docnames = set(build_docnames)
+
+        # add all toctree-containing files that may have changed
+        for docname in list(docnames):
+            for tocdocname in self.env.files_to_rebuild.get(docname, []):
+                docnames.add(tocdocname)
+        docnames.add(self.config.master_doc)
+
+        self.info(bold('preparing documents... '), nonl=True)
+        self.prepare_writing(docnames)
+        self.info('done')
+
+        # write target files
+        warnings = []
+        self.env.set_warnfunc(warnings.append)
+        for docname in self.status_iterator(sorted(docnames),
+                                            'writing output... ', darkgreen):
+            doctree = self.env.get_and_resolve_doctree(docname, self)
+            self.write_doc(docname, doctree)
+        for warning in warnings:
+            if warning.strip():
+                self.warn(warning)
+        self.env.set_warnfunc(self.warn)
+
+    def prepare_writing(self, docnames):
+        raise NotImplementedError
+
+    def write_doc(self, docname, doctree):
+        raise NotImplementedError
+
+    def finish(self):
+        """
+        Finish the building process.  The default implementation does nothing.
+        """
+        pass
+
+
+BUILTIN_BUILDERS = {
+    'html':      ('html', 'StandaloneHTMLBuilder'),
+    'pickle':    ('html', 'PickleHTMLBuilder'),
+    'json':      ('html', 'JSONHTMLBuilder'),
+    'web':       ('html', 'PickleHTMLBuilder'),
+    'htmlhelp':  ('htmlhelp', 'HTMLHelpBuilder'),
+    'qthelp':    ('qthelp', 'QtHelpBuilder'),
+    'latex':     ('latex', 'LaTeXBuilder'),
+    'text':      ('text', 'TextBuilder'),
+    'changes':   ('changes', 'ChangesBuilder'),
+    'linkcheck': ('linkcheck', 'CheckExternalLinksBuilder'),
+}

Added: doctools/trunk/sphinx/builders/changes.py
==============================================================================
--- (empty file)
+++ doctools/trunk/sphinx/builders/changes.py	Sun Jan  4 21:38:57 2009
@@ -0,0 +1,137 @@
+# -*- coding: utf-8 -*-
+"""
+    sphinx.builders.changes
+    ~~~~~~~~~~~~~~~~~~~~~~~
+
+    Changelog builder.
+
+    :copyright: Copyright 2007-2009 by the Sphinx team, see AUTHORS.
+    :license: BSD, see LICENSE for details.
+"""
+
+import codecs
+import shutil
+from os import path
+from cgi import escape
+
+from sphinx import package_dir
+from sphinx.util import ensuredir, os_path
+from sphinx.builders import Builder
+from sphinx.util.console import bold
+
+
+class ChangesBuilder(Builder):
+    """
+    Write a summary with all versionadded/changed directives.
+    """
+    name = 'changes'
+
+    def init(self):
+        self.init_templates()
+
+    def get_outdated_docs(self):
+        return self.outdir
+
+    typemap = {
+        'versionadded': 'added',
+        'versionchanged': 'changed',
+        'deprecated': 'deprecated',
+    }
+
+    def write(self, *ignored):
+        version = self.config.version
+        libchanges = {}
+        apichanges = []
+        otherchanges = {}
+        if version not in self.env.versionchanges:
+            self.info(bold('no changes in this version.'))
+            return
+        self.info(bold('writing summary file...'))
+        for type, docname, lineno, module, descname, content in \
+                self.env.versionchanges[version]:
+            ttext = self.typemap[type]
+            context = content.replace('\n', ' ')
+            if descname and docname.startswith('c-api'):
+                if not descname:
+                    continue
+                if context:
+                    entry = '<b>%s</b>: <i>%s:</i> %s' % (descname, ttext, context)
+                else:
+                    entry = '<b>%s</b>: <i>%s</i>.' % (descname, ttext)
+                apichanges.append((entry, docname, lineno))
+            elif descname or module:
+                if not module:
+                    module = _('Builtins')
+                if not descname:
+                    descname = _('Module level')
+                if context:
+                    entry = '<b>%s</b>: <i>%s:</i> %s' % (descname, ttext, context)
+                else:
+                    entry = '<b>%s</b>: <i>%s</i>.' % (descname, ttext)
+                libchanges.setdefault(module, []).append((entry, docname, lineno))
+            else:
+                if not context:
+                    continue
+                entry = '<i>%s:</i> %s' % (ttext.capitalize(), context)
+                title = self.env.titles[docname].astext()
+                otherchanges.setdefault((docname, title), []).append(
+                    (entry, docname, lineno))
+
+        ctx = {
+            'project': self.config.project,
+            'version': version,
+            'docstitle': self.config.html_title,
+            'shorttitle': self.config.html_short_title,
+            'libchanges': sorted(libchanges.iteritems()),
+            'apichanges': sorted(apichanges),
+            'otherchanges': sorted(otherchanges.iteritems()),
+            'show_sphinx': self.config.html_show_sphinx,
+        }
+        f = codecs.open(path.join(self.outdir, 'index.html'), 'w', 'utf8')
+        try:
+            f.write(self.templates.render('changes/frameset.html', ctx))
+        finally:
+            f.close()
+        f = codecs.open(path.join(self.outdir, 'changes.html'), 'w', 'utf8')
+        try:
+            f.write(self.templates.render('changes/versionchanges.html', ctx))
+        finally:
+            f.close()
+
+        hltext = ['.. versionadded:: %s' % version,
+                  '.. versionchanged:: %s' % version,
+                  '.. deprecated:: %s' % version]
+
+        def hl(no, line):
+            line = '<a name="L%s"> </a>' % no + escape(line)
+            for x in hltext:
+                if x in line:
+                    line = '<span class="hl">%s</span>' % line
+                    break
+            return line
+
+        self.info(bold('copying source files...'))
+        for docname in self.env.all_docs:
+            f = codecs.open(self.env.doc2path(docname), 'r', 'latin1')
+            lines = f.readlines()
+            targetfn = path.join(self.outdir, 'rst', os_path(docname)) + '.html'
+            ensuredir(path.dirname(targetfn))
+            f = codecs.open(targetfn, 'w', 'latin1')
+            try:
+                text = ''.join(hl(i+1, line) for (i, line) in enumerate(lines))
+                ctx = {'filename': self.env.doc2path(docname, None), 'text': text}
+                f.write(self.templates.render('changes/rstsource.html', ctx))
+            finally:
+                f.close()
+        shutil.copyfile(path.join(package_dir, 'static', 'default.css'),
+                        path.join(self.outdir, 'default.css'))
+
+    def hl(self, text, version):
+        text = escape(text)
+        for directive in ['versionchanged', 'versionadded', 'deprecated']:
+            text = text.replace('.. %s:: %s' % (directive, version),
+                                '<b>.. %s:: %s</b>' % (directive, version))
+        return text
+
+    def finish(self):
+        pass

Added: doctools/trunk/sphinx/builders/html.py
==============================================================================
--- (empty file)
+++ doctools/trunk/sphinx/builders/html.py	Sun Jan  4 21:38:57 2009
@@ -0,0 +1,632 @@
+# -*- coding: utf-8 -*-
+"""
+    sphinx.builders.html
+    ~~~~~~~~~~~~~~~~~~~~
+
+    Several HTML builders.
+
+    :copyright: Copyright 2007-2009 by the Sphinx team, see AUTHORS.
+    :license: BSD, see LICENSE for details.
+"""
+
+import os
+import codecs
+import shutil
+import cPickle as pickle
+from os import path
+
+from docutils.io import DocTreeInput, StringOutput
+from docutils.core import publish_parts
+from docutils.utils import new_document
+from docutils.frontend import OptionParser
+from docutils.readers.doctree import Reader as DoctreeReader
+
+from sphinx import package_dir, __version__
+from sphinx.util import SEP, os_path, relative_uri, ensuredir, ustrftime
+from sphinx.search import js_index
+from sphinx.builders import Builder, ENV_PICKLE_FILENAME
+from sphinx.highlighting import PygmentsBridge
+from sphinx.util.console import bold
+from sphinx.writers.html import HTMLWriter, HTMLTranslator, SmartyPantsHTMLTranslator
+
+try:
+    import json
+except ImportError:
+    try:
+        import simplejson as json
+    except ImportError:
+        json = None
+
+#: the filename for the inventory of objects
+INVENTORY_FILENAME = 'objects.inv'
+#: the filename for the "last build" file (for serializing builders)
+LAST_BUILD_FILENAME = 'last_build'
+
+
+class StandaloneHTMLBuilder(Builder):
+    """
+    Builds standalone HTML docs.
+    """
+    name = 'html'
+    copysource = True
+    out_suffix = '.html'
+    link_suffix = '.html'  # defaults to matching out_suffix
+    indexer_format = js_index
+    supported_image_types = ['image/svg+xml', 'image/png', 'image/gif',
+                             'image/jpeg']
+    searchindex_filename = 'searchindex.js'
+    add_permalinks = True
+    embedded = False  # for things like HTML help or Qt help: suppresses sidebar
+
+    # This is a class attribute because it is mutated by Sphinx.add_javascript.
+    script_files = ['_static/jquery.js', '_static/doctools.js']
+
+    def init(self):
+        """Load templates."""
+        self.init_templates()
+        self.init_translator_class()
+        if self.config.html_file_suffix:
+            self.out_suffix = self.config.html_file_suffix
+
+        if self.config.html_link_suffix is not None:
+            self.link_suffix = self.config.html_link_suffix
+        else:
+            self.link_suffix = self.out_suffix
+
+        if self.config.language is not None:
+            jsfile = path.join(package_dir, 'locale', self.config.language,
+                               'LC_MESSAGES', 'sphinx.js')
+            if path.isfile(jsfile):
+                self.script_files.append('_static/translations.js')
+
+    def init_translator_class(self):
+        if self.config.html_translator_class:
+            self.translator_class = self.app.import_object(
+                self.config.html_translator_class, 'html_translator_class setting')
+        elif self.config.html_use_smartypants:
+            self.translator_class = SmartyPantsHTMLTranslator
+        else:
+            self.translator_class = HTMLTranslator
+
+    def render_partial(self, node):
+        """Utility: Render a lone doctree node."""
+        doc = new_document('<partial node>')
+        doc.append(node)
+        return publish_parts(
+            doc,
+            source_class=DocTreeInput,
+            reader=DoctreeReader(),
+            writer=HTMLWriter(self),
+            settings_overrides={'output_encoding': 'unicode'}
+        )
+
+    def prepare_writing(self, docnames):
+        from sphinx.search import IndexBuilder
+
+        self.indexer = IndexBuilder(self.env)
+        self.load_indexer(docnames)
+        self.docwriter = HTMLWriter(self)
+        self.docsettings = OptionParser(
+            defaults=self.env.settings,
+            components=(self.docwriter,)).get_default_values()
+
+        # format the "last updated on" string, only once is enough since it
+        # typically doesn't include the time of day
+        lufmt = self.config.html_last_updated_fmt
+        if lufmt is not None:
+            self.last_updated = ustrftime(lufmt or _('%b %d, %Y'))
+        else:
+            self.last_updated = None
+
+        logo = self.config.html_logo and \
+               path.basename(self.config.html_logo) or ''
+
+        favicon = self.config.html_favicon and \
+                  path.basename(self.config.html_favicon) or ''
+        if favicon and os.path.splitext(favicon)[1] != '.ico':
+            self.warn('html_favicon is not an .ico file')
+
+        if not isinstance(self.config.html_use_opensearch, basestring):
+            self.warn('html_use_opensearch config value must now be a string')
+
+        self.relations = self.env.collect_relations()
+
+        rellinks = []
+        if self.config.html_use_index:
+            rellinks.append(('genindex', _('General Index'), 'I', _('index')))
+        if self.config.html_use_modindex and self.env.modules:
+            rellinks.append(('modindex', _('Global Module Index'), 'M', _('modules')))
+
+        self.globalcontext = dict(
+            embedded = self.embedded,
+            project = self.config.project,
+            release = self.config.release,
+            version = self.config.version,
+            last_updated = self.last_updated,
+            copyright = self.config.copyright,
+            master_doc = self.config.master_doc,
+            style = self.config.html_style,
+            use_opensearch = self.config.html_use_opensearch,
+            docstitle = self.config.html_title,
+            shorttitle = self.config.html_short_title,
+            show_sphinx = self.config.html_show_sphinx,
+            has_source = self.config.html_copy_source,
+            show_source = self.config.html_show_sourcelink,
+            file_suffix = self.out_suffix,
+            script_files = self.script_files,
+            sphinx_version = __version__,
+            rellinks = rellinks,
+            builder = self.name,
+            parents = [],
+            logo = logo,
+            favicon = favicon,
+        )
+        self.globalcontext.update(self.config.html_context)
+
+    def get_doc_context(self, docname, body, metatags):
+        """Collect items for the template context of a page."""
+        # find out relations
+        prev = next = None
+        parents = []
+        rellinks = self.globalcontext['rellinks'][:]
+        related = self.relations.get(docname)
+        titles = self.env.titles
+        if related and related[2]:
+            try:
+                next = {'link': self.get_relative_uri(docname, related[2]),
+                        'title': self.render_partial(titles[related[2]])['title']}
+                rellinks.append((related[2], next['title'], 'N', _('next')))
+            except KeyError:
+                next = None
+        if related and related[1]:
+            try:
+                prev = {'link': self.get_relative_uri(docname, related[1]),
+                        'title': self.render_partial(titles[related[1]])['title']}
+                rellinks.append((related[1], prev['title'], 'P', _('previous')))
+            except KeyError:
+                # the relation is (somehow) not in the TOC tree, handle that gracefully
+                prev = None
+        while related and related[0]:
+            try:
+                parents.append(
+                    {'link': self.get_relative_uri(docname, related[0]),
+                     'title': self.render_partial(titles[related[0]])['title']})
+            except KeyError:
+                pass
+            related = self.relations.get(related[0])
+        if parents:
+            parents.pop() # remove link to the master file; we have a generic
+                          # "back to index" link already
+        parents.reverse()
+
+        # title rendered as HTML
+        title = titles.get(docname)
+        title = title and self.render_partial(title)['title'] or ''
+        # the name for the copied source
+        sourcename = self.config.html_copy_source and docname + '.txt' or ''
+
+        # metadata for the document
+        meta = self.env.metadata.get(docname)
+
+        return dict(
+            parents = parents,
+            prev = prev,
+            next = next,
+            title = title,
+            meta = meta,
+            body = body,
+            metatags = metatags,
+            rellinks = rellinks,
+            sourcename = sourcename,
+            toc = self.render_partial(self.env.get_toc_for(docname))['fragment'],
+            # only display a TOC if there's more than one item to show
+            display_toc = (self.env.toc_num_entries[docname] > 1),
+        )
+
+    def write_doc(self, docname, doctree):
+        self.post_process_images(doctree)
+        destination = StringOutput(encoding='utf-8')
+        doctree.settings = self.docsettings
+
+        self.imgpath = relative_uri(self.get_target_uri(docname), '_images')
+        self.dlpath = relative_uri(self.get_target_uri(docname), '_downloads')
+        self.docwriter.write(doctree, destination)
+        self.docwriter.assemble_parts()
+        body = self.docwriter.parts['fragment']
+        metatags = self.docwriter.clean_meta
+
+        ctx = self.get_doc_context(docname, body, metatags)
+        self.index_page(docname, doctree, ctx.get('title', ''))
+        self.handle_page(docname, ctx, event_arg=doctree)
+
+    def finish(self):
+        self.info(bold('writing additional files...'), nonl=1)
+
+        # the global general index
+
+        if self.config.html_use_index:
+            # the total count of lines for each index letter, used to distribute
+            # the entries into two columns
+            genindex = self.env.create_index(self)
+            indexcounts = []
+            for _, entries in genindex:
+                indexcounts.append(sum(1 + len(subitems)
+                                       for _, (_, subitems) in entries))
+
+            genindexcontext = dict(
+                genindexentries = genindex,
+                genindexcounts = indexcounts,
+                split_index = self.config.html_split_index,
+            )
+            self.info(' genindex', nonl=1)
+
+            if self.config.html_split_index:
+                self.handle_page('genindex', genindexcontext, 'genindex-split.html')
+                self.handle_page('genindex-all', genindexcontext, 'genindex.html')
+                for (key, entries), count in zip(genindex, indexcounts):
+                    ctx = {'key': key, 'entries': entries, 'count': count,
+                           'genindexentries': genindex}
+                    self.handle_page('genindex-' + key, ctx, 'genindex-single.html')
+            else:
+                self.handle_page('genindex', genindexcontext, 'genindex.html')
+
+        # the global module index
+
+        if self.config.html_use_modindex and self.env.modules:
+            # the sorted list of all modules, for the global module index
+            modules = sorted(((mn, (self.get_relative_uri('modindex', fn) +
+                                    '#module-' + mn, sy, pl, dep))
+                              for (mn, (fn, sy, pl, dep)) in
+                              self.env.modules.iteritems()),
+                             key=lambda x: x[0].lower())
+            # collect all platforms
+            platforms = set()
+            # sort out collapsable modules
+            modindexentries = []
+            letters = []
+            pmn = ''
+            num_toplevels = 0
+            num_collapsables = 0
+            cg = 0 # collapse group
+            fl = '' # first letter
+            for mn, (fn, sy, pl, dep) in modules:
+                pl = pl and pl.split(', ') or []
+                platforms.update(pl)
+                if fl != mn[0].lower() and mn[0] != '_':
+                    # heading
+                    modindexentries.append(['', False, 0, False,
+                                            mn[0].upper(), '', [], False])
+                    letters.append(mn[0].upper())
+                tn = mn.split('.')[0]
+                if tn != mn:
+                    # submodule
+                    if pmn == tn:
+                        # first submodule - make parent collapsable
+                        modindexentries[-1][1] = True
+                        num_collapsables += 1
+                    elif not pmn.startswith(tn):
+                        # submodule without parent in list, add dummy entry
+                        cg += 1
+                        modindexentries.append([tn, True, cg, False, '', '', [], False])
+                else:
+                    num_toplevels += 1
+                    cg += 1
+                modindexentries.append([mn, False, cg, (tn != mn), fn, sy, pl, dep])
+                pmn = mn
+                fl = mn[0].lower()
+            platforms = sorted(platforms)
+
+            # apply heuristics when to collapse modindex at page load:
+            # only collapse if number of toplevel modules is larger than
+            # number of submodules
+            collapse = len(modules) - num_toplevels < num_toplevels
+
+            modindexcontext = dict(
+                modindexentries = modindexentries,
+                platforms = platforms,
+                letters = letters,
+                collapse_modindex = collapse,
+            )
+            self.info(' modindex', nonl=1)
+            self.handle_page('modindex', modindexcontext, 'modindex.html')
+
+        # the search page
+        if self.name != 'htmlhelp':
+            self.info(' search', nonl=1)
+            self.handle_page('search', {}, 'search.html')
+
+        # additional pages from conf.py
+        for pagename, template in self.config.html_additional_pages.items():
+            self.info(' '+pagename, nonl=1)
+            self.handle_page(pagename, {}, template)
+
+        if self.config.html_use_opensearch and self.name != 'htmlhelp':
+            self.info(' opensearch', nonl=1)
+            fn = path.join(self.outdir, '_static', 'opensearch.xml')
+            self.handle_page('opensearch', {}, 'opensearch.xml', outfilename=fn)
+
+        self.info()
+
+        # copy image files
+        if self.images:
+            self.info(bold('copying images...'), nonl=True)
+            ensuredir(path.join(self.outdir, '_images'))
+            for src, dest in self.images.iteritems():
+                self.info(' '+src, nonl=1)
+                shutil.copyfile(path.join(self.srcdir, src),
+                                path.join(self.outdir, '_images', dest))
+            self.info()
+
+        # copy downloadable files
+        if self.env.dlfiles:
+            self.info(bold('copying downloadable files...'), nonl=True)
+            ensuredir(path.join(self.outdir, '_downloads'))
+            for src, (_, dest) in self.env.dlfiles.iteritems():
+                self.info(' '+src, nonl=1)
+                shutil.copyfile(path.join(self.srcdir, src),
+                                path.join(self.outdir, '_downloads', dest))
+            self.info()
+
+        # copy static files
+        self.info(bold('copying static files... '), nonl=True)
+        ensuredir(path.join(self.outdir, '_static'))
+        # first, create pygments style file
+        f = open(path.join(self.outdir, '_static', 'pygments.css'), 'w')
+        f.write(PygmentsBridge('html', self.config.pygments_style).get_stylesheet())
+        f.close()
+        # then, copy translations JavaScript file
+        if self.config.language is not None:
+            jsfile = path.join(package_dir, 'locale', self.config.language,
+                               'LC_MESSAGES', 'sphinx.js')
+            if path.isfile(jsfile):
+                shutil.copyfile(jsfile, path.join(self.outdir, '_static',
+                                                  'translations.js'))
+        # then, copy over all user-supplied static files
+        staticdirnames = [path.join(package_dir, 'static')] + \
+                         [path.join(self.confdir, spath)
+                          for spath in self.config.html_static_path]
+        for staticdirname in staticdirnames:
+            for filename in os.listdir(staticdirname):
+                if filename.startswith('.'):
+                    continue
+                fullname = path.join(staticdirname, filename)
+                targetname = path.join(self.outdir, '_static', filename)
+                if path.isfile(fullname):
+                    shutil.copyfile(fullname, targetname)
+                elif path.isdir(fullname):
+                    if filename in self.config.exclude_dirnames:
+                        continue
+                    if path.exists(targetname):
+                        shutil.rmtree(targetname)
+                    shutil.copytree(fullname, targetname)
+        # last, copy logo file (handled differently)
+        if self.config.html_logo:
+            logobase = path.basename(self.config.html_logo)
+            shutil.copyfile(path.join(self.confdir, self.config.html_logo),
+                            path.join(self.outdir, '_static', logobase))
+        self.info('done')
+
+        # dump the search index
+        self.handle_finish()
+
+    def get_outdated_docs(self):
+        if self.templates:
+            template_mtime = self.templates.newest_template_mtime()
+        else:
+            template_mtime = 0
+        for docname in self.env.found_docs:
+            if docname not in self.env.all_docs:
+                yield docname
+                continue
+            targetname = self.env.doc2path(docname, self.outdir, self.out_suffix)
+            try:
+                targetmtime = path.getmtime(targetname)
+            except Exception:
+                targetmtime = 0
+            try:
+                srcmtime = max(path.getmtime(self.env.doc2path(docname)),
+                               template_mtime)
+                if srcmtime > targetmtime:
+                    yield docname
+            except EnvironmentError:
+                # source doesn't exist anymore
+                pass
+
+    def load_indexer(self, docnames):
+        keep = set(self.env.all_docs) - set(docnames)
+        try:
+            f = open(path.join(self.outdir, self.searchindex_filename), 'rb')
+            try:
+                self.indexer.load(f, self.indexer_format)
+            finally:
+                f.close()
+        except (IOError, OSError, ValueError):
+            if keep:
+                self.warn("search index couldn't be loaded, but not all documents "
+                          "will be built: the index will be incomplete.")
+        # delete all entries for files that will be rebuilt
+        self.indexer.prune(keep)
+
+    def index_page(self, pagename, doctree, title):
+        # only index pages with title
+        if self.indexer is not None and title:
+            self.indexer.feed(pagename, title, doctree)
+
+    # --------- these are overwritten by the serialization builder
+
+    def get_target_uri(self, docname, typ=None):
+        return docname + self.link_suffix
+
+    def handle_page(self, pagename, addctx, templatename='page.html',
+                    outfilename=None, event_arg=None):
+        ctx = self.globalcontext.copy()
+        # current_page_name is backwards compatibility
+        ctx['pagename'] = ctx['current_page_name'] = pagename
+
+        def pathto(otheruri, resource=False,
+                   baseuri=self.get_target_uri(pagename)):
+            if not resource:
+                otheruri = self.get_target_uri(otheruri)
+            return relative_uri(baseuri, otheruri)
+        ctx['pathto'] = pathto
+        ctx['hasdoc'] = lambda name: name in self.env.all_docs
+        ctx['customsidebar'] = self.config.html_sidebars.get(pagename)
+        ctx.update(addctx)
+
+        self.app.emit('html-page-context', pagename, templatename, ctx, event_arg)
+
+        output = self.templates.render(templatename, ctx)
+        if not outfilename:
+            outfilename = path.join(self.outdir, os_path(pagename) + self.out_suffix)
+        ensuredir(path.dirname(outfilename)) # normally different from self.outdir
+        try:
+            f = codecs.open(outfilename, 'w', 'utf-8')
+            try:
+                f.write(output)
+            finally:
+                f.close()
+        except (IOError, OSError), err:
+            self.warn("Error writing file %s: %s" % (outfilename, err))
+        if self.copysource and ctx.get('sourcename'):
+            # copy the source file for the "show source" link
+            source_name = path.join(self.outdir, '_sources', os_path(ctx['sourcename']))
+            ensuredir(path.dirname(source_name))
+            shutil.copyfile(self.env.doc2path(pagename), source_name)
+
+    def handle_finish(self):
+        self.info(bold('dumping search index... '), nonl=True)
+        self.indexer.prune(self.env.all_docs)
+        searchindexfn = path.join(self.outdir, self.searchindex_filename)
+        # first write to a temporary file, so that if dumping fails, the existing
+        # index won't be overwritten
+        f = open(searchindexfn + '.tmp', 'wb')
+        try:
+            self.indexer.dump(f, self.indexer_format)
+        finally:
+            f.close()
+        os.rename(searchindexfn + '.tmp', searchindexfn)
+        self.info('done')
+
+        self.info(bold('dumping object inventory... '), nonl=True)
+        f = open(path.join(self.outdir, INVENTORY_FILENAME), 'w')
+        try:
+            f.write('# Sphinx inventory version 1\n')
+            f.write('# Project: %s\n' % self.config.project.encode('utf-8'))
+            f.write('# Version: %s\n' % self.config.version)
+            for modname, info in self.env.modules.iteritems():
+                f.write('%s mod %s\n' % (modname, self.get_target_uri(info[0])))
+            for refname, (docname, desctype) in self.env.descrefs.iteritems():
+                f.write('%s %s %s\n' % (refname, desctype, self.get_target_uri(docname)))
+        finally:
+            f.close()
+        self.info('done')
+
+
+class SerializingHTMLBuilder(StandaloneHTMLBuilder):
+    """
+    An abstract builder that serializes the HTML generated.
+    """
+    #: the serializing implementation to use.  Set this to a module that
+    #: implements a `dump`, `load`, `dumps` and `loads` functions
+    #: (pickle, simplejson etc.)
+    implementation = None
+
+    #: the filename for the global context file
+    globalcontext_filename = None
+
+    supported_image_types = ('image/svg+xml', 'image/png', 'image/gif',
+                             'image/jpeg')
+
+    def init(self):
+        self.init_translator_class()
+        self.templates = None   # no template bridge necessary
+
+    def get_target_uri(self, docname, typ=None):
+        if docname == 'index':
+            return ''
+        if docname.endswith(SEP + 'index'):
+            return docname[:-5] # up to sep
+        return docname + SEP
+
+    def handle_page(self, pagename, ctx, templatename='page.html',
+                    outfilename=None, event_arg=None):
+        ctx['current_page_name'] = pagename
+        sidebarfile = self.config.html_sidebars.get(pagename)
+        if sidebarfile:
+            ctx['customsidebar'] = sidebarfile
+
+        if not outfilename:
+            outfilename = path.join(self.outdir, os_path(pagename) + self.out_suffix)
+
+        self.app.emit('html-page-context', pagename, templatename, ctx, event_arg)
+
+        ensuredir(path.dirname(outfilename))
+        f = open(outfilename, 'wb')
+        try:
+            self.implementation.dump(ctx, f, 2)
+        finally:
+            f.close()
+
+        # if there is a source file, copy the source file for the
+        # "show source" link
+        if ctx.get('sourcename'):
+            source_name = path.join(self.outdir, '_sources',
+                                    os_path(ctx['sourcename']))
+            ensuredir(path.dirname(source_name))
+            shutil.copyfile(self.env.doc2path(pagename), source_name)
+
+    def handle_finish(self):
+        # dump the global context
+        outfilename = path.join(self.outdir, self.globalcontext_filename)
+        f = open(outfilename, 'wb')
+        try:
+            self.implementation.dump(self.globalcontext, f, 2)
+        finally:
+            f.close()
+
+        # super here to dump the search index
+        StandaloneHTMLBuilder.handle_finish(self)
+
+        # copy the environment file from the doctree dir to the output dir
+        # as needed by the web app
+        shutil.copyfile(path.join(self.doctreedir, ENV_PICKLE_FILENAME),
+                        path.join(self.outdir, ENV_PICKLE_FILENAME))
+
+        # touch 'last build' file, used by the web application to determine
+        # when to reload its environment and clear the cache
+        open(path.join(self.outdir, LAST_BUILD_FILENAME), 'w').close()
+
+
+class PickleHTMLBuilder(SerializingHTMLBuilder):
+    """
+    A Builder that dumps the generated HTML into pickle files.
+    """
+    implementation = pickle
+    indexer_format = pickle
+    name = 'pickle'
+    out_suffix = '.fpickle'
+    globalcontext_filename = 'globalcontext.pickle'
+    searchindex_filename = 'searchindex.pickle'
+
+# compatibility alias
+WebHTMLBuilder = PickleHTMLBuilder
+
+
+class JSONHTMLBuilder(SerializingHTMLBuilder):
+    """
+    A builder that dumps the generated HTML into JSON files.
+    """
+    implementation = json
+    indexer_format = json
+    name = 'json'
+    out_suffix = '.fjson'
+    globalcontext_filename = 'globalcontext.json'
+    searchindex_filename = 'searchindex.json'
+
+    def init(self):
+        if json is None:
+            from sphinx.application import SphinxError
+            raise SphinxError('The module simplejson (or json in Python >= 2.6) '
+                              'is not available. The JSONHTMLBuilder builder '
+                              'will not work.')
+        SerializingHTMLBuilder.init(self)

Added: doctools/trunk/sphinx/builders/htmlhelp.py
==============================================================================
--- (empty file)
+++ doctools/trunk/sphinx/builders/htmlhelp.py	Sun Jan  4 21:38:57 2009
@@ -0,0 +1,246 @@
+# -*- coding: utf-8 -*-
+"""
+    sphinx.builders.htmlhelp
+    ~~~~~~~~~~~~~~~~~~~~~~~~
+
+    Build HTML help support files.
+    Parts adapted from Python's Doc/tools/prechm.py.
+
+    :copyright: Copyright 2007-2009 by the Sphinx team, see AUTHORS.
+    :license: BSD, see LICENSE for details.
+"""
+
+import os
+import cgi
+from os import path
+
+from docutils import nodes
+
+from sphinx import addnodes
+from sphinx.builders.html import StandaloneHTMLBuilder
+
+
+# Project file (*.hhp) template.  'outname' is the file basename (like
+# the pythlp in pythlp.hhp); 'version' is the doc version number (like
+# the 2.2 in Python 2.2).
+# The magical numbers in the long line under [WINDOWS] set most of the
+# user-visible features (visible buttons, tabs, etc).
+# About 0x10384e:  This defines the buttons in the help viewer.  The
+# following defns are taken from htmlhelp.h.  Not all possibilities
+# actually work, and not all those that work are available from the Help
+# Workshop GUI.  In particular, the Zoom/Font button works and is not
+# available from the GUI.  The ones we're using are marked with 'x':
+#
+#    0x000002   Hide/Show   x
+#    0x000004   Back        x
+#    0x000008   Forward     x
+#    0x000010   Stop
+#    0x000020   Refresh
+#    0x000040   Home        x
+#    0x000080   Forward
+#    0x000100   Back
+#    0x000200   Notes
+#    0x000400   Contents
+#    0x000800   Locate      x
+#    0x001000   Options     x
+#    0x002000   Print       x
+#    0x004000   Index
+#    0x008000   Search
+#    0x010000   History
+#    0x020000   Favorites
+#    0x040000   Jump 1
+#    0x080000   Jump 2
+#    0x100000   Zoom/Font   x
+#    0x200000   TOC Next
+#    0x400000   TOC Prev
+
+project_template = '''\
+[OPTIONS]
+Binary TOC=Yes
+Binary Index=No
+Compiled file=%(outname)s.chm
+Contents file=%(outname)s.hhc
+Default Window=%(outname)s
+Default topic=index.html
+Display compile progress=No
+Full text search stop list file=%(outname)s.stp
+Full-text search=Yes
+Index file=%(outname)s.hhk
+Language=0x409
+Title=%(title)s
+
+[WINDOWS]
+%(outname)s="%(title)s","%(outname)s.hhc","%(outname)s.hhk",\
+"index.html","index.html",,,,,0x63520,220,0x10384e,[0,0,1024,768],,,,,,,0
+
+[FILES]
+'''
+
+contents_header = '''\
+<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
+<HTML>
+<HEAD>
+<meta name="GENERATOR" content="Microsoft&reg; HTML Help Workshop 4.1">
+<!-- Sitemap 1.0 -->
+</HEAD><BODY>
+<OBJECT type="text/site properties">
+        <param name="Window Styles" value="0x801227">
+        <param name="ImageType" value="Folder">
+</OBJECT>
+<UL>
+'''
+
+contents_footer = '''\
+</UL></BODY></HTML>
+'''
+
+object_sitemap = '''\
+<OBJECT type="text/sitemap">
+    <param name="Name" value="%s">
+    <param name="Local" value="%s">
+</OBJECT>
+'''
+
+# List of words the full text search facility shouldn't index.  This
+# becomes file outname.stp.  Note that this list must be pretty small!
+# Different versions of the MS docs claim the file has a maximum size of
+# 256 or 512 bytes (including \r\n at the end of each line).
+# Note that "and", "or", "not" and "near" are operators in the search
+# language, so no point indexing them even if we wanted to.
+stopwords = """
+a  and  are  as  at
+be  but  by
+for
+if  in  into  is  it
+near  no  not
+of  on  or
+such
+that  the  their  then  there  these  they  this  to
+was  will  with
+""".split()
+
+
+class HTMLHelpBuilder(StandaloneHTMLBuilder):
+    """
+    Builder that also outputs Windows HTML help project, contents and index files.
+    Adapted from the original Doc/tools/prechm.py.
+    """
+    name = 'htmlhelp'
+
+    # don't copy the reST source
+    copysource = False
+    supported_image_types = ['image/png', 'image/gif', 'image/jpeg']
+
+    # don't add links
+    add_permalinks = False
+    # don't add sidebar etc.
+    embedded = True
+
+    def init(self):
+        StandaloneHTMLBuilder.init(self)
+        # the output files for HTML help must be .html only
+        self.out_suffix = '.html'
+
+    def handle_finish(self):
+        self.build_hhx(self.outdir, self.config.htmlhelp_basename)
+
+    def build_hhx(self, outdir, outname):
+        self.info('dumping stopword list...')
+        f = open(path.join(outdir, outname+'.stp'), 'w')
+        try:
+            for word in sorted(stopwords):
+                print >>f, word
+        finally:
+            f.close()
+
+        self.info('writing project file...')
+        f = open(path.join(outdir, outname+'.hhp'), 'w')
+        try:
+            f.write(project_template % {'outname': outname,
+                                        'title': self.config.html_title,
+                                        'version': self.config.version,
+                                        'project': self.config.project})
+            if not outdir.endswith(os.sep):
+                outdir += os.sep
+            olen = len(outdir)
+            for root, dirs, files in os.walk(outdir):
+                staticdir = (root == path.join(outdir, '_static'))
+                for fn in files:
+                    if (staticdir and not fn.endswith('.js')) or fn.endswith('.html'):
+                        print >>f, path.join(root, fn)[olen:].replace(os.sep, '\\')
+        finally:
+            f.close()
+
+        self.info('writing TOC file...')
+        f = open(path.join(outdir, outname+'.hhc'), 'w')
+        try:
+            f.write(contents_header)
+            # special books
+            f.write('<LI> ' + object_sitemap % (self.config.html_short_title,
+                                                'index.html'))
+            if self.config.html_use_modindex:
+                f.write('<LI> ' + object_sitemap % (_('Global Module Index'),
+                                                    'modindex.html'))
+            # the TOC
+            tocdoc = self.env.get_and_resolve_doctree(self.config.master_doc, self,
+                                                      prune_toctrees=False)
+            def write_toc(node, ullevel=0):
+                if isinstance(node, nodes.list_item):
+                    f.write('<LI> ')
+                    for subnode in node:
+                        write_toc(subnode, ullevel)
+                elif isinstance(node, nodes.reference):
+                    link = node['refuri']
+                    title = cgi.escape(node.astext()).replace('"','&quot;')
+                    item = object_sitemap % (title, link)
+                    f.write(item.encode('ascii', 'xmlcharrefreplace'))
+                elif isinstance(node, nodes.bullet_list):
+                    if ullevel != 0:
+                        f.write('<UL>\n')
+                    for subnode in node:
+                        write_toc(subnode, ullevel+1)
+                    if ullevel != 0:
+                        f.write('</UL>\n')
+                elif isinstance(node, addnodes.compact_paragraph):
+                    for subnode in node:
+                        write_toc(subnode, ullevel)
+            istoctree = lambda node: isinstance(node, addnodes.compact_paragraph) and \
+                        node.has_key('toctree')
+            for node in tocdoc.traverse(istoctree):
+                write_toc(node)
+            f.write(contents_footer)
+        finally:
+            f.close()
+
+        self.info('writing index file...')
+        index = self.env.create_index(self)
+        f = open(path.join(outdir, outname+'.hhk'), 'w')
+        try:
+            f.write('<UL>\n')
+            def write_index(title, refs, subitems):
+                def write_param(name, value):
+                    item = '    <param name="%s" value="%s">\n' % (name, value)
+                    f.write(item.encode('ascii', 'xmlcharrefreplace'))
+                title = cgi.escape(title)
+                f.write('<LI> <OBJECT type="text/sitemap">\n')
+                write_param('Keyword', title)
+                if len(refs) == 0:
+                    write_param('See Also', title)
+                elif len(refs) == 1:
+                    write_param('Local', refs[0])
+                else:
+                    for i, ref in enumerate(refs):
+                        write_param('Name', '[%d] %s' % (i, ref)) # XXX: better title?
+                        write_param('Local', ref)
+                f.write('</OBJECT>\n')
+                if subitems:
+                    f.write('<UL> ')
+                    for subitem in subitems:
+                        write_index(subitem[0], subitem[1], [])
+                    f.write('</UL>')
+            for (key, group) in index:
+                for title, (refs, subitems) in group:
+                    write_index(title, refs, subitems)
+            f.write('</UL>\n')
+        finally:
+            f.close()

Added: doctools/trunk/sphinx/builders/latex.py
==============================================================================
--- (empty file)
+++ doctools/trunk/sphinx/builders/latex.py	Sun Jan  4 21:38:57 2009
@@ -0,0 +1,186 @@
+# -*- coding: utf-8 -*-
+"""
+    sphinx.builders.latex
+    ~~~~~~~~~~~~~~~~~~~~~
+
+    LaTeX builder.
+
+    :copyright: Copyright 2007-2009 by the Sphinx team, see AUTHORS.
+    :license: BSD, see LICENSE for details.
+"""
+
+import os
+import shutil
+from os import path
+
+from docutils import nodes
+from docutils.io import FileOutput
+from docutils.utils import new_document
+from docutils.frontend import OptionParser
+
+from sphinx import package_dir, addnodes
+from sphinx.util import SEP, texescape
+from sphinx.builders import Builder
+from sphinx.environment import NoUri
+from sphinx.util.console import bold, darkgreen
+from sphinx.writers.latex import LaTeXWriter
+
+
+class LaTeXBuilder(Builder):
+    """
+    Builds LaTeX output to create PDF.
+    """
+    name = 'latex'
+    supported_image_types = ['application/pdf', 'image/png', 'image/gif',
+                             'image/jpeg']
+
+    def init(self):
+        self.docnames = []
+        self.document_data = []
+        texescape.init()
+
+    def get_outdated_docs(self):
+        return 'all documents' # for now
+
+    def get_target_uri(self, docname, typ=None):
+        if typ == 'token':
+            # token references are always inside production lists and must be
+            # replaced by \token{} in LaTeX
+            return '@token'
+        if docname not in self.docnames:
+            raise NoUri
+        else:
+            return '%' + docname
+
+    def init_document_data(self):
+        preliminary_document_data = map(list, self.config.latex_documents)
+        if not preliminary_document_data:
+            self.warn('No "latex_documents" config value found; no documents '
+                      'will be written.')
+            return
+        # assign subdirs to titles
+        self.titles = []
+        for entry in preliminary_document_data:
+            docname = entry[0]
+            if docname not in self.env.all_docs:
+                self.warn('"latex_documents" config value references unknown '
+                          'document %s' % docname)
+                continue
+            self.document_data.append(entry)
+            if docname.endswith(SEP+'index'):
+                docname = docname[:-5]
+            self.titles.append((docname, entry[2]))
+
+    def write(self, *ignored):
+        # first, assemble the "appendix" docs that are in every PDF
+        appendices = []
+        for fname in self.config.latex_appendices:
+            appendices.append(self.env.get_doctree(fname))
+
+        docwriter = LaTeXWriter(self)
+        docsettings = OptionParser(
+            defaults=self.env.settings,
+            components=(docwriter,)).get_default_values()
+
+        self.init_document_data()
+
+        for entry in self.document_data:
+            docname, targetname, title, author, docclass = entry[:5]
+            toctree_only = False
+            if len(entry) > 5:
+                toctree_only = entry[5]
+            destination = FileOutput(
+                destination_path=path.join(self.outdir, targetname),
+                encoding='utf-8')
+            self.info("processing " + targetname + "... ", nonl=1)
+            doctree = self.assemble_doctree(docname, toctree_only,
+                appendices=(docclass == 'manual') and appendices or [])
+            self.post_process_images(doctree)
+            self.info("writing... ", nonl=1)
+            doctree.settings = docsettings
+            doctree.settings.author = author
+            doctree.settings.title = title
+            doctree.settings.docname = docname
+            doctree.settings.docclass = docclass
+            docwriter.write(doctree, destination)
+            self.info("done")
+
+    def assemble_doctree(self, indexfile, toctree_only, appendices):
+        self.docnames = set([indexfile] + appendices)
+        self.info(darkgreen(indexfile) + " ", nonl=1)
+        def process_tree(docname, tree):
+            tree = tree.deepcopy()
+            for toctreenode in tree.traverse(addnodes.toctree):
+                newnodes = []
+                includefiles = map(str, toctreenode['includefiles'])
+                for includefile in includefiles:
+                    try:
+                        self.info(darkgreen(includefile) + " ", nonl=1)
+                        subtree = process_tree(includefile,
+                                               self.env.get_doctree(includefile))
+                        self.docnames.add(includefile)
+                    except Exception:
+                        self.warn('%s: toctree contains ref to nonexisting file %r' %
+                                  (docname, includefile))
+                    else:
+                        sof = addnodes.start_of_file(docname=includefile)
+                        sof.children = subtree.children
+                        newnodes.append(sof)
+                toctreenode.parent.replace(toctreenode, newnodes)
+            return tree
+        tree = self.env.get_doctree(indexfile)
+        tree['docname'] = indexfile
+        if toctree_only:
+            # extract toctree nodes from the tree and put them in a fresh document
+            new_tree = new_document('<latex output>')
+            new_sect = nodes.section()
+            new_sect += nodes.title(u'<Set title in conf.py>', u'<Set title in conf.py>')
+            new_tree += new_sect
+            for node in tree.traverse(addnodes.toctree):
+                new_sect += node
+            tree = new_tree
+        largetree = process_tree(indexfile, tree)
+        largetree.extend(appendices)
+        self.info()
+        self.info("resolving references...")
+        self.env.resolve_references(largetree, indexfile, self)
+        # resolve :ref:s to distant tex files -- we can't add a cross-reference,
+        # but append the document name
+        for pendingnode in largetree.traverse(addnodes.pending_xref):
+            docname = pendingnode['refdocname']
+            sectname = pendingnode['refsectname']
+            newnodes = [nodes.emphasis(sectname, sectname)]
+            for subdir, title in self.titles:
+                if docname.startswith(subdir):
+                    newnodes.append(nodes.Text(_(' (in '), _(' (in ')))
+                    newnodes.append(nodes.emphasis(title, title))
+                    newnodes.append(nodes.Text(')', ')'))
+                    break
+            else:
+                pass
+            pendingnode.replace_self(newnodes)
+        return largetree
+
+    def finish(self):
+        # copy image files
+        if self.images:
+            self.info(bold('copying images...'), nonl=1)
+            for src, dest in self.images.iteritems():
+                self.info(' '+src, nonl=1)
+                shutil.copyfile(path.join(self.srcdir, src),
+                                path.join(self.outdir, dest))
+            self.info()
+
+        # the logo is handled differently
+        if self.config.latex_logo:
+            logobase = path.basename(self.config.latex_logo)
+            shutil.copyfile(path.join(self.confdir, self.config.latex_logo),
+                            path.join(self.outdir, logobase))
+
+        self.info(bold('copying TeX support files... '), nonl=True)
+        staticdirname = path.join(package_dir, 'texinputs')
+        for filename in os.listdir(staticdirname):
+            if not filename.startswith('.'):
+                shutil.copyfile(path.join(staticdirname, filename),
+                                path.join(self.outdir, filename))
+        self.info('done')

Added: doctools/trunk/sphinx/builders/linkcheck.py
==============================================================================
--- (empty file)
+++ doctools/trunk/sphinx/builders/linkcheck.py	Sun Jan  4 21:38:57 2009
@@ -0,0 +1,130 @@
+# -*- coding: utf-8 -*-
+"""
+    sphinx.builders.linkcheck
+    ~~~~~~~~~~~~~~~~~~~~~~~~~
+
+    The CheckExternalLinksBuilder class.
+
+    :copyright: Copyright 2007-2009 by the Sphinx team, see AUTHORS.
+    :license: BSD, see LICENSE for details.
+"""
+
+import socket
+from os import path
+from urllib2 import build_opener, HTTPError
+
+from docutils import nodes
+
+from sphinx.builders import Builder
+from sphinx.util.console import purple, red, darkgreen
+
+# create an opener that will simulate a browser user-agent
+opener = build_opener()
+opener.addheaders = [('User-agent', 'Mozilla/5.0')]
+
+
+class CheckExternalLinksBuilder(Builder):
+    """
+    Checks for broken external links.
+    """
+    name = 'linkcheck'
+
+    def init(self):
+        self.good = set()
+        self.broken = {}
+        self.redirected = {}
+        # set a timeout for non-responding servers
+        socket.setdefaulttimeout(5.0)
+        # create output file
+        open(path.join(self.outdir, 'output.txt'), 'w').close()
+
+    def get_target_uri(self, docname, typ=None):
+        return ''
+
+    def get_outdated_docs(self):
+        return self.env.found_docs
+
+    def prepare_writing(self, docnames):
+        return
+
+    def write_doc(self, docname, doctree):
+        self.info()
+        for node in doctree.traverse(nodes.reference):
+            try:
+                self.check(node, docname)
+            except KeyError:
+                continue
+
+    def check(self, node, docname):
+        uri = node['refuri']
+
+        if '#' in uri:
+            uri = uri.split('#')[0]
+
+        if uri in self.good:
+            return
+
+        lineno = None
+        while lineno is None and node:
+            node = node.parent
+            lineno = node.line
+
+        if uri[0:5] == 'http:' or uri[0:6] == 'https:':
+            self.info(uri, nonl=1)
+
+            if uri in self.broken:
+                (r, s) = self.broken[uri]
+            elif uri in self.redirected:
+                (r, s) = self.redirected[uri]
+            else:
+                (r, s) = self.resolve(uri)
+
+            if r == 0:
+                self.info(' - ' + darkgreen('working'))
+                self.good.add(uri)
+            elif r == 2:
+                self.info(' - ' + red('broken: ') + s)
+                self.write_entry('broken', docname, lineno, uri + ': ' + s)
+                self.broken[uri] = (r, s)
+                if self.app.quiet:
+                    self.warn('%s:%s: broken link: %s' % (docname, lineno, uri))
+            else:
+                self.info(' - ' + purple('redirected') + ' to ' + s)
+                self.write_entry('redirected', docname, lineno, uri + ' to ' + s)
+                self.redirected[uri] = (r, s)
+        elif len(uri) == 0 or uri[0:7] == 'mailto:' or uri[0:4] == 'ftp:':
+            return
+        else:
+            self.warn(uri + ' - ' + red('malformed!'))
+            self.write_entry('malformed', docname, lineno, uri)
+            if self.app.quiet:
+                self.warn('%s:%s: malformed link: %s' % (docname, lineno, uri))
+            self.app.statuscode = 1
+
+        if self.broken:
+            self.app.statuscode = 1
+
+    def write_entry(self, what, docname, line, uri):
+        output = open(path.join(self.outdir, 'output.txt'), 'a')
+        output.write("%s:%s: [%s] %s\n" % (self.env.doc2path(docname, None),
+                                           line, what, uri))
+        output.close()
+
+    def resolve(self, uri):
+        try:
+            f = opener.open(uri)
+            f.close()
+        except HTTPError, err:
+            #if err.code == 403 and uri.startswith('http://en.wikipedia.org/'):
+            #    # Wikipedia blocks requests from urllib User-Agent
+            #    return (0, 0)
+            return (2, str(err))
+        except Exception, err:
+            return (2, str(err))
+        if f.url.rstrip('/') == uri.rstrip('/'):
+            return (0, 0)
+        else:
+            return (1, f.url)
+
+    def finish(self):
+        return

Added: doctools/trunk/sphinx/builders/qthelp.py
==============================================================================
--- (empty file)
+++ doctools/trunk/sphinx/builders/qthelp.py	Sun Jan  4 21:38:57 2009
@@ -0,0 +1,261 @@
+# -*- coding: utf-8 -*-
+"""
+    sphinx.builders.qthelp
+    ~~~~~~~~~~~~~~~~~~~~~~
+
+    Build input files for the Qt collection generator.
+
+    :copyright: Copyright 2007-2009 by the Sphinx team, see AUTHORS.
+    :license: BSD, see LICENSE for details.
+"""
+
+import os
+import re
+import cgi
+from os import path
+
+from docutils import nodes
+
+from sphinx import addnodes
+from sphinx.builders.html import StandaloneHTMLBuilder
+
+_idpattern = re.compile('(?P<title>.+) (\((?P<id>[\w\.]+)( (?P<descr>\w+))?\))$')
+
+
+# Qt Help Collection Project (.qhcp).
+# Is the input file for the help collection generator.
+# It contains references to compressed help files which should be
+# included in the collection.
+# It may contain various other information for customizing Qt Assistant.
+collection_template = '''\
+<?xml version="1.0" encoding="utf-8" ?>
+<QHelpCollectionProject version="1.0">
+    <docFiles>
+        <generate>
+            <file>
+                <input>%(outname)s.qhp</input>
+                <output>%(outname)s.qch</output>
+            </file>
+        </generate>
+        <register>
+            <file>%(outname)s.qch</file>
+        </register>
+    </docFiles>
+</QHelpCollectionProject>
+'''
+
+# Qt Help Project (.qhp)
+# This is the input file for the help generator.
+# It contains the table of contents, indices and references to the
+# actual documentation files (*.html).
+# In addition it defines a unique namespace for the documentation.
+project_template = '''\
+<?xml version="1.0" encoding="UTF-8"?>
+<QtHelpProject version="1.0">
+    <namespace>%(outname)s.org.%(outname)s.%(nversion)s</namespace>
+    <virtualFolder>doc</virtualFolder>
+    <customFilter name="%(project)s %(version)s">
+        <filterAttribute>%(outname)s</filterAttribute>
+        <filterAttribute>%(version)s</filterAttribute>
+    </customFilter>
+    <filterSection>
+        <filterAttribute>%(outname)s</filterAttribute>
+        <filterAttribute>%(version)s</filterAttribute>
+        <toc>
+            <section title="%(title)s" ref="%(masterdoc)s.html">
+%(sections)s
+            </section>
+        </toc>
+        <keywords>
+%(keywords)s
+        </keywords>
+        <files>
+%(files)s
+        </files>
+    </filterSection>
+</QtHelpProject>
+'''
+
+section_template = '<section title="%(title)s" ref="%(ref)s"/>'
+file_template = ' '*12 + '<file>%(filename)s</file>'
+
+
+class QtHelpBuilder(StandaloneHTMLBuilder):
+    """
+    Builder that also outputs Qt help project, contents and index files.
+    """
+    name = 'qthelp'
+
+    # don't copy the reST source
+    copysource = False
+    supported_image_types = ['image/svg+xml', 'image/png', 'image/gif',
+                             'image/jpeg']
+
+    # don't add links
+    add_permalinks = False
+    # don't add sidebar etc.
+    embedded = True
+
+    def init(self):
+        StandaloneHTMLBuilder.init(self)
+        # the output files for HTML help must be .html only
+        self.out_suffix = '.html'
+        #self.config.html_style = 'traditional.css'
+
+    def handle_finish(self):
+        self.build_qhcp(self.outdir, self.config.qthelp_basename)
+        self.build_qhp(self.outdir, self.config.qthelp_basename)
+
+    def build_qhcp(self, outdir, outname):
+        self.info('writing collection project file...')
+        f = open(path.join(outdir, outname+'.qhcp'), 'w')
+        try:
+            f.write(collection_template % {'outname': outname})
+        finally:
+            f.close()
+
+    def build_qhp(self, outdir, outname):
+        self.info('writing project file...')
+
+        # sections
+        tocdoc = self.env.get_and_resolve_doctree(self.config.master_doc, self,
+                                                  prune_toctrees=False)
+        istoctree = lambda node: (
+                        isinstance(node, addnodes.compact_paragraph)
+                            and node.has_key('toctree'))
+        sections = []
+        for node in tocdoc.traverse(istoctree):
+            sections.extend(self.write_toc(node))
+
+        if self.config.html_use_modindex:
+            item = section_template % {'title': _('Global Module Index'),
+                                       'ref': 'modindex.html'}
+            sections.append(' '*4*4 + item)
+        sections = '\n'.join(sections)
+
+        # keywords
+        keywords = []
+        index = self.env.create_index(self)
+        for (key, group) in index:
+            for title, (refs, subitems) in group:
+                keywords.extend(self.build_keywords(title, refs, subitems))
+        keywords = '\n'.join(keywords)
+
+        # files
+        if not outdir.endswith(os.sep):
+            outdir += os.sep
+        olen = len(outdir)
+        projectfiles = []
+        for root, dirs, files in os.walk(outdir):
+            staticdir = (root == path.join(outdir, '_static'))
+            for fn in files:
+                if (staticdir and not fn.endswith('.js')) or fn.endswith('.html'):
+                    filename = path.join(root, fn)[olen:]
+                    #filename = filename.replace(os.sep, '\\') # XXX
+                    projectfiles.append(file_template % {'filename': filename})
+        projectfiles = '\n'.join(projectfiles)
+
+        # write the project file
+        f = open(path.join(outdir, outname+'.qhp'), 'w')
+        try:
+            nversion = self.config.version.replace('.', '_')
+            nversion = nversion.replace(' ', '_')
+            f.write(project_template % {'outname': outname,
+                                        'title': self.config.html_title,
+                                        'version': self.config.version,
+                                        'project': self.config.project,
+                                        'nversion': nversion,
+                                        'masterdoc': self.config.master_doc,
+                                        'sections': sections,
+                                        'keywords': keywords,
+                                        'files': projectfiles})
+        finally:
+            f.close()
+
+    def isdocnode(self, node):
+        if not isinstance(node, nodes.list_item):
+            return False
+        if len(node.children) != 2:
+            return False
+        if not isinstance(node.children[0], addnodes.compact_paragraph):
+            return False
+        if not isinstance(node.children[0][0], nodes.reference):
+            return False
+        if not isinstance(node.children[1], nodes.bullet_list):
+            return False
+        return True
+
+    def write_toc(self, node, indentlevel=4):
+        parts = []
+        if self.isdocnode(node):
+            refnode = node.children[0][0]
+            link = refnode['refuri']
+            title = cgi.escape(refnode.astext()).replace('"','&quot;')
+            item = '<section title="%(title)s" ref="%(ref)s">' % {
+                                                                'title': title,
+                                                                'ref': link}
+            parts.append(' '*4*indentlevel + item)
+            for subnode in node.children[1]:
+                parts.extend(self.write_toc(subnode, indentlevel+1))
+            parts.append(' '*4*indentlevel + '</section>')
+        elif isinstance(node, nodes.list_item):
+            for subnode in node:
+                parts.extend(self.write_toc(subnode, indentlevel))
+        elif isinstance(node, nodes.reference):
+            link = node['refuri']
+            title = cgi.escape(node.astext()).replace('"','&quot;')
+            item = section_template % {'title': title, 'ref': link}
+            item = ' '*4*indentlevel + item.encode('ascii', 'xmlcharrefreplace')
+            parts.append(item.encode('ascii', 'xmlcharrefreplace'))
+        elif isinstance(node, nodes.bullet_list):
+            for subnode in node:
+                parts.extend(self.write_toc(subnode, indentlevel))
+        elif isinstance(node, addnodes.compact_paragraph):
+            for subnode in node:
+                parts.extend(self.write_toc(subnode, indentlevel))
+
+        return parts
+
+    def keyword_item(self, name, ref):
+        matchobj = _idpattern.match(name)
+        if matchobj:
+            groupdict = matchobj.groupdict()
+            shortname = groupdict['title']
+            id = groupdict.get('id')
+#            descr = groupdict.get('descr')
+            if shortname.endswith('()'):
+                shortname = shortname[:-2]
+            id = '%s.%s' % (id, shortname)
+        else:
+            id = descr = None
+
+        if id:
+            item = ' '*12 + '<keyword name="%s" id="%s" ref="%s"/>' % (
+                                                                name, id, ref)
+        else:
+            item = ' '*12 + '<keyword name="%s" ref="%s"/>' % (name, ref)
+        item.encode('ascii', 'xmlcharrefreplace')
+        return item
+
+    def build_keywords(self, title, refs, subitems):
+        keywords = []
+
+        title = cgi.escape(title)
+#        if len(refs) == 0: # XXX
+#            write_param('See Also', title)
+        if len(refs) == 1:
+            keywords.append(self.keyword_item(title, refs[0]))
+        elif len(refs) > 1:
+            for i, ref in enumerate(refs):  # XXX
+#                item = (' '*12 +
+#                        '<keyword name="%s [%d]" ref="%s"/>' % (
+#                                                        title, i, ref))
+#                item.encode('ascii', 'xmlcharrefreplace')
+#                keywords.append(item)
+                keywords.append(self.keyword_item(title, ref))
+
+        if subitems:
+            for subitem in subitems:
+                keywords.extend(self.build_keywords(subitem[0], subitem[1], []))
+
+        return keywords

Added: doctools/trunk/sphinx/builders/text.py
==============================================================================
--- (empty file)
+++ doctools/trunk/sphinx/builders/text.py	Sun Jan  4 21:38:57 2009
@@ -0,0 +1,68 @@
+# -*- coding: utf-8 -*-
+"""
+    sphinx.builders.text
+    ~~~~~~~~~~~~~~~~~~~~
+
+    Plain-text Sphinx builder.
+
+    :copyright: Copyright 2007-2009 by the Sphinx team, see AUTHORS.
+    :license: BSD, see LICENSE for details.
+"""
+
+import codecs
+from os import path
+
+from docutils.io import StringOutput
+
+from sphinx.util import ensuredir, os_path
+from sphinx.builders import Builder
+from sphinx.writers.text import TextWriter
+
+
+class TextBuilder(Builder):
+    name = 'text'
+    out_suffix = '.txt'
+
+    def init(self):
+        pass
+
+    def get_outdated_docs(self):
+        for docname in self.env.found_docs:
+            if docname not in self.env.all_docs:
+                yield docname
+                continue
+            targetname = self.env.doc2path(docname, self.outdir, self.out_suffix)
+            try:
+                targetmtime = path.getmtime(targetname)
+            except Exception:
+                targetmtime = 0
+            try:
+                srcmtime = path.getmtime(self.env.doc2path(docname))
+                if srcmtime > targetmtime:
+                    yield docname
+            except EnvironmentError:
+                # source doesn't exist anymore
+                pass
+
+    def get_target_uri(self, docname, typ=None):
+        return ''
+
+    def prepare_writing(self, docnames):
+        self.writer = TextWriter(self)
+
+    def write_doc(self, docname, doctree):
+        destination = StringOutput(encoding='utf-8')
+        self.writer.write(doctree, destination)
+        outfilename = path.join(self.outdir, os_path(docname) + self.out_suffix)
+        ensuredir(path.dirname(outfilename)) # normally different from self.outdir
+        try:
+            f = codecs.open(outfilename, 'w', 'utf-8')
+            try:
+                f.write(self.writer.output)
+            finally:
+                f.close()
+        except (IOError, OSError), err:
+            self.warn("Error writing file %s: %s" % (outfilename, err))
+
+    def finish(self):
+        pass

Modified: doctools/trunk/sphinx/cmdline.py
==============================================================================
--- doctools/trunk/sphinx/cmdline.py	(original)
+++ doctools/trunk/sphinx/cmdline.py	Sun Jan  4 21:38:57 2009
@@ -5,8 +5,8 @@
 
     sphinx-build command-line handling.
 
-    :copyright: 2008 by Georg Brandl.
-    :license: BSD.
+    :copyright: Copyright 2007-2009 by the Sphinx team, see AUTHORS.
+    :license: BSD, see LICENSE for details.
 """
 
 import os

Modified: doctools/trunk/sphinx/config.py
==============================================================================
--- doctools/trunk/sphinx/config.py	(original)
+++ doctools/trunk/sphinx/config.py	Sun Jan  4 21:38:57 2009
@@ -5,13 +5,15 @@
 
     Build configuration file handling.
 
-    :copyright: 2008 by Georg Brandl.
-    :license: BSD license.
+    :copyright: Copyright 2007-2009 by the Sphinx team, see AUTHORS.
+    :license: BSD, see LICENSE for details.
 """
 
 import os
 from os import path
 
+from sphinx.util import make_filename
+
 
 class Config(object):
     """Configuration file abstraction."""
@@ -65,16 +67,22 @@
         html_sidebars = ({}, False),
         html_additional_pages = ({}, False),
         html_use_modindex = (True, False),
+        html_add_permalinks = (True, False),
         html_use_index = (True, False),
         html_split_index = (False, False),
         html_copy_source = (True, False),
+        html_show_sourcelink = (True, False),
         html_use_opensearch = ('', False),
         html_file_suffix = (None, False),
+        html_link_suffix = (None, False),
         html_show_sphinx = (True, False),
         html_context = ({}, False),
 
         # HTML help only options
-        htmlhelp_basename = ('pydoc', False),
+        htmlhelp_basename = (lambda self: make_filename(self.project), False),
+
+        # Qt help only options
+        qthelp_basename = (lambda self: make_filename(self.project), False),
 
         # LaTeX options
         latex_documents = ([], False),
@@ -111,6 +119,12 @@
 
     def init_values(self):
         config = self._raw_config
+        for valname, value in self.overrides.iteritems():
+            if '.' in valname:
+                realvalname, key = valname.split('.', 1)
+                config.setdefault(realvalname, {})[key] = value
+            else:
+                config[valname] = value
         config.update(self.overrides)
         for name in config:
             if name in self.values:

Modified: doctools/trunk/sphinx/directives/__init__.py
==============================================================================
--- doctools/trunk/sphinx/directives/__init__.py	(original)
+++ doctools/trunk/sphinx/directives/__init__.py	Sun Jan  4 21:38:57 2009
@@ -5,8 +5,8 @@
 
     Handlers for additional ReST directives.
 
-    :copyright: 2008 by Georg Brandl.
-    :license: BSD.
+    :copyright: Copyright 2007-2009 by the Sphinx team, see AUTHORS.
+    :license: BSD, see LICENSE for details.
 """
 
 from sphinx.directives.desc import *

Modified: doctools/trunk/sphinx/directives/code.py
==============================================================================
--- doctools/trunk/sphinx/directives/code.py	(original)
+++ doctools/trunk/sphinx/directives/code.py	Sun Jan  4 21:38:57 2009
@@ -3,8 +3,8 @@
     sphinx.directives.code
     ~~~~~~~~~~~~~~~~~~~~~~
 
-    :copyright: 2007-2008 by Georg Brandl.
-    :license: BSD.
+    :copyright: Copyright 2007-2009 by the Sphinx team, see AUTHORS.
+    :license: BSD, see LICENSE for details.
 """
 
 import sys
@@ -15,6 +15,7 @@
 from docutils.parsers.rst import directives
 
 from sphinx import addnodes
+from sphinx.util import parselinenos
 
 
 # ------ highlight directive --------------------------------------------------------
@@ -68,32 +69,78 @@
         lineno - state_machine.input_offset - 1)))
     fn = path.normpath(path.join(source_dir, rel_fn))
 
+    if 'pyobject' in options and 'lines' in options:
+        return [state.document.reporter.warning(
+            'Cannot use both "pyobject" and "lines" options', line=lineno)]
+
     encoding = options.get('encoding', env.config.source_encoding)
     try:
         f = codecs.open(fn, 'r', encoding)
-        text = f.read()
+        lines = f.readlines()
         f.close()
     except (IOError, OSError):
-        retnode = state.document.reporter.warning(
-            'Include file %r not found or reading it failed' % arguments[0], line=lineno)
+        return [state.document.reporter.warning(
+            'Include file %r not found or reading it failed' % arguments[0],
+            line=lineno)]
     except UnicodeError:
-        retnode = state.document.reporter.warning(
+        return [state.document.reporter.warning(
             'Encoding %r used for reading included file %r seems to '
             'be wrong, try giving an :encoding: option' %
-            (encoding, arguments[0]))
-    else:
-        retnode = nodes.literal_block(text, text, source=fn)
-        retnode.line = 1
-        if options.get('language', ''):
-            retnode['language'] = options['language']
-        if 'linenos' in options:
-            retnode['linenos'] = True
-        state.document.settings.env.note_dependency(rel_fn)
+            (encoding, arguments[0]))]
+
+    objectname = options.get('pyobject')
+    if objectname is not None:
+        from sphinx.pycode import ModuleAnalyzer
+        analyzer = ModuleAnalyzer.for_file(fn, '')
+        tags = analyzer.find_tags()
+        if objectname not in tags:
+            return [state.document.reporter.warning(
+                'Object named %r not found in include file %r' %
+                (objectname, arguments[0]), line=lineno)]
+        else:
+            lines = lines[tags[objectname][1] - 1 : tags[objectname][2] - 1]
+
+    linespec = options.get('lines')
+    if linespec is not None:
+        try:
+            linelist = parselinenos(linespec, len(lines))
+        except ValueError, err:
+            return [state.document.reporter.warning(str(err), line=lineno)]
+        lines = [lines[i] for i in linelist]
+
+    startafter = options.get('start-after')
+    endbefore = options.get('end-before')
+    if startafter is not None or endbefore is not None:
+        use = not startafter
+        res = []
+        for line in lines:
+            if not use and startafter in line:
+                use = True
+            elif use and endbefore in line:
+                use = False
+                break
+            elif use:
+                res.append(line)
+        lines = res
+
+    text = ''.join(lines)
+    retnode = nodes.literal_block(text, text, source=fn)
+    retnode.line = 1
+    if options.get('language', ''):
+        retnode['language'] = options['language']
+    if 'linenos' in options:
+        retnode['linenos'] = True
+    state.document.settings.env.note_dependency(rel_fn)
     return [retnode]
 
 literalinclude_directive.options = {'linenos': directives.flag,
-                                    'language': directives.unchanged,
-                                    'encoding': directives.encoding}
+                                    'language': directives.unchanged_required,
+                                    'encoding': directives.encoding,
+                                    'pyobject': directives.unchanged_required,
+                                    'lines': directives.unchanged_required,
+                                    'start-after': directives.unchanged_required,
+                                    'end-before': directives.unchanged_required,
+                                    }
 literalinclude_directive.content = 0
 literalinclude_directive.arguments = (1, 0, 0)
 directives.register_directive('literalinclude', literalinclude_directive)

Modified: doctools/trunk/sphinx/directives/desc.py
==============================================================================
--- doctools/trunk/sphinx/directives/desc.py	(original)
+++ doctools/trunk/sphinx/directives/desc.py	Sun Jan  4 21:38:57 2009
@@ -3,8 +3,8 @@
     sphinx.directives.desc
     ~~~~~~~~~~~~~~~~~~~~~~
 
-    :copyright: 2007-2008 by Georg Brandl.
-    :license: BSD.
+    :copyright: Copyright 2007-2009 by the Sphinx team, see AUTHORS.
+    :license: BSD, see LICENSE for details.
 """
 
 import re
@@ -58,6 +58,18 @@
             return _('%s() (%s.%s static method)') % (methname, module, clsname)
         else:
             return _('%s() (%s static method)') % (methname, clsname)
+    elif desctype == 'classmethod':
+        try:
+            clsname, methname = name.rsplit('.', 1)
+        except ValueError:
+            if module:
+                return '%s() (in module %s)' % (name, module)
+            else:
+                return '%s()' % name
+        if module:
+            return '%s() (%s.%s class method)' % (methname, module, clsname)
+        else:
+            return '%s() (%s class method)' % (methname, clsname)
     elif desctype == 'attribute':
         try:
             clsname, attrname = name.rsplit('.', 1)
@@ -118,12 +130,27 @@
 
 del _
 
+
+def _is_only_paragraph(node):
+    # determine if the node only contains one paragraph (and system messages)
+    if len(node) == 0:
+        return False
+    elif len(node) > 1:
+        for subnode in node[1:]:
+            if not isinstance(subnode, nodes.system_message):
+                return False
+    if isinstance(node[0], nodes.paragraph):
+        return True
+    return False
+
+
 def handle_doc_fields(node, env):
     # don't traverse, only handle field lists that are immediate children
     for child in node.children:
         if not isinstance(child, nodes.field_list):
             continue
-        params = None
+        params = []
+        pfield = None
         param_nodes = {}
         param_types = {}
         new_list = nodes.field_list()
@@ -132,18 +159,14 @@
             try:
                 typ, obj = fname.astext().split(None, 1)
                 typdesc = _(doc_fields_with_arg[typ])
-                if len(fbody.children) == 1 and \
-                   isinstance(fbody.children[0], nodes.paragraph):
+                if _is_only_paragraph(fbody):
                     children = fbody.children[0].children
                 else:
                     children = fbody.children
                 if typdesc == '%param':
                     if not params:
+                        # add the field that later gets all the parameters
                         pfield = nodes.field()
-                        pfield += nodes.field_name('', _('Parameters'))
-                        pfield += nodes.field_body()
-                        params = nodes.bullet_list()
-                        pfield[1] += params
                         new_list += pfield
                     dlitem = nodes.list_item()
                     dlpar = nodes.paragraph()
@@ -152,9 +175,13 @@
                     dlpar += children
                     param_nodes[obj] = dlpar
                     dlitem += dlpar
-                    params += dlitem
+                    params.append(dlitem)
                 elif typdesc == '%type':
-                    param_types[obj] = fbody.astext()
+                    typenodes = fbody.children
+                    if _is_only_paragraph(fbody):
+                        typenodes = [nodes.Text(' (')] + \
+                                    typenodes[0].children + [nodes.Text(')')]
+                    param_types[obj] = typenodes
                 else:
                     fieldname = typdesc + ' '
                     nfield = nodes.field()
@@ -181,9 +208,20 @@
                     typ = fnametext.capitalize()
                 fname[0] = nodes.Text(typ)
                 new_list += field
+        if params:
+            if len(params) == 1:
+                pfield += nodes.field_name('', _('Parameter'))
+                pfield += nodes.field_body()
+                pfield[1] += params[0][0]
+            else:
+                pfield += nodes.field_name('', _('Parameters'))
+                pfield += nodes.field_body()
+                pfield[1] += nodes.bullet_list()
+                pfield[1][0].extend(params)
+
         for param, type in param_types.iteritems():
             if param in param_nodes:
-                param_nodes[param].insert(1, nodes.Text(' (%s)' % type))
+                param_nodes[param][1:1] = type
         child.replace_self(new_list)
 
 
@@ -192,8 +230,9 @@
 py_sig_re = re.compile(
     r'''^ ([\w.]*\.)?            # class name(s)
           (\w+)  \s*             # thing name
-          (?: \((.*)\)           # optional arguments
-          (\s* -> \s* .*)? )? $  # optional return annotation
+          (?: \((.*)\)           # optional: arguments
+           (?:\s* -> \s* (.*))?  #           return annotation
+          )? $                   # and nothing more
           ''', re.VERBOSE)
 
 py_paramlist_re = re.compile(r'([\[\],])')  # split at '[', ']' and ','
@@ -212,9 +251,6 @@
         raise ValueError
     classname, name, arglist, retann = m.groups()
 
-    if retann:
-        retann = u' \N{RIGHTWARDS ARROW} ' + retann.strip()[2:]
-
     if env.currclass:
         add_module = False
         if classname and classname.startswith(env.currclass):
@@ -234,6 +270,8 @@
 
     if desctype == 'staticmethod':
         signode += addnodes.desc_annotation('static ', 'static ')
+    elif desctype == 'classmethod':
+        signode += addnodes.desc_annotation('classmethod ', 'classmethod ')
 
     if classname:
         signode += addnodes.desc_addname(classname, classname)
@@ -246,11 +284,11 @@
 
     signode += addnodes.desc_name(name, name)
     if not arglist:
-        if desctype in ('function', 'method', 'staticmethod'):
+        if desctype in ('function', 'method', 'staticmethod', 'classmethod'):
             # for callables, add an empty parameter list
             signode += addnodes.desc_parameterlist()
         if retann:
-            signode += addnodes.desc_type(retann, retann)
+            signode += addnodes.desc_returns(retann, retann)
         return fullname, classname
     signode += addnodes.desc_parameterlist()
 
@@ -273,7 +311,7 @@
     if len(stack) != 1:
         raise ValueError
     if retann:
-        signode += addnodes.desc_type(retann, retann)
+        signode += addnodes.desc_returns(retann, retann)
     return fullname, classname
 
 
@@ -302,7 +340,7 @@
     # add cross-ref nodes for all words
     for part in filter(None, wsplit_re.split(ctype)):
         tnode = nodes.Text(part, part)
-        if part[0] in string.letters+'_' and part not in stopwords:
+        if part[0] in string.ascii_letters+'_' and part not in stopwords:
             pnode = addnodes.pending_xref(
                 '', reftype='ctype', reftarget=part, modname=None, classname=None)
             pnode += tnode
@@ -409,7 +447,8 @@
         node.append(signode)
         try:
             if desctype in ('function', 'data', 'class', 'exception',
-                            'method', 'staticmethod', 'attribute'):
+                            'method', 'staticmethod', 'classmethod',
+                            'attribute'):
                 name, clsname = parse_py_signature(signode, sig, desctype, module, env)
             elif desctype in ('cfunction', 'cmember', 'cmacro', 'ctype', 'cvar'):
                 name = parse_c_signature(signode, sig, desctype)
@@ -486,8 +525,8 @@
     if desctype in ('class', 'exception') and names:
         env.currclass = names[0]
         clsname_set = True
-    elif desctype in ('method', 'staticmethod', 'attribute') and \
-             clsname and not env.currclass:
+    elif desctype in ('method', 'staticmethod', 'classmethod',
+                      'attribute') and clsname and not env.currclass:
         env.currclass = clsname.strip('.')
         clsname_set = True
     # needed for association of version{added,changed} directives
@@ -512,6 +551,7 @@
     'data',
     'class',
     'method',
+    'classmethod',
     'staticmethod',
     'attribute',
     'exception',

Modified: doctools/trunk/sphinx/directives/other.py
==============================================================================
--- doctools/trunk/sphinx/directives/other.py	(original)
+++ doctools/trunk/sphinx/directives/other.py	Sun Jan  4 21:38:57 2009
@@ -3,19 +3,18 @@
     sphinx.directives.other
     ~~~~~~~~~~~~~~~~~~~~~~~
 
-    :copyright: 2007-2008 by Georg Brandl.
-    :license: BSD.
+    :copyright: Copyright 2007-2009 by the Sphinx team, see AUTHORS.
+    :license: BSD, see LICENSE for details.
 """
 
 import re
-import posixpath
 
 from docutils import nodes
 from docutils.parsers.rst import directives
 
 from sphinx import addnodes
 from sphinx.locale import pairindextypes
-from sphinx.util import patfilter, ws_re, caption_ref_re
+from sphinx.util import patfilter, ws_re, caption_ref_re, docname_join
 from sphinx.util.compat import make_admonition
 
 
@@ -25,11 +24,9 @@
                       content_offset, block_text, state, state_machine):
     env = state.document.settings.env
     suffix = env.config.source_suffix
-    dirname = posixpath.dirname(env.docname)
     glob = 'glob' in options
 
     ret = []
-    subnode = addnodes.toctree()
     includefiles = []
     includetitles = {}
     all_docnames = env.found_docs.copy()
@@ -50,14 +47,14 @@
             if docname.endswith(suffix):
                 docname = docname[:-len(suffix)]
             # absolutize filenames
-            docname = posixpath.normpath(posixpath.join(dirname, docname))
+            docname = docname_join(env.docname, docname)
             if docname not in env.found_docs:
                 ret.append(state.document.reporter.warning(
                     'toctree references unknown document %r' % docname, line=lineno))
             else:
                 includefiles.append(docname)
         else:
-            patname = posixpath.normpath(posixpath.join(dirname, entry))
+            patname = docname_join(env.docname, entry)
             docnames = sorted(patfilter(all_docnames, patname))
             for docname in docnames:
                 all_docnames.remove(docname) # don't include it again
@@ -66,15 +63,18 @@
                 ret.append(state.document.reporter.warning(
                     'toctree glob pattern %r didn\'t match any documents' % entry,
                     line=lineno))
+    subnode = addnodes.toctree()
     subnode['includefiles'] = includefiles
     subnode['includetitles'] = includetitles
     subnode['maxdepth'] = options.get('maxdepth', -1)
     subnode['glob'] = glob
+    subnode['hidden'] = 'hidden' in options
     ret.append(subnode)
     return ret
 
 toctree_directive.content = 1
-toctree_directive.options = {'maxdepth': int, 'glob': directives.flag}
+toctree_directive.options = {'maxdepth': int, 'glob': directives.flag,
+                             'hidden': directives.flag}
 directives.register_directive('toctree', toctree_directive)
 
 

Modified: doctools/trunk/sphinx/environment.py
==============================================================================
--- doctools/trunk/sphinx/environment.py	(original)
+++ doctools/trunk/sphinx/environment.py	Sun Jan  4 21:38:57 2009
@@ -5,8 +5,8 @@
 
     Global creation environment.
 
-    :copyright: 2007-2008 by Georg Brandl.
-    :license: BSD.
+    :copyright: Copyright 2007-2009 by the Sphinx team, see AUTHORS.
+    :license: BSD, see LICENSE for details.
 """
 
 import re
@@ -15,11 +15,12 @@
 import heapq
 import types
 import imghdr
+import string
 import difflib
 import cPickle as pickle
 from os import path
 from glob import glob
-from string import uppercase
+from string import ascii_uppercase as uppercase
 from itertools import izip, groupby
 try:
     import hashlib
@@ -42,7 +43,8 @@
 from docutils.transforms.parts import ContentsFilter
 
 from sphinx import addnodes
-from sphinx.util import get_matching_docs, SEP, ustrftime
+from sphinx.util import get_matching_docs, SEP, ustrftime, docname_join, \
+     FilenameUniqDict
 from sphinx.directives import additional_xref_types
 
 default_settings = {
@@ -57,7 +59,7 @@
 
 # This is increased every time an environment attribute is added
 # or changed to properly invalidate pickle files.
-ENV_VERSION = 26
+ENV_VERSION = 27
 
 
 default_substitutions = set([
@@ -203,7 +205,9 @@
         self.set_warnfunc(None)
         values = self.config.values
         del self.config.values
-        picklefile = open(filename, 'wb')
+        # first write to a temporary file, so that if dumping fails, the existing
+        # environment won't be overwritten
+        picklefile = open(filename + '.tmp', 'wb')
         # remove potentially pickling-problematic values from config
         for key, val in vars(self.config).items():
             if key.startswith('_') or \
@@ -215,6 +219,7 @@
             pickle.dump(self, picklefile, pickle.HIGHEST_PROTOCOL)
         finally:
             picklefile.close()
+        os.rename(filename + '.tmp', filename)
         # reset attributes
         self.config.values = values
         self.set_warnfunc(warnfunc)
@@ -276,7 +281,8 @@
                                     # (type, string, target, aliasname)
         self.versionchanges = {}    # version -> list of
                                     # (type, docname, lineno, module, descname, content)
-        self.images = {}            # absolute path -> (docnames, unique filename)
+        self.images = FilenameUniqDict()  # absolute path -> (docnames, unique filename)
+        self.dlfiles = FilenameUniqDict() # absolute path -> (docnames, unique filename)
 
         # These are set while parsing a file
         self.docname = None         # current document name
@@ -288,9 +294,12 @@
         self.gloss_entries = set()  # existing definition labels
 
         # Some magically present labels
-        self.labels['genindex'] = ('genindex', '', _('Index'))
-        self.labels['modindex'] = ('modindex', '', _('Module Index'))
-        self.labels['search']   = ('search', '', _('Search Page'))
+        def add_magic_label(name, description):
+            self.labels[name] = (name, '', description)
+            self.anonlabels[name] = (name, '')
+        add_magic_label('genindex', _('Index'))
+        add_magic_label('modindex', _('Module Index'))
+        add_magic_label('search', _('Search Page'))
 
     def set_warnfunc(self, func):
         self._warnfunc = func
@@ -317,6 +326,8 @@
             self.filemodules.pop(docname, None)
             self.indexentries.pop(docname, None)
             self.glob_toctrees.discard(docname)
+            self.images.purge_doc(docname)
+            self.dlfiles.purge_doc(docname)
 
             for subfn, fnset in self.files_to_rebuild.items():
                 fnset.discard(docname)
@@ -340,10 +351,6 @@
             for version, changes in self.versionchanges.items():
                 new = [change for change in changes if change[1] != docname]
                 changes[:] = new
-            for fullpath, (docs, _) in self.images.items():
-                docs.discard(docname)
-                if not docs:
-                    del self.images[fullpath]
 
     def doc2path(self, docname, base=True, suffix=None):
         """
@@ -480,12 +487,6 @@
                       self.doc2path(config.master_doc))
 
         self.app = None
-
-        # remove all non-existing images from inventory
-        for imgsrc in self.images.keys():
-            if not os.access(path.join(self.srcdir, imgsrc), os.R_OK):
-                del self.images[imgsrc]
-
         if app:
             app.emit('env-updated', self)
 
@@ -544,6 +545,7 @@
         self.filter_messages(doctree)
         self.process_dependencies(docname, doctree)
         self.process_images(docname, doctree)
+        self.process_downloads(docname, doctree)
         self.process_metadata(docname, doctree)
         self.create_title_from(docname, doctree)
         self.note_labels_from(docname, doctree)
@@ -608,11 +610,25 @@
             dep = path.join(docdir, dep)
             self.dependencies.setdefault(docname, set()).add(dep)
 
+    def process_downloads(self, docname, doctree):
+        """
+        Process downloadable file paths.
+        """
+        docdir = path.dirname(self.doc2path(docname, base=None))
+        for node in doctree.traverse(addnodes.download_reference):
+            filepath = path.normpath(path.join(docdir, node['reftarget']))
+            self.dependencies.setdefault(docname, set()).add(filepath)
+            if not os.access(path.join(self.srcdir, filepath), os.R_OK):
+                self.warn(docname, 'Download file not readable: %s' % filepath,
+                          getattr(node, 'line', None))
+                continue
+            uniquename = self.dlfiles.add_file(docname, filepath)
+            node['filename'] = uniquename
+
     def process_images(self, docname, doctree):
         """
         Process and rewrite image URIs.
         """
-        existing_names = set(v[1] for v in self.images.itervalues())
         docdir = path.dirname(self.doc2path(docname, base=None))
         for node in doctree.traverse(nodes.image):
             # Map the mimetype to the corresponding image.  The writer may
@@ -625,15 +641,17 @@
                 self.warn(docname, 'Nonlocal image URI found: %s' % imguri, node.line)
                 candidates['?'] = imguri
                 continue
+            # imgpath is the image path *from srcdir*
             imgpath = path.normpath(path.join(docdir, imguri))
+            # set imgpath as default URI
             node['uri'] = imgpath
             if imgpath.endswith(os.extsep + '*'):
                 for filename in glob(path.join(self.srcdir, imgpath)):
-                    relname = relative_path(self.srcdir, filename)
+                    new_imgpath = relative_path(self.srcdir, filename)
                     if filename.lower().endswith('.pdf'):
-                        candidates['application/pdf'] = path.join(docdir, relname)
+                        candidates['application/pdf'] = new_imgpath
                     elif filename.lower().endswith('.svg'):
-                        candidates['image/svg+xml'] = path.join(docdir, relname)
+                        candidates['image/svg+xml'] = new_imgpath
                     else:
                         try:
                             f = open(filename, 'rb')
@@ -644,25 +662,18 @@
                         except (OSError, IOError):
                             self.warn(docname, 'Image file %s not readable' % filename)
                         if imgtype:
-                            candidates['image/' + imgtype] = path.join(docdir, relname)
+                            candidates['image/' + imgtype] = new_imgpath
             else:
                 candidates['*'] = imgpath
+            # map image paths to unique image names (so that they can be put
+            # into a single directory)
             for imgpath in candidates.itervalues():
                 self.dependencies.setdefault(docname, set()).add(imgpath)
                 if not os.access(path.join(self.srcdir, imgpath), os.R_OK):
                     self.warn(docname, 'Image file not readable: %s' % imgpath,
                               node.line)
-                if imgpath in self.images:
-                    self.images[imgpath][0].add(docname)
                     continue
-                uniquename = path.basename(imgpath)
-                base, ext = path.splitext(uniquename)
-                i = 0
-                while uniquename in existing_names:
-                    i += 1
-                    uniquename = '%s%s%s' % (base, i, ext)
-                self.images[imgpath] = (set([docname]), uniquename)
-                existing_names.add(uniquename)
+                self.images.add_file(docname, imgpath)
 
     def process_metadata(self, docname, doctree):
         """
@@ -898,6 +909,8 @@
         If *titles_only* is True, only toplevel document titles will be in the
         resulting tree.
         """
+        if toctree.get('hidden', False):
+            return None
 
         def _walk_depth(node, depth, maxdepth, titleoverrides):
             """Utility: Cut a TOC at a specified depth."""
@@ -911,7 +924,7 @@
                     else:
                         _walk_depth(subnode, depth+1, maxdepth, titleoverrides)
 
-        def _entries_from_toctree(toctreenode, separate=False):
+        def _entries_from_toctree(toctreenode, separate=False, subtree=False):
             """Return TOC entries for a toctree node."""
             includefiles = map(str, toctreenode['includefiles'])
 
@@ -941,7 +954,7 @@
                     # resolve all sub-toctrees
                     for toctreenode in toc.traverse(addnodes.toctree):
                         i = toctreenode.parent.index(toctreenode) + 1
-                        for item in _entries_from_toctree(toctreenode):
+                        for item in _entries_from_toctree(toctreenode, subtree=True):
                             toctreenode.parent.insert(i, item)
                             i += 1
                         toctreenode.parent.remove(toctreenode)
@@ -949,12 +962,19 @@
                         entries.append(toc)
                     else:
                         entries.extend(toc.children)
+            if not subtree and not separate:
+                ret = nodes.bullet_list()
+                ret += entries
+                return [ret]
             return entries
 
         maxdepth = maxdepth or toctree.get('maxdepth', -1)
         titleoverrides = toctree.get('includetitles', {})
 
-        tocentries = _entries_from_toctree(toctree, separate=True)
+        # NOTE: previously, this was separate=True, but that leads to artificial
+        # separation when two or more toctree entries form a logical unit, so
+        # separating mode is no longer used -- it's kept here for history's sake
+        tocentries = _entries_from_toctree(toctree, separate=False)
         if not tocentries:
             return None
 
@@ -1023,6 +1043,24 @@
                             if labelid:
                                 newnode['refuri'] += '#' + labelid
                         newnode.append(innernode)
+                elif typ == 'doc':
+                    # directly reference to document by source name; can be absolute
+                    # or relative
+                    docname = docname_join(fromdocname, target)
+                    if docname not in self.all_docs:
+                        newnode = doctree.reporter.system_message(
+                            2, 'unknown document: %s' % docname)
+                    else:
+                        if node['refcaption']:
+                            # reference with explicit title
+                            caption = node.astext()
+                        else:
+                            caption = self.titles[docname].astext()
+                        innernode = nodes.emphasis(caption, caption)
+                        newnode = nodes.reference('', '')
+                        newnode['refuri'] = builder.get_relative_uri(
+                            fromdocname, docname)
+                        newnode.append(innernode)
                 elif typ == 'keyword':
                     # keywords are referenced by named labels
                     docname, labelid, _ = self.labels.get(target, ('','',''))

Modified: doctools/trunk/sphinx/ext/__init__.py
==============================================================================
--- doctools/trunk/sphinx/ext/__init__.py	(original)
+++ doctools/trunk/sphinx/ext/__init__.py	Sun Jan  4 21:38:57 2009
@@ -5,6 +5,6 @@
 
     Contains Sphinx features not activated by default.
 
-    :copyright: 2008 by Georg Brandl.
-    :license: BSD.
+    :copyright: Copyright 2007-2009 by the Sphinx team, see AUTHORS.
+    :license: BSD, see LICENSE for details.
 """

Modified: doctools/trunk/sphinx/ext/autodoc.py
==============================================================================
--- doctools/trunk/sphinx/ext/autodoc.py	(original)
+++ doctools/trunk/sphinx/ext/autodoc.py	Sun Jan  4 21:38:57 2009
@@ -7,46 +7,57 @@
     the doctree, thus avoiding duplication between docstrings and documentation
     for those who like elaborate docstrings.
 
-    :copyright: 2008 by Georg Brandl, Pauli Virtanen, Martin Hans.
-    :license: BSD.
+    :copyright: Copyright 2007-2009 by the Sphinx team, see AUTHORS.
+    :license: BSD, see LICENSE for details.
 """
 
 import re
 import sys
-import types
 import inspect
 import linecache
-from types import FunctionType, BuiltinMethodType, MethodType
+from types import FunctionType, BuiltinFunctionType, MethodType, ClassType
 
 from docutils import nodes
 from docutils.parsers.rst import directives
 from docutils.statemachine import ViewList
 
-from sphinx.util import rpartition, nested_parse_with_titles
-from sphinx.directives.desc import py_sig_re
+from sphinx.util import rpartition, nested_parse_with_titles, force_decode
+from sphinx.pycode import ModuleAnalyzer, PycodeError
+from sphinx.util.docstrings import prepare_docstring
 
+clstypes = (type, ClassType)
 try:
     base_exception = BaseException
 except NameError:
     base_exception = Exception
 
-_charset_re = re.compile(r'coding[:=]\s*([-\w.]+)')
-_module_charsets = {}
+
+py_ext_sig_re = re.compile(
+    r'''^ ([\w.]+::)?            # explicit module name
+          ([\w.]+\.)?            # module and/or class name(s)
+          (\w+)  \s*             # thing name
+          (?: \((.*)\)           # optional: arguments
+           (?:\s* -> \s* (.*))?  #           return annotation
+          )? $                   # and nothing more
+          ''', re.VERBOSE)
 
 
 class Options(object):
     pass
 
 
-def is_static_method(obj):
-    """Check if the object given is a static method."""
-    if isinstance(obj, (FunctionType, classmethod)):
-        return True
-    elif isinstance(obj, BuiltinMethodType):
-        return obj.__self__ is not None
-    elif isinstance(obj, MethodType):
-        return obj.im_self is not None
-    return False
+def get_method_type(obj):
+    """
+    Return the method type for an object: method, staticmethod or classmethod.
+    """
+    if isinstance(obj, classmethod) or \
+           (isinstance(obj, MethodType) and obj.im_self is not None):
+        return 'classmethod'
+    elif isinstance(obj, FunctionType) or \
+             (isinstance(obj, BuiltinFunctionType) and obj.__self__ is not None):
+        return 'staticmethod'
+    else:
+        return 'method'
 
 
 class AutodocReporter(object):
@@ -160,56 +171,6 @@
     return False
 
 
-def prepare_docstring(s):
-    """
-    Convert a docstring into lines of parseable reST.  Return it as a list of
-    lines usable for inserting into a docutils ViewList (used as argument
-    of nested_parse().)  An empty line is added to act as a separator between
-    this docstring and following content.
-    """
-    lines = s.expandtabs().splitlines()
-    # Find minimum indentation of any non-blank lines after first line.
-    margin = sys.maxint
-    for line in lines[1:]:
-        content = len(line.lstrip())
-        if content:
-            indent = len(line) - content
-            margin = min(margin, indent)
-    # Remove indentation.
-    if lines:
-        lines[0] = lines[0].lstrip()
-    if margin < sys.maxint:
-        for i in range(1, len(lines)): lines[i] = lines[i][margin:]
-    # Remove any leading blank lines.
-    while lines and not lines[0]:
-        lines.pop(0)
-    # make sure there is an empty line at the end
-    if lines and lines[-1]:
-        lines.append('')
-    return lines
-
-
-def get_module_charset(module):
-    """Return the charset of the given module (cached in _module_charsets)."""
-    if module in _module_charsets:
-        return _module_charsets[module]
-    try:
-        filename = __import__(module, None, None, ['foo']).__file__
-    except (ImportError, AttributeError):
-        return None
-    if filename[-4:].lower() in ('.pyc', '.pyo'):
-        filename = filename[:-1]
-    for line in [linecache.getline(filename, x) for x in (1, 2)]:
-        match = _charset_re.search(line)
-        if match is not None:
-            charset = match.group(1)
-            break
-    else:
-        charset = 'ascii'
-    _module_charsets[module] = charset
-    return charset
-
-
 class RstGenerator(object):
     def __init__(self, options, document, lineno):
         self.options = options
@@ -223,15 +184,19 @@
     def warn(self, msg):
         self.warnings.append(self.reporter.warning(msg, line=self.lineno))
 
-    def get_doc(self, what, name, obj):
-        """Format and yield lines of the docstring(s) for the object."""
+    def get_doc(self, what, obj, encoding=None):
+        """Decode and return lines of the docstring(s) for the object."""
         docstrings = []
+
+        # add the regular docstring if present
         if getattr(obj, '__doc__', None):
             docstrings.append(obj.__doc__)
-        # skip some lines in module docstrings if configured
+
+        # skip some lines in module docstrings if configured (deprecated!)
         if what == 'module' and self.env.config.automodule_skip_lines and docstrings:
             docstrings[0] = '\n'.join(docstrings[0].splitlines()
                                       [self.env.config.automodule_skip_lines:])
+
         # for classes, what the "docstring" is can be controlled via an option
         if what in ('class', 'exception'):
             content = self.env.config.autoclass_content
@@ -244,27 +209,16 @@
                     if content == 'init':
                         docstrings = [initdocstring]
                     else:
-                        docstrings.append('\n\n' + initdocstring)
+                        docstrings.append(initdocstring)
             # the default is only the class docstring
 
-        # decode the docstrings using the module's source encoding
-        charset = None
-        module = getattr(obj, '__module__', None)
-        if module is not None:
-            charset = get_module_charset(module)
-
-        for docstring in docstrings:
-            if isinstance(docstring, str):
-                if charset:
-                    docstring = docstring.decode(charset)
-                else:
-                    try:
-                        # try decoding with utf-8, should only work for real UTF-8
-                        docstring = docstring.decode('utf-8')
-                    except UnicodeError:
-                        # last resort -- can't fail
-                        docstring = docstring.decode('latin1')
-            docstringlines = prepare_docstring(docstring)
+        # make sure we have Unicode docstrings, then sanitize and split into lines
+        return [prepare_docstring(force_decode(docstring, encoding))
+                for docstring in docstrings]
+
+    def process_doc(self, docstrings, what, name, obj):
+        """Let the user process the docstrings."""
+        for docstringlines in docstrings:
             if self.env.app:
                 # let extensions preprocess docstrings
                 self.env.app.emit('autodoc-process-docstring',
@@ -282,58 +236,71 @@
         # first, parse the definition -- auto directives for classes and functions
         # can contain a signature which is then used instead of an autogenerated one
         try:
-            path, base, args, retann = py_sig_re.match(name).groups()
+            mod, path, base, args, retann = py_ext_sig_re.match(name).groups()
         except:
             self.warn('invalid signature for auto%s (%r)' % (what, name))
-            return
-        # fullname is the fully qualified name, base the name after the last dot
-        fullname = (path or '') + base
+            return None, [], None, None
+
+        # support explicit module and class name separation via ::
+        if mod is not None:
+            mod = mod[:-2]
+            parents = path and path.rstrip('.').split('.') or []
+        else:
+            parents = []
 
         if what == 'module':
+            if mod is not None:
+                self.warn('"::" in automodule name doesn\'t make sense')
             if args or retann:
                 self.warn('ignoring signature arguments and return annotation '
-                          'for automodule %s' % fullname)
-            return fullname, fullname, [], None, None
+                          'for automodule %s' % name)
+            return (path or '') + base, [], None, None
 
-        elif what in ('class', 'exception', 'function'):
-            if path:
-                mod = path.rstrip('.')
-            else:
-                mod = None
-                # if documenting a toplevel object without explicit module, it can
-                # be contained in another auto directive ...
-                if hasattr(self.env, 'autodoc_current_module'):
+        elif what in ('exception', 'function', 'class', 'data'):
+            if mod is None:
+                if path:
+                    mod = path.rstrip('.')
+                else:
+                    # if documenting a toplevel object without explicit module, it can
+                    # be contained in another auto directive ...
+                    if hasattr(self.env, 'autodoc_current_module'):
+                        mod = self.env.autodoc_current_module
+                    # ... or in the scope of a module directive
+                    if not mod:
+                        mod = self.env.currmodule
+            return mod, parents + [base], args, retann
+
+        else:
+            if mod is None:
+                if path:
+                    mod_cls = path.rstrip('.')
+                else:
+                    mod_cls = None
+                    # if documenting a class-level object without path, there must be a
+                    # current class, either from a parent auto directive ...
+                    if hasattr(self.env, 'autodoc_current_class'):
+                        mod_cls = self.env.autodoc_current_class
+                    # ... or from a class directive
+                    if mod_cls is None:
+                        mod_cls = self.env.currclass
+                    # ... if still None, there's no way to know
+                    if mod_cls is None:
+                        return None, [], None, None
+                mod, cls = rpartition(mod_cls, '.')
+                parents = [cls]
+                # if the module name is still missing, get it like above
+                if not mod and hasattr(self.env, 'autodoc_current_module'):
                     mod = self.env.autodoc_current_module
-                # ... or in the scope of a module directive
                 if not mod:
                     mod = self.env.currmodule
-            return fullname, mod, [base], args, retann
-
-        else:
-            if path:
-                mod_cls = path.rstrip('.')
-            else:
-                mod_cls = None
-                # if documenting a class-level object without path, there must be a
-                # current class, either from a parent auto directive ...
-                if hasattr(self.env, 'autodoc_current_class'):
-                    mod_cls = self.env.autodoc_current_class
-                # ... or from a class directive
-                if mod_cls is None:
-                    mod_cls = self.env.currclass
-            mod, cls = rpartition(mod_cls, '.')
-            # if the module name is still missing, get it like above
-            if not mod and hasattr(self.env, 'autodoc_current_module'):
-                mod = self.env.autodoc_current_module
-            if not mod:
-                mod = self.env.currmodule
-            return fullname, mod, [cls, base], args, retann
+            return mod, parents + [base], args, retann
 
     def format_signature(self, what, name, obj, args, retann):
         """
         Return the signature of the object, formatted for display.
         """
-        if what not in ('class', 'method', 'function'):
+        if what not in ('class', 'method', 'staticmethod', 'classmethod',
+                        'function'):
             return ''
 
         err = None
@@ -358,7 +325,8 @@
                     getargs = False
                 if getargs:
                     argspec = inspect.getargspec(obj)
-                    if what in ('class', 'method') and argspec[0] and \
+                    if what in ('class', 'method', 'staticmethod',
+                                'classmethod') and argspec[0] and \
                            argspec[0][0] in ('cls', 'self'):
                         del argspec[0][0]
                     args = inspect.formatargspec(*argspec)
@@ -372,38 +340,35 @@
             args, retann = result
 
         if args is not None:
-            return '%s%s' % (args, retann or '')
+            return '%s%s' % (args, retann and (' -> %s' % retann) or '')
         elif err:
             # re-raise the error for perusal of the handler in generate()
             raise RuntimeError(err)
         else:
             return ''
 
-    def generate(self, what, name, members, add_content, indent=u'', check_module=False):
+    def generate(self, what, name, members, add_content, indent=u'', check_module=False,
+                 no_docstring=False):
         """
         Generate reST for the object in self.result.
         """
-        fullname, mod, objpath, args, retann = self.resolve_name(what, name)
+        mod, objpath, args, retann = self.resolve_name(what, name)
         if not mod:
             # need a module to import
             self.warn('don\'t know which module to import for autodocumenting %r '
                       '(try placing a "module" or "currentmodule" directive in the '
-                      'document, or giving an explicit module name)' % fullname)
+                      'document, or giving an explicit module name)' % name)
             return
+        # fully-qualified name
+        fullname = mod + (objpath and '.' + '.'.join(objpath) or '')
 
         # the name to put into the generated directive -- doesn't contain the module
         name_in_directive = '.'.join(objpath) or mod
 
         # now, import the module and get object to document
         try:
-            todoc = module = __import__(mod, None, None, ['foo'])
-            if hasattr(module, '__file__') and module.__file__:
-                modfile = module.__file__
-                if modfile[-4:].lower() in ('.pyc', '.pyo'):
-                    modfile = modfile[:-1]
-                self.filename_set.add(modfile)
-            else:
-                modfile = None  # e.g. for builtin and C modules
+            __import__(mod)
+            todoc = module = sys.modules[mod]
             for part in objpath:
                 todoc = getattr(todoc, part)
         except (ImportError, AttributeError), err:
@@ -412,28 +377,39 @@
                       (what, str(fullname), err))
             return
 
+        # try to also get a source code analyzer for attribute docs
+        try:
+            analyzer = ModuleAnalyzer.for_module(mod)
+        except PycodeError, err:
+            # no source file -- e.g. for builtin and C modules
+            analyzer = None
+        else:
+            self.filename_set.add(analyzer.srcname)
+
         # check __module__ of object if wanted (for members not given explicitly)
         if check_module:
             if hasattr(todoc, '__module__'):
                 if todoc.__module__ != mod:
                     return
 
+        # make sure that the result starts with an empty line.  This is
+        # necessary for some situations where another directive preprocesses
+        # reST and no starting newline is present
+        self.result.append(u'', '')
+
         # format the object's signature, if any
         try:
-            sig = self.format_signature(what, name, todoc, args, retann)
+            sig = self.format_signature(what, fullname, todoc, args, retann)
         except Exception, err:
             self.warn('error while formatting signature for %s: %s' %
                       (fullname, err))
             sig = ''
 
-        # make sure that the result starts with an empty line.  This is
-        # necessary for some situations where another directive preprocesses
-        # reST and no starting newline is present
-        self.result.append(u'', '')
-
         # now, create the directive header
-        directive = (what == 'method' and is_static_method(todoc)) \
-                    and 'staticmethod' or what
+        if what == 'method':
+            directive = get_method_type(todoc)
+        else:
+            directive = what
         self.result.append(indent + u'.. %s:: %s%s' %
                            (directive, name_in_directive, sig), '<autodoc>')
         if what == 'module':
@@ -454,13 +430,14 @@
             self.result.append(indent + u'   :noindex:', '<autodoc>')
         self.result.append(u'', '<autodoc>')
 
+        # add inheritance info, if wanted
         if self.options.show_inheritance and what in ('class', 'exception'):
             if len(todoc.__bases__):
                 bases = [b.__module__ == '__builtin__' and
                          u':class:`%s`' % b.__name__ or
                          u':class:`%s.%s`' % (b.__module__, b.__name__)
                          for b in todoc.__bases__]
-                self.result.append(indent + u'   Bases: %s' % ', '.join(bases),
+                self.result.append(indent + _(u'   Bases: %s') % ', '.join(bases),
                                    '<autodoc>')
                 self.result.append(u'', '<autodoc>')
 
@@ -468,22 +445,38 @@
         if what != 'module':
             indent += u'   '
 
-        if modfile:
-            sourcename = '%s:docstring of %s' % (modfile, fullname)
+        # add content from attribute documentation
+        if analyzer:
+            sourcename = '%s:docstring of %s' % (analyzer.srcname, fullname)
+            attr_docs = analyzer.find_attr_docs()
+            if what in ('data', 'attribute'):
+                key = ('.'.join(objpath[:-1]), objpath[-1])
+                if key in attr_docs:
+                    no_docstring = True
+                    docstrings = [attr_docs[key]]
+                    for i, line in enumerate(self.process_doc(docstrings, what,
+                                                              fullname, todoc)):
+                        self.result.append(indent + line, sourcename, i)
         else:
             sourcename = 'docstring of %s' % fullname
+            attr_docs = {}
 
         # add content from docstrings
-        for i, line in enumerate(self.get_doc(what, fullname, todoc)):
-            self.result.append(indent + line, sourcename, i)
+        if not no_docstring:
+            encoding = analyzer and analyzer.encoding
+            docstrings = self.get_doc(what, todoc, encoding)
+            for i, line in enumerate(self.process_doc(docstrings, what,
+                                                      fullname, todoc)):
+                self.result.append(indent + line, sourcename, i)
 
-        # add source content, if present
+        # add additional content (e.g. from document), if present
         if add_content:
             for line, src in zip(add_content.data, add_content.items):
                 self.result.append(indent + line, src[0], src[1])
 
         # document members?
-        if not members or what in ('function', 'method', 'attribute'):
+        if not members or what in ('function', 'method', 'staticmethod',
+                                   'classmethod', 'data', 'attribute'):
             return
 
         # set current namespace for finding members
@@ -491,10 +484,10 @@
         if objpath:
             self.env.autodoc_current_class = objpath[0]
 
-        # add members, if possible
-        _all = members == ['__all__']
+        # look for members to include
+        want_all_members = members == ['__all__']
         members_check_module = False
-        if _all:
+        if want_all_members:
             # unqualified :members: given
             if what == 'module':
                 if hasattr(todoc, '__all__'):
@@ -522,14 +515,29 @@
                     all_members = sorted(todoc.__dict__.iteritems())
         else:
             all_members = [(mname, getattr(todoc, mname)) for mname in members]
+
+        # search for members in source code too
+        namespace = '.'.join(objpath)  # will be empty for modules
+
         for (membername, member) in all_members:
-            # ignore members whose name starts with _ by default
-            if _all and membername.startswith('_'):
-                continue
+            # if isattr is True, the member is documented as an attribute
+            isattr = False
+            # if content is not None, no extra content from docstrings will be added
+            content = None
+
+            if want_all_members and membername.startswith('_'):
+                # ignore members whose name starts with _ by default
+                skip = True
+            else:
+                if (namespace, membername) in attr_docs:
+                    # keep documented attributes
+                    skip = False
+                    isattr = True
+                else:
+                    # ignore undocumented members if :undoc-members: is not given
+                    doc = getattr(member, '__doc__', None)
+                    skip = not self.options.undoc_members and not doc
 
-            # ignore undocumented members if :undoc-members: is not given
-            doc = getattr(member, '__doc__', None)
-            skip = not self.options.undoc_members and not doc
             # give the user a chance to decide whether this member should be skipped
             if self.env.app:
                 # let extensions preprocess docstrings
@@ -540,30 +548,48 @@
             if skip:
                 continue
 
+            # determine member type
             if what == 'module':
-                if isinstance(member, (types.FunctionType,
-                                       types.BuiltinFunctionType)):
+                if isinstance(member, (FunctionType, BuiltinFunctionType)):
                     memberwhat = 'function'
-                elif isinstance(member, types.ClassType) or \
-                     isinstance(member, type):
-                    if issubclass(member, base_exception):
+                elif isattr:
+                    memberwhat = 'attribute'
+                elif isinstance(member, clstypes):
+                    if member.__name__ != membername:
+                        # assume it's aliased
+                        memberwhat = 'data'
+                        content = ViewList([_('alias of :class:`%s`') % member.__name__],
+                                           source='')
+                    elif issubclass(member, base_exception):
                         memberwhat = 'exception'
                     else:
                         memberwhat = 'class'
                 else:
-                    # XXX: todo -- attribute docs
                     continue
             else:
-                if callable(member):
+                if inspect.isroutine(member):
                     memberwhat = 'method'
+                elif isattr:
+                    memberwhat = 'attribute'
+                elif isinstance(member, clstypes):
+                    if member.__name__ != membername:
+                        # assume it's aliased
+                        memberwhat = 'attribute'
+                        content = ViewList([_('alias of :class:`%s`') % member.__name__],
+                                           source='')
+                    else:
+                        memberwhat = 'class'
                 elif isdescriptor(member):
                     memberwhat = 'attribute'
                 else:
-                    # XXX: todo -- attribute docs
                     continue
-            full_membername = fullname + '.' + membername
-            self.generate(memberwhat, full_membername, ['__all__'], None, indent,
-                          check_module=members_check_module)
+
+            # give explicitly separated module name, so that members of inner classes
+            # can be documented
+            full_membername = mod + '::' + '.'.join(objpath + [membername])
+            self.generate(memberwhat, full_membername, ['__all__'],
+                          add_content=content, no_docstring=bool(content),
+                          indent=indent, check_module=members_check_module)
 
         self.env.autodoc_current_module = None
         self.env.autodoc_current_class = None
@@ -638,6 +664,8 @@
                       1, (1, 0, 1), **cls_options)
     app.add_directive('autoexception', autoclass_directive,
                       1, (1, 0, 1), **cls_options)
+    app.add_directive('autodata', auto_directive, 1, (1, 0, 1),
+                      noindex=directives.flag)
     app.add_directive('autofunction', auto_directive, 1, (1, 0, 1),
                       noindex=directives.flag)
     app.add_directive('automethod', auto_directive, 1, (1, 0, 1),

Modified: doctools/trunk/sphinx/ext/coverage.py
==============================================================================
--- doctools/trunk/sphinx/ext/coverage.py	(original)
+++ doctools/trunk/sphinx/ext/coverage.py	Sun Jan  4 21:38:57 2009
@@ -6,8 +6,8 @@
     Check Python modules and C API for coverage.  Mostly written by Josip
     Dzolonga for the Google Highly Open Participation contest.
 
-    :copyright: 2008 by Josip Dzolonga, Georg Brandl.
-    :license: BSD.
+    :copyright: Copyright 2007-2009 by the Sphinx team, see AUTHORS.
+    :license: BSD, see LICENSE for details.
 """
 
 import re
@@ -16,7 +16,7 @@
 import cPickle as pickle
 from os import path
 
-from sphinx.builder import Builder
+from sphinx.builders import Builder
 
 
 # utility

Modified: doctools/trunk/sphinx/ext/doctest.py
==============================================================================
--- doctools/trunk/sphinx/ext/doctest.py	(original)
+++ doctools/trunk/sphinx/ext/doctest.py	Sun Jan  4 21:38:57 2009
@@ -6,13 +6,14 @@
     Mimic doctest by automatically executing code snippets and checking
     their results.
 
-    :copyright: 2008 by Georg Brandl.
-    :license: BSD.
+    :copyright: Copyright 2007-2009 by the Sphinx team, see AUTHORS.
+    :license: BSD, see LICENSE for details.
 """
 
 import re
 import sys
 import time
+import codecs
 import StringIO
 from os import path
 # circumvent relative import
@@ -21,7 +22,7 @@
 from docutils import nodes
 from docutils.parsers.rst import directives
 
-from sphinx.builder import Builder
+from sphinx.builders import Builder
 from sphinx.util.console import bold
 
 blankline_re = re.compile(r'^\s*<BLANKLINE>', re.MULTILINE)
@@ -98,9 +99,12 @@
         self.setup = []
         self.tests = []
 
-    def add_code(self, code):
+    def add_code(self, code, prepend=False):
         if code.type == 'testsetup':
-            self.setup.append(code)
+            if prepend:
+                self.setup.insert(0, code)
+            else:
+                self.setup.append(code)
         elif code.type == 'doctest':
             self.tests.append([code])
         elif code.type == 'testcode':
@@ -169,7 +173,8 @@
 
         date = time.strftime('%Y-%m-%d %H:%M:%S')
 
-        self.outfile = file(path.join(self.outdir, 'output.txt'), 'w')
+        self.outfile = codecs.open(path.join(self.outdir, 'output.txt'),
+                                   'w', encoding='utf-8')
         self.outfile.write('''\
 Results of doctest builder run on %s
 ==================================%s
@@ -179,6 +184,12 @@
         self.info(text, nonl=True)
         self.outfile.write(text)
 
+    def _warn_out(self, text):
+        self.info(text, nonl=True)
+        if self.app.quiet:
+            self.warn(text)
+        self.outfile.write(text)
+
     def get_target_uri(self, docname, typ=None):
         return ''
 
@@ -200,6 +211,9 @@
        self.setup_failures, s(self.setup_failures)))
         self.outfile.close()
 
+        if self.total_failures or self.setup_failures:
+            self.app.statuscode = 1
+
         sys.path[0:0] = self.config.doctest_path
 
     def write(self, build_docnames, updated_docnames, method='update'):
@@ -229,8 +243,12 @@
                 return isinstance(node, (nodes.literal_block, nodes.comment)) \
                         and node.has_key('testnodetype')
         for node in doctree.traverse(condition):
-            code = TestCode(node.has_key('test') and node['test'] or node.astext(),
-                            type=node.get('testnodetype', 'doctest'),
+            source = node.has_key('test') and node['test'] or node.astext()
+            if not source:
+                self.warn('no code/output in %s block at %s:%s' %
+                          (node.get('testnodetype', 'doctest'),
+                           self.env.doc2path(docname), node.line))
+            code = TestCode(source, type=node.get('testnodetype', 'doctest'),
                             lineno=node.line, options=node.get('options'))
             node_groups = node.get('groups', ['default'])
             if '*' in node_groups:
@@ -243,6 +261,10 @@
         for code in add_to_all_groups:
             for group in groups.itervalues():
                 group.add_code(code)
+        if self.config.doctest_global_setup:
+            code = TestCode(self.config.doctest_global_setup, 'testsetup', lineno=0)
+            for group in groups.itervalues():
+                group.add_code(code, prepend=True)
         if not groups:
             return
 
@@ -274,7 +296,7 @@
             setup_doctest.globs = ns
             old_f = self.setup_runner.failures
             self.type = 'exec' # the snippet may contain multiple statements
-            self.setup_runner.run(setup_doctest, out=self._out,
+            self.setup_runner.run(setup_doctest, out=self._warn_out,
                                   clear_globs=False)
             if self.setup_runner.failures > old_f:
                 # don't run the group
@@ -284,8 +306,6 @@
                 test = parser.get_doctest(code[0].code, {},
                                           group.name, filename, code[0].lineno)
                 if not test.examples:
-                    self._out('WARNING: no examples in doctest block at '
-                              + filename + ', line %s\n' % code[0].lineno)
                     continue
                 for example in test.examples:
                     # apply directive's comparison options
@@ -307,7 +327,7 @@
             # DocTest.__init__ copies the globs namespace, which we don't want
             test.globs = ns
             # also don't clear the globs namespace after running the doctest
-            self.test_runner.run(test, out=self._out, clear_globs=False)
+            self.test_runner.run(test, out=self._warn_out, clear_globs=False)
 
 
 def setup(app):
@@ -322,3 +342,4 @@
     # this config value adds to sys.path
     app.add_config_value('doctest_path', [], False)
     app.add_config_value('doctest_test_doctest_blocks', 'default', False)
+    app.add_config_value('doctest_global_setup', '', False)

Modified: doctools/trunk/sphinx/ext/ifconfig.py
==============================================================================
--- doctools/trunk/sphinx/ext/ifconfig.py	(original)
+++ doctools/trunk/sphinx/ext/ifconfig.py	Sun Jan  4 21:38:57 2009
@@ -16,8 +16,8 @@
     namespace of the project configuration (that is, all variables from ``conf.py``
     are available.)
 
-    :copyright: 2008 by Georg Brandl.
-    :license: BSD.
+    :copyright: Copyright 2007-2009 by the Sphinx team, see AUTHORS.
+    :license: BSD, see LICENSE for details.
 """
 
 from docutils import nodes

Modified: doctools/trunk/sphinx/ext/intersphinx.py
==============================================================================
--- doctools/trunk/sphinx/ext/intersphinx.py	(original)
+++ doctools/trunk/sphinx/ext/intersphinx.py	Sun Jan  4 21:38:57 2009
@@ -20,8 +20,8 @@
       also be specified individually, e.g. if the docs should be buildable
       without Internet access.
 
-    :copyright: 2008 by Georg Brandl.
-    :license: BSD.
+    :copyright: Copyright 2007-2009 by the Sphinx team, see AUTHORS.
+    :license: BSD, see LICENSE for details.
 """
 
 import time
@@ -31,7 +31,7 @@
 
 from docutils import nodes
 
-from sphinx.builder import INVENTORY_FILENAME
+from sphinx.builders.html import INVENTORY_FILENAME
 
 
 def fetch_inventory(app, uri, inv):

Modified: doctools/trunk/sphinx/ext/jsmath.py
==============================================================================
--- doctools/trunk/sphinx/ext/jsmath.py	(original)
+++ doctools/trunk/sphinx/ext/jsmath.py	Sun Jan  4 21:38:57 2009
@@ -6,8 +6,8 @@
     Set up everything for use of JSMath to display math in HTML
     via JavaScript.
 
-    :copyright: 2008 by Georg Brandl.
-    :license: BSD.
+    :copyright: Copyright 2007-2009 by the Sphinx team, see AUTHORS.
+    :license: BSD, see LICENSE for details.
 """
 
 from docutils import nodes

Modified: doctools/trunk/sphinx/ext/mathbase.py
==============================================================================
--- doctools/trunk/sphinx/ext/mathbase.py	(original)
+++ doctools/trunk/sphinx/ext/mathbase.py	Sun Jan  4 21:38:57 2009
@@ -5,8 +5,8 @@
 
     Set up math support in source files and LaTeX/text output.
 
-    :copyright: 2008 by Georg Brandl.
-    :license: BSD.
+    :copyright: Copyright 2007-2009 by the Sphinx team, see AUTHORS.
+    :license: BSD, see LICENSE for details.
 """
 
 from docutils import nodes, utils

Modified: doctools/trunk/sphinx/ext/pngmath.py
==============================================================================
--- doctools/trunk/sphinx/ext/pngmath.py	(original)
+++ doctools/trunk/sphinx/ext/pngmath.py	Sun Jan  4 21:38:57 2009
@@ -5,12 +5,11 @@
 
     Render math in HTML via dvipng.
 
-    :copyright: 2008 by Georg Brandl.
-    :license: BSD.
+    :copyright: Copyright 2007-2009 by the Sphinx team, see AUTHORS.
+    :license: BSD, see LICENSE for details.
 """
 
 import re
-import shlex
 import shutil
 import tempfile
 import posixpath
@@ -24,6 +23,7 @@
 from docutils import nodes
 
 from sphinx.util import ensuredir
+from sphinx.util.png import read_png_depth, write_png_depth
 from sphinx.application import SphinxError
 from sphinx.ext.mathbase import setup as mathbase_setup, wrap_displaymath
 
@@ -79,7 +79,8 @@
     relfn = posixpath.join(self.builder.imgpath, 'math', shasum)
     outfn = path.join(self.builder.outdir, '_images', 'math', shasum)
     if path.isfile(outfn):
-        return relfn, self.builder.env._pngmath_depth.get(shasum, None)
+        depth = read_png_depth(outfn)
+        return relfn, depth
 
     latex = DOC_HEAD + self.builder.config.pngmath_latex_preamble
     latex += (use_preview and DOC_BODY_PREVIEW or DOC_BODY) % math
@@ -101,8 +102,10 @@
     # build latex command; old versions of latex don't have the
     # --output-directory option, so we have to manually chdir to the
     # temp dir to run it.
-    ltx_args = shlex.split(self.builder.config.pngmath_latex)
-    ltx_args += ['--interaction=nonstopmode', 'math.tex']
+    ltx_args = [self.builder.config.pngmath_latex, '--interaction=nonstopmode']
+    # add custom args from the config file
+    ltx_args.extend(self.builder.config.pngmath_latex_args)
+    ltx_args.append('math.tex')
 
     curdir = getcwd()
     chdir(tempdir)
@@ -129,7 +132,7 @@
 
     ensuredir(path.dirname(outfn))
     # use some standard dvipng arguments
-    dvipng_args = shlex.split(self.builder.config.pngmath_dvipng)
+    dvipng_args = [self.builder.config.pngmath_dvipng]
     dvipng_args += ['-o', outfn, '-T', 'tight', '-z9']
     # add custom ones from config value
     dvipng_args.extend(self.builder.config.pngmath_dvipng_args)
@@ -158,15 +161,11 @@
             m = depth_re.match(line)
             if m:
                 depth = int(m.group(1))
-                self.builder.env._pngmath_depth[shasum] = depth
+                write_png_depth(outfn, depth)
                 break
 
     return relfn, depth
 
-def ensure_depthcache(app, env):
-    if not hasattr(env, '_pngmath_depth'):
-        env._pngmath_depth = {}
-
 def cleanup_tempdir(app, exc):
     if exc:
         return
@@ -220,6 +219,6 @@
     app.add_config_value('pngmath_latex', 'latex', False)
     app.add_config_value('pngmath_use_preview', False, False)
     app.add_config_value('pngmath_dvipng_args', ['-gamma 1.5', '-D 110'], False)
+    app.add_config_value('pngmath_latex_args', [], False)
     app.add_config_value('pngmath_latex_preamble', '', False)
-    app.connect('env-updated', ensure_depthcache)
     app.connect('build-finished', cleanup_tempdir)

Modified: doctools/trunk/sphinx/ext/refcounting.py
==============================================================================
--- doctools/trunk/sphinx/ext/refcounting.py	(original)
+++ doctools/trunk/sphinx/ext/refcounting.py	Sun Jan  4 21:38:57 2009
@@ -9,8 +9,8 @@
     Usage: Set the `refcount_file` config value to the path to the reference
     count data file.
 
-    :copyright: 2008 by Georg Brandl.
-    :license: BSD.
+    :copyright: Copyright 2007-2009 by the Sphinx team, see AUTHORS.
+    :license: BSD, see LICENSE for details.
 """
 
 from os import path

Modified: doctools/trunk/sphinx/ext/todo.py
==============================================================================
--- doctools/trunk/sphinx/ext/todo.py	(original)
+++ doctools/trunk/sphinx/ext/todo.py	Sun Jan  4 21:38:57 2009
@@ -8,8 +8,8 @@
     all todos of your project and lists them along with a backlink to the
     original location.
 
-    :copyright: 2008 Daniel Bültmann.
-    :license: BSD.
+    :copyright: Copyright 2007-2009 by the Sphinx team, see AUTHORS.
+    :license: BSD, see LICENSE for details.
 """
 
 from docutils import nodes

Modified: doctools/trunk/sphinx/highlighting.py
==============================================================================
--- doctools/trunk/sphinx/highlighting.py	(original)
+++ doctools/trunk/sphinx/highlighting.py	Sun Jan  4 21:38:57 2009
@@ -5,8 +5,8 @@
 
     Highlight code blocks using Pygments.
 
-    :copyright: 2007-2008 by Georg Brandl.
-    :license: BSD.
+    :copyright: Copyright 2007-2009 by the Sphinx team, see AUTHORS.
+    :license: BSD, see LICENSE for details.
 """
 
 import sys
@@ -30,6 +30,8 @@
     from pygments.token import Generic, Comment, Number
 except ImportError:
     pygments = None
+    lexers = None
+    HtmlFormatter = LatexFormatter = None
 else:
     class SphinxStyle(Style):
         """
@@ -81,6 +83,11 @@
 
 
 class PygmentsBridge(object):
+    # Set these attributes if you want to have different Pygments formatters
+    # than the default ones.
+    html_formatter = HtmlFormatter
+    latex_formatter = LatexFormatter
+
     def __init__(self, dest='html', stylename='sphinx'):
         self.dest = dest
         if not pygments:
@@ -89,14 +96,17 @@
             style = SphinxStyle
         elif '.' in stylename:
             module, stylename = stylename.rsplit('.', 1)
-            style = getattr(__import__(module, None, None, ['']), stylename)
+            style = getattr(__import__(module, None, None, ['__name__']), stylename)
         else:
             style = get_style_by_name(stylename)
-        self.hfmter = {False: HtmlFormatter(style=style),
-                       True: HtmlFormatter(style=style, linenos=True)}
-        self.lfmter = {False: LatexFormatter(style=style, commandprefix='PYG'),
-                       True: LatexFormatter(style=style, linenos=True,
-                                            commandprefix='PYG')}
+        if dest == 'html':
+            self.fmter = {False: self.html_formatter(style=style),
+                          True: self.html_formatter(style=style, linenos=True)}
+        else:
+            self.fmter = {False: self.latex_formatter(style=style,
+                                                      commandprefix='PYG'),
+                          True: self.latex_formatter(style=style, linenos=True,
+                                                     commandprefix='PYG')}
 
     def unhighlighted(self, source):
         if self.dest == 'html':
@@ -170,9 +180,9 @@
                 lexer.add_filter('raiseonerror')
         try:
             if self.dest == 'html':
-                return highlight(source, lexer, self.hfmter[bool(linenos)])
+                return highlight(source, lexer, self.fmter[bool(linenos)])
             else:
-                hlsource = highlight(source, lexer, self.lfmter[bool(linenos)])
+                hlsource = highlight(source, lexer, self.fmter[bool(linenos)])
                 return hlsource.translate(tex_hl_escape_map)
         except ErrorToken:
             # this is most probably not the selected language,
@@ -186,9 +196,9 @@
             # no HTML styles needed
             return ''
         if self.dest == 'html':
-            return self.hfmter[0].get_style_defs()
+            return self.fmter[0].get_style_defs()
         else:
-            styledefs = self.lfmter[0].get_style_defs()
+            styledefs = self.fmter[0].get_style_defs()
             # workaround for Pygments < 0.12
             if styledefs.startswith('\\newcommand\\at{@}'):
                 styledefs += _LATEX_STYLES

Added: doctools/trunk/sphinx/jinja2glue.py
==============================================================================
--- (empty file)
+++ doctools/trunk/sphinx/jinja2glue.py	Sun Jan  4 21:38:57 2009
@@ -0,0 +1,86 @@
+# -*- coding: utf-8 -*-
+"""
+    sphinx.jinja2glue
+    ~~~~~~~~~~~~~~~~~
+
+    Glue code for the jinja2 templating engine.
+
+    :copyright: Copyright 2007-2009 by the Sphinx team, see AUTHORS.
+    :license: BSD, see LICENSE for details.
+"""
+
+import codecs
+from os import path
+
+import jinja2
+
+from sphinx.util import mtimes_of_files
+from sphinx.application import TemplateBridge
+
+
+class SphinxLoader(jinja2.BaseLoader):
+    """
+    A jinja2 reimplementation of `sphinx._jinja.SphinxFileSystemLoader`.
+    """
+
+    def __init__(self, basepath, extpaths, encoding='utf-8'):
+        """
+        Create a new loader for sphinx.
+
+        *extpaths* is a list of directories, which provide additional templates
+        to sphinx.
+
+        *encoding* is used to decode the templates into unicode strings.
+        Defaults to utf-8.
+
+        If *basepath* is set, this path is used to load sphinx core templates.
+        If False, these templates are loaded from the sphinx package.
+        """
+        self.core_loader = jinja2.FileSystemLoader(basepath)
+        self.all_loaders = jinja2.ChoiceLoader(
+            [jinja2.FileSystemLoader(extpath) for extpath in extpaths] +
+            [self.core_loader])
+
+    def get_source(self, environment, template):
+        # exclamation mark forces loading from core
+        if template.startswith('!'):
+            return self.core_loader.get_source(environment, template[1:])
+        # check if the template is probably an absolute path
+        fs_path = template.replace('/', path.sep)
+        if path.isabs(fs_path):
+            if not path.exists(fs_path):
+                raise jinja2.TemplateNotFound(template)
+            f = codecs.open(fs_path, 'r', self.encoding)
+            try:
+                mtime = path.getmtime(path)
+                return (f.read(), fs_path,
+                        lambda: mtime == path.getmtime(path))
+            finally:
+                f.close()
+        # finally try to load from custom templates
+        return self.all_loaders.get_source(environment, template)
+
+
+class BuiltinTemplates(TemplateBridge):
+    """
+    Interfaces the rendering environment of jinja2 for use in sphinx.
+    """
+
+    def init(self, builder):
+        base_templates_path = path.join(path.dirname(__file__), 'templates')
+        ext_templates_path = [path.join(builder.confdir, dir)
+                              for dir in builder.config.templates_path]
+        self.templates_path = [base_templates_path] + ext_templates_path
+        loader = SphinxLoader(base_templates_path, ext_templates_path)
+        use_i18n = builder.translator is not None
+        extensions = use_i18n and ['jinja2.ext.i18n'] or []
+        self.environment = jinja2.Environment(loader=loader,
+                                              extensions=extensions)
+        if use_i18n:
+            self.environment.install_gettext_translations(builder.translator)
+
+    def render(self, template, context):
+        return self.environment.get_template(template).render(context)
+
+    def newest_template_mtime(self):
+        return max(mtimes_of_files(self.templates_path, '.html'))

Modified: doctools/trunk/sphinx/locale/__init__.py
==============================================================================
--- doctools/trunk/sphinx/locale/__init__.py	(original)
+++ doctools/trunk/sphinx/locale/__init__.py	Sun Jan  4 21:38:57 2009
@@ -5,8 +5,8 @@
 
     Locale utilities.
 
-    :copyright: 2008 by Georg Brandl.
-    :license: BSD.
+    :copyright: Copyright 2007-2009 by the Sphinx team, see AUTHORS.
+    :license: BSD, see LICENSE for details.
 """
 
 _ = lambda x: x

Modified: doctools/trunk/sphinx/locale/cs/LC_MESSAGES/sphinx.js
==============================================================================
--- doctools/trunk/sphinx/locale/cs/LC_MESSAGES/sphinx.js	(original)
+++ doctools/trunk/sphinx/locale/cs/LC_MESSAGES/sphinx.js	Sun Jan  4 21:38:57 2009
@@ -1 +1 @@
-Documentation.addTranslations({"locale": "cs", "plural_expr": "(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2)", "messages": {"module, in ": "modul", "Preparing search...": "", "Your search did not match any documents. Please make sure that all words are spelled correctly and that you've selected enough categories.": "", "Search finished, found %s page(s) matching the search query.": "", ", in ": "", "Permalink to this headline": "Trval\u00fd odkaz na tento nadpis", "Searching": "hledej", "Permalink to this definition": "Trval\u00fd odkaz na tuto definici", "Hide Search Matches": "", "Search Results": "V\u00fdsledky hled\u00e1n\u00ed"}});
\ No newline at end of file
+Documentation.addTranslations({"locale": "cs", "plural_expr": "(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2)", "messages": {"module, in ": "modul, v", "Preparing search...": "Připravuji hledání...", "Your search did not match any documents. Please make sure that all words are spelled correctly and that you've selected enough categories.": "Nenalezli jsme žádný dokument. Ujistěte se prosím, že všechna slova jsou správně.", "Search finished, found %s page(s) matching the search query.": "Vyhledávání skončilo, nalezeno %s stran.", ", in ": ", v", "Permalink to this headline": "Trvalý odkaz na tento nadpis", "Searching": "Hledám", "Permalink to this definition": "Trvalý odkaz na tuto definici", "Hide Search Matches": "Skrýt výsledky hledání", "Search Results": "Výsledky hledání"}});

Modified: doctools/trunk/sphinx/locale/cs/LC_MESSAGES/sphinx.mo
==============================================================================
Binary files doctools/trunk/sphinx/locale/cs/LC_MESSAGES/sphinx.mo	(original) and doctools/trunk/sphinx/locale/cs/LC_MESSAGES/sphinx.mo	Sun Jan  4 21:38:57 2009 differ

Modified: doctools/trunk/sphinx/locale/cs/LC_MESSAGES/sphinx.po
==============================================================================
--- doctools/trunk/sphinx/locale/cs/LC_MESSAGES/sphinx.po	(original)
+++ doctools/trunk/sphinx/locale/cs/LC_MESSAGES/sphinx.po	Sun Jan  4 21:38:57 2009
@@ -7,23 +7,25 @@
 msgstr ""
 "Project-Id-Version: Sphinx 0.5\n"
 "Report-Msgid-Bugs-To: EMAIL at ADDRESS\n"
-"POT-Creation-Date: 2008-08-10 11:43+0000\n"
-"PO-Revision-Date: 2008-11-27 18:40+0100\n"
+"POT-Creation-Date: 2008-11-27 18:39+0100\n"
+"PO-Revision-Date: 2008-12-25 05:59+0100\n"
 "Last-Translator: Pavel Kosina <pavel.kosina at gmail.com>\n"
 "Language-Team: Pavel Kosina <pavel.kosina at gmail.com>\n"
-"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && "
-"n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2)\n"
 "MIME-Version: 1.0\n"
-"Content-Type: text/plain; charset=utf-8\n"
+"Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2)\n"
 "Generated-By: Babel 0.9.4\n"
+"X-Poedit-Language: Czech\n"
+"X-Poedit-Country: CZECH REPUBLIC\n"
 
 #: sphinx/builder.py:408
 #, python-format
 msgid "%b %d, %Y"
 msgstr "%d.%m.%Y"
 
-#: sphinx/builder.py:427 sphinx/templates/defindex.html:21
+#: sphinx/builder.py:427
+#: sphinx/templates/defindex.html:21
 msgid "General Index"
 msgstr "Rejstřík indexů"
 
@@ -31,11 +33,13 @@
 msgid "index"
 msgstr "index"
 
-#: sphinx/builder.py:429 sphinx/htmlhelp.py:156
-#: sphinx/templates/defindex.html:19 sphinx/templates/modindex.html:2
+#: sphinx/builder.py:429
+#: sphinx/htmlhelp.py:156
+#: sphinx/templates/defindex.html:19
+#: sphinx/templates/modindex.html:2
 #: sphinx/templates/modindex.html:13
 msgid "Global Module Index"
-msgstr "Rejstřík modulů"
+msgstr "Celkový rejstřík modulů"
 
 #: sphinx/builder.py:429
 msgid "modules"
@@ -51,45 +55,51 @@
 
 #: sphinx/builder.py:1054
 msgid " (in "
-msgstr ""
+msgstr "(v"
 
 #: sphinx/builder.py:1129
 msgid "Builtins"
-msgstr "Vestavěné funkce"
+msgstr "Vestavěné funkce "
 
 #: sphinx/builder.py:1131
 msgid "Module level"
 msgstr "Úroveň modulů"
 
-#: sphinx/environment.py:102 sphinx/latexwriter.py:169
+#: sphinx/environment.py:102
+#: sphinx/latexwriter.py:169
 #, python-format
 msgid "%B %d, %Y"
 msgstr "%d.%m.%Y"
 
-#: sphinx/environment.py:291 sphinx/latexwriter.py:175
+#: sphinx/environment.py:291
+#: sphinx/latexwriter.py:175
 #: sphinx/templates/genindex-single.html:2
 #: sphinx/templates/genindex-split.html:2
-#: sphinx/templates/genindex-split.html:5 sphinx/templates/genindex.html:2
-#: sphinx/templates/genindex.html:5 sphinx/templates/genindex.html:48
+#: sphinx/templates/genindex-split.html:5
+#: sphinx/templates/genindex.html:2
+#: sphinx/templates/genindex.html:5
+#: sphinx/templates/genindex.html:48
 #: sphinx/templates/layout.html:130
 msgid "Index"
 msgstr "Index"
 
-#: sphinx/environment.py:292 sphinx/latexwriter.py:174
-#, fuzzy
+#: sphinx/environment.py:292
+#: sphinx/latexwriter.py:174
 msgid "Module Index"
-msgstr "Rejstřík modulů"
+msgstr "Rejstřík modulů "
 
-#: sphinx/environment.py:293 sphinx/templates/defindex.html:16
-#, fuzzy
+#: sphinx/environment.py:293
+#: sphinx/templates/defindex.html:16
 msgid "Search Page"
 msgstr "Vyhledávací stránka"
 
-#: sphinx/htmlwriter.py:79 sphinx/static/doctools.js:145
+#: sphinx/htmlwriter.py:79
+#: sphinx/static/doctools.js:145
 msgid "Permalink to this definition"
 msgstr "Trvalý odkaz na tuto definici"
 
-#: sphinx/htmlwriter.py:399 sphinx/static/doctools.js:139
+#: sphinx/htmlwriter.py:399
+#: sphinx/static/doctools.js:139
 msgid "Permalink to this headline"
 msgstr "Trvalý odkaz na tento nadpis"
 
@@ -97,7 +107,8 @@
 msgid "Release"
 msgstr "Vydání"
 
-#: sphinx/roles.py:53 sphinx/directives/desc.py:537
+#: sphinx/roles.py:53
+#: sphinx/directives/desc.py:537
 #, python-format
 msgid "environment variable; %s"
 msgstr "promměná prostředí, %s"
@@ -121,7 +132,8 @@
 msgid "%s() (built-in function)"
 msgstr "%s() (vestavěná funkce)"
 
-#: sphinx/directives/desc.py:26 sphinx/directives/desc.py:42
+#: sphinx/directives/desc.py:26
+#: sphinx/directives/desc.py:42
 #: sphinx/directives/desc.py:54
 #, python-format
 msgid "%s() (in module %s)"
@@ -132,15 +144,16 @@
 msgid "%s (built-in variable)"
 msgstr "%s() (vestavěná proměnná)"
 
-#: sphinx/directives/desc.py:30 sphinx/directives/desc.py:66
+#: sphinx/directives/desc.py:30
+#: sphinx/directives/desc.py:66
 #, python-format
 msgid "%s (in module %s)"
 msgstr "%s() (v modulu %s)"
 
 #: sphinx/directives/desc.py:33
-#, fuzzy, python-format
+#, python-format
 msgid "%s (built-in class)"
-msgstr "%s() (vestavěná proměnná)"
+msgstr "%s () (vestavěná proměnná)"
 
 #: sphinx/directives/desc.py:34
 #, python-format
@@ -223,9 +236,9 @@
 msgstr "Parametry"
 
 #: sphinx/directives/desc.py:423
-#, fuzzy, python-format
+#, python-format
 msgid "%scommand line option; %s"
-msgstr "%sparametry příkazového řádku; %s"
+msgstr "%s parametry příkazového řádku; %s"
 
 #: sphinx/directives/other.py:101
 msgid "Platforms: "
@@ -254,16 +267,16 @@
 
 #: sphinx/ext/todo.py:31
 msgid "Todo"
-msgstr ""
+msgstr "Todo"
 
 #: sphinx/ext/todo.py:75
 #, python-format
 msgid "(The original entry is located in %s, line %d and can be found "
-msgstr ""
+msgstr "(Původní záznam je v %s, řádka %d a lze jej nalézt"
 
 #: sphinx/ext/todo.py:81
 msgid "here"
-msgstr ""
+msgstr "zde"
 
 #: sphinx/locale/__init__.py:15
 msgid "Attention"
@@ -350,40 +363,37 @@
 
 #: sphinx/static/doctools.js:174
 msgid "Hide Search Matches"
-msgstr ""
+msgstr "Skrýt výsledky vyhledávání"
 
 #: sphinx/static/searchtools.js:274
-#, fuzzy
 msgid "Searching"
-msgstr "hledej"
+msgstr "Hledám"
 
 #: sphinx/static/searchtools.js:279
 msgid "Preparing search..."
-msgstr ""
+msgstr "Připravuji vyhledávání...."
 
 #: sphinx/static/searchtools.js:338
-#, fuzzy
 msgid "module, in "
-msgstr "modul"
+msgstr "modul, v"
 
 #: sphinx/static/searchtools.js:347
 msgid ", in "
-msgstr ""
+msgstr ", v"
 
-#: sphinx/static/searchtools.js:447 sphinx/templates/search.html:18
+#: sphinx/static/searchtools.js:447
+#: sphinx/templates/search.html:18
 msgid "Search Results"
 msgstr "Výsledky hledání"
 
 #: sphinx/static/searchtools.js:449
-msgid ""
-"Your search did not match any documents. Please make sure that all words "
-"are spelled correctly and that you've selected enough categories."
-msgstr ""
+msgid "Your search did not match any documents. Please make sure that all words are spelled correctly and that you've selected enough categories."
+msgstr "Nenalezli jsme žádný dokument. Ujistěte se prosím, že všechna slova jsou správně a že jste vybral dostatek kategorií."
 
 #: sphinx/static/searchtools.js:451
 #, python-format
 msgid "Search finished, found %s page(s) matching the search query."
-msgstr ""
+msgstr "Vyhledávání skončilo, nalezeno %s stran."
 
 #: sphinx/templates/defindex.html:2
 msgid "Overview"
@@ -420,7 +430,8 @@
 
 #: sphinx/templates/genindex-single.html:44
 #: sphinx/templates/genindex-split.html:14
-#: sphinx/templates/genindex-split.html:27 sphinx/templates/genindex.html:54
+#: sphinx/templates/genindex-split.html:27
+#: sphinx/templates/genindex.html:54
 msgid "Full index on one page"
 msgstr "Plný index na jedné stránce"
 
@@ -464,7 +475,8 @@
 msgid "Suggest Change"
 msgstr "Návrh změnu"
 
-#: sphinx/templates/layout.html:60 sphinx/templates/layout.html:62
+#: sphinx/templates/layout.html:60
+#: sphinx/templates/layout.html:62
 msgid "Show Source"
 msgstr "Ukázat zdroj"
 
@@ -493,7 +505,8 @@
 msgid "About these documents"
 msgstr "O těchto dokumentech"
 
-#: sphinx/templates/layout.html:131 sphinx/templates/search.html:2
+#: sphinx/templates/layout.html:131
+#: sphinx/templates/search.html:2
 #: sphinx/templates/search.html:5
 msgid "Search"
 msgstr "Hledání"
@@ -515,16 +528,12 @@
 #: sphinx/templates/layout.html:183
 #, python-format
 msgid "Last updated on %(last_updated)s."
-msgstr "Naposledy aktualizováno dne %(last_updated)s."
+msgstr "Aktualizováno dne %(last_updated)s."
 
 #: sphinx/templates/layout.html:186
 #, python-format
-msgid ""
-"Created using <a href=\"http://sphinx.pocoo.org/\">Sphinx</a> "
-"%(sphinx_version)s."
-msgstr ""
-"Vytvořeno pomocí <a href=\"http://sphinx.pocoo.org/\">Sphinx</a> "
-"%(sphinx_version)s."
+msgid "Created using <a href=\"http://sphinx.pocoo.org/\">Sphinx</a> %(sphinx_version)s."
+msgstr "Vytvořeno pomocí <a href=\"http://sphinx.pocoo.org/\">Sphinx</a> %(sphinx_version)s."
 
 #: sphinx/templates/modindex.html:15
 msgid "Most popular modules:"
@@ -544,27 +553,18 @@
 msgstr "Prohledat %(docstitle)s"
 
 #: sphinx/templates/page.html:8
-msgid ""
-"<strong>Note:</strong> You requested an out-of-date URL from this server."
-" We've tried to redirect you to the new location of this page, but it may"
-" not be the right one."
-msgstr ""
-"<strong>Poznámka:</strong> Stránka, kterou hledáte, "
-"neexistuje.<br>Snažili jsme se najít nové umístění této stránky, ale "
-"nepovedlo se."
+msgid "<strong>Note:</strong> You requested an out-of-date URL from this server. We've tried to redirect you to the new location of this page, but it may not be the right one."
+msgstr "<strong>Poznámka:</strong> Stránka, kterou hledáte, neexistuje.<br>Snažili jsme se najít nové umístění této stránky, ale nepovedlo se."
 
 #: sphinx/templates/search.html:7
-#, fuzzy
 msgid ""
 "From here you can search these documents. Enter your search\n"
 "    words into the box below and click \"search\". Note that the search\n"
 "    function will automatically search for all of the words. Pages\n"
 "    containing fewer words won't appear in the result list."
 msgstr ""
-"Toto je vyhledávací stránka. Zadejte klíčová slova    do pole níže a "
-"klikněte na \"hledej\". \n"
-"Prohledávání funkcí  hledá automaticky všechna slova. Stránky obsahující"
-"    slov méně, nebudou nalezeny."
+"Toto je vyhledávací stránka. Zadejte klíčová slova a klikněte na \"hledej\". \n"
+"Vyhledávání hledá automaticky všechna slova. Nebudou tedy nalezeny stránky, obsahující méně slov."
 
 #: sphinx/templates/search.html:14
 msgid "search"

Modified: doctools/trunk/sphinx/locale/de/LC_MESSAGES/sphinx.po
==============================================================================
--- doctools/trunk/sphinx/locale/de/LC_MESSAGES/sphinx.po	(original)
+++ doctools/trunk/sphinx/locale/de/LC_MESSAGES/sphinx.po	Sun Jan  4 21:38:57 2009
@@ -7,93 +7,37 @@
 "Project-Id-Version: PROJECT VERSION\n"
 "Report-Msgid-Bugs-To: EMAIL at ADDRESS\n"
 "POT-Creation-Date: 2008-08-07 21:40+0200\n"
-"PO-Revision-Date: 2008-11-27 18:40+0100\n"
+"PO-Revision-Date: 2008-12-28 23:40+0100\n"
 "Last-Translator: Horst Gutmann <zerok at zerokspot.com>\n"
 "Language-Team: de <LL at li.org>\n"
 "Plural-Forms: nplurals=2; plural=(n != 1)\n"
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=utf-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"Generated-By: Babel 0.9.4\n"
+"Generated-By: Babel 0.9.3\n"
 
-#: sphinx/builder.py:408
-#, python-format
-msgid "%b %d, %Y"
-msgstr "%d. %m. %Y"
-
-#: sphinx/builder.py:427 sphinx/templates/defindex.html:21
-msgid "General Index"
-msgstr "Allgemeiner Index"
-
-#: sphinx/builder.py:427
-msgid "index"
-msgstr "Index"
-
-#: sphinx/builder.py:429 sphinx/htmlhelp.py:156
-#: sphinx/templates/defindex.html:19 sphinx/templates/modindex.html:2
-#: sphinx/templates/modindex.html:13
-msgid "Global Module Index"
-msgstr "Globaler Modulindex"
-
-#: sphinx/builder.py:429
-msgid "modules"
-msgstr "Module"
-
-#: sphinx/builder.py:466
-msgid "next"
-msgstr "weiter"
-
-#: sphinx/builder.py:473
-msgid "previous"
-msgstr "zurück"
-
-#: sphinx/builder.py:1054
-msgid " (in "
-msgstr ""
-
-#: sphinx/builder.py:1129
-msgid "Builtins"
-msgstr "Builtins"
-
-#: sphinx/builder.py:1131
-msgid "Module level"
-msgstr "Modulebene"
-
-#: sphinx/environment.py:102 sphinx/latexwriter.py:169
+#: sphinx/environment.py:103 sphinx/writers/latex.py:170
 #, python-format
 msgid "%B %d, %Y"
 msgstr "%d. %m. %Y"
 
-#: sphinx/environment.py:291 sphinx/latexwriter.py:175
-#: sphinx/templates/genindex-single.html:2
+#: sphinx/environment.py:293 sphinx/templates/genindex-single.html:2
 #: sphinx/templates/genindex-split.html:2
 #: sphinx/templates/genindex-split.html:5 sphinx/templates/genindex.html:2
 #: sphinx/templates/genindex.html:5 sphinx/templates/genindex.html:48
-#: sphinx/templates/layout.html:130
+#: sphinx/templates/layout.html:117 sphinx/writers/latex.py:176
 msgid "Index"
 msgstr "Stichwortverzeichnis"
 
-#: sphinx/environment.py:292 sphinx/latexwriter.py:174
+#: sphinx/environment.py:294 sphinx/writers/latex.py:175
 msgid "Module Index"
 msgstr "Modulindex"
 
-#: sphinx/environment.py:293 sphinx/templates/defindex.html:16
+#: sphinx/environment.py:295 sphinx/templates/defindex.html:16
 msgid "Search Page"
 msgstr "Suche"
 
-#: sphinx/htmlwriter.py:79 sphinx/static/doctools.js:145
-msgid "Permalink to this definition"
-msgstr "Permalink zu dieser Definition"
-
-#: sphinx/htmlwriter.py:399 sphinx/static/doctools.js:139
-msgid "Permalink to this headline"
-msgstr "Permalink zu dieser Überschrift"
-
-#: sphinx/latexwriter.py:172
-msgid "Release"
-msgstr "Release"
-
-#: sphinx/roles.py:53 sphinx/directives/desc.py:537
+#: sphinx/roles.py:53 sphinx/directives/desc.py:564
 #, python-format
 msgid "environment variable; %s"
 msgstr "Umgebungsvariable; %s"
@@ -103,14 +47,48 @@
 msgid "Python Enhancement Proposals!PEP %s"
 msgstr "Python Enhancement Proposals!PEP %s"
 
-#: sphinx/textwriter.py:166
+#: sphinx/builders/changes.py:64
+msgid "Builtins"
+msgstr "Builtins"
+
+#: sphinx/builders/changes.py:66
+msgid "Module level"
+msgstr "Modulebene"
+
+#: sphinx/builders/html.py:115
 #, python-format
-msgid "Platform: %s"
-msgstr "Plattform: %s"
+msgid "%b %d, %Y"
+msgstr "%d. %m. %Y"
 
-#: sphinx/textwriter.py:422
-msgid "[image]"
-msgstr "[Bild]"
+#: sphinx/builders/html.py:134 sphinx/templates/defindex.html:21
+msgid "General Index"
+msgstr "Allgemeiner Index"
+
+#: sphinx/builders/html.py:134
+msgid "index"
+msgstr "Index"
+
+#: sphinx/builders/html.py:136 sphinx/builders/htmlhelp.py:180
+#: sphinx/builders/qthelp.py:129 sphinx/templates/defindex.html:19
+#: sphinx/templates/modindex.html:2 sphinx/templates/modindex.html:13
+msgid "Global Module Index"
+msgstr "Globaler Modulindex"
+
+#: sphinx/builders/html.py:136
+msgid "modules"
+msgstr "Module"
+
+#: sphinx/builders/html.py:175
+msgid "next"
+msgstr "weiter"
+
+#: sphinx/builders/html.py:182
+msgid "previous"
+msgstr "zurück"
+
+#: sphinx/builders/latex.py:155
+msgid " (in "
+msgstr ""
 
 #: sphinx/directives/desc.py:25
 #, python-format
@@ -214,11 +192,16 @@
 msgid "Return type"
 msgstr "Rückgabetyp"
 
-#: sphinx/directives/desc.py:143
+#: sphinx/directives/desc.py:201
+#, fuzzy
+msgid "Parameter"
+msgstr "Parameter"
+
+#: sphinx/directives/desc.py:205
 msgid "Parameters"
 msgstr "Parameter"
 
-#: sphinx/directives/desc.py:423
+#: sphinx/directives/desc.py:450
 #, python-format
 msgid "%scommand line option; %s"
 msgstr "%sKommandozeilenoption; %s"
@@ -244,10 +227,15 @@
 msgid "Author: "
 msgstr "Autor: "
 
-#: sphinx/directives/other.py:246
+#: sphinx/directives/other.py:249
 msgid "See also"
 msgstr "Siehe auch"
 
+#: sphinx/ext/autodoc.py:576 sphinx/ext/autodoc.py:590
+#, python-format
+msgid "alias of :class:`%s`"
+msgstr ""
+
 #: sphinx/ext/todo.py:31
 msgid "Todo"
 msgstr ""
@@ -344,6 +332,14 @@
 msgid "built-in function"
 msgstr "eingebaute Funktion"
 
+#: sphinx/static/doctools.js:139 sphinx/writers/html.py:415
+msgid "Permalink to this headline"
+msgstr "Permalink zu dieser Überschrift"
+
+#: sphinx/static/doctools.js:145 sphinx/writers/html.py:80
+msgid "Permalink to this definition"
+msgstr "Permalink zu dieser Definition"
+
 #: sphinx/static/doctools.js:174
 msgid "Hide Search Matches"
 msgstr "Suchergebnisse ausblenden"
@@ -364,11 +360,11 @@
 msgid ", in "
 msgstr ""
 
-#: sphinx/static/searchtools.js:447 sphinx/templates/search.html:18
+#: sphinx/static/searchtools.js:453 sphinx/templates/search.html:18
 msgid "Search Results"
 msgstr "Suchergebnisse"
 
-#: sphinx/static/searchtools.js:449
+#: sphinx/static/searchtools.js:455
 msgid ""
 "Your search did not match any documents. Please make sure that all words "
 "are spelled correctly and that you've selected enough categories."
@@ -376,7 +372,7 @@
 "Es wurden keine Dokumente gefunden. Haben Sie alle Suchworte richtig "
 "geschrieben und genügend Kategorien ausgewählt?"
 
-#: sphinx/static/searchtools.js:451
+#: sphinx/static/searchtools.js:457
 #, python-format
 msgid "Search finished, found %s page(s) matching the search query."
 msgstr "Suche beendet, %s Seite(n) mit Ergebnissen wurden gefunden."
@@ -452,68 +448,61 @@
 msgid "next chapter"
 msgstr "nächstes Kapitel"
 
-#: sphinx/templates/layout.html:55
+#: sphinx/templates/layout.html:56
 msgid "This Page"
 msgstr "Diese Seite"
 
-#: sphinx/templates/layout.html:59
-msgid "Suggest Change"
-msgstr "Änderung vorschlagen"
-
-#: sphinx/templates/layout.html:60 sphinx/templates/layout.html:62
+#: sphinx/templates/layout.html:58
 msgid "Show Source"
 msgstr "Quelltext anzeigen"
 
-#: sphinx/templates/layout.html:71
+#: sphinx/templates/layout.html:67
 msgid "Quick search"
 msgstr "Schnellsuche"
 
-#: sphinx/templates/layout.html:71
-msgid "Keyword search"
-msgstr "Stichwortsuche"
-
-#: sphinx/templates/layout.html:73
+#: sphinx/templates/layout.html:69
 msgid "Go"
 msgstr "Los"
 
-#: sphinx/templates/layout.html:78
-msgid "Enter a module, class or function name."
+#: sphinx/templates/layout.html:73
+#, fuzzy
+msgid "Enter search terms or a module, class or function name."
 msgstr "Gib einen Modul-, Klassen- oder Funktionsnamen an."
 
-#: sphinx/templates/layout.html:119
+#: sphinx/templates/layout.html:106
 #, python-format
 msgid "Search within %(docstitle)s"
 msgstr "Suche in %(docstitle)s"
 
-#: sphinx/templates/layout.html:128
+#: sphinx/templates/layout.html:115
 msgid "About these documents"
 msgstr "Über diese Dokumentation"
 
-#: sphinx/templates/layout.html:131 sphinx/templates/search.html:2
+#: sphinx/templates/layout.html:118 sphinx/templates/search.html:2
 #: sphinx/templates/search.html:5
 msgid "Search"
 msgstr "Suche"
 
-#: sphinx/templates/layout.html:133
+#: sphinx/templates/layout.html:120
 msgid "Copyright"
 msgstr "Copyright"
 
-#: sphinx/templates/layout.html:178
+#: sphinx/templates/layout.html:165
 #, python-format
 msgid "&copy; <a href=\"%(path)s\">Copyright</a> %(copyright)s."
 msgstr "&copy; <a href=\"%(path)s\">Copyright</a> %(copyright)s."
 
-#: sphinx/templates/layout.html:180
+#: sphinx/templates/layout.html:167
 #, python-format
 msgid "&copy; Copyright %(copyright)s."
 msgstr "&copy; Copyright %(copyright)s."
 
-#: sphinx/templates/layout.html:183
+#: sphinx/templates/layout.html:170
 #, python-format
 msgid "Last updated on %(last_updated)s."
 msgstr "Zuletzt aktualisiert am %(last_updated)s."
 
-#: sphinx/templates/layout.html:186
+#: sphinx/templates/layout.html:173
 #, python-format
 msgid ""
 "Created using <a href=\"http://sphinx.pocoo.org/\">Sphinx</a> "
@@ -522,15 +511,7 @@
 "Mit <a href=\"http://sphinx.pocoo.org/\">Sphinx</a> %(sphinx_version)s "
 "erstellt."
 
-#: sphinx/templates/modindex.html:15
-msgid "Most popular modules:"
-msgstr "Beliebteste Module:"
-
-#: sphinx/templates/modindex.html:24
-msgid "Show modules only available on these platforms"
-msgstr "Zeige nur Module, die auf diesen Plattformen verfügbar sind"
-
-#: sphinx/templates/modindex.html:56
+#: sphinx/templates/modindex.html:36
 msgid "Deprecated"
 msgstr "Veraltet"
 
@@ -539,16 +520,6 @@
 msgid "Search %(docstitle)s"
 msgstr "Suche in %(docstitle)s"
 
-#: sphinx/templates/page.html:8
-msgid ""
-"<strong>Note:</strong> You requested an out-of-date URL from this server."
-" We've tried to redirect you to the new location of this page, but it may"
-" not be the right one."
-msgstr ""
-"<strong>Anmerkung:</strong> Du hast eine nicht länger gültige URL von "
-"diesem Server angefragt. Wir haben versucht dich auf die neue Adresse "
-"dieser Seite umzuleiten, aber dies muss nicht die richtige Seite sein."
-
 #: sphinx/templates/search.html:7
 #, fuzzy
 msgid ""
@@ -599,3 +570,42 @@
 msgid "Other changes"
 msgstr "Andere Änderungen"
 
+#: sphinx/writers/latex.py:173
+msgid "Release"
+msgstr "Release"
+
+#: sphinx/writers/text.py:166
+#, python-format
+msgid "Platform: %s"
+msgstr "Plattform: %s"
+
+#: sphinx/writers/text.py:427
+msgid "[image]"
+msgstr "[Bild]"
+
+#~ msgid "Suggest Change"
+#~ msgstr "Änderung vorschlagen"
+
+#~ msgid "Keyword search"
+#~ msgstr "Stichwortsuche"
+
+#~ msgid "Most popular modules:"
+#~ msgstr "Beliebteste Module:"
+
+#~ msgid "Show modules only available on these platforms"
+#~ msgstr "Zeige nur Module, die auf diesen Plattformen verfügbar sind"
+
+#~ msgid ""
+#~ "<strong>Note:</strong> You requested an "
+#~ "out-of-date URL from this server. "
+#~ "We've tried to redirect you to the"
+#~ " new location of this page, but "
+#~ "it may not be the right one."
+#~ msgstr ""
+#~ "<strong>Anmerkung:</strong> Du hast eine nicht"
+#~ " länger gültige URL von diesem Server"
+#~ " angefragt. Wir haben versucht dich "
+#~ "auf die neue Adresse dieser Seite "
+#~ "umzuleiten, aber dies muss nicht die "
+#~ "richtige Seite sein."
+

Modified: doctools/trunk/sphinx/locale/es/LC_MESSAGES/sphinx.po
==============================================================================
--- doctools/trunk/sphinx/locale/es/LC_MESSAGES/sphinx.po	(original)
+++ doctools/trunk/sphinx/locale/es/LC_MESSAGES/sphinx.po	Sun Jan  4 21:38:57 2009
@@ -8,96 +8,37 @@
 "Project-Id-Version: Sphinx 0.5\n"
 "Report-Msgid-Bugs-To: guillem at torroja.dmt.upm.es\n"
 "POT-Creation-Date: 2008-09-11 23:58+0200\n"
-"PO-Revision-Date: 2008-11-27 18:40+0100\n"
+"PO-Revision-Date: 2008-12-28 23:40+0100\n"
 "Last-Translator: Guillem Borrell <guillem at torroja.dmt.upm.es>\n"
 "Language-Team: es <LL at li.org>\n"
 "Plural-Forms: nplurals=2; plural=(n != 1)\n"
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=utf-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"Generated-By: Babel 0.9.4\n"
+"Generated-By: Babel 0.9.3\n"
 
-#: sphinx/builder.py:408
-#, python-format
-msgid "%b %d, %Y"
-msgstr "%d %b, %Y"
-
-#: sphinx/builder.py:427 sphinx/templates/defindex.html:21
-msgid "General Index"
-msgstr "Índice General"
-
-#: sphinx/builder.py:427
-msgid "index"
-msgstr "índice"
-
-#: sphinx/builder.py:429 sphinx/htmlhelp.py:156
-#: sphinx/templates/defindex.html:19 sphinx/templates/modindex.html:2
-#: sphinx/templates/modindex.html:13
-msgid "Global Module Index"
-msgstr "Índice Global de Módulos"
-
-#: sphinx/builder.py:429
-msgid "modules"
-msgstr "módulos"
-
-#: sphinx/builder.py:466
-msgid "next"
-msgstr "siguiente"
-
-#: sphinx/builder.py:473
-msgid "previous"
-msgstr "anterior"
-
-#: sphinx/builder.py:1054
-msgid " (in "
-msgstr ""
-
-#: sphinx/builder.py:1129
-#, fuzzy
-msgid "Builtins"
-msgstr "Funciones de base"
-
-#: sphinx/builder.py:1131
-#, fuzzy
-msgid "Module level"
-msgstr "Módulos"
-
-#: sphinx/environment.py:102 sphinx/latexwriter.py:169
+#: sphinx/environment.py:103 sphinx/writers/latex.py:170
 #, fuzzy, python-format
 msgid "%B %d, %Y"
 msgstr "%d de %B de %Y"
 
-#: sphinx/environment.py:291 sphinx/latexwriter.py:175
-#: sphinx/templates/genindex-single.html:2
+#: sphinx/environment.py:293 sphinx/templates/genindex-single.html:2
 #: sphinx/templates/genindex-split.html:2
 #: sphinx/templates/genindex-split.html:5 sphinx/templates/genindex.html:2
 #: sphinx/templates/genindex.html:5 sphinx/templates/genindex.html:48
-#: sphinx/templates/layout.html:130
+#: sphinx/templates/layout.html:117 sphinx/writers/latex.py:176
 msgid "Index"
 msgstr "Índice"
 
-#: sphinx/environment.py:292 sphinx/latexwriter.py:174
+#: sphinx/environment.py:294 sphinx/writers/latex.py:175
 msgid "Module Index"
 msgstr "Índice de Módulos"
 
-#: sphinx/environment.py:293 sphinx/templates/defindex.html:16
+#: sphinx/environment.py:295 sphinx/templates/defindex.html:16
 msgid "Search Page"
 msgstr "Página de Búsqueda"
 
-#: sphinx/htmlwriter.py:79 sphinx/static/doctools.js:145
-msgid "Permalink to this definition"
-msgstr "Enlazar permanentemente con esta definición"
-
-#: sphinx/htmlwriter.py:399 sphinx/static/doctools.js:139
-msgid "Permalink to this headline"
-msgstr "Enlazar permanentemente con este título"
-
-#: sphinx/latexwriter.py:172
-#, fuzzy
-msgid "Release"
-msgstr "Versión"
-
-#: sphinx/roles.py:53 sphinx/directives/desc.py:537
+#: sphinx/roles.py:53 sphinx/directives/desc.py:564
 #, python-format
 msgid "environment variable; %s"
 msgstr "variables de entorno; %s"
@@ -107,14 +48,50 @@
 msgid "Python Enhancement Proposals!PEP %s"
 msgstr "Python Enhancement Proposals!PEP %s"
 
-#: sphinx/textwriter.py:166
+#: sphinx/builders/changes.py:64
+#, fuzzy
+msgid "Builtins"
+msgstr "Funciones de base"
+
+#: sphinx/builders/changes.py:66
+#, fuzzy
+msgid "Module level"
+msgstr "Módulos"
+
+#: sphinx/builders/html.py:115
 #, python-format
-msgid "Platform: %s"
-msgstr "Plataforma: %s"
+msgid "%b %d, %Y"
+msgstr "%d %b, %Y"
 
-#: sphinx/textwriter.py:422
-msgid "[image]"
-msgstr "[imagen]"
+#: sphinx/builders/html.py:134 sphinx/templates/defindex.html:21
+msgid "General Index"
+msgstr "Índice General"
+
+#: sphinx/builders/html.py:134
+msgid "index"
+msgstr "índice"
+
+#: sphinx/builders/html.py:136 sphinx/builders/htmlhelp.py:180
+#: sphinx/builders/qthelp.py:129 sphinx/templates/defindex.html:19
+#: sphinx/templates/modindex.html:2 sphinx/templates/modindex.html:13
+msgid "Global Module Index"
+msgstr "Índice Global de Módulos"
+
+#: sphinx/builders/html.py:136
+msgid "modules"
+msgstr "módulos"
+
+#: sphinx/builders/html.py:175
+msgid "next"
+msgstr "siguiente"
+
+#: sphinx/builders/html.py:182
+msgid "previous"
+msgstr "anterior"
+
+#: sphinx/builders/latex.py:155
+msgid " (in "
+msgstr ""
 
 #: sphinx/directives/desc.py:25
 #, fuzzy, python-format
@@ -219,11 +196,16 @@
 msgid "Return type"
 msgstr "Tipo del argumento devuelto"
 
-#: sphinx/directives/desc.py:143
+#: sphinx/directives/desc.py:201
+#, fuzzy
+msgid "Parameter"
+msgstr "Parámetros"
+
+#: sphinx/directives/desc.py:205
 msgid "Parameters"
 msgstr "Parámetros"
 
-#: sphinx/directives/desc.py:423
+#: sphinx/directives/desc.py:450
 #, fuzzy, python-format
 msgid "%scommand line option; %s"
 msgstr "%sOpciones en línea de comandos; %s"
@@ -249,10 +231,15 @@
 msgid "Author: "
 msgstr "Autor:"
 
-#: sphinx/directives/other.py:246
+#: sphinx/directives/other.py:249
 msgid "See also"
 msgstr "Ver también"
 
+#: sphinx/ext/autodoc.py:576 sphinx/ext/autodoc.py:590
+#, python-format
+msgid "alias of :class:`%s`"
+msgstr ""
+
 #: sphinx/ext/todo.py:31
 msgid "Todo"
 msgstr ""
@@ -350,6 +337,14 @@
 msgid "built-in function"
 msgstr "función de base"
 
+#: sphinx/static/doctools.js:139 sphinx/writers/html.py:415
+msgid "Permalink to this headline"
+msgstr "Enlazar permanentemente con este título"
+
+#: sphinx/static/doctools.js:145 sphinx/writers/html.py:80
+msgid "Permalink to this definition"
+msgstr "Enlazar permanentemente con esta definición"
+
 #: sphinx/static/doctools.js:174
 #, fuzzy
 msgid "Hide Search Matches"
@@ -372,11 +367,11 @@
 msgid ", in "
 msgstr ""
 
-#: sphinx/static/searchtools.js:447 sphinx/templates/search.html:18
+#: sphinx/static/searchtools.js:453 sphinx/templates/search.html:18
 msgid "Search Results"
 msgstr "Resultados de la búsqueda"
 
-#: sphinx/static/searchtools.js:449
+#: sphinx/static/searchtools.js:455
 msgid ""
 "Your search did not match any documents. Please make sure that all words "
 "are spelled correctly and that you've selected enough categories."
@@ -385,7 +380,7 @@
 "todas las palabras correctamente y que ha seleccionado suficientes "
 "categorías"
 
-#: sphinx/static/searchtools.js:451
+#: sphinx/static/searchtools.js:457
 #, python-format
 msgid "Search finished, found %s page(s) matching the search query."
 msgstr ""
@@ -463,68 +458,61 @@
 msgid "next chapter"
 msgstr "Próximo capítulo"
 
-#: sphinx/templates/layout.html:55
+#: sphinx/templates/layout.html:56
 msgid "This Page"
 msgstr "Esta página"
 
-#: sphinx/templates/layout.html:59
-msgid "Suggest Change"
-msgstr "Sugerir una modificación"
-
-#: sphinx/templates/layout.html:60 sphinx/templates/layout.html:62
+#: sphinx/templates/layout.html:58
 msgid "Show Source"
 msgstr "Enseñar el código"
 
-#: sphinx/templates/layout.html:71
+#: sphinx/templates/layout.html:67
 msgid "Quick search"
 msgstr "Búsqueda rápida"
 
-#: sphinx/templates/layout.html:71
-msgid "Keyword search"
-msgstr "Búsqueda por palabras clave"
-
-#: sphinx/templates/layout.html:73
+#: sphinx/templates/layout.html:69
 msgid "Go"
 msgstr "Ir a"
 
-#: sphinx/templates/layout.html:78
-msgid "Enter a module, class or function name."
+#: sphinx/templates/layout.html:73
+#, fuzzy
+msgid "Enter search terms or a module, class or function name."
 msgstr "Introducir en nombre de un módulo, clase o función"
 
-#: sphinx/templates/layout.html:119
+#: sphinx/templates/layout.html:106
 #, python-format
 msgid "Search within %(docstitle)s"
 msgstr "Buscar en %(docstitle)s"
 
-#: sphinx/templates/layout.html:128
+#: sphinx/templates/layout.html:115
 msgid "About these documents"
 msgstr "Sobre este documento"
 
-#: sphinx/templates/layout.html:131 sphinx/templates/search.html:2
+#: sphinx/templates/layout.html:118 sphinx/templates/search.html:2
 #: sphinx/templates/search.html:5
 msgid "Search"
 msgstr "Búsqueda"
 
-#: sphinx/templates/layout.html:133
+#: sphinx/templates/layout.html:120
 msgid "Copyright"
 msgstr "Copyright"
 
-#: sphinx/templates/layout.html:178
+#: sphinx/templates/layout.html:165
 #, python-format
 msgid "&copy; <a href=\"%(path)s\">Copyright</a> %(copyright)s."
 msgstr "&copy; <a href=\\\"%(path)s\\\">Copyright</a> %(copyright)s."
 
-#: sphinx/templates/layout.html:180
+#: sphinx/templates/layout.html:167
 #, python-format
 msgid "&copy; Copyright %(copyright)s."
 msgstr "&copy; Copyright %(copyright)s."
 
-#: sphinx/templates/layout.html:183
+#: sphinx/templates/layout.html:170
 #, python-format
 msgid "Last updated on %(last_updated)s."
 msgstr "Actualizado por última vez en %(last_updated)s."
 
-#: sphinx/templates/layout.html:186
+#: sphinx/templates/layout.html:173
 #, python-format
 msgid ""
 "Created using <a href=\"http://sphinx.pocoo.org/\">Sphinx</a> "
@@ -533,15 +521,7 @@
 "Creado con <a href=\"http://sphinx.pocoo.org/\">Sphinx</a> "
 "%(sphinx_version)s."
 
-#: sphinx/templates/modindex.html:15
-msgid "Most popular modules:"
-msgstr "Módulos más comunes:"
-
-#: sphinx/templates/modindex.html:24
-msgid "Show modules only available on these platforms"
-msgstr "Mostrar sólo los módulos disponibles en estas plataformas"
-
-#: sphinx/templates/modindex.html:56
+#: sphinx/templates/modindex.html:36
 msgid "Deprecated"
 msgstr "Obsoleto"
 
@@ -550,16 +530,6 @@
 msgid "Search %(docstitle)s"
 msgstr "Buscar en %(docstitle)s"
 
-#: sphinx/templates/page.html:8
-msgid ""
-"<strong>Note:</strong> You requested an out-of-date URL from this server."
-" We've tried to redirect you to the new location of this page, but it may"
-" not be the right one."
-msgstr ""
-"<strong>Nota:</strong> Has solicitado una dirección desactualizada a este"
-" servidor.  Hemos intentado redirigirte a la nueva dirección de la misma "
-"página pero puede no ser la correcta."
-
 #: sphinx/templates/search.html:7
 #, fuzzy
 msgid ""
@@ -609,3 +579,42 @@
 msgid "Other changes"
 msgstr "Otros cambios"
 
+#: sphinx/writers/latex.py:173
+#, fuzzy
+msgid "Release"
+msgstr "Versión"
+
+#: sphinx/writers/text.py:166
+#, python-format
+msgid "Platform: %s"
+msgstr "Plataforma: %s"
+
+#: sphinx/writers/text.py:427
+msgid "[image]"
+msgstr "[imagen]"
+
+#~ msgid "Suggest Change"
+#~ msgstr "Sugerir una modificación"
+
+#~ msgid "Keyword search"
+#~ msgstr "Búsqueda por palabras clave"
+
+#~ msgid "Most popular modules:"
+#~ msgstr "Módulos más comunes:"
+
+#~ msgid "Show modules only available on these platforms"
+#~ msgstr "Mostrar sólo los módulos disponibles en estas plataformas"
+
+#~ msgid ""
+#~ "<strong>Note:</strong> You requested an "
+#~ "out-of-date URL from this server. "
+#~ "We've tried to redirect you to the"
+#~ " new location of this page, but "
+#~ "it may not be the right one."
+#~ msgstr ""
+#~ "<strong>Nota:</strong> Has solicitado una "
+#~ "dirección desactualizada a este servidor.  "
+#~ "Hemos intentado redirigirte a la nueva"
+#~ " dirección de la misma página pero"
+#~ " puede no ser la correcta."
+

Modified: doctools/trunk/sphinx/locale/fr/LC_MESSAGES/sphinx.po
==============================================================================
--- doctools/trunk/sphinx/locale/fr/LC_MESSAGES/sphinx.po	(original)
+++ doctools/trunk/sphinx/locale/fr/LC_MESSAGES/sphinx.po	Sun Jan  4 21:38:57 2009
@@ -9,93 +9,37 @@
 "Project-Id-Version: Sphinx 0.5\n"
 "Report-Msgid-Bugs-To: larlet at gmail.com\n"
 "POT-Creation-Date: 2008-08-08 12:39+0000\n"
-"PO-Revision-Date: 2008-11-27 18:40+0100\n"
+"PO-Revision-Date: 2008-12-28 23:40+0100\n"
 "Last-Translator: Sébastien Douche <sdouche at gmail.com>\n"
 "Language-Team: French Translation Team <sphinx-dev at googlegroups.com>\n"
 "Plural-Forms: nplurals=2; plural=(n > 1)\n"
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=utf-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"Generated-By: Babel 0.9.4\n"
+"Generated-By: Babel 0.9.3\n"
 
-#: sphinx/builder.py:408
-#, python-format
-msgid "%b %d, %Y"
-msgstr "%d %b %Y"
-
-#: sphinx/builder.py:427 sphinx/templates/defindex.html:21
-msgid "General Index"
-msgstr "Index général"
-
-#: sphinx/builder.py:427
-msgid "index"
-msgstr "index"
-
-#: sphinx/builder.py:429 sphinx/htmlhelp.py:156
-#: sphinx/templates/defindex.html:19 sphinx/templates/modindex.html:2
-#: sphinx/templates/modindex.html:13
-msgid "Global Module Index"
-msgstr "Index général des modules"
-
-#: sphinx/builder.py:429
-msgid "modules"
-msgstr "modules"
-
-#: sphinx/builder.py:466
-msgid "next"
-msgstr "suivant"
-
-#: sphinx/builder.py:473
-msgid "previous"
-msgstr "précédent"
-
-#: sphinx/builder.py:1054
-msgid " (in "
-msgstr "(dans"
-
-#: sphinx/builder.py:1129
-msgid "Builtins"
-msgstr "Fonctions de base"
-
-#: sphinx/builder.py:1131
-msgid "Module level"
-msgstr "Module"
-
-#: sphinx/environment.py:102 sphinx/latexwriter.py:169
+#: sphinx/environment.py:103 sphinx/writers/latex.py:170
 #, python-format
 msgid "%B %d, %Y"
 msgstr "%d %B %Y"
 
-#: sphinx/environment.py:291 sphinx/latexwriter.py:175
-#: sphinx/templates/genindex-single.html:2
+#: sphinx/environment.py:293 sphinx/templates/genindex-single.html:2
 #: sphinx/templates/genindex-split.html:2
 #: sphinx/templates/genindex-split.html:5 sphinx/templates/genindex.html:2
 #: sphinx/templates/genindex.html:5 sphinx/templates/genindex.html:48
-#: sphinx/templates/layout.html:130
+#: sphinx/templates/layout.html:117 sphinx/writers/latex.py:176
 msgid "Index"
 msgstr "Index"
 
-#: sphinx/environment.py:292 sphinx/latexwriter.py:174
+#: sphinx/environment.py:294 sphinx/writers/latex.py:175
 msgid "Module Index"
 msgstr "Index du module"
 
-#: sphinx/environment.py:293 sphinx/templates/defindex.html:16
+#: sphinx/environment.py:295 sphinx/templates/defindex.html:16
 msgid "Search Page"
 msgstr "Page de recherche"
 
-#: sphinx/htmlwriter.py:79 sphinx/static/doctools.js:145
-msgid "Permalink to this definition"
-msgstr "Lien permanent vers cette définition"
-
-#: sphinx/htmlwriter.py:399 sphinx/static/doctools.js:139
-msgid "Permalink to this headline"
-msgstr "Lien permanent vers ce titre"
-
-#: sphinx/latexwriter.py:172
-msgid "Release"
-msgstr "Version"
-
-#: sphinx/roles.py:53 sphinx/directives/desc.py:537
+#: sphinx/roles.py:53 sphinx/directives/desc.py:564
 #, python-format
 msgid "environment variable; %s"
 msgstr "variable d'environnement; %s"
@@ -105,14 +49,48 @@
 msgid "Python Enhancement Proposals!PEP %s"
 msgstr "Python Enhancement Proposals!PEP %s"
 
-#: sphinx/textwriter.py:166
+#: sphinx/builders/changes.py:64
+msgid "Builtins"
+msgstr "Fonctions de base"
+
+#: sphinx/builders/changes.py:66
+msgid "Module level"
+msgstr "Module"
+
+#: sphinx/builders/html.py:115
 #, python-format
-msgid "Platform: %s"
-msgstr "Plateforme : %s"
+msgid "%b %d, %Y"
+msgstr "%d %b %Y"
 
-#: sphinx/textwriter.py:422
-msgid "[image]"
-msgstr "[image]"
+#: sphinx/builders/html.py:134 sphinx/templates/defindex.html:21
+msgid "General Index"
+msgstr "Index général"
+
+#: sphinx/builders/html.py:134
+msgid "index"
+msgstr "index"
+
+#: sphinx/builders/html.py:136 sphinx/builders/htmlhelp.py:180
+#: sphinx/builders/qthelp.py:129 sphinx/templates/defindex.html:19
+#: sphinx/templates/modindex.html:2 sphinx/templates/modindex.html:13
+msgid "Global Module Index"
+msgstr "Index général des modules"
+
+#: sphinx/builders/html.py:136
+msgid "modules"
+msgstr "modules"
+
+#: sphinx/builders/html.py:175
+msgid "next"
+msgstr "suivant"
+
+#: sphinx/builders/html.py:182
+msgid "previous"
+msgstr "précédent"
+
+#: sphinx/builders/latex.py:155
+msgid " (in "
+msgstr "(dans"
 
 #: sphinx/directives/desc.py:25
 #, python-format
@@ -216,11 +194,16 @@
 msgid "Return type"
 msgstr "Type retourné"
 
-#: sphinx/directives/desc.py:143
+#: sphinx/directives/desc.py:201
+#, fuzzy
+msgid "Parameter"
+msgstr "Paramètres"
+
+#: sphinx/directives/desc.py:205
 msgid "Parameters"
 msgstr "Paramètres"
 
-#: sphinx/directives/desc.py:423
+#: sphinx/directives/desc.py:450
 #, python-format
 msgid "%scommand line option; %s"
 msgstr "%soption de ligne de commande; %s"
@@ -246,10 +229,15 @@
 msgid "Author: "
 msgstr "Auteur : "
 
-#: sphinx/directives/other.py:246
+#: sphinx/directives/other.py:249
 msgid "See also"
 msgstr "Voir aussi"
 
+#: sphinx/ext/autodoc.py:576 sphinx/ext/autodoc.py:590
+#, python-format
+msgid "alias of :class:`%s`"
+msgstr ""
+
 #: sphinx/ext/todo.py:31
 msgid "Todo"
 msgstr "A faire"
@@ -346,6 +334,14 @@
 msgid "built-in function"
 msgstr "fonction de base"
 
+#: sphinx/static/doctools.js:139 sphinx/writers/html.py:415
+msgid "Permalink to this headline"
+msgstr "Lien permanent vers ce titre"
+
+#: sphinx/static/doctools.js:145 sphinx/writers/html.py:80
+msgid "Permalink to this definition"
+msgstr "Lien permanent vers cette définition"
+
 #: sphinx/static/doctools.js:174
 msgid "Hide Search Matches"
 msgstr "Cacher les résultats de la recherche"
@@ -366,11 +362,11 @@
 msgid ", in "
 msgstr ", dans"
 
-#: sphinx/static/searchtools.js:447 sphinx/templates/search.html:18
+#: sphinx/static/searchtools.js:453 sphinx/templates/search.html:18
 msgid "Search Results"
 msgstr "Résultats de la recherche"
 
-#: sphinx/static/searchtools.js:449
+#: sphinx/static/searchtools.js:455
 msgid ""
 "Your search did not match any documents. Please make sure that all words "
 "are spelled correctly and that you've selected enough categories."
@@ -379,7 +375,7 @@
 "des termes de recherche et que vous avez sélectionné suffisamment de "
 "catégories."
 
-#: sphinx/static/searchtools.js:451
+#: sphinx/static/searchtools.js:457
 #, python-format
 msgid "Search finished, found %s page(s) matching the search query."
 msgstr "La recherche est terminée, %s page(s) correspond(ent) à la requête."
@@ -455,68 +451,61 @@
 msgid "next chapter"
 msgstr "Chapitre suivant"
 
-#: sphinx/templates/layout.html:55
+#: sphinx/templates/layout.html:56
 msgid "This Page"
 msgstr "Cette page"
 
-#: sphinx/templates/layout.html:59
-msgid "Suggest Change"
-msgstr "Suggérer une modification"
-
-#: sphinx/templates/layout.html:60 sphinx/templates/layout.html:62
+#: sphinx/templates/layout.html:58
 msgid "Show Source"
 msgstr "Montrer la source"
 
-#: sphinx/templates/layout.html:71
+#: sphinx/templates/layout.html:67
 msgid "Quick search"
 msgstr "Recherche rapide"
 
-#: sphinx/templates/layout.html:71
-msgid "Keyword search"
-msgstr "Recherche par mot-clé"
-
-#: sphinx/templates/layout.html:73
+#: sphinx/templates/layout.html:69
 msgid "Go"
 msgstr "Go"
 
-#: sphinx/templates/layout.html:78
-msgid "Enter a module, class or function name."
+#: sphinx/templates/layout.html:73
+#, fuzzy
+msgid "Enter search terms or a module, class or function name."
 msgstr "Saisissez un nom de module, classe ou fonction."
 
-#: sphinx/templates/layout.html:119
+#: sphinx/templates/layout.html:106
 #, python-format
 msgid "Search within %(docstitle)s"
 msgstr "Recherchez dans %(docstitle)s"
 
-#: sphinx/templates/layout.html:128
+#: sphinx/templates/layout.html:115
 msgid "About these documents"
 msgstr "À propos de ces documents"
 
-#: sphinx/templates/layout.html:131 sphinx/templates/search.html:2
+#: sphinx/templates/layout.html:118 sphinx/templates/search.html:2
 #: sphinx/templates/search.html:5
 msgid "Search"
 msgstr "Recherche"
 
-#: sphinx/templates/layout.html:133
+#: sphinx/templates/layout.html:120
 msgid "Copyright"
 msgstr "Copyright"
 
-#: sphinx/templates/layout.html:178
+#: sphinx/templates/layout.html:165
 #, python-format
 msgid "&copy; <a href=\"%(path)s\">Copyright</a> %(copyright)s."
 msgstr "&copy; <a href=\"%(path)s\">Copyright</a> %(copyright)s."
 
-#: sphinx/templates/layout.html:180
+#: sphinx/templates/layout.html:167
 #, python-format
 msgid "&copy; Copyright %(copyright)s."
 msgstr "&copy; Copyright %(copyright)s."
 
-#: sphinx/templates/layout.html:183
+#: sphinx/templates/layout.html:170
 #, python-format
 msgid "Last updated on %(last_updated)s."
 msgstr "Mis à jour le %(last_updated)s."
 
-#: sphinx/templates/layout.html:186
+#: sphinx/templates/layout.html:173
 #, python-format
 msgid ""
 "Created using <a href=\"http://sphinx.pocoo.org/\">Sphinx</a> "
@@ -525,15 +514,7 @@
 "Créé avec <a href=\"http://sphinx.pocoo.org/\">Sphinx</a> "
 "%(sphinx_version)s."
 
-#: sphinx/templates/modindex.html:15
-msgid "Most popular modules:"
-msgstr "Modules les plus utilisés :"
-
-#: sphinx/templates/modindex.html:24
-msgid "Show modules only available on these platforms"
-msgstr "N'afficher que les modules disponibles sur ces plateformes"
-
-#: sphinx/templates/modindex.html:56
+#: sphinx/templates/modindex.html:36
 msgid "Deprecated"
 msgstr "Obsolète"
 
@@ -542,16 +523,6 @@
 msgid "Search %(docstitle)s"
 msgstr "Rechercher %(docstitle)s"
 
-#: sphinx/templates/page.html:8
-msgid ""
-"<strong>Note:</strong> You requested an out-of-date URL from this server."
-" We've tried to redirect you to the new location of this page, but it may"
-" not be the right one."
-msgstr ""
-"<strong>Note :</strong> Vous tentez d'accéder à une ancienne URL de ce "
-"serveur. Nous avons essayé de vous rediriger vers la nouvelle adresse de "
-"cette page, mais ce n'est peut-être pas la bonne."
-
 #: sphinx/templates/search.html:7
 #, fuzzy
 msgid ""
@@ -604,3 +575,42 @@
 msgid "Other changes"
 msgstr "Autres modifications"
 
+#: sphinx/writers/latex.py:173
+msgid "Release"
+msgstr "Version"
+
+#: sphinx/writers/text.py:166
+#, python-format
+msgid "Platform: %s"
+msgstr "Plateforme : %s"
+
+#: sphinx/writers/text.py:427
+msgid "[image]"
+msgstr "[image]"
+
+#~ msgid "Suggest Change"
+#~ msgstr "Suggérer une modification"
+
+#~ msgid "Keyword search"
+#~ msgstr "Recherche par mot-clé"
+
+#~ msgid "Most popular modules:"
+#~ msgstr "Modules les plus utilisés :"
+
+#~ msgid "Show modules only available on these platforms"
+#~ msgstr "N'afficher que les modules disponibles sur ces plateformes"
+
+#~ msgid ""
+#~ "<strong>Note:</strong> You requested an "
+#~ "out-of-date URL from this server. "
+#~ "We've tried to redirect you to the"
+#~ " new location of this page, but "
+#~ "it may not be the right one."
+#~ msgstr ""
+#~ "<strong>Note :</strong> Vous tentez d'accéder"
+#~ " à une ancienne URL de ce "
+#~ "serveur. Nous avons essayé de vous "
+#~ "rediriger vers la nouvelle adresse de"
+#~ " cette page, mais ce n'est peut-être"
+#~ " pas la bonne."
+

Added: doctools/trunk/sphinx/locale/it/LC_MESSAGES/sphinx.js
==============================================================================
--- (empty file)
+++ doctools/trunk/sphinx/locale/it/LC_MESSAGES/sphinx.js	Sun Jan  4 21:38:57 2009
@@ -0,0 +1 @@
+Documentation.addTranslations({"locale": "it", "plural_expr": "(n != 1)", "messages": {"module, in ": "modulo, in", "Preparing search...": "Preparazione della ricerca", "Your search did not match any documents. Please make sure that all words are spelled correctly and that you've selected enough categories.": "La tua ricerca non ha trovato alcun risultato. Controlla la corettezzadei termini di ricerca e di avere selezionato un numero sufficiente di categorie", "Search finished, found %s page(s) matching the search query.": "Ricera terminata, trovate %s pagine corrispondenti alla ricerca.", ", in ": ", in ", "Permalink to this headline": "link permanente per questa inestazione", "Searching": "Ricerca in corso", "Permalink to this definition": "link permanente per questa definizione", "Hide Search Matches": "Nascondi i risultati della ricerca", "Search Results": "Risultati della ricerca"}});
\ No newline at end of file

Added: doctools/trunk/sphinx/locale/it/LC_MESSAGES/sphinx.mo
==============================================================================
Binary file. No diff available.

Added: doctools/trunk/sphinx/locale/it/LC_MESSAGES/sphinx.po
==============================================================================
--- (empty file)
+++ doctools/trunk/sphinx/locale/it/LC_MESSAGES/sphinx.po	Sun Jan  4 21:38:57 2009
@@ -0,0 +1,612 @@
+# Italian translations for Sphinx.
+# Copyright (C) 2008 ORGANIZATION
+# This file is distributed under the same license as the Sphinx project.
+# Sandro Dentella <sandro at e-den.it>, 2008.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: Sphinx 0.5\n"
+"Report-Msgid-Bugs-To: EMAIL at ADDRESS\n"
+"POT-Creation-Date: 2008-11-27 18:39+0100\n"
+"PO-Revision-Date: 2008-12-28 23:40+0100\n"
+"Last-Translator: FULL NAME <EMAIL at ADDRESS>\n"
+"Language-Team: it <LL at li.org>\n"
+"Plural-Forms: nplurals=2; plural=(n != 1)\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=utf-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Generated-By: Babel 0.9.3\n"
+
+#: sphinx/environment.py:103 sphinx/writers/latex.py:170
+#, python-format
+msgid "%B %d, %Y"
+msgstr "%d %B %Y"
+
+#: sphinx/environment.py:293 sphinx/templates/genindex-single.html:2
+#: sphinx/templates/genindex-split.html:2
+#: sphinx/templates/genindex-split.html:5 sphinx/templates/genindex.html:2
+#: sphinx/templates/genindex.html:5 sphinx/templates/genindex.html:48
+#: sphinx/templates/layout.html:117 sphinx/writers/latex.py:176
+msgid "Index"
+msgstr "Indice"
+
+#: sphinx/environment.py:294 sphinx/writers/latex.py:175
+msgid "Module Index"
+msgstr "Indice dei Moduli"
+
+#: sphinx/environment.py:295 sphinx/templates/defindex.html:16
+msgid "Search Page"
+msgstr "Cerca"
+
+#: sphinx/roles.py:53 sphinx/directives/desc.py:564
+#, python-format
+msgid "environment variable; %s"
+msgstr "variabile dámbiente, %s"
+
+#: sphinx/roles.py:60
+#, python-format
+msgid "Python Enhancement Proposals!PEP %s"
+msgstr "Python Enhancement Proposals!PEP %s"
+
+#: sphinx/builders/changes.py:64
+msgid "Builtins"
+msgstr "Builtin"
+
+#: sphinx/builders/changes.py:66
+msgid "Module level"
+msgstr "Modulo"
+
+#: sphinx/builders/html.py:115
+#, python-format
+msgid "%b %d, %Y"
+msgstr "%d/%b/%Y"
+
+#: sphinx/builders/html.py:134 sphinx/templates/defindex.html:21
+msgid "General Index"
+msgstr "Indice generale"
+
+#: sphinx/builders/html.py:134
+msgid "index"
+msgstr "indice"
+
+#: sphinx/builders/html.py:136 sphinx/builders/htmlhelp.py:180
+#: sphinx/builders/qthelp.py:129 sphinx/templates/defindex.html:19
+#: sphinx/templates/modindex.html:2 sphinx/templates/modindex.html:13
+msgid "Global Module Index"
+msgstr "Indice dei moduli"
+
+#: sphinx/builders/html.py:136
+msgid "modules"
+msgstr "moduli"
+
+#: sphinx/builders/html.py:175
+msgid "next"
+msgstr "successivo"
+
+#: sphinx/builders/html.py:182
+msgid "previous"
+msgstr "precedente"
+
+#: sphinx/builders/latex.py:155
+msgid " (in "
+msgstr " (in "
+
+#: sphinx/directives/desc.py:25
+#, python-format
+msgid "%s() (built-in function)"
+msgstr "%s() (funzione built-in)"
+
+#: sphinx/directives/desc.py:26 sphinx/directives/desc.py:42
+#: sphinx/directives/desc.py:54
+#, python-format
+msgid "%s() (in module %s)"
+msgstr "%s() (nel modulo %s)"
+
+#: sphinx/directives/desc.py:29
+#, python-format
+msgid "%s (built-in variable)"
+msgstr "%s (variabile built-in)"
+
+#: sphinx/directives/desc.py:30 sphinx/directives/desc.py:66
+#, python-format
+msgid "%s (in module %s)"
+msgstr "%s (nel modulo %s)"
+
+#: sphinx/directives/desc.py:33
+#, python-format
+msgid "%s (built-in class)"
+msgstr "%s (classe built-in)"
+
+#: sphinx/directives/desc.py:34
+#, python-format
+msgid "%s (class in %s)"
+msgstr "%s (classe in %s)"
+
+#: sphinx/directives/desc.py:46
+#, python-format
+msgid "%s() (%s.%s method)"
+msgstr "%s() (%s.%s metodo)"
+
+#: sphinx/directives/desc.py:48
+#, python-format
+msgid "%s() (%s method)"
+msgstr "%s() (%s metodo)"
+
+#: sphinx/directives/desc.py:58
+#, python-format
+msgid "%s() (%s.%s static method)"
+msgstr "%s() (%s.%s metodo statico)"
+
+#: sphinx/directives/desc.py:60
+#, python-format
+msgid "%s() (%s static method)"
+msgstr "%s() (%s metodo statico)"
+
+#: sphinx/directives/desc.py:70
+#, python-format
+msgid "%s (%s.%s attribute)"
+msgstr "%s (%s.%s attributo)"
+
+#: sphinx/directives/desc.py:72
+#, python-format
+msgid "%s (%s attribute)"
+msgstr "%s (%s attributo)"
+
+#: sphinx/directives/desc.py:74
+#, python-format
+msgid "%s (C function)"
+msgstr "%s (functione C)"
+
+#: sphinx/directives/desc.py:76
+#, python-format
+msgid "%s (C member)"
+msgstr "%s (membro C )"
+
+#: sphinx/directives/desc.py:78
+#, python-format
+msgid "%s (C macro)"
+msgstr "%s (macro C)"
+
+#: sphinx/directives/desc.py:80
+#, python-format
+msgid "%s (C type)"
+msgstr "%s (tipo C)"
+
+#: sphinx/directives/desc.py:82
+#, python-format
+msgid "%s (C variable)"
+msgstr "%s (variabile C)"
+
+#: sphinx/directives/desc.py:100
+msgid "Raises"
+msgstr "Solleva"
+
+#: sphinx/directives/desc.py:104
+msgid "Variable"
+msgstr "Variabile"
+
+#: sphinx/directives/desc.py:107
+msgid "Returns"
+msgstr "Ritorna"
+
+#: sphinx/directives/desc.py:116
+msgid "Return type"
+msgstr "Tipo di ritorno"
+
+#: sphinx/directives/desc.py:201
+#, fuzzy
+msgid "Parameter"
+msgstr "Parametri"
+
+#: sphinx/directives/desc.py:205
+msgid "Parameters"
+msgstr "Parametri"
+
+#: sphinx/directives/desc.py:450
+#, python-format
+msgid "%scommand line option; %s"
+msgstr "%sopzione di linea di comando; %s"
+
+#: sphinx/directives/other.py:101
+msgid "Platforms: "
+msgstr "Piattaforme:"
+
+#: sphinx/directives/other.py:106
+#, python-format
+msgid "%s (module)"
+msgstr "%s (modulo)"
+
+#: sphinx/directives/other.py:146
+msgid "Section author: "
+msgstr "Autore della sezione"
+
+#: sphinx/directives/other.py:148
+msgid "Module author: "
+msgstr "Autore del modulo"
+
+#: sphinx/directives/other.py:150
+msgid "Author: "
+msgstr "Autore: "
+
+#: sphinx/directives/other.py:249
+msgid "See also"
+msgstr "Vedi anche"
+
+#: sphinx/ext/autodoc.py:576 sphinx/ext/autodoc.py:590
+#, python-format
+msgid "alias of :class:`%s`"
+msgstr ""
+
+#: sphinx/ext/todo.py:31
+msgid "Todo"
+msgstr "Da fare"
+
+#: sphinx/ext/todo.py:75
+#, python-format
+msgid "(The original entry is located in %s, line %d and can be found "
+msgstr "(La riga originale si trova in %s, linea %d e può essere trovata "
+
+#: sphinx/ext/todo.py:81
+msgid "here"
+msgstr "qui"
+
+#: sphinx/locale/__init__.py:15
+msgid "Attention"
+msgstr "Attenzione"
+
+#: sphinx/locale/__init__.py:16
+msgid "Caution"
+msgstr "Attenzione"
+
+#: sphinx/locale/__init__.py:17
+msgid "Danger"
+msgstr "Pericolo"
+
+#: sphinx/locale/__init__.py:18
+msgid "Error"
+msgstr "Errore"
+
+#: sphinx/locale/__init__.py:19
+msgid "Hint"
+msgstr "Consiglio"
+
+#: sphinx/locale/__init__.py:20
+msgid "Important"
+msgstr "Importante"
+
+#: sphinx/locale/__init__.py:21
+msgid "Note"
+msgstr "Nota"
+
+#: sphinx/locale/__init__.py:22
+msgid "See Also"
+msgstr "Vedi anche"
+
+#: sphinx/locale/__init__.py:23
+msgid "Tip"
+msgstr "Suggerimento"
+
+#: sphinx/locale/__init__.py:24
+msgid "Warning"
+msgstr "Avvertimento"
+
+#: sphinx/locale/__init__.py:28
+#, python-format
+msgid "New in version %s"
+msgstr "Nuovo nella versione %s"
+
+#: sphinx/locale/__init__.py:29
+#, python-format
+msgid "Changed in version %s"
+msgstr "Cambiato nella versione %s"
+
+#: sphinx/locale/__init__.py:30
+#, python-format
+msgid "Deprecated since version %s"
+msgstr "Deprecato dalla versione %s"
+
+#: sphinx/locale/__init__.py:34
+msgid "module"
+msgstr "modulo"
+
+#: sphinx/locale/__init__.py:35
+msgid "keyword"
+msgstr "keyword"
+
+#: sphinx/locale/__init__.py:36
+msgid "operator"
+msgstr "operatore"
+
+#: sphinx/locale/__init__.py:37
+msgid "object"
+msgstr "oggetto"
+
+#: sphinx/locale/__init__.py:38
+msgid "exception"
+msgstr "eccezione"
+
+#: sphinx/locale/__init__.py:39
+msgid "statement"
+msgstr "statement"
+
+#: sphinx/locale/__init__.py:40
+msgid "built-in function"
+msgstr "funzione built-in"
+
+#: sphinx/static/doctools.js:139 sphinx/writers/html.py:415
+msgid "Permalink to this headline"
+msgstr "link permanente per questa inestazione"
+
+#: sphinx/static/doctools.js:145 sphinx/writers/html.py:80
+msgid "Permalink to this definition"
+msgstr "link permanente per questa definizione"
+
+#: sphinx/static/doctools.js:174
+msgid "Hide Search Matches"
+msgstr "Nascondi i risultati della ricerca"
+
+#: sphinx/static/searchtools.js:274
+msgid "Searching"
+msgstr "Ricerca in corso"
+
+#: sphinx/static/searchtools.js:279
+msgid "Preparing search..."
+msgstr "Preparazione della ricerca"
+
+#: sphinx/static/searchtools.js:338
+msgid "module, in "
+msgstr "modulo, in"
+
+#: sphinx/static/searchtools.js:347
+msgid ", in "
+msgstr ", in "
+
+#: sphinx/static/searchtools.js:453 sphinx/templates/search.html:18
+msgid "Search Results"
+msgstr "Risultati della ricerca"
+
+#: sphinx/static/searchtools.js:455
+msgid ""
+"Your search did not match any documents. Please make sure that all words "
+"are spelled correctly and that you've selected enough categories."
+msgstr ""
+"La tua ricerca non ha trovato alcun risultato. Controlla la corettezzadei"
+" termini di ricerca e di avere selezionato un numero sufficiente di "
+"categorie"
+
+#: sphinx/static/searchtools.js:457
+#, python-format
+msgid "Search finished, found %s page(s) matching the search query."
+msgstr "Ricera terminata, trovate %s pagine corrispondenti alla ricerca."
+
+#: sphinx/templates/defindex.html:2
+msgid "Overview"
+msgstr "Sintesi"
+
+#: sphinx/templates/defindex.html:11
+msgid "Indices and tables:"
+msgstr "Indici e tabelle:"
+
+#: sphinx/templates/defindex.html:14
+msgid "Complete Table of Contents"
+msgstr "Tabella dei contenuti completa"
+
+#: sphinx/templates/defindex.html:15
+msgid "lists all sections and subsections"
+msgstr "elenca l'insieme delle sezioni e sottosezioni"
+
+#: sphinx/templates/defindex.html:17
+msgid "search this documentation"
+msgstr "cerca in questa documentazione"
+
+#: sphinx/templates/defindex.html:20
+msgid "quick access to all modules"
+msgstr "accesso veloce ai moduli"
+
+#: sphinx/templates/defindex.html:22
+msgid "all functions, classes, terms"
+msgstr "tutte le funzioni, classi e moduli"
+
+#: sphinx/templates/genindex-single.html:5
+#, python-format
+msgid "Index &ndash; %(key)s"
+msgstr "Indice &ndash; %(key)s"
+
+#: sphinx/templates/genindex-single.html:44
+#: sphinx/templates/genindex-split.html:14
+#: sphinx/templates/genindex-split.html:27 sphinx/templates/genindex.html:54
+msgid "Full index on one page"
+msgstr "Indice completo in una pagina"
+
+#: sphinx/templates/genindex-split.html:7
+msgid "Index pages by letter"
+msgstr "Indice delle pagine per lettera"
+
+#: sphinx/templates/genindex-split.html:15
+msgid "can be huge"
+msgstr "può essere enorme"
+
+#: sphinx/templates/layout.html:9
+msgid "Navigation"
+msgstr "Navigazione"
+
+#: sphinx/templates/layout.html:40
+msgid "Table Of Contents"
+msgstr "Tablella dei contenuti"
+
+#: sphinx/templates/layout.html:46
+msgid "Previous topic"
+msgstr "Argomento precedente"
+
+#: sphinx/templates/layout.html:47
+msgid "previous chapter"
+msgstr "capitolo precedente"
+
+#: sphinx/templates/layout.html:50
+msgid "Next topic"
+msgstr "Argomento successivo"
+
+#: sphinx/templates/layout.html:51
+msgid "next chapter"
+msgstr "capitolo successivo"
+
+#: sphinx/templates/layout.html:56
+msgid "This Page"
+msgstr "Questa pagina"
+
+#: sphinx/templates/layout.html:58
+msgid "Show Source"
+msgstr "Mostra sorgente"
+
+#: sphinx/templates/layout.html:67
+msgid "Quick search"
+msgstr "Ricerca veloce"
+
+#: sphinx/templates/layout.html:69
+msgid "Go"
+msgstr "Vai"
+
+#: sphinx/templates/layout.html:73
+#, fuzzy
+msgid "Enter search terms or a module, class or function name."
+msgstr "Inserisci un modulo, classe o nome di funzione"
+
+#: sphinx/templates/layout.html:106
+#, python-format
+msgid "Search within %(docstitle)s"
+msgstr "Cerca in %(docstitle)s"
+
+#: sphinx/templates/layout.html:115
+msgid "About these documents"
+msgstr "A proposito di questi documenti"
+
+#: sphinx/templates/layout.html:118 sphinx/templates/search.html:2
+#: sphinx/templates/search.html:5
+msgid "Search"
+msgstr "Cerca"
+
+#: sphinx/templates/layout.html:120
+msgid "Copyright"
+msgstr "Copyright"
+
+#: sphinx/templates/layout.html:165
+#, python-format
+msgid "&copy; <a href=\"%(path)s\">Copyright</a> %(copyright)s."
+msgstr "&copy; <a href=\"%(path)s\">Copyright</a> %(copyright)s."
+
+#: sphinx/templates/layout.html:167
+#, python-format
+msgid "&copy; Copyright %(copyright)s."
+msgstr "&copy; Copyright %(copyright)s."
+
+#: sphinx/templates/layout.html:170
+#, python-format
+msgid "Last updated on %(last_updated)s."
+msgstr "Ultimo Aggiornamento on %(last_updated)s."
+
+#: sphinx/templates/layout.html:173
+#, python-format
+msgid ""
+"Created using <a href=\"http://sphinx.pocoo.org/\">Sphinx</a> "
+"%(sphinx_version)s."
+msgstr ""
+"Creato con <a href=\"http://sphinx.pocoo.org/\">Sphinx</a> "
+"%(sphinx_version)s."
+
+#: sphinx/templates/modindex.html:36
+msgid "Deprecated"
+msgstr "Deprecato"
+
+#: sphinx/templates/opensearch.xml:4
+#, python-format
+msgid "Search %(docstitle)s"
+msgstr "Cerca %(docstitle)s"
+
+#: sphinx/templates/search.html:7
+msgid ""
+"From here you can search these documents. Enter your search\n"
+"    words into the box below and click \"search\". Note that the search\n"
+"    function will automatically search for all of the words. Pages\n"
+"    containing fewer words won't appear in the result list."
+msgstr ""
+"Puoi effettuare una ricerca in questi documenti. Immetti le parole chiave"
+" \n"
+"    della tua ricerca nel riquadro sottostante \"search\". Nota che la "
+"funzione\n"
+"    di ricerca cerca automaticamente per tutte le parole. Le pagine\n"
+"    che contendono meno parole non compariranno nei risultati di ricerca."
+
+#: sphinx/templates/search.html:14
+msgid "search"
+msgstr "cerca"
+
+#: sphinx/templates/search.html:20
+msgid "Your search did not match any results."
+msgstr "La tua ricerca non ha ottenuto risultati"
+
+#: sphinx/templates/changes/frameset.html:5
+#: sphinx/templates/changes/versionchanges.html:12
+#, python-format
+msgid "Changes in Version %(version)s &mdash; %(docstitle)s"
+msgstr "Modifiche nella  Versione %(version)s &mdash; %(docstitle)s"
+
+#: sphinx/templates/changes/rstsource.html:5
+#, python-format
+msgid "%(filename)s &mdash; %(docstitle)s"
+msgstr "%(filename)s &mdash; %(docstitle)s"
+
+#: sphinx/templates/changes/versionchanges.html:17
+#, python-format
+msgid "Automatically generated list of changes in version %(version)s"
+msgstr "Lista delle modifiche generata automaticamente nella versione %(version)s"
+
+#: sphinx/templates/changes/versionchanges.html:18
+msgid "Library changes"
+msgstr "Modifiche nela libreria"
+
+#: sphinx/templates/changes/versionchanges.html:23
+msgid "C API changes"
+msgstr "Modifche nelle API C"
+
+#: sphinx/templates/changes/versionchanges.html:25
+msgid "Other changes"
+msgstr "Altre modifiche"
+
+#: sphinx/writers/latex.py:173
+#, fuzzy
+msgid "Release"
+msgstr "Release"
+
+#: sphinx/writers/text.py:166
+#, python-format
+msgid "Platform: %s"
+msgstr "Piattaforma: %s"
+
+#: sphinx/writers/text.py:427
+msgid "[image]"
+msgstr "[immagine]"
+
+#~ msgid "Suggest Change"
+#~ msgstr "Suggerisci una modifica"
+
+#~ msgid "Keyword search"
+#~ msgstr "Ricerca per parola chiave"
+
+#~ msgid "Most popular modules:"
+#~ msgstr "Moduli più utilizzati"
+
+#~ msgid "Show modules only available on these platforms"
+#~ msgstr "Mostra solo i moduli disponibili su questa piattaforma"
+
+#~ msgid ""
+#~ "<strong>Note:</strong> You requested an "
+#~ "out-of-date URL from this server. "
+#~ "We've tried to redirect you to the"
+#~ " new location of this page, but "
+#~ "it may not be the right one."
+#~ msgstr ""
+#~ "<strong>Nota:</strong> Hai chiesto un URL "
+#~ "non più valido. Abbiamo provato a "
+#~ "ridirigerti verso il nuovo indirizzo, ma"
+#~ " potrebbe  non essere quello giusto"
+

Modified: doctools/trunk/sphinx/locale/ja/LC_MESSAGES/sphinx.po
==============================================================================
--- doctools/trunk/sphinx/locale/ja/LC_MESSAGES/sphinx.po	(original)
+++ doctools/trunk/sphinx/locale/ja/LC_MESSAGES/sphinx.po	Sun Jan  4 21:38:57 2009
@@ -8,93 +8,37 @@
 "Project-Id-Version: Sphinx 0.5\n"
 "Report-Msgid-Bugs-To: EMAIL at ADDRESS\n"
 "POT-Creation-Date: 2008-09-11 23:58+0200\n"
-"PO-Revision-Date: 2008-11-27 18:40+0100\n"
+"PO-Revision-Date: 2008-12-28 23:40+0100\n"
 "Last-Translator: Yasushi MASUDA <whosaysni at gmail.com>\n"
 "Language-Team: ja <LL at li.org>\n"
 "Plural-Forms: nplurals=1; plural=0\n"
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=utf-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"Generated-By: Babel 0.9.4\n"
+"Generated-By: Babel 0.9.3\n"
 
-#: sphinx/builder.py:408
-#, python-format
-msgid "%b %d, %Y"
-msgstr "%Y 年 %m 月 %d 日"
-
-#: sphinx/builder.py:427 sphinx/templates/defindex.html:21
-msgid "General Index"
-msgstr "総合索引"
-
-#: sphinx/builder.py:427
-msgid "index"
-msgstr "索引"
-
-#: sphinx/builder.py:429 sphinx/htmlhelp.py:156
-#: sphinx/templates/defindex.html:19 sphinx/templates/modindex.html:2
-#: sphinx/templates/modindex.html:13
-msgid "Global Module Index"
-msgstr "モジュール総索引"
-
-#: sphinx/builder.py:429
-msgid "modules"
-msgstr "モジュール"
-
-#: sphinx/builder.py:466
-msgid "next"
-msgstr "次へ"
-
-#: sphinx/builder.py:473
-msgid "previous"
-msgstr "前へ"
-
-#: sphinx/builder.py:1054
-msgid " (in "
-msgstr ""
-
-#: sphinx/builder.py:1129
-msgid "Builtins"
-msgstr "組み込み"
-
-#: sphinx/builder.py:1131
-msgid "Module level"
-msgstr "モジュールレベル"
-
-#: sphinx/environment.py:102 sphinx/latexwriter.py:169
+#: sphinx/environment.py:103 sphinx/writers/latex.py:170
 #, python-format
 msgid "%B %d, %Y"
 msgstr "%Y 年 %m 月 %d 日"
 
-#: sphinx/environment.py:291 sphinx/latexwriter.py:175
-#: sphinx/templates/genindex-single.html:2
+#: sphinx/environment.py:293 sphinx/templates/genindex-single.html:2
 #: sphinx/templates/genindex-split.html:2
 #: sphinx/templates/genindex-split.html:5 sphinx/templates/genindex.html:2
 #: sphinx/templates/genindex.html:5 sphinx/templates/genindex.html:48
-#: sphinx/templates/layout.html:130
+#: sphinx/templates/layout.html:117 sphinx/writers/latex.py:176
 msgid "Index"
 msgstr "索引"
 
-#: sphinx/environment.py:292 sphinx/latexwriter.py:174
+#: sphinx/environment.py:294 sphinx/writers/latex.py:175
 msgid "Module Index"
 msgstr "モジュール索引"
 
-#: sphinx/environment.py:293 sphinx/templates/defindex.html:16
+#: sphinx/environment.py:295 sphinx/templates/defindex.html:16
 msgid "Search Page"
 msgstr "検索ページ"
 
-#: sphinx/htmlwriter.py:79 sphinx/static/doctools.js:145
-msgid "Permalink to this definition"
-msgstr "この定義へのパーマリンク"
-
-#: sphinx/htmlwriter.py:399 sphinx/static/doctools.js:139
-msgid "Permalink to this headline"
-msgstr "このヘッドラインへのパーマリンク"
-
-#: sphinx/latexwriter.py:172
-msgid "Release"
-msgstr "リリース"
-
-#: sphinx/roles.py:53 sphinx/directives/desc.py:537
+#: sphinx/roles.py:53 sphinx/directives/desc.py:564
 #, python-format
 msgid "environment variable; %s"
 msgstr "環境変数; %s"
@@ -104,14 +48,48 @@
 msgid "Python Enhancement Proposals!PEP %s"
 msgstr "Python Enhancement Proposals!PEP %s"
 
-#: sphinx/textwriter.py:166
+#: sphinx/builders/changes.py:64
+msgid "Builtins"
+msgstr "組み込み"
+
+#: sphinx/builders/changes.py:66
+msgid "Module level"
+msgstr "モジュールレベル"
+
+#: sphinx/builders/html.py:115
 #, python-format
-msgid "Platform: %s"
-msgstr "プラットフォーム: %s"
+msgid "%b %d, %Y"
+msgstr "%Y 年 %m 月 %d 日"
 
-#: sphinx/textwriter.py:422
-msgid "[image]"
-msgstr "[画像]"
+#: sphinx/builders/html.py:134 sphinx/templates/defindex.html:21
+msgid "General Index"
+msgstr "総合索引"
+
+#: sphinx/builders/html.py:134
+msgid "index"
+msgstr "索引"
+
+#: sphinx/builders/html.py:136 sphinx/builders/htmlhelp.py:180
+#: sphinx/builders/qthelp.py:129 sphinx/templates/defindex.html:19
+#: sphinx/templates/modindex.html:2 sphinx/templates/modindex.html:13
+msgid "Global Module Index"
+msgstr "モジュール総索引"
+
+#: sphinx/builders/html.py:136
+msgid "modules"
+msgstr "モジュール"
+
+#: sphinx/builders/html.py:175
+msgid "next"
+msgstr "次へ"
+
+#: sphinx/builders/html.py:182
+msgid "previous"
+msgstr "前へ"
+
+#: sphinx/builders/latex.py:155
+msgid " (in "
+msgstr ""
 
 #: sphinx/directives/desc.py:25
 #, python-format
@@ -215,11 +193,16 @@
 msgid "Return type"
 msgstr "戻り値の型"
 
-#: sphinx/directives/desc.py:143
+#: sphinx/directives/desc.py:201
+#, fuzzy
+msgid "Parameter"
+msgstr "パラメタ"
+
+#: sphinx/directives/desc.py:205
 msgid "Parameters"
 msgstr "パラメタ"
 
-#: sphinx/directives/desc.py:423
+#: sphinx/directives/desc.py:450
 #, fuzzy, python-format
 msgid "%scommand line option; %s"
 msgstr "%sコマンドラインオプション; %s"
@@ -245,10 +228,15 @@
 msgid "Author: "
 msgstr "作者: "
 
-#: sphinx/directives/other.py:246
+#: sphinx/directives/other.py:249
 msgid "See also"
 msgstr "参考"
 
+#: sphinx/ext/autodoc.py:576 sphinx/ext/autodoc.py:590
+#, python-format
+msgid "alias of :class:`%s`"
+msgstr ""
+
 #: sphinx/ext/todo.py:31
 msgid "Todo"
 msgstr ""
@@ -345,6 +333,14 @@
 msgid "built-in function"
 msgstr "組み込み関数"
 
+#: sphinx/static/doctools.js:139 sphinx/writers/html.py:415
+msgid "Permalink to this headline"
+msgstr "このヘッドラインへのパーマリンク"
+
+#: sphinx/static/doctools.js:145 sphinx/writers/html.py:80
+msgid "Permalink to this definition"
+msgstr "この定義へのパーマリンク"
+
 #: sphinx/static/doctools.js:174
 msgid "Hide Search Matches"
 msgstr "検索結果を隠す"
@@ -366,17 +362,17 @@
 msgid ", in "
 msgstr ""
 
-#: sphinx/static/searchtools.js:447 sphinx/templates/search.html:18
+#: sphinx/static/searchtools.js:453 sphinx/templates/search.html:18
 msgid "Search Results"
 msgstr "検索結果"
 
-#: sphinx/static/searchtools.js:449
+#: sphinx/static/searchtools.js:455
 msgid ""
 "Your search did not match any documents. Please make sure that all words "
 "are spelled correctly and that you've selected enough categories."
 msgstr "検索条件に一致するドキュメントはありませんでした。検索したい言葉を正しいつづりで入力しているか確認してください。また、正しいカテゴリの検索を行っているか確認してください。"
 
-#: sphinx/static/searchtools.js:451
+#: sphinx/static/searchtools.js:457
 #, python-format
 msgid "Search finished, found %s page(s) matching the search query."
 msgstr "検索が終了し、条件に一致するページが %s 個みつかりました。"
@@ -452,68 +448,61 @@
 msgid "next chapter"
 msgstr "次の章へ"
 
-#: sphinx/templates/layout.html:55
+#: sphinx/templates/layout.html:56
 msgid "This Page"
 msgstr "このページ"
 
-#: sphinx/templates/layout.html:59
-msgid "Suggest Change"
-msgstr "変更のサジェスト"
-
-#: sphinx/templates/layout.html:60 sphinx/templates/layout.html:62
+#: sphinx/templates/layout.html:58
 msgid "Show Source"
 msgstr "ソースコードを表示"
 
-#: sphinx/templates/layout.html:71
+#: sphinx/templates/layout.html:67
 msgid "Quick search"
 msgstr "クイック検索"
 
-#: sphinx/templates/layout.html:71
-msgid "Keyword search"
-msgstr "キーワード検索"
-
-#: sphinx/templates/layout.html:73
+#: sphinx/templates/layout.html:69
 msgid "Go"
 msgstr "検索"
 
-#: sphinx/templates/layout.html:78
-msgid "Enter a module, class or function name."
+#: sphinx/templates/layout.html:73
+#, fuzzy
+msgid "Enter search terms or a module, class or function name."
 msgstr "モジュール、クラス、または関数名を入力してください"
 
-#: sphinx/templates/layout.html:119
+#: sphinx/templates/layout.html:106
 #, python-format
 msgid "Search within %(docstitle)s"
 msgstr "%(docstitle)s 内を検索"
 
-#: sphinx/templates/layout.html:128
+#: sphinx/templates/layout.html:115
 msgid "About these documents"
 msgstr "このドキュメントについて"
 
-#: sphinx/templates/layout.html:131 sphinx/templates/search.html:2
+#: sphinx/templates/layout.html:118 sphinx/templates/search.html:2
 #: sphinx/templates/search.html:5
 msgid "Search"
 msgstr "検索"
 
-#: sphinx/templates/layout.html:133
+#: sphinx/templates/layout.html:120
 msgid "Copyright"
 msgstr "著作権"
 
-#: sphinx/templates/layout.html:178
+#: sphinx/templates/layout.html:165
 #, python-format
 msgid "&copy; <a href=\"%(path)s\">Copyright</a> %(copyright)s."
 msgstr "&copy; <a href=\"%(path)s\">Copyright</a> %(copyright)s."
 
-#: sphinx/templates/layout.html:180
+#: sphinx/templates/layout.html:167
 #, python-format
 msgid "&copy; Copyright %(copyright)s."
 msgstr "&copy; Copyright %(copyright)s."
 
-#: sphinx/templates/layout.html:183
+#: sphinx/templates/layout.html:170
 #, python-format
 msgid "Last updated on %(last_updated)s."
 msgstr "最終更新: %(last_updated)s"
 
-#: sphinx/templates/layout.html:186
+#: sphinx/templates/layout.html:173
 #, python-format
 msgid ""
 "Created using <a href=\"http://sphinx.pocoo.org/\">Sphinx</a> "
@@ -522,15 +511,7 @@
 "このドキュメントは <a href=\"http://sphinx.pocoo.org/\">Sphinx</a> "
 "%(sphinx_version)s で生成しました。"
 
-#: sphinx/templates/modindex.html:15
-msgid "Most popular modules:"
-msgstr "よく参照されているモジュール:"
-
-#: sphinx/templates/modindex.html:24
-msgid "Show modules only available on these platforms"
-msgstr "このプラットフォームで利用可能なモジュールだけを表示する"
-
-#: sphinx/templates/modindex.html:56
+#: sphinx/templates/modindex.html:36
 msgid "Deprecated"
 msgstr "撤廃"
 
@@ -539,15 +520,6 @@
 msgid "Search %(docstitle)s"
 msgstr "%(docstitle)s 内を検索"
 
-#: sphinx/templates/page.html:8
-msgid ""
-"<strong>Note:</strong> You requested an out-of-date URL from this server."
-" We've tried to redirect you to the new location of this page, but it may"
-" not be the right one."
-msgstr ""
-"<strong>注意:</strong> あなたが表示しようとしているのは古い URL です。このページに対応する新しい URL "
-"へのリダイレクトを試みますが、適切なリダイレクト先でないかもしれないので注意してください。"
-
 #: sphinx/templates/search.html:7
 #, fuzzy
 msgid ""
@@ -593,3 +565,39 @@
 msgid "Other changes"
 msgstr "その多の変更"
 
+#: sphinx/writers/latex.py:173
+msgid "Release"
+msgstr "リリース"
+
+#: sphinx/writers/text.py:166
+#, python-format
+msgid "Platform: %s"
+msgstr "プラットフォーム: %s"
+
+#: sphinx/writers/text.py:427
+msgid "[image]"
+msgstr "[画像]"
+
+#~ msgid "Suggest Change"
+#~ msgstr "変更のサジェスト"
+
+#~ msgid "Keyword search"
+#~ msgstr "キーワード検索"
+
+#~ msgid "Most popular modules:"
+#~ msgstr "よく参照されているモジュール:"
+
+#~ msgid "Show modules only available on these platforms"
+#~ msgstr "このプラットフォームで利用可能なモジュールだけを表示する"
+
+#~ msgid ""
+#~ "<strong>Note:</strong> You requested an "
+#~ "out-of-date URL from this server. "
+#~ "We've tried to redirect you to the"
+#~ " new location of this page, but "
+#~ "it may not be the right one."
+#~ msgstr ""
+#~ "<strong>注意:</strong> あなたが表示しようとしているのは古い URL "
+#~ "です。このページに対応する新しい URL "
+#~ "へのリダイレクトを試みますが、適切なリダイレクト先でないかもしれないので注意してください。"
+

Modified: doctools/trunk/sphinx/locale/nl/LC_MESSAGES/sphinx.po
==============================================================================
--- doctools/trunk/sphinx/locale/nl/LC_MESSAGES/sphinx.po	(original)
+++ doctools/trunk/sphinx/locale/nl/LC_MESSAGES/sphinx.po	Sun Jan  4 21:38:57 2009
@@ -7,93 +7,37 @@
 "Project-Id-Version: Sphinx 0.5\n"
 "Report-Msgid-Bugs-To: EMAIL at ADDRESS\n"
 "POT-Creation-Date: 2008-09-11 23:58+0200\n"
-"PO-Revision-Date: 2008-11-27 18:40+0100\n"
+"PO-Revision-Date: 2008-12-28 23:40+0100\n"
 "Last-Translator: FULL NAME <EMAIL at ADDRESS>\n"
 "Language-Team: nl <LL at li.org>\n"
 "Plural-Forms: nplurals=2; plural=(n != 1)\n"
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=utf-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"Generated-By: Babel 0.9.4\n"
+"Generated-By: Babel 0.9.3\n"
 
-#: sphinx/builder.py:408
-#, python-format
-msgid "%b %d, %Y"
-msgstr "%d.%b.%Y"
-
-#: sphinx/builder.py:427 sphinx/templates/defindex.html:21
-msgid "General Index"
-msgstr "Algemene index"
-
-#: sphinx/builder.py:427
-msgid "index"
-msgstr "Index"
-
-#: sphinx/builder.py:429 sphinx/htmlhelp.py:156
-#: sphinx/templates/defindex.html:19 sphinx/templates/modindex.html:2
-#: sphinx/templates/modindex.html:13
-msgid "Global Module Index"
-msgstr "Globale Module-index"
-
-#: sphinx/builder.py:429
-msgid "modules"
-msgstr "modules"
-
-#: sphinx/builder.py:466
-msgid "next"
-msgstr "volgende"
-
-#: sphinx/builder.py:473
-msgid "previous"
-msgstr "vorige"
-
-#: sphinx/builder.py:1054
-msgid " (in "
-msgstr ""
-
-#: sphinx/builder.py:1129
-msgid "Builtins"
-msgstr "Builtins"
-
-#: sphinx/builder.py:1131
-msgid "Module level"
-msgstr "Moduleniveau"
-
-#: sphinx/environment.py:102 sphinx/latexwriter.py:169
+#: sphinx/environment.py:103 sphinx/writers/latex.py:170
 #, python-format
 msgid "%B %d, %Y"
 msgstr "%d. %B %Y"
 
-#: sphinx/environment.py:291 sphinx/latexwriter.py:175
-#: sphinx/templates/genindex-single.html:2
+#: sphinx/environment.py:293 sphinx/templates/genindex-single.html:2
 #: sphinx/templates/genindex-split.html:2
 #: sphinx/templates/genindex-split.html:5 sphinx/templates/genindex.html:2
 #: sphinx/templates/genindex.html:5 sphinx/templates/genindex.html:48
-#: sphinx/templates/layout.html:130
+#: sphinx/templates/layout.html:117 sphinx/writers/latex.py:176
 msgid "Index"
 msgstr "Index"
 
-#: sphinx/environment.py:292 sphinx/latexwriter.py:174
+#: sphinx/environment.py:294 sphinx/writers/latex.py:175
 msgid "Module Index"
 msgstr "Module-index"
 
-#: sphinx/environment.py:293 sphinx/templates/defindex.html:16
+#: sphinx/environment.py:295 sphinx/templates/defindex.html:16
 msgid "Search Page"
 msgstr "Zoekpagina"
 
-#: sphinx/htmlwriter.py:79 sphinx/static/doctools.js:145
-msgid "Permalink to this definition"
-msgstr "Permanente link naar deze definitie"
-
-#: sphinx/htmlwriter.py:399 sphinx/static/doctools.js:139
-msgid "Permalink to this headline"
-msgstr "Permanente link naar deze titel"
-
-#: sphinx/latexwriter.py:172
-msgid "Release"
-msgstr "Release"
-
-#: sphinx/roles.py:53 sphinx/directives/desc.py:537
+#: sphinx/roles.py:53 sphinx/directives/desc.py:564
 #, python-format
 msgid "environment variable; %s"
 msgstr "Omgevingsvariabele; %s"
@@ -103,14 +47,48 @@
 msgid "Python Enhancement Proposals!PEP %s"
 msgstr "Python Enhancement Proposals!PEP %s"
 
-#: sphinx/textwriter.py:166
+#: sphinx/builders/changes.py:64
+msgid "Builtins"
+msgstr "Builtins"
+
+#: sphinx/builders/changes.py:66
+msgid "Module level"
+msgstr "Moduleniveau"
+
+#: sphinx/builders/html.py:115
 #, python-format
-msgid "Platform: %s"
-msgstr "Platform: %s"
+msgid "%b %d, %Y"
+msgstr "%d.%b.%Y"
 
-#: sphinx/textwriter.py:422
-msgid "[image]"
-msgstr "[afbeelding]"
+#: sphinx/builders/html.py:134 sphinx/templates/defindex.html:21
+msgid "General Index"
+msgstr "Algemene index"
+
+#: sphinx/builders/html.py:134
+msgid "index"
+msgstr "Index"
+
+#: sphinx/builders/html.py:136 sphinx/builders/htmlhelp.py:180
+#: sphinx/builders/qthelp.py:129 sphinx/templates/defindex.html:19
+#: sphinx/templates/modindex.html:2 sphinx/templates/modindex.html:13
+msgid "Global Module Index"
+msgstr "Globale Module-index"
+
+#: sphinx/builders/html.py:136
+msgid "modules"
+msgstr "modules"
+
+#: sphinx/builders/html.py:175
+msgid "next"
+msgstr "volgende"
+
+#: sphinx/builders/html.py:182
+msgid "previous"
+msgstr "vorige"
+
+#: sphinx/builders/latex.py:155
+msgid " (in "
+msgstr ""
 
 #: sphinx/directives/desc.py:25
 #, python-format
@@ -214,11 +192,16 @@
 msgid "Return type"
 msgstr "Return type"
 
-#: sphinx/directives/desc.py:143
+#: sphinx/directives/desc.py:201
+#, fuzzy
+msgid "Parameter"
+msgstr "Parameters"
+
+#: sphinx/directives/desc.py:205
 msgid "Parameters"
 msgstr "Parameters"
 
-#: sphinx/directives/desc.py:423
+#: sphinx/directives/desc.py:450
 #, fuzzy, python-format
 msgid "%scommand line option; %s"
 msgstr "%scommandolijn optie; %s"
@@ -244,10 +227,15 @@
 msgid "Author: "
 msgstr "Auteur: "
 
-#: sphinx/directives/other.py:246
+#: sphinx/directives/other.py:249
 msgid "See also"
 msgstr "Zie ook"
 
+#: sphinx/ext/autodoc.py:576 sphinx/ext/autodoc.py:590
+#, python-format
+msgid "alias of :class:`%s`"
+msgstr ""
+
 #: sphinx/ext/todo.py:31
 msgid "Todo"
 msgstr ""
@@ -344,6 +332,14 @@
 msgid "built-in function"
 msgstr "geïntegreerde functie"
 
+#: sphinx/static/doctools.js:139 sphinx/writers/html.py:415
+msgid "Permalink to this headline"
+msgstr "Permanente link naar deze titel"
+
+#: sphinx/static/doctools.js:145 sphinx/writers/html.py:80
+msgid "Permalink to this definition"
+msgstr "Permanente link naar deze definitie"
+
 #: sphinx/static/doctools.js:174
 msgid "Hide Search Matches"
 msgstr "Zoekresultaten verbergen"
@@ -365,11 +361,11 @@
 msgid ", in "
 msgstr ""
 
-#: sphinx/static/searchtools.js:447 sphinx/templates/search.html:18
+#: sphinx/static/searchtools.js:453 sphinx/templates/search.html:18
 msgid "Search Results"
 msgstr "Zoekresultaten"
 
-#: sphinx/static/searchtools.js:449
+#: sphinx/static/searchtools.js:455
 msgid ""
 "Your search did not match any documents. Please make sure that all words "
 "are spelled correctly and that you've selected enough categories."
@@ -377,7 +373,7 @@
 "Uw zoekopdracht leverde geen resultaten op.  Controleer of alle "
 "woordencorrect gespeld zijn en dat u genoeg categoriën hebt geselecteerd."
 
-#: sphinx/static/searchtools.js:451
+#: sphinx/static/searchtools.js:457
 #, python-format
 msgid "Search finished, found %s page(s) matching the search query."
 msgstr "Zoeken voltooid, %s pagina(s) gevonden."
@@ -453,68 +449,61 @@
 msgid "next chapter"
 msgstr "volgend hoofdstuk"
 
-#: sphinx/templates/layout.html:55
+#: sphinx/templates/layout.html:56
 msgid "This Page"
 msgstr "Deze Pagina"
 
-#: sphinx/templates/layout.html:59
-msgid "Suggest Change"
-msgstr "Wijziging Voorstellen"
-
-#: sphinx/templates/layout.html:60 sphinx/templates/layout.html:62
+#: sphinx/templates/layout.html:58
 msgid "Show Source"
 msgstr "Broncode weergeven"
 
-#: sphinx/templates/layout.html:71
+#: sphinx/templates/layout.html:67
 msgid "Quick search"
 msgstr "Snel zoeken"
 
-#: sphinx/templates/layout.html:71
-msgid "Keyword search"
-msgstr "Trefwoord opzoeken"
-
-#: sphinx/templates/layout.html:73
+#: sphinx/templates/layout.html:69
 msgid "Go"
 msgstr "Go"
 
-#: sphinx/templates/layout.html:78
-msgid "Enter a module, class or function name."
+#: sphinx/templates/layout.html:73
+#, fuzzy
+msgid "Enter search terms or a module, class or function name."
 msgstr "Geef de naam van een module, klasse of functie."
 
-#: sphinx/templates/layout.html:119
+#: sphinx/templates/layout.html:106
 #, python-format
 msgid "Search within %(docstitle)s"
 msgstr "Zoeken in %(docstitle)s"
 
-#: sphinx/templates/layout.html:128
+#: sphinx/templates/layout.html:115
 msgid "About these documents"
 msgstr "Over deze documenten"
 
-#: sphinx/templates/layout.html:131 sphinx/templates/search.html:2
+#: sphinx/templates/layout.html:118 sphinx/templates/search.html:2
 #: sphinx/templates/search.html:5
 msgid "Search"
 msgstr "Zoeken"
 
-#: sphinx/templates/layout.html:133
+#: sphinx/templates/layout.html:120
 msgid "Copyright"
 msgstr "Copyright"
 
-#: sphinx/templates/layout.html:178
+#: sphinx/templates/layout.html:165
 #, python-format
 msgid "&copy; <a href=\"%(path)s\">Copyright</a> %(copyright)s."
 msgstr "&copy; <a href=\"%(path)s\">Copyright</a> %(copyright)s."
 
-#: sphinx/templates/layout.html:180
+#: sphinx/templates/layout.html:167
 #, python-format
 msgid "&copy; Copyright %(copyright)s."
 msgstr "&copy; Copyright %(copyright)s."
 
-#: sphinx/templates/layout.html:183
+#: sphinx/templates/layout.html:170
 #, python-format
 msgid "Last updated on %(last_updated)s."
 msgstr "Laatste aanpassing op %(last_updated)s."
 
-#: sphinx/templates/layout.html:186
+#: sphinx/templates/layout.html:173
 #, python-format
 msgid ""
 "Created using <a href=\"http://sphinx.pocoo.org/\">Sphinx</a> "
@@ -523,15 +512,7 @@
 "Aangemaakt met <a href=\"http://sphinx.pocoo.org/\">Sphinx</a> "
 "%(sphinx_version)s."
 
-#: sphinx/templates/modindex.html:15
-msgid "Most popular modules:"
-msgstr "Populairste modules:"
-
-#: sphinx/templates/modindex.html:24
-msgid "Show modules only available on these platforms"
-msgstr "Enkel modules weergeven die op deze platformen beschikbaar zijn"
-
-#: sphinx/templates/modindex.html:56
+#: sphinx/templates/modindex.html:36
 msgid "Deprecated"
 msgstr "Verouderd"
 
@@ -540,16 +521,6 @@
 msgid "Search %(docstitle)s"
 msgstr "Zoeken %(docstitle)s"
 
-#: sphinx/templates/page.html:8
-msgid ""
-"<strong>Note:</strong> You requested an out-of-date URL from this server."
-" We've tried to redirect you to the new location of this page, but it may"
-" not be the right one."
-msgstr ""
-"<strong>Opgelet:</strong> U heeft een verouderde URL aangevraagd op deze "
-"server. Wij hebben probeerd u door te verwijzen naar de nieuwe locatie "
-"van deze pagina,  maar dat is misschien niet gelukt."
-
 #: sphinx/templates/search.html:7
 #, fuzzy
 msgid ""
@@ -601,3 +572,42 @@
 msgid "Other changes"
 msgstr "Andere veranderingen"
 
+#: sphinx/writers/latex.py:173
+msgid "Release"
+msgstr "Release"
+
+#: sphinx/writers/text.py:166
+#, python-format
+msgid "Platform: %s"
+msgstr "Platform: %s"
+
+#: sphinx/writers/text.py:427
+msgid "[image]"
+msgstr "[afbeelding]"
+
+#~ msgid "Suggest Change"
+#~ msgstr "Wijziging Voorstellen"
+
+#~ msgid "Keyword search"
+#~ msgstr "Trefwoord opzoeken"
+
+#~ msgid "Most popular modules:"
+#~ msgstr "Populairste modules:"
+
+#~ msgid "Show modules only available on these platforms"
+#~ msgstr "Enkel modules weergeven die op deze platformen beschikbaar zijn"
+
+#~ msgid ""
+#~ "<strong>Note:</strong> You requested an "
+#~ "out-of-date URL from this server. "
+#~ "We've tried to redirect you to the"
+#~ " new location of this page, but "
+#~ "it may not be the right one."
+#~ msgstr ""
+#~ "<strong>Opgelet:</strong> U heeft een "
+#~ "verouderde URL aangevraagd op deze "
+#~ "server. Wij hebben probeerd u door "
+#~ "te verwijzen naar de nieuwe locatie "
+#~ "van deze pagina,  maar dat is "
+#~ "misschien niet gelukt."
+

Modified: doctools/trunk/sphinx/locale/pl/LC_MESSAGES/sphinx.po
==============================================================================
--- doctools/trunk/sphinx/locale/pl/LC_MESSAGES/sphinx.po	(original)
+++ doctools/trunk/sphinx/locale/pl/LC_MESSAGES/sphinx.po	Sun Jan  4 21:38:57 2009
@@ -4,7 +4,7 @@
 "Project-Id-Version: Sphinx 0.5\n"
 "Report-Msgid-Bugs-To: EMAIL at ADDRESS\n"
 "POT-Creation-Date: 2008-08-10 11:43+0000\n"
-"PO-Revision-Date: 2008-11-27 18:40+0100\n"
+"PO-Revision-Date: 2008-12-28 23:40+0100\n"
 "Last-Translator: Michał Kandulski <Michal.Kandulski at poczta.onet.pl>\n"
 "Language-Team: \n"
 "Plural-Forms: nplurals=3; plural=(n==1 ? 0 : n%10>=2 && n%10<=4 && "
@@ -12,86 +12,30 @@
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=utf-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"Generated-By: Babel 0.9.4\n"
+"Generated-By: Babel 0.9.3\n"
 
-#: sphinx/builder.py:408
-#, python-format
-msgid "%b %d, %Y"
-msgstr "%b %d %Y"
-
-#: sphinx/builder.py:427 sphinx/templates/defindex.html:21
-msgid "General Index"
-msgstr "Indeks ogólny"
-
-#: sphinx/builder.py:427
-msgid "index"
-msgstr "indeks"
-
-#: sphinx/builder.py:429 sphinx/htmlhelp.py:156
-#: sphinx/templates/defindex.html:19 sphinx/templates/modindex.html:2
-#: sphinx/templates/modindex.html:13
-msgid "Global Module Index"
-msgstr "Indeks modułów"
-
-#: sphinx/builder.py:429
-msgid "modules"
-msgstr "moduły"
-
-#: sphinx/builder.py:466
-msgid "next"
-msgstr "dalej"
-
-#: sphinx/builder.py:473
-msgid "previous"
-msgstr "wstecz"
-
-#: sphinx/builder.py:1054
-msgid " (in "
-msgstr ""
-
-#: sphinx/builder.py:1129
-msgid "Builtins"
-msgstr "Wbudowane"
-
-#: sphinx/builder.py:1131
-msgid "Module level"
-msgstr "Poziom modułu"
-
-#: sphinx/environment.py:102 sphinx/latexwriter.py:169
+#: sphinx/environment.py:103 sphinx/writers/latex.py:170
 #, python-format
 msgid "%B %d, %Y"
 msgstr "%B %d %Y"
 
-#: sphinx/environment.py:291 sphinx/latexwriter.py:175
-#: sphinx/templates/genindex-single.html:2
+#: sphinx/environment.py:293 sphinx/templates/genindex-single.html:2
 #: sphinx/templates/genindex-split.html:2
 #: sphinx/templates/genindex-split.html:5 sphinx/templates/genindex.html:2
 #: sphinx/templates/genindex.html:5 sphinx/templates/genindex.html:48
-#: sphinx/templates/layout.html:130
+#: sphinx/templates/layout.html:117 sphinx/writers/latex.py:176
 msgid "Index"
 msgstr "Indeks"
 
-#: sphinx/environment.py:292 sphinx/latexwriter.py:174
+#: sphinx/environment.py:294 sphinx/writers/latex.py:175
 msgid "Module Index"
 msgstr "Indeks modułów"
 
-#: sphinx/environment.py:293 sphinx/templates/defindex.html:16
+#: sphinx/environment.py:295 sphinx/templates/defindex.html:16
 msgid "Search Page"
 msgstr "Wyszukiwanie"
 
-#: sphinx/htmlwriter.py:79 sphinx/static/doctools.js:145
-msgid "Permalink to this definition"
-msgstr "Stały odnośnik do tej definicji"
-
-#: sphinx/htmlwriter.py:399 sphinx/static/doctools.js:139
-msgid "Permalink to this headline"
-msgstr "Stały odnośnik do tego nagłówka"
-
-#: sphinx/latexwriter.py:172
-msgid "Release"
-msgstr "Wydanie"
-
-#: sphinx/roles.py:53 sphinx/directives/desc.py:537
+#: sphinx/roles.py:53 sphinx/directives/desc.py:564
 #, python-format
 msgid "environment variable; %s"
 msgstr "zmienna środowiskowa; %s"
@@ -101,14 +45,48 @@
 msgid "Python Enhancement Proposals!PEP %s"
 msgstr "Python Enhancement Proposals!PEP %s"
 
-#: sphinx/textwriter.py:166
+#: sphinx/builders/changes.py:64
+msgid "Builtins"
+msgstr "Wbudowane"
+
+#: sphinx/builders/changes.py:66
+msgid "Module level"
+msgstr "Poziom modułu"
+
+#: sphinx/builders/html.py:115
 #, python-format
-msgid "Platform: %s"
-msgstr "Platforma: %s"
+msgid "%b %d, %Y"
+msgstr "%b %d %Y"
 
-#: sphinx/textwriter.py:422
-msgid "[image]"
-msgstr "[obrazek]"
+#: sphinx/builders/html.py:134 sphinx/templates/defindex.html:21
+msgid "General Index"
+msgstr "Indeks ogólny"
+
+#: sphinx/builders/html.py:134
+msgid "index"
+msgstr "indeks"
+
+#: sphinx/builders/html.py:136 sphinx/builders/htmlhelp.py:180
+#: sphinx/builders/qthelp.py:129 sphinx/templates/defindex.html:19
+#: sphinx/templates/modindex.html:2 sphinx/templates/modindex.html:13
+msgid "Global Module Index"
+msgstr "Indeks modułów"
+
+#: sphinx/builders/html.py:136
+msgid "modules"
+msgstr "moduły"
+
+#: sphinx/builders/html.py:175
+msgid "next"
+msgstr "dalej"
+
+#: sphinx/builders/html.py:182
+msgid "previous"
+msgstr "wstecz"
+
+#: sphinx/builders/latex.py:155
+msgid " (in "
+msgstr ""
 
 #: sphinx/directives/desc.py:25
 #, python-format
@@ -212,11 +190,16 @@
 msgid "Return type"
 msgstr "Typ zwracany"
 
-#: sphinx/directives/desc.py:143
+#: sphinx/directives/desc.py:201
+#, fuzzy
+msgid "Parameter"
+msgstr "Parametry"
+
+#: sphinx/directives/desc.py:205
 msgid "Parameters"
 msgstr "Parametry"
 
-#: sphinx/directives/desc.py:423
+#: sphinx/directives/desc.py:450
 #, fuzzy, python-format
 msgid "%scommand line option; %s"
 msgstr "%sopcja linii komend; %s"
@@ -242,10 +225,15 @@
 msgid "Author: "
 msgstr "Autor: "
 
-#: sphinx/directives/other.py:246
+#: sphinx/directives/other.py:249
 msgid "See also"
 msgstr "Zobacz także"
 
+#: sphinx/ext/autodoc.py:576 sphinx/ext/autodoc.py:590
+#, python-format
+msgid "alias of :class:`%s`"
+msgstr ""
+
 #: sphinx/ext/todo.py:31
 msgid "Todo"
 msgstr ""
@@ -342,6 +330,14 @@
 msgid "built-in function"
 msgstr "funkcja wbudowana"
 
+#: sphinx/static/doctools.js:139 sphinx/writers/html.py:415
+msgid "Permalink to this headline"
+msgstr "Stały odnośnik do tego nagłówka"
+
+#: sphinx/static/doctools.js:145 sphinx/writers/html.py:80
+msgid "Permalink to this definition"
+msgstr "Stały odnośnik do tej definicji"
+
 #: sphinx/static/doctools.js:174
 msgid "Hide Search Matches"
 msgstr "Ukryj wyniki wyszukiwania"
@@ -363,11 +359,11 @@
 msgid ", in "
 msgstr ""
 
-#: sphinx/static/searchtools.js:447 sphinx/templates/search.html:18
+#: sphinx/static/searchtools.js:453 sphinx/templates/search.html:18
 msgid "Search Results"
 msgstr "Wyniki wyszukiwania"
 
-#: sphinx/static/searchtools.js:449
+#: sphinx/static/searchtools.js:455
 msgid ""
 "Your search did not match any documents. Please make sure that all words "
 "are spelled correctly and that you've selected enough categories."
@@ -375,7 +371,7 @@
 "Nie znaleziono żadnych pasujących dokumentów. Upewnij się, że wszystkie "
 "słowa są poprawnie wpisane i że wybrałeś wystarczającąliczbę kategorii."
 
-#: sphinx/static/searchtools.js:451
+#: sphinx/static/searchtools.js:457
 #, python-format
 msgid "Search finished, found %s page(s) matching the search query."
 msgstr "Przeszukiwanie zakończone, znaleziono %s pasujących stron."
@@ -451,68 +447,61 @@
 msgid "next chapter"
 msgstr "następny rozdział"
 
-#: sphinx/templates/layout.html:55
+#: sphinx/templates/layout.html:56
 msgid "This Page"
 msgstr "Ta strona"
 
-#: sphinx/templates/layout.html:59
-msgid "Suggest Change"
-msgstr "Zasugeruj zmianę"
-
-#: sphinx/templates/layout.html:60 sphinx/templates/layout.html:62
+#: sphinx/templates/layout.html:58
 msgid "Show Source"
 msgstr "Pokaż źródło"
 
-#: sphinx/templates/layout.html:71
+#: sphinx/templates/layout.html:67
 msgid "Quick search"
 msgstr "Szybkie wyszukiwanie"
 
-#: sphinx/templates/layout.html:71
-msgid "Keyword search"
-msgstr "Szukanie wg słowa kluczowego"
-
-#: sphinx/templates/layout.html:73
+#: sphinx/templates/layout.html:69
 msgid "Go"
 msgstr "Szukaj"
 
-#: sphinx/templates/layout.html:78
-msgid "Enter a module, class or function name."
+#: sphinx/templates/layout.html:73
+#, fuzzy
+msgid "Enter search terms or a module, class or function name."
 msgstr "Wprowadź nazwę modułu, klasy lub funkcji."
 
-#: sphinx/templates/layout.html:119
+#: sphinx/templates/layout.html:106
 #, python-format
 msgid "Search within %(docstitle)s"
 msgstr "Szukaj pośród %(docstitle)s"
 
-#: sphinx/templates/layout.html:128
+#: sphinx/templates/layout.html:115
 msgid "About these documents"
 msgstr "O tych dokumentach"
 
-#: sphinx/templates/layout.html:131 sphinx/templates/search.html:2
+#: sphinx/templates/layout.html:118 sphinx/templates/search.html:2
 #: sphinx/templates/search.html:5
 msgid "Search"
 msgstr "Szukaj"
 
-#: sphinx/templates/layout.html:133
+#: sphinx/templates/layout.html:120
 msgid "Copyright"
 msgstr "Copyright"
 
-#: sphinx/templates/layout.html:178
+#: sphinx/templates/layout.html:165
 #, python-format
 msgid "&copy; <a href=\"%(path)s\">Copyright</a> %(copyright)s."
 msgstr "&copy; <a href=\"%(path)s\">Copyright</a> %(copyright)s."
 
-#: sphinx/templates/layout.html:180
+#: sphinx/templates/layout.html:167
 #, python-format
 msgid "&copy; Copyright %(copyright)s."
 msgstr "&copy; Copyright %(copyright)s."
 
-#: sphinx/templates/layout.html:183
+#: sphinx/templates/layout.html:170
 #, python-format
 msgid "Last updated on %(last_updated)s."
 msgstr "Ostatnia modyfikacja %(last_updated)s."
 
-#: sphinx/templates/layout.html:186
+#: sphinx/templates/layout.html:173
 #, python-format
 msgid ""
 "Created using <a href=\"http://sphinx.pocoo.org/\">Sphinx</a> "
@@ -521,15 +510,7 @@
 "Utworzone przy pomocy <a href=\"http://sphinx.pocoo.org/\">Sphinx</a>'a "
 "%(sphinx_version)s."
 
-#: sphinx/templates/modindex.html:15
-msgid "Most popular modules:"
-msgstr "Najbardziej popularne moduły:"
-
-#: sphinx/templates/modindex.html:24
-msgid "Show modules only available on these platforms"
-msgstr "Pokaż moduły dostępne tylko na tych platformach"
-
-#: sphinx/templates/modindex.html:56
+#: sphinx/templates/modindex.html:36
 msgid "Deprecated"
 msgstr "Niezalecane"
 
@@ -538,16 +519,6 @@
 msgid "Search %(docstitle)s"
 msgstr "Przeszukaj %(docstitle)s"
 
-#: sphinx/templates/page.html:8
-msgid ""
-"<strong>Note:</strong> You requested an out-of-date URL from this server."
-" We've tried to redirect you to the new location of this page, but it may"
-" not be the right one."
-msgstr ""
-"<strong>Uwaga:</strong> Zażądano przedawnionego URL'a z tego serwera. "
-"Nastąpiła próba przekierowania do nowej lokalizacji, ale może ona być "
-"niewłaściwa."
-
 #: sphinx/templates/search.html:7
 #, fuzzy
 msgid ""
@@ -598,3 +569,40 @@
 msgid "Other changes"
 msgstr "Inne zmiany"
 
+#: sphinx/writers/latex.py:173
+msgid "Release"
+msgstr "Wydanie"
+
+#: sphinx/writers/text.py:166
+#, python-format
+msgid "Platform: %s"
+msgstr "Platforma: %s"
+
+#: sphinx/writers/text.py:427
+msgid "[image]"
+msgstr "[obrazek]"
+
+#~ msgid "Suggest Change"
+#~ msgstr "Zasugeruj zmianę"
+
+#~ msgid "Keyword search"
+#~ msgstr "Szukanie wg słowa kluczowego"
+
+#~ msgid "Most popular modules:"
+#~ msgstr "Najbardziej popularne moduły:"
+
+#~ msgid "Show modules only available on these platforms"
+#~ msgstr "Pokaż moduły dostępne tylko na tych platformach"
+
+#~ msgid ""
+#~ "<strong>Note:</strong> You requested an "
+#~ "out-of-date URL from this server. "
+#~ "We've tried to redirect you to the"
+#~ " new location of this page, but "
+#~ "it may not be the right one."
+#~ msgstr ""
+#~ "<strong>Uwaga:</strong> Zażądano przedawnionego "
+#~ "URL'a z tego serwera. Nastąpiła próba"
+#~ " przekierowania do nowej lokalizacji, ale"
+#~ " może ona być niewłaściwa."
+

Modified: doctools/trunk/sphinx/locale/pt_BR/LC_MESSAGES/sphinx.po
==============================================================================
--- doctools/trunk/sphinx/locale/pt_BR/LC_MESSAGES/sphinx.po	(original)
+++ doctools/trunk/sphinx/locale/pt_BR/LC_MESSAGES/sphinx.po	Sun Jan  4 21:38:57 2009
@@ -8,93 +8,37 @@
 "Project-Id-Version: Sphinx 0.5\n"
 "Report-Msgid-Bugs-To: roger.demetrescu at gmail.com\n"
 "POT-Creation-Date: 2008-11-09 19:46+0100\n"
-"PO-Revision-Date: 2008-11-27 18:40+0100\n"
+"PO-Revision-Date: 2008-12-28 23:40+0100\n"
 "Last-Translator: Roger Demetrescu <roger.demetrescu at gmail.com>\n"
 "Language-Team: pt_BR <roger.demetrescu at gmail.com>\n"
 "Plural-Forms: nplurals=2; plural=(n > 1)\n"
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=utf-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"Generated-By: Babel 0.9.4\n"
+"Generated-By: Babel 0.9.3\n"
 
-#: sphinx/builder.py:408
-#, python-format
-msgid "%b %d, %Y"
-msgstr "%d/%m/%Y"
-
-#: sphinx/builder.py:427 sphinx/templates/defindex.html:21
-msgid "General Index"
-msgstr "Índice Geral"
-
-#: sphinx/builder.py:427
-msgid "index"
-msgstr "índice"
-
-#: sphinx/builder.py:429 sphinx/htmlhelp.py:156
-#: sphinx/templates/defindex.html:19 sphinx/templates/modindex.html:2
-#: sphinx/templates/modindex.html:13
-msgid "Global Module Index"
-msgstr "Índice Global de Módulos"
-
-#: sphinx/builder.py:429
-msgid "modules"
-msgstr "módulos"
-
-#: sphinx/builder.py:466
-msgid "next"
-msgstr "próximo"
-
-#: sphinx/builder.py:473
-msgid "previous"
-msgstr "anterior"
-
-#: sphinx/builder.py:1054
-msgid " (in "
-msgstr " (em "
-
-#: sphinx/builder.py:1129
-msgid "Builtins"
-msgstr "Internos"
-
-#: sphinx/builder.py:1131
-msgid "Module level"
-msgstr "Módulo"
-
-#: sphinx/environment.py:102 sphinx/latexwriter.py:169
+#: sphinx/environment.py:103 sphinx/writers/latex.py:170
 #, python-format
 msgid "%B %d, %Y"
 msgstr "%d/%m/%Y"
 
-#: sphinx/environment.py:291 sphinx/latexwriter.py:175
-#: sphinx/templates/genindex-single.html:2
+#: sphinx/environment.py:293 sphinx/templates/genindex-single.html:2
 #: sphinx/templates/genindex-split.html:2
 #: sphinx/templates/genindex-split.html:5 sphinx/templates/genindex.html:2
 #: sphinx/templates/genindex.html:5 sphinx/templates/genindex.html:48
-#: sphinx/templates/layout.html:130
+#: sphinx/templates/layout.html:117 sphinx/writers/latex.py:176
 msgid "Index"
 msgstr "Índice"
 
-#: sphinx/environment.py:292 sphinx/latexwriter.py:174
+#: sphinx/environment.py:294 sphinx/writers/latex.py:175
 msgid "Module Index"
 msgstr "Índice do Módulo"
 
-#: sphinx/environment.py:293 sphinx/templates/defindex.html:16
+#: sphinx/environment.py:295 sphinx/templates/defindex.html:16
 msgid "Search Page"
 msgstr "Página de Pesquisa"
 
-#: sphinx/htmlwriter.py:79 sphinx/static/doctools.js:145
-msgid "Permalink to this definition"
-msgstr "Link permanente para esta definição"
-
-#: sphinx/htmlwriter.py:399 sphinx/static/doctools.js:139
-msgid "Permalink to this headline"
-msgstr "Link permanente para este título"
-
-#: sphinx/latexwriter.py:172
-msgid "Release"
-msgstr "Versão"
-
-#: sphinx/roles.py:53 sphinx/directives/desc.py:537
+#: sphinx/roles.py:53 sphinx/directives/desc.py:564
 #, python-format
 msgid "environment variable; %s"
 msgstr "váriavel de ambiente; %s"
@@ -104,14 +48,48 @@
 msgid "Python Enhancement Proposals!PEP %s"
 msgstr "Python Enhancement Proposals!PEP %s"
 
-#: sphinx/textwriter.py:166
+#: sphinx/builders/changes.py:64
+msgid "Builtins"
+msgstr "Internos"
+
+#: sphinx/builders/changes.py:66
+msgid "Module level"
+msgstr "Módulo"
+
+#: sphinx/builders/html.py:115
 #, python-format
-msgid "Platform: %s"
-msgstr "Plataforma: %s"
+msgid "%b %d, %Y"
+msgstr "%d/%m/%Y"
 
-#: sphinx/textwriter.py:422
-msgid "[image]"
-msgstr "[imagem]"
+#: sphinx/builders/html.py:134 sphinx/templates/defindex.html:21
+msgid "General Index"
+msgstr "Índice Geral"
+
+#: sphinx/builders/html.py:134
+msgid "index"
+msgstr "índice"
+
+#: sphinx/builders/html.py:136 sphinx/builders/htmlhelp.py:180
+#: sphinx/builders/qthelp.py:129 sphinx/templates/defindex.html:19
+#: sphinx/templates/modindex.html:2 sphinx/templates/modindex.html:13
+msgid "Global Module Index"
+msgstr "Índice Global de Módulos"
+
+#: sphinx/builders/html.py:136
+msgid "modules"
+msgstr "módulos"
+
+#: sphinx/builders/html.py:175
+msgid "next"
+msgstr "próximo"
+
+#: sphinx/builders/html.py:182
+msgid "previous"
+msgstr "anterior"
+
+#: sphinx/builders/latex.py:155
+msgid " (in "
+msgstr " (em "
 
 #: sphinx/directives/desc.py:25
 #, python-format
@@ -215,11 +193,16 @@
 msgid "Return type"
 msgstr "Tipo de retorno"
 
-#: sphinx/directives/desc.py:143
+#: sphinx/directives/desc.py:201
+#, fuzzy
+msgid "Parameter"
+msgstr "Parâmetros"
+
+#: sphinx/directives/desc.py:205
 msgid "Parameters"
 msgstr "Parâmetros"
 
-#: sphinx/directives/desc.py:423
+#: sphinx/directives/desc.py:450
 #, python-format
 msgid "%scommand line option; %s"
 msgstr "%sopção de linha de comando; %s"
@@ -245,10 +228,15 @@
 msgid "Author: "
 msgstr "Autor: "
 
-#: sphinx/directives/other.py:246
+#: sphinx/directives/other.py:249
 msgid "See also"
 msgstr "Veja também"
 
+#: sphinx/ext/autodoc.py:576 sphinx/ext/autodoc.py:590
+#, python-format
+msgid "alias of :class:`%s`"
+msgstr ""
+
 #: sphinx/ext/todo.py:31
 msgid "Todo"
 msgstr "Por fazer"
@@ -345,6 +333,14 @@
 msgid "built-in function"
 msgstr "função interna"
 
+#: sphinx/static/doctools.js:139 sphinx/writers/html.py:415
+msgid "Permalink to this headline"
+msgstr "Link permanente para este título"
+
+#: sphinx/static/doctools.js:145 sphinx/writers/html.py:80
+msgid "Permalink to this definition"
+msgstr "Link permanente para esta definição"
+
 #: sphinx/static/doctools.js:174
 msgid "Hide Search Matches"
 msgstr "Esconder Resultados da Pesquisa"
@@ -365,11 +361,11 @@
 msgid ", in "
 msgstr ", em "
 
-#: sphinx/static/searchtools.js:447 sphinx/templates/search.html:18
+#: sphinx/static/searchtools.js:453 sphinx/templates/search.html:18
 msgid "Search Results"
 msgstr "Resultados da Pesquisa"
 
-#: sphinx/static/searchtools.js:449
+#: sphinx/static/searchtools.js:455
 msgid ""
 "Your search did not match any documents. Please make sure that all words "
 "are spelled correctly and that you've selected enough categories."
@@ -378,7 +374,7 @@
 " todas as palavras foram digitadas corretamente e de que você tenha "
 "selecionado o mínimo de categorias."
 
-#: sphinx/static/searchtools.js:451
+#: sphinx/static/searchtools.js:457
 #, python-format
 msgid "Search finished, found %s page(s) matching the search query."
 msgstr ""
@@ -456,68 +452,61 @@
 msgid "next chapter"
 msgstr "próximo capítulo"
 
-#: sphinx/templates/layout.html:55
+#: sphinx/templates/layout.html:56
 msgid "This Page"
 msgstr "Esta Página"
 
-#: sphinx/templates/layout.html:59
-msgid "Suggest Change"
-msgstr "Sugerir Alteração"
-
-#: sphinx/templates/layout.html:60 sphinx/templates/layout.html:62
+#: sphinx/templates/layout.html:58
 msgid "Show Source"
 msgstr "Exibir Fonte"
 
-#: sphinx/templates/layout.html:71
+#: sphinx/templates/layout.html:67
 msgid "Quick search"
 msgstr "Pesquisa rápida"
 
-#: sphinx/templates/layout.html:71
-msgid "Keyword search"
-msgstr "Pesquisa de palavras-chave"
-
-#: sphinx/templates/layout.html:73
+#: sphinx/templates/layout.html:69
 msgid "Go"
 msgstr "Ir"
 
-#: sphinx/templates/layout.html:78
-msgid "Enter a module, class or function name."
+#: sphinx/templates/layout.html:73
+#, fuzzy
+msgid "Enter search terms or a module, class or function name."
 msgstr "Informe o nome de um módulo, classe ou função."
 
-#: sphinx/templates/layout.html:119
+#: sphinx/templates/layout.html:106
 #, python-format
 msgid "Search within %(docstitle)s"
 msgstr "Pesquisar dentro de %(docstitle)s"
 
-#: sphinx/templates/layout.html:128
+#: sphinx/templates/layout.html:115
 msgid "About these documents"
 msgstr "Sobre estes documentos"
 
-#: sphinx/templates/layout.html:131 sphinx/templates/search.html:2
+#: sphinx/templates/layout.html:118 sphinx/templates/search.html:2
 #: sphinx/templates/search.html:5
 msgid "Search"
 msgstr "Pesquisar"
 
-#: sphinx/templates/layout.html:133
+#: sphinx/templates/layout.html:120
 msgid "Copyright"
 msgstr "Copyright"
 
-#: sphinx/templates/layout.html:178
+#: sphinx/templates/layout.html:165
 #, python-format
 msgid "&copy; <a href=\"%(path)s\">Copyright</a> %(copyright)s."
 msgstr "&copy; <a href=\"%(path)s\">Copyright</a> %(copyright)s."
 
-#: sphinx/templates/layout.html:180
+#: sphinx/templates/layout.html:167
 #, python-format
 msgid "&copy; Copyright %(copyright)s."
 msgstr "&copy; Copyright %(copyright)s."
 
-#: sphinx/templates/layout.html:183
+#: sphinx/templates/layout.html:170
 #, python-format
 msgid "Last updated on %(last_updated)s."
 msgstr "Última atualização em %(last_updated)s."
 
-#: sphinx/templates/layout.html:186
+#: sphinx/templates/layout.html:173
 #, python-format
 msgid ""
 "Created using <a href=\"http://sphinx.pocoo.org/\">Sphinx</a> "
@@ -526,15 +515,7 @@
 "Criado com <a href=\"http://sphinx.pocoo.org/\">Sphinx</a> "
 "%(sphinx_version)s."
 
-#: sphinx/templates/modindex.html:15
-msgid "Most popular modules:"
-msgstr "Módulos mais populares:"
-
-#: sphinx/templates/modindex.html:24
-msgid "Show modules only available on these platforms"
-msgstr "Exibir somente módulos disponíveis nestas plataformas"
-
-#: sphinx/templates/modindex.html:56
+#: sphinx/templates/modindex.html:36
 msgid "Deprecated"
 msgstr "Obsoleto"
 
@@ -543,16 +524,6 @@
 msgid "Search %(docstitle)s"
 msgstr "Pesquisar em %(docstitle)s"
 
-#: sphinx/templates/page.html:8
-msgid ""
-"<strong>Note:</strong> You requested an out-of-date URL from this server."
-" We've tried to redirect you to the new location of this page, but it may"
-" not be the right one."
-msgstr ""
-"<strong>Nota:</strong> Você requisitou uma URL desatualizada deste "
-"servidor. Tentamos redirecioná-lo para um novo endereço desta página, "
-"porém é possível que o mesmo não seja o correto."
-
 #: sphinx/templates/search.html:7
 #, fuzzy
 msgid ""
@@ -604,3 +575,41 @@
 msgid "Other changes"
 msgstr "Outras alterações"
 
+#: sphinx/writers/latex.py:173
+msgid "Release"
+msgstr "Versão"
+
+#: sphinx/writers/text.py:166
+#, python-format
+msgid "Platform: %s"
+msgstr "Plataforma: %s"
+
+#: sphinx/writers/text.py:427
+msgid "[image]"
+msgstr "[imagem]"
+
+#~ msgid "Suggest Change"
+#~ msgstr "Sugerir Alteração"
+
+#~ msgid "Keyword search"
+#~ msgstr "Pesquisa de palavras-chave"
+
+#~ msgid "Most popular modules:"
+#~ msgstr "Módulos mais populares:"
+
+#~ msgid "Show modules only available on these platforms"
+#~ msgstr "Exibir somente módulos disponíveis nestas plataformas"
+
+#~ msgid ""
+#~ "<strong>Note:</strong> You requested an "
+#~ "out-of-date URL from this server. "
+#~ "We've tried to redirect you to the"
+#~ " new location of this page, but "
+#~ "it may not be the right one."
+#~ msgstr ""
+#~ "<strong>Nota:</strong> Você requisitou uma URL"
+#~ " desatualizada deste servidor. Tentamos "
+#~ "redirecioná-lo para um novo endereço "
+#~ "desta página, porém é possível que "
+#~ "o mesmo não seja o correto."
+

Modified: doctools/trunk/sphinx/locale/sl/LC_MESSAGES/sphinx.po
==============================================================================
--- doctools/trunk/sphinx/locale/sl/LC_MESSAGES/sphinx.po	(original)
+++ doctools/trunk/sphinx/locale/sl/LC_MESSAGES/sphinx.po	Sun Jan  4 21:38:57 2009
@@ -4,93 +4,37 @@
 "Project-Id-Version:  Sphinx\n"
 "Report-Msgid-Bugs-To: EMAIL at ADDRESS\n"
 "POT-Creation-Date: 2008-09-11 23:58+0200\n"
-"PO-Revision-Date: 2008-11-27 18:40+0100\n"
+"PO-Revision-Date: 2008-12-28 23:40+0100\n"
 "Last-Translator: Rok Garbas <rok.garbas at gmail.com>\n"
 "Language-Team: Rok Garbas <rok.garbas at gmail.com>\n"
 "Plural-Forms: nplurals=1; plural=0\n"
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=utf-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"Generated-By: Babel 0.9.4\n"
+"Generated-By: Babel 0.9.3\n"
 
-#: sphinx/builder.py:408
-#, python-format
-msgid "%b %d, %Y"
-msgstr "%d %b, %Y"
-
-#: sphinx/builder.py:427 sphinx/templates/defindex.html:21
-msgid "General Index"
-msgstr "Splošni abecedni seznam"
-
-#: sphinx/builder.py:427
-msgid "index"
-msgstr "abecedni seznam"
-
-#: sphinx/builder.py:429 sphinx/htmlhelp.py:156
-#: sphinx/templates/defindex.html:19 sphinx/templates/modindex.html:2
-#: sphinx/templates/modindex.html:13
-msgid "Global Module Index"
-msgstr "Splošen Seznam Modulov"
-
-#: sphinx/builder.py:429
-msgid "modules"
-msgstr "Moduli"
-
-#: sphinx/builder.py:466
-msgid "next"
-msgstr "naprej"
-
-#: sphinx/builder.py:473
-msgid "previous"
-msgstr "nazaj"
-
-#: sphinx/builder.py:1054
-msgid " (in "
-msgstr "(v "
-
-#: sphinx/builder.py:1129
-msgid "Builtins"
-msgstr "Vgrajeni deli"
-
-#: sphinx/builder.py:1131
-msgid "Module level"
-msgstr "Nivo modula"
-
-#: sphinx/environment.py:102 sphinx/latexwriter.py:169
+#: sphinx/environment.py:103 sphinx/writers/latex.py:170
 #, python-format
 msgid "%B %d, %Y"
 msgstr "%d %B, %Y"
 
-#: sphinx/environment.py:291 sphinx/latexwriter.py:175
-#: sphinx/templates/genindex-single.html:2
+#: sphinx/environment.py:293 sphinx/templates/genindex-single.html:2
 #: sphinx/templates/genindex-split.html:2
 #: sphinx/templates/genindex-split.html:5 sphinx/templates/genindex.html:2
 #: sphinx/templates/genindex.html:5 sphinx/templates/genindex.html:48
-#: sphinx/templates/layout.html:130
+#: sphinx/templates/layout.html:117 sphinx/writers/latex.py:176
 msgid "Index"
 msgstr "Abecedni seznam"
 
-#: sphinx/environment.py:292 sphinx/latexwriter.py:174
+#: sphinx/environment.py:294 sphinx/writers/latex.py:175
 msgid "Module Index"
 msgstr "Seznam modulov"
 
-#: sphinx/environment.py:293 sphinx/templates/defindex.html:16
+#: sphinx/environment.py:295 sphinx/templates/defindex.html:16
 msgid "Search Page"
 msgstr "Iskalna stran"
 
-#: sphinx/htmlwriter.py:79 sphinx/static/doctools.js:145
-msgid "Permalink to this definition"
-msgstr "Povezava na to definicijo"
-
-#: sphinx/htmlwriter.py:399 sphinx/static/doctools.js:139
-msgid "Permalink to this headline"
-msgstr "Povezava na naslov"
-
-#: sphinx/latexwriter.py:172
-msgid "Release"
-msgstr "Izdaja"
-
-#: sphinx/roles.py:53 sphinx/directives/desc.py:537
+#: sphinx/roles.py:53 sphinx/directives/desc.py:564
 #, python-format
 msgid "environment variable; %s"
 msgstr "globalna spremenljivka; %s"
@@ -100,14 +44,48 @@
 msgid "Python Enhancement Proposals!PEP %s"
 msgstr "Python Enhancement Proposals!PEP %s"
 
-#: sphinx/textwriter.py:166
+#: sphinx/builders/changes.py:64
+msgid "Builtins"
+msgstr "Vgrajeni deli"
+
+#: sphinx/builders/changes.py:66
+msgid "Module level"
+msgstr "Nivo modula"
+
+#: sphinx/builders/html.py:115
 #, python-format
-msgid "Platform: %s"
-msgstr "Platforma: %s"
+msgid "%b %d, %Y"
+msgstr "%d %b, %Y"
 
-#: sphinx/textwriter.py:422
-msgid "[image]"
-msgstr "[slika]"
+#: sphinx/builders/html.py:134 sphinx/templates/defindex.html:21
+msgid "General Index"
+msgstr "Splošni abecedni seznam"
+
+#: sphinx/builders/html.py:134
+msgid "index"
+msgstr "abecedni seznam"
+
+#: sphinx/builders/html.py:136 sphinx/builders/htmlhelp.py:180
+#: sphinx/builders/qthelp.py:129 sphinx/templates/defindex.html:19
+#: sphinx/templates/modindex.html:2 sphinx/templates/modindex.html:13
+msgid "Global Module Index"
+msgstr "Splošen Seznam Modulov"
+
+#: sphinx/builders/html.py:136
+msgid "modules"
+msgstr "Moduli"
+
+#: sphinx/builders/html.py:175
+msgid "next"
+msgstr "naprej"
+
+#: sphinx/builders/html.py:182
+msgid "previous"
+msgstr "nazaj"
+
+#: sphinx/builders/latex.py:155
+msgid " (in "
+msgstr "(v "
 
 #: sphinx/directives/desc.py:25
 #, python-format
@@ -211,11 +189,16 @@
 msgid "Return type"
 msgstr "Vrne tip"
 
-#: sphinx/directives/desc.py:143
+#: sphinx/directives/desc.py:201
+#, fuzzy
+msgid "Parameter"
+msgstr "Parametri"
+
+#: sphinx/directives/desc.py:205
 msgid "Parameters"
 msgstr "Parametri"
 
-#: sphinx/directives/desc.py:423
+#: sphinx/directives/desc.py:450
 #, python-format
 msgid "%scommand line option; %s"
 msgstr "%sopcija komandne linije; %s"
@@ -241,10 +224,15 @@
 msgid "Author: "
 msgstr "Avtor:"
 
-#: sphinx/directives/other.py:246
+#: sphinx/directives/other.py:249
 msgid "See also"
 msgstr "Poglej tudi"
 
+#: sphinx/ext/autodoc.py:576 sphinx/ext/autodoc.py:590
+#, python-format
+msgid "alias of :class:`%s`"
+msgstr ""
+
 #: sphinx/ext/todo.py:31
 msgid "Todo"
 msgstr "Naredi"
@@ -341,6 +329,14 @@
 msgid "built-in function"
 msgstr "vgrajene funkcije"
 
+#: sphinx/static/doctools.js:139 sphinx/writers/html.py:415
+msgid "Permalink to this headline"
+msgstr "Povezava na naslov"
+
+#: sphinx/static/doctools.js:145 sphinx/writers/html.py:80
+msgid "Permalink to this definition"
+msgstr "Povezava na to definicijo"
+
 #: sphinx/static/doctools.js:174
 msgid "Hide Search Matches"
 msgstr "Skrij Resultate Iskanja"
@@ -361,11 +357,11 @@
 msgid ", in "
 msgstr ", v "
 
-#: sphinx/static/searchtools.js:447 sphinx/templates/search.html:18
+#: sphinx/static/searchtools.js:453 sphinx/templates/search.html:18
 msgid "Search Results"
 msgstr "Rezultati Iskanja"
 
-#: sphinx/static/searchtools.js:449
+#: sphinx/static/searchtools.js:455
 msgid ""
 "Your search did not match any documents. Please make sure that all words "
 "are spelled correctly and that you've selected enough categories."
@@ -373,7 +369,7 @@
 "Za vaše iskanje ni rezultatov. Prosimo preglejte ali so vse besede "
 "pravilno črkovane in ali ste izbrali dovolj kategorij."
 
-#: sphinx/static/searchtools.js:451
+#: sphinx/static/searchtools.js:457
 #, python-format
 msgid "Search finished, found %s page(s) matching the search query."
 msgstr "Iskanje končano, najdeno %s strani, ki ustrezajo iskalnemu nizu."
@@ -449,68 +445,61 @@
 msgid "next chapter"
 msgstr "naslednje poglavje"
 
-#: sphinx/templates/layout.html:55
+#: sphinx/templates/layout.html:56
 msgid "This Page"
 msgstr "Ta stran"
 
-#: sphinx/templates/layout.html:59
-msgid "Suggest Change"
-msgstr "Predlagaj spremembo"
-
-#: sphinx/templates/layout.html:60 sphinx/templates/layout.html:62
+#: sphinx/templates/layout.html:58
 msgid "Show Source"
 msgstr "Prikaži izvorno kodo"
 
-#: sphinx/templates/layout.html:71
+#: sphinx/templates/layout.html:67
 msgid "Quick search"
 msgstr "Hitro iskanje"
 
-#: sphinx/templates/layout.html:71
-msgid "Keyword search"
-msgstr "Iskanje po ključniih besedah"
-
-#: sphinx/templates/layout.html:73
+#: sphinx/templates/layout.html:69
 msgid "Go"
 msgstr "Potrdi"
 
-#: sphinx/templates/layout.html:78
-msgid "Enter a module, class or function name."
+#: sphinx/templates/layout.html:73
+#, fuzzy
+msgid "Enter search terms or a module, class or function name."
 msgstr "Vnesi ime mudla, razreda ali funkcije."
 
-#: sphinx/templates/layout.html:119
+#: sphinx/templates/layout.html:106
 #, python-format
 msgid "Search within %(docstitle)s"
 msgstr "Išči med %(docstitle)s"
 
-#: sphinx/templates/layout.html:128
+#: sphinx/templates/layout.html:115
 msgid "About these documents"
 msgstr "O teh dokumentih"
 
-#: sphinx/templates/layout.html:131 sphinx/templates/search.html:2
+#: sphinx/templates/layout.html:118 sphinx/templates/search.html:2
 #: sphinx/templates/search.html:5
 msgid "Search"
 msgstr "Išči"
 
-#: sphinx/templates/layout.html:133
+#: sphinx/templates/layout.html:120
 msgid "Copyright"
 msgstr "Vse pravice pridržane"
 
-#: sphinx/templates/layout.html:178
+#: sphinx/templates/layout.html:165
 #, python-format
 msgid "&copy; <a href=\"%(path)s\">Copyright</a> %(copyright)s."
 msgstr "&copy; <a href=\"%(path)s\">Vse pravice pridržane</a> %(copyright)s."
 
-#: sphinx/templates/layout.html:180
+#: sphinx/templates/layout.html:167
 #, python-format
 msgid "&copy; Copyright %(copyright)s."
 msgstr "&copy; Vse pravice pridržane %(copyright)s."
 
-#: sphinx/templates/layout.html:183
+#: sphinx/templates/layout.html:170
 #, python-format
 msgid "Last updated on %(last_updated)s."
 msgstr "Zadnjič posodobljeno na %(last_updated)s."
 
-#: sphinx/templates/layout.html:186
+#: sphinx/templates/layout.html:173
 #, python-format
 msgid ""
 "Created using <a href=\"http://sphinx.pocoo.org/\">Sphinx</a> "
@@ -519,15 +508,7 @@
 "Narejeno s <a href=\"http://sphinx.pocoo.org/\">Sphinx</a> "
 "%(sphinx_version)s."
 
-#: sphinx/templates/modindex.html:15
-msgid "Most popular modules:"
-msgstr "Najbolj popularni moduli:"
-
-#: sphinx/templates/modindex.html:24
-msgid "Show modules only available on these platforms"
-msgstr "Prikaži module na razpolago na platformah"
-
-#: sphinx/templates/modindex.html:56
+#: sphinx/templates/modindex.html:36
 msgid "Deprecated"
 msgstr "Zastarelo"
 
@@ -536,16 +517,6 @@
 msgid "Search %(docstitle)s"
 msgstr "Išči %(docstitle)s"
 
-#: sphinx/templates/page.html:8
-msgid ""
-"<strong>Note:</strong> You requested an out-of-date URL from this server."
-" We've tried to redirect you to the new location of this page, but it may"
-" not be the right one."
-msgstr ""
-"<strong>Opomba:</strong> Vaš zahtevek za URL s tega streznika je "
-"zastaral. Poskušali smo vas preusmeriti na novo lokacijo, vendar utegne "
-"biti napačna."
-
 #: sphinx/templates/search.html:7
 #, fuzzy
 msgid ""
@@ -595,3 +566,40 @@
 msgid "Other changes"
 msgstr "Ostale spremembe"
 
+#: sphinx/writers/latex.py:173
+msgid "Release"
+msgstr "Izdaja"
+
+#: sphinx/writers/text.py:166
+#, python-format
+msgid "Platform: %s"
+msgstr "Platforma: %s"
+
+#: sphinx/writers/text.py:427
+msgid "[image]"
+msgstr "[slika]"
+
+#~ msgid "Suggest Change"
+#~ msgstr "Predlagaj spremembo"
+
+#~ msgid "Keyword search"
+#~ msgstr "Iskanje po ključniih besedah"
+
+#~ msgid "Most popular modules:"
+#~ msgstr "Najbolj popularni moduli:"
+
+#~ msgid "Show modules only available on these platforms"
+#~ msgstr "Prikaži module na razpolago na platformah"
+
+#~ msgid ""
+#~ "<strong>Note:</strong> You requested an "
+#~ "out-of-date URL from this server. "
+#~ "We've tried to redirect you to the"
+#~ " new location of this page, but "
+#~ "it may not be the right one."
+#~ msgstr ""
+#~ "<strong>Opomba:</strong> Vaš zahtevek za URL"
+#~ " s tega streznika je zastaral. "
+#~ "Poskušali smo vas preusmeriti na novo"
+#~ " lokacijo, vendar utegne biti napačna."
+

Modified: doctools/trunk/sphinx/locale/sphinx.pot
==============================================================================
--- doctools/trunk/sphinx/locale/sphinx.pot	(original)
+++ doctools/trunk/sphinx/locale/sphinx.pot	Sun Jan  4 21:38:57 2009
@@ -6,111 +6,89 @@
 #, fuzzy
 msgid ""
 msgstr ""
-"Project-Id-Version: Sphinx 0.5\n"
+"Project-Id-Version: Sphinx 0.6\n"
 "Report-Msgid-Bugs-To: EMAIL at ADDRESS\n"
-"POT-Creation-Date: 2008-11-27 18:39+0100\n"
+"POT-Creation-Date: 2008-12-28 23:40+0100\n"
 "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
 "Last-Translator: FULL NAME <EMAIL at ADDRESS>\n"
 "Language-Team: LANGUAGE <LL at li.org>\n"
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=utf-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"Generated-By: Babel 0.9.4\n"
+"Generated-By: Babel 0.9.3\n"
 
-#: sphinx/builder.py:408
+#: sphinx/environment.py:103 sphinx/writers/latex.py:170
 #, python-format
-msgid "%b %d, %Y"
-msgstr ""
-
-#: sphinx/builder.py:427 sphinx/templates/defindex.html:21
-msgid "General Index"
-msgstr ""
-
-#: sphinx/builder.py:427
-msgid "index"
+msgid "%B %d, %Y"
 msgstr ""
 
-#: sphinx/builder.py:429 sphinx/htmlhelp.py:156
-#: sphinx/templates/defindex.html:19 sphinx/templates/modindex.html:2
-#: sphinx/templates/modindex.html:13
-msgid "Global Module Index"
+#: sphinx/environment.py:293 sphinx/templates/genindex-single.html:2
+#: sphinx/templates/genindex-split.html:2
+#: sphinx/templates/genindex-split.html:5 sphinx/templates/genindex.html:2
+#: sphinx/templates/genindex.html:5 sphinx/templates/genindex.html:48
+#: sphinx/templates/layout.html:117 sphinx/writers/latex.py:176
+msgid "Index"
 msgstr ""
 
-#: sphinx/builder.py:429
-msgid "modules"
+#: sphinx/environment.py:294 sphinx/writers/latex.py:175
+msgid "Module Index"
 msgstr ""
 
-#: sphinx/builder.py:466
-msgid "next"
+#: sphinx/environment.py:295 sphinx/templates/defindex.html:16
+msgid "Search Page"
 msgstr ""
 
-#: sphinx/builder.py:473
-msgid "previous"
+#: sphinx/roles.py:53 sphinx/directives/desc.py:564
+#, python-format
+msgid "environment variable; %s"
 msgstr ""
 
-#: sphinx/builder.py:1054
-msgid " (in "
+#: sphinx/roles.py:60
+#, python-format
+msgid "Python Enhancement Proposals!PEP %s"
 msgstr ""
 
-#: sphinx/builder.py:1129
+#: sphinx/builders/changes.py:64
 msgid "Builtins"
 msgstr ""
 
-#: sphinx/builder.py:1131
+#: sphinx/builders/changes.py:66
 msgid "Module level"
 msgstr ""
 
-#: sphinx/environment.py:102 sphinx/latexwriter.py:169
+#: sphinx/builders/html.py:115
 #, python-format
-msgid "%B %d, %Y"
-msgstr ""
-
-#: sphinx/environment.py:291 sphinx/latexwriter.py:175
-#: sphinx/templates/genindex-single.html:2
-#: sphinx/templates/genindex-split.html:2
-#: sphinx/templates/genindex-split.html:5 sphinx/templates/genindex.html:2
-#: sphinx/templates/genindex.html:5 sphinx/templates/genindex.html:48
-#: sphinx/templates/layout.html:130
-msgid "Index"
-msgstr ""
-
-#: sphinx/environment.py:292 sphinx/latexwriter.py:174
-msgid "Module Index"
-msgstr ""
-
-#: sphinx/environment.py:293 sphinx/templates/defindex.html:16
-msgid "Search Page"
+msgid "%b %d, %Y"
 msgstr ""
 
-#: sphinx/htmlwriter.py:79 sphinx/static/doctools.js:145
-msgid "Permalink to this definition"
+#: sphinx/builders/html.py:134 sphinx/templates/defindex.html:21
+msgid "General Index"
 msgstr ""
 
-#: sphinx/htmlwriter.py:399 sphinx/static/doctools.js:139
-msgid "Permalink to this headline"
+#: sphinx/builders/html.py:134
+msgid "index"
 msgstr ""
 
-#: sphinx/latexwriter.py:172
-msgid "Release"
+#: sphinx/builders/html.py:136 sphinx/builders/htmlhelp.py:180
+#: sphinx/builders/qthelp.py:129 sphinx/templates/defindex.html:19
+#: sphinx/templates/modindex.html:2 sphinx/templates/modindex.html:13
+msgid "Global Module Index"
 msgstr ""
 
-#: sphinx/roles.py:53 sphinx/directives/desc.py:537
-#, python-format
-msgid "environment variable; %s"
+#: sphinx/builders/html.py:136
+msgid "modules"
 msgstr ""
 
-#: sphinx/roles.py:60
-#, python-format
-msgid "Python Enhancement Proposals!PEP %s"
+#: sphinx/builders/html.py:175
+msgid "next"
 msgstr ""
 
-#: sphinx/textwriter.py:166
-#, python-format
-msgid "Platform: %s"
+#: sphinx/builders/html.py:182
+msgid "previous"
 msgstr ""
 
-#: sphinx/textwriter.py:422
-msgid "[image]"
+#: sphinx/builders/latex.py:155
+msgid " (in "
 msgstr ""
 
 #: sphinx/directives/desc.py:25
@@ -215,11 +193,15 @@
 msgid "Return type"
 msgstr ""
 
-#: sphinx/directives/desc.py:143
+#: sphinx/directives/desc.py:201
+msgid "Parameter"
+msgstr ""
+
+#: sphinx/directives/desc.py:205
 msgid "Parameters"
 msgstr ""
 
-#: sphinx/directives/desc.py:423
+#: sphinx/directives/desc.py:450
 #, python-format
 msgid "%scommand line option; %s"
 msgstr ""
@@ -245,10 +227,15 @@
 msgid "Author: "
 msgstr ""
 
-#: sphinx/directives/other.py:246
+#: sphinx/directives/other.py:249
 msgid "See also"
 msgstr ""
 
+#: sphinx/ext/autodoc.py:576 sphinx/ext/autodoc.py:590
+#, python-format
+msgid "alias of :class:`%s`"
+msgstr ""
+
 #: sphinx/ext/todo.py:31
 msgid "Todo"
 msgstr ""
@@ -345,6 +332,14 @@
 msgid "built-in function"
 msgstr ""
 
+#: sphinx/static/doctools.js:139 sphinx/writers/html.py:415
+msgid "Permalink to this headline"
+msgstr ""
+
+#: sphinx/static/doctools.js:145 sphinx/writers/html.py:80
+msgid "Permalink to this definition"
+msgstr ""
+
 #: sphinx/static/doctools.js:174
 msgid "Hide Search Matches"
 msgstr ""
@@ -365,17 +360,17 @@
 msgid ", in "
 msgstr ""
 
-#: sphinx/static/searchtools.js:447 sphinx/templates/search.html:18
+#: sphinx/static/searchtools.js:453 sphinx/templates/search.html:18
 msgid "Search Results"
 msgstr ""
 
-#: sphinx/static/searchtools.js:449
+#: sphinx/static/searchtools.js:455
 msgid ""
 "Your search did not match any documents. Please make sure that all words "
 "are spelled correctly and that you've selected enough categories."
 msgstr ""
 
-#: sphinx/static/searchtools.js:451
+#: sphinx/static/searchtools.js:457
 #, python-format
 msgid "Search finished, found %s page(s) matching the search query."
 msgstr ""
@@ -451,83 +446,67 @@
 msgid "next chapter"
 msgstr ""
 
-#: sphinx/templates/layout.html:55
+#: sphinx/templates/layout.html:56
 msgid "This Page"
 msgstr ""
 
-#: sphinx/templates/layout.html:59
-msgid "Suggest Change"
-msgstr ""
-
-#: sphinx/templates/layout.html:60 sphinx/templates/layout.html:62
+#: sphinx/templates/layout.html:58
 msgid "Show Source"
 msgstr ""
 
-#: sphinx/templates/layout.html:71
+#: sphinx/templates/layout.html:67
 msgid "Quick search"
 msgstr ""
 
-#: sphinx/templates/layout.html:71
-msgid "Keyword search"
-msgstr ""
-
-#: sphinx/templates/layout.html:73
+#: sphinx/templates/layout.html:69
 msgid "Go"
 msgstr ""
 
-#: sphinx/templates/layout.html:78
-msgid "Enter a module, class or function name."
+#: sphinx/templates/layout.html:73
+msgid "Enter search terms or a module, class or function name."
 msgstr ""
 
-#: sphinx/templates/layout.html:119
+#: sphinx/templates/layout.html:106
 #, python-format
 msgid "Search within %(docstitle)s"
 msgstr ""
 
-#: sphinx/templates/layout.html:128
+#: sphinx/templates/layout.html:115
 msgid "About these documents"
 msgstr ""
 
-#: sphinx/templates/layout.html:131 sphinx/templates/search.html:2
+#: sphinx/templates/layout.html:118 sphinx/templates/search.html:2
 #: sphinx/templates/search.html:5
 msgid "Search"
 msgstr ""
 
-#: sphinx/templates/layout.html:133
+#: sphinx/templates/layout.html:120
 msgid "Copyright"
 msgstr ""
 
-#: sphinx/templates/layout.html:178
+#: sphinx/templates/layout.html:165
 #, python-format
 msgid "&copy; <a href=\"%(path)s\">Copyright</a> %(copyright)s."
 msgstr ""
 
-#: sphinx/templates/layout.html:180
+#: sphinx/templates/layout.html:167
 #, python-format
 msgid "&copy; Copyright %(copyright)s."
 msgstr ""
 
-#: sphinx/templates/layout.html:183
+#: sphinx/templates/layout.html:170
 #, python-format
 msgid "Last updated on %(last_updated)s."
 msgstr ""
 
-#: sphinx/templates/layout.html:186
+#: sphinx/templates/layout.html:173
 #, python-format
 msgid ""
 "Created using <a href=\"http://sphinx.pocoo.org/\">Sphinx</a> "
 "%(sphinx_version)s."
 msgstr ""
 
-#: sphinx/templates/modindex.html:15
-msgid "Most popular modules:"
-msgstr ""
-
-#: sphinx/templates/modindex.html:24
-msgid "Show modules only available on these platforms"
-msgstr ""
-
-#: sphinx/templates/modindex.html:56
+#: sphinx/templates/modindex.html:36
 msgid "Deprecated"
 msgstr ""
 
@@ -536,13 +515,6 @@
 msgid "Search %(docstitle)s"
 msgstr ""
 
-#: sphinx/templates/page.html:8
-msgid ""
-"<strong>Note:</strong> You requested an out-of-date URL from this server."
-" We've tried to redirect you to the new location of this page, but it may"
-" not be the right one."
-msgstr ""
-
 #: sphinx/templates/search.html:7
 msgid ""
 "From here you can search these documents. Enter your search\n"
@@ -587,3 +559,16 @@
 msgid "Other changes"
 msgstr ""
 
+#: sphinx/writers/latex.py:173
+msgid "Release"
+msgstr ""
+
+#: sphinx/writers/text.py:166
+#, python-format
+msgid "Platform: %s"
+msgstr ""
+
+#: sphinx/writers/text.py:427
+msgid "[image]"
+msgstr ""
+

Modified: doctools/trunk/sphinx/locale/zh_TW/LC_MESSAGES/sphinx.po
==============================================================================
--- doctools/trunk/sphinx/locale/zh_TW/LC_MESSAGES/sphinx.po	(original)
+++ doctools/trunk/sphinx/locale/zh_TW/LC_MESSAGES/sphinx.po	Sun Jan  4 21:38:57 2009
@@ -8,93 +8,37 @@
 "Project-Id-Version: Sphinx 0.5\n"
 "Report-Msgid-Bugs-To: EMAIL at ADDRESS\n"
 "POT-Creation-Date: 2008-11-09 19:46+0100\n"
-"PO-Revision-Date: 2008-11-27 18:40+0100\n"
+"PO-Revision-Date: 2008-12-28 23:40+0100\n"
 "Last-Translator: Fred Lin <gasolin at gmail.com>\n"
 "Language-Team: tw <LL at li.org>\n"
 "Plural-Forms: nplurals=1; plural=0\n"
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=utf-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"Generated-By: Babel 0.9.4\n"
+"Generated-By: Babel 0.9.3\n"
 
-#: sphinx/builder.py:408
-#, python-format
-msgid "%b %d, %Y"
-msgstr "%Y 年 %m 月 %d 日"
-
-#: sphinx/builder.py:427 sphinx/templates/defindex.html:21
-msgid "General Index"
-msgstr "總索引"
-
-#: sphinx/builder.py:427
-msgid "index"
-msgstr "索引"
-
-#: sphinx/builder.py:429 sphinx/htmlhelp.py:156
-#: sphinx/templates/defindex.html:19 sphinx/templates/modindex.html:2
-#: sphinx/templates/modindex.html:13
-msgid "Global Module Index"
-msgstr ""
-
-#: sphinx/builder.py:429
-msgid "modules"
-msgstr "模組"
-
-#: sphinx/builder.py:466
-msgid "next"
-msgstr "下一頁"
-
-#: sphinx/builder.py:473
-msgid "previous"
-msgstr "上一頁"
-
-#: sphinx/builder.py:1054
-msgid " (in "
-msgstr ""
-
-#: sphinx/builder.py:1129
-msgid "Builtins"
-msgstr ""
-
-#: sphinx/builder.py:1131
-msgid "Module level"
-msgstr ""
-
-#: sphinx/environment.py:102 sphinx/latexwriter.py:169
+#: sphinx/environment.py:103 sphinx/writers/latex.py:170
 #, python-format
 msgid "%B %d, %Y"
 msgstr "%Y 年 %m 月 %d 日"
 
-#: sphinx/environment.py:291 sphinx/latexwriter.py:175
-#: sphinx/templates/genindex-single.html:2
+#: sphinx/environment.py:293 sphinx/templates/genindex-single.html:2
 #: sphinx/templates/genindex-split.html:2
 #: sphinx/templates/genindex-split.html:5 sphinx/templates/genindex.html:2
 #: sphinx/templates/genindex.html:5 sphinx/templates/genindex.html:48
-#: sphinx/templates/layout.html:130
+#: sphinx/templates/layout.html:117 sphinx/writers/latex.py:176
 msgid "Index"
 msgstr "索引"
 
-#: sphinx/environment.py:292 sphinx/latexwriter.py:174
+#: sphinx/environment.py:294 sphinx/writers/latex.py:175
 msgid "Module Index"
 msgstr "模組索引"
 
-#: sphinx/environment.py:293 sphinx/templates/defindex.html:16
+#: sphinx/environment.py:295 sphinx/templates/defindex.html:16
 msgid "Search Page"
 msgstr "搜尋頁面"
 
-#: sphinx/htmlwriter.py:79 sphinx/static/doctools.js:145
-msgid "Permalink to this definition"
-msgstr ""
-
-#: sphinx/htmlwriter.py:399 sphinx/static/doctools.js:139
-msgid "Permalink to this headline"
-msgstr ""
-
-#: sphinx/latexwriter.py:172
-msgid "Release"
-msgstr "釋出"
-
-#: sphinx/roles.py:53 sphinx/directives/desc.py:537
+#: sphinx/roles.py:53 sphinx/directives/desc.py:564
 #, python-format
 msgid "environment variable; %s"
 msgstr "環境變數; %s"
@@ -104,14 +48,48 @@
 msgid "Python Enhancement Proposals!PEP %s"
 msgstr "Python 建議文件!PEP %s"
 
-#: sphinx/textwriter.py:166
+#: sphinx/builders/changes.py:64
+msgid "Builtins"
+msgstr ""
+
+#: sphinx/builders/changes.py:66
+msgid "Module level"
+msgstr ""
+
+#: sphinx/builders/html.py:115
 #, python-format
-msgid "Platform: %s"
-msgstr "平台:%s"
+msgid "%b %d, %Y"
+msgstr "%Y 年 %m 月 %d 日"
 
-#: sphinx/textwriter.py:422
-msgid "[image]"
-msgstr "[圖片]"
+#: sphinx/builders/html.py:134 sphinx/templates/defindex.html:21
+msgid "General Index"
+msgstr "總索引"
+
+#: sphinx/builders/html.py:134
+msgid "index"
+msgstr "索引"
+
+#: sphinx/builders/html.py:136 sphinx/builders/htmlhelp.py:180
+#: sphinx/builders/qthelp.py:129 sphinx/templates/defindex.html:19
+#: sphinx/templates/modindex.html:2 sphinx/templates/modindex.html:13
+msgid "Global Module Index"
+msgstr ""
+
+#: sphinx/builders/html.py:136
+msgid "modules"
+msgstr "模組"
+
+#: sphinx/builders/html.py:175
+msgid "next"
+msgstr "下一頁"
+
+#: sphinx/builders/html.py:182
+msgid "previous"
+msgstr "上一頁"
+
+#: sphinx/builders/latex.py:155
+msgid " (in "
+msgstr ""
 
 #: sphinx/directives/desc.py:25
 #, python-format
@@ -215,11 +193,16 @@
 msgid "Return type"
 msgstr "返回類別"
 
-#: sphinx/directives/desc.py:143
+#: sphinx/directives/desc.py:201
+#, fuzzy
+msgid "Parameter"
+msgstr "參數"
+
+#: sphinx/directives/desc.py:205
 msgid "Parameters"
 msgstr "參數"
 
-#: sphinx/directives/desc.py:423
+#: sphinx/directives/desc.py:450
 #, python-format
 msgid "%scommand line option; %s"
 msgstr "%s命令列選項; %s"
@@ -245,10 +228,15 @@
 msgid "Author: "
 msgstr "作者:"
 
-#: sphinx/directives/other.py:246
+#: sphinx/directives/other.py:249
 msgid "See also"
 msgstr ""
 
+#: sphinx/ext/autodoc.py:576 sphinx/ext/autodoc.py:590
+#, python-format
+msgid "alias of :class:`%s`"
+msgstr ""
+
 #: sphinx/ext/todo.py:31
 msgid "Todo"
 msgstr "待辦"
@@ -345,6 +333,14 @@
 msgid "built-in function"
 msgstr "內建函式"
 
+#: sphinx/static/doctools.js:139 sphinx/writers/html.py:415
+msgid "Permalink to this headline"
+msgstr ""
+
+#: sphinx/static/doctools.js:145 sphinx/writers/html.py:80
+msgid "Permalink to this definition"
+msgstr ""
+
 #: sphinx/static/doctools.js:174
 msgid "Hide Search Matches"
 msgstr ""
@@ -365,17 +361,17 @@
 msgid ", in "
 msgstr ""
 
-#: sphinx/static/searchtools.js:447 sphinx/templates/search.html:18
+#: sphinx/static/searchtools.js:453 sphinx/templates/search.html:18
 msgid "Search Results"
 msgstr "搜尋結果"
 
-#: sphinx/static/searchtools.js:449
+#: sphinx/static/searchtools.js:455
 msgid ""
 "Your search did not match any documents. Please make sure that all words "
 "are spelled correctly and that you've selected enough categories."
 msgstr ""
 
-#: sphinx/static/searchtools.js:451
+#: sphinx/static/searchtools.js:457
 #, python-format
 msgid "Search finished, found %s page(s) matching the search query."
 msgstr ""
@@ -451,83 +447,68 @@
 msgid "next chapter"
 msgstr "下一章"
 
-#: sphinx/templates/layout.html:55
+#: sphinx/templates/layout.html:56
 msgid "This Page"
 msgstr "本頁"
 
-#: sphinx/templates/layout.html:59
-msgid "Suggest Change"
-msgstr ""
-
-#: sphinx/templates/layout.html:60 sphinx/templates/layout.html:62
+#: sphinx/templates/layout.html:58
 msgid "Show Source"
 msgstr "顯示原始碼"
 
-#: sphinx/templates/layout.html:71
+#: sphinx/templates/layout.html:67
 msgid "Quick search"
 msgstr "快速搜尋"
 
-#: sphinx/templates/layout.html:71
-msgid "Keyword search"
-msgstr "關鍵字搜尋"
-
-#: sphinx/templates/layout.html:73
+#: sphinx/templates/layout.html:69
 msgid "Go"
 msgstr ""
 
-#: sphinx/templates/layout.html:78
-msgid "Enter a module, class or function name."
+#: sphinx/templates/layout.html:73
+#, fuzzy
+msgid "Enter search terms or a module, class or function name."
 msgstr "輸入一個模組、類別、或是函式名稱."
 
-#: sphinx/templates/layout.html:119
+#: sphinx/templates/layout.html:106
 #, python-format
 msgid "Search within %(docstitle)s"
 msgstr "在 %(docstitle)s 中搜尋"
 
-#: sphinx/templates/layout.html:128
+#: sphinx/templates/layout.html:115
 msgid "About these documents"
 msgstr ""
 
-#: sphinx/templates/layout.html:131 sphinx/templates/search.html:2
+#: sphinx/templates/layout.html:118 sphinx/templates/search.html:2
 #: sphinx/templates/search.html:5
 msgid "Search"
 msgstr "搜尋"
 
-#: sphinx/templates/layout.html:133
+#: sphinx/templates/layout.html:120
 msgid "Copyright"
 msgstr "版權所有"
 
-#: sphinx/templates/layout.html:178
+#: sphinx/templates/layout.html:165
 #, python-format
 msgid "&copy; <a href=\"%(path)s\">Copyright</a> %(copyright)s."
 msgstr ""
 
-#: sphinx/templates/layout.html:180
+#: sphinx/templates/layout.html:167
 #, python-format
 msgid "&copy; Copyright %(copyright)s."
 msgstr ""
 
-#: sphinx/templates/layout.html:183
+#: sphinx/templates/layout.html:170
 #, python-format
 msgid "Last updated on %(last_updated)s."
 msgstr "最後更新日期是 %(last_updated)s."
 
-#: sphinx/templates/layout.html:186
+#: sphinx/templates/layout.html:173
 #, python-format
 msgid ""
 "Created using <a href=\"http://sphinx.pocoo.org/\">Sphinx</a> "
 "%(sphinx_version)s."
 msgstr ""
 
-#: sphinx/templates/modindex.html:15
-msgid "Most popular modules:"
-msgstr ""
-
-#: sphinx/templates/modindex.html:24
-msgid "Show modules only available on these platforms"
-msgstr ""
-
-#: sphinx/templates/modindex.html:56
+#: sphinx/templates/modindex.html:36
 msgid "Deprecated"
 msgstr "已移除"
 
@@ -536,13 +517,6 @@
 msgid "Search %(docstitle)s"
 msgstr "搜尋 %(docstitle)s"
 
-#: sphinx/templates/page.html:8
-msgid ""
-"<strong>Note:</strong> You requested an out-of-date URL from this server."
-" We've tried to redirect you to the new location of this page, but it may"
-" not be the right one."
-msgstr ""
-
 #: sphinx/templates/search.html:7
 msgid ""
 "From here you can search these documents. Enter your search\n"
@@ -587,12 +561,36 @@
 msgid "Other changes"
 msgstr "其他改變:"
 
+#: sphinx/writers/latex.py:173
+msgid "Release"
+msgstr "釋出"
+
+#: sphinx/writers/text.py:166
+#, python-format
+msgid "Platform: %s"
+msgstr "平台:%s"
+
+#: sphinx/writers/text.py:427
+msgid "[image]"
+msgstr "[圖片]"
+
+#~ msgid "Suggest Change"
+#~ msgstr ""
+
+#~ msgid "Keyword search"
+#~ msgstr "關鍵字搜尋"
+
+#~ msgid "Most popular modules:"
+#~ msgstr ""
+
+#~ msgid "Show modules only available on these platforms"
+#~ msgstr ""
+
 #~ msgid ""
-#~ "From here you can search these documents. Enter your search\n"
-#~ "    words into the box below and"
-#~ " click \"search\". Note that the "
-#~ "search\n"
-#~ "    function will automatically search for all of the words. Pages\n"
-#~ "    containing less words won't appear in the result list."
+#~ "<strong>Note:</strong> You requested an "
+#~ "out-of-date URL from this server. "
+#~ "We've tried to redirect you to the"
+#~ " new location of this page, but "
+#~ "it may not be the right one."
 #~ msgstr ""
 

Added: doctools/trunk/sphinx/pycode/Grammar.txt
==============================================================================
--- (empty file)
+++ doctools/trunk/sphinx/pycode/Grammar.txt	Sun Jan  4 21:38:57 2009
@@ -0,0 +1,155 @@
+# Grammar for Python
+
+# Note:  Changing the grammar specified in this file will most likely
+#        require corresponding changes in the parser module
+#        (../Modules/parsermodule.c).  If you can't make the changes to
+#        that module yourself, please co-ordinate the required changes
+#        with someone who can; ask around on python-dev for help.  Fred
+#        Drake <fdrake at acm.org> will probably be listening there.
+
+# NOTE WELL: You should also follow all the steps listed in PEP 306,
+# "How to Change Python's Grammar"
+
+# Commands for Kees Blom's railroad program
+#diagram:token NAME
+#diagram:token NUMBER
+#diagram:token STRING
+#diagram:token NEWLINE
+#diagram:token ENDMARKER
+#diagram:token INDENT
+#diagram:output\input python.bla
+#diagram:token DEDENT
+#diagram:output\textwidth 20.04cm\oddsidemargin  0.0cm\evensidemargin 0.0cm
+#diagram:rules
+
+# Start symbols for the grammar:
+#	file_input is a module or sequence of commands read from an input file;
+#	single_input is a single interactive statement;
+#	eval_input is the input for the eval() and input() functions.
+# NB: compound_stmt in single_input is followed by extra NEWLINE!
+file_input: (NEWLINE | stmt)* ENDMARKER
+single_input: NEWLINE | simple_stmt | compound_stmt NEWLINE
+eval_input: testlist NEWLINE* ENDMARKER
+
+decorator: '@' dotted_name [ '(' [arglist] ')' ] NEWLINE
+decorators: decorator+
+decorated: decorators (classdef | funcdef)
+funcdef: 'def' NAME parameters ['->' test] ':' suite
+parameters: '(' [typedargslist] ')'
+typedargslist: ((tfpdef ['=' test] ',')*
+                ('*' [tname] (',' tname ['=' test])* [',' '**' tname] | '**' tname)
+                | tfpdef ['=' test] (',' tfpdef ['=' test])* [','])
+tname: NAME [':' test]
+tfpdef: tname | '(' tfplist ')'
+tfplist: tfpdef (',' tfpdef)* [',']
+varargslist: ((vfpdef ['=' test] ',')*
+              ('*' [vname] (',' vname ['=' test])*  [',' '**' vname] | '**' vname)
+              | vfpdef ['=' test] (',' vfpdef ['=' test])* [','])
+vname: NAME
+vfpdef: vname | '(' vfplist ')'
+vfplist: vfpdef (',' vfpdef)* [',']
+
+stmt: simple_stmt | compound_stmt
+simple_stmt: small_stmt (';' small_stmt)* [';'] NEWLINE
+small_stmt: (expr_stmt | print_stmt  | del_stmt | pass_stmt | flow_stmt |
+             import_stmt | global_stmt | exec_stmt | assert_stmt)
+expr_stmt: testlist (augassign (yield_expr|testlist) |
+                     ('=' (yield_expr|testlist))*)
+augassign: ('+=' | '-=' | '*=' | '/=' | '%=' | '&=' | '|=' | '^=' |
+            '<<=' | '>>=' | '**=' | '//=')
+# For normal assignments, additional restrictions enforced by the interpreter
+print_stmt: 'print' ( [ test (',' test)* [','] ] |
+                      '>>' test [ (',' test)+ [','] ] )
+del_stmt: 'del' exprlist
+pass_stmt: 'pass'
+flow_stmt: break_stmt | continue_stmt | return_stmt | raise_stmt | yield_stmt
+break_stmt: 'break'
+continue_stmt: 'continue'
+return_stmt: 'return' [testlist]
+yield_stmt: yield_expr
+raise_stmt: 'raise' [test ['from' test | ',' test [',' test]]]
+import_stmt: import_name | import_from
+import_name: 'import' dotted_as_names
+import_from: ('from' ('.'* dotted_name | '.'+)
+              'import' ('*' | '(' import_as_names ')' | import_as_names))
+import_as_name: NAME ['as' NAME]
+dotted_as_name: dotted_name ['as' NAME]
+import_as_names: import_as_name (',' import_as_name)* [',']
+dotted_as_names: dotted_as_name (',' dotted_as_name)*
+dotted_name: NAME ('.' NAME)*
+global_stmt: ('global' | 'nonlocal') NAME (',' NAME)*
+exec_stmt: 'exec' expr ['in' test [',' test]]
+assert_stmt: 'assert' test [',' test]
+
+compound_stmt: if_stmt | while_stmt | for_stmt | try_stmt | with_stmt | funcdef | classdef | decorated
+if_stmt: 'if' test ':' suite ('elif' test ':' suite)* ['else' ':' suite]
+while_stmt: 'while' test ':' suite ['else' ':' suite]
+for_stmt: 'for' exprlist 'in' testlist ':' suite ['else' ':' suite]
+try_stmt: ('try' ':' suite
+           ((except_clause ':' suite)+
+	    ['else' ':' suite]
+	    ['finally' ':' suite] |
+	   'finally' ':' suite))
+with_stmt: 'with' test [ with_var ] ':' suite
+with_var: 'as' expr
+# NB compile.c makes sure that the default except clause is last
+except_clause: 'except' [test [(',' | 'as') test]]
+suite: simple_stmt | NEWLINE INDENT stmt+ DEDENT
+
+# Backward compatibility cruft to support:
+# [ x for x in lambda: True, lambda: False if x() ]
+# even while also allowing:
+# lambda x: 5 if x else 2
+# (But not a mix of the two)
+testlist_safe: old_test [(',' old_test)+ [',']]
+old_test: or_test | old_lambdef
+old_lambdef: 'lambda' [varargslist] ':' old_test
+
+test: or_test ['if' or_test 'else' test] | lambdef
+or_test: and_test ('or' and_test)*
+and_test: not_test ('and' not_test)*
+not_test: 'not' not_test | comparison
+comparison: expr (comp_op expr)*
+comp_op: '<'|'>'|'=='|'>='|'<='|'<>'|'!='|'in'|'not' 'in'|'is'|'is' 'not'
+expr: xor_expr ('|' xor_expr)*
+xor_expr: and_expr ('^' and_expr)*
+and_expr: shift_expr ('&' shift_expr)*
+shift_expr: arith_expr (('<<'|'>>') arith_expr)*
+arith_expr: term (('+'|'-') term)*
+term: factor (('*'|'/'|'%'|'//') factor)*
+factor: ('+'|'-'|'~') factor | power
+power: atom trailer* ['**' factor]
+atom: ('(' [yield_expr|testlist_gexp] ')' |
+       '[' [listmaker] ']' |
+       '{' [dictsetmaker] '}' |
+       '`' testlist1 '`' |
+       NAME | NUMBER | STRING+ | '.' '.' '.')
+listmaker: test ( comp_for | (',' test)* [','] )
+testlist_gexp: test ( comp_for | (',' test)* [','] )
+lambdef: 'lambda' [varargslist] ':' test
+trailer: '(' [arglist] ')' | '[' subscriptlist ']' | '.' NAME
+subscriptlist: subscript (',' subscript)* [',']
+subscript: test | [test] ':' [test] [sliceop]
+sliceop: ':' [test]
+exprlist: expr (',' expr)* [',']
+testlist: test (',' test)* [',']
+dictsetmaker: ( (test ':' test (comp_for | (',' test ':' test)* [','])) |
+                (test (comp_for | (',' test)* [','])) )
+
+classdef: 'class' NAME ['(' [arglist] ')'] ':' suite
+
+arglist: (argument ',')* (argument [',']
+                         |'*' test (',' argument)* [',' '**' test] 
+                         |'**' test)
+argument: test [comp_for] | test '=' test  # Really [keyword '='] test
+
+comp_iter: comp_for | comp_if
+comp_for: 'for' exprlist 'in' testlist_safe [comp_iter]
+comp_if: 'if' old_test [comp_iter]
+
+testlist1: test (',' test)*
+
+# not used in grammar, but may appear in "node" passed from Parser to Compiler
+encoding_decl: NAME
+
+yield_expr: 'yield' [testlist]

Added: doctools/trunk/sphinx/pycode/__init__.py
==============================================================================
--- (empty file)
+++ doctools/trunk/sphinx/pycode/__init__.py	Sun Jan  4 21:38:57 2009
@@ -0,0 +1,303 @@
+# -*- coding: utf-8 -*-
+"""
+    sphinx.pycode
+    ~~~~~~~~~~~~~
+
+    Utilities parsing and analyzing Python code.
+
+    :copyright: Copyright 2007-2009 by the Sphinx team, see AUTHORS.
+    :license: BSD, see LICENSE for details.
+"""
+
+import re
+import sys
+from os import path
+from cStringIO import StringIO
+
+from sphinx.pycode import nodes
+from sphinx.pycode.pgen2 import driver, token, tokenize, parse, literals
+from sphinx.util.docstrings import prepare_docstring, prepare_commentdoc
+
+
+# load the Python grammar
+_grammarfile = path.join(path.dirname(__file__), 'Grammar.txt')
+pygrammar = driver.load_grammar(_grammarfile)
+pydriver = driver.Driver(pygrammar, convert=nodes.convert)
+
+# an object with attributes corresponding to token and symbol names
+class sym: pass
+for k, v in pygrammar.symbol2number.iteritems():
+    setattr(sym, k, v)
+for k, v in token.tok_name.iteritems():
+    setattr(sym, v, k)
+
+# a dict mapping terminal and nonterminal numbers to their names
+number2name = pygrammar.number2symbol.copy()
+number2name.update(token.tok_name)
+
+
+# a regex to recognize coding cookies
+_coding_re = re.compile(r'coding[:=]\s*([-\w.]+)')
+
+_eq = nodes.Leaf(token.EQUAL, '=')
+
+
+class AttrDocVisitor(nodes.NodeVisitor):
+    """
+    Visitor that collects docstrings for attribute assignments on toplevel and
+    in classes.
+
+    The docstrings can either be in special '#:' comments before the assignment
+    or in a docstring after it.
+    """
+    def init(self, scope, encoding):
+        self.scope = scope
+        self.encoding = encoding
+        self.namespace = []
+        self.collected = {}
+
+    def visit_classdef(self, node):
+        self.namespace.append(node[1].value)
+        self.generic_visit(node)
+        self.namespace.pop()
+
+    def visit_expr_stmt(self, node):
+        """Visit an assignment which may have a special comment before it."""
+        if _eq not in node.children:
+            # not an assignment (we don't care for augmented assignments)
+            return
+        pnode = node[0]
+        prefix = pnode.get_prefix()
+        # if the assignment is the first statement on a new indentation
+        # level, its preceding whitespace and comments are not assigned
+        # to that token, but the first INDENT or DEDENT token
+        while not prefix:
+            pnode = pnode.get_prev_leaf()
+            if not pnode or pnode.type not in (token.INDENT, token.DEDENT):
+                break
+            prefix = pnode.get_prefix()
+        prefix = prefix.decode(self.encoding)
+        docstring = prepare_commentdoc(prefix)
+        if docstring:
+            self.add_docstring(node, docstring)
+
+    def visit_simple_stmt(self, node):
+        """Visit a docstring statement which may have an assignment before."""
+        if node[0].type != token.STRING:
+            # not a docstring; but still need to visit children
+            return self.generic_visit(node)
+        prev = node.get_prev_sibling()
+        if not prev:
+            return
+        if prev.type == sym.simple_stmt and \
+               prev[0].type == sym.expr_stmt and _eq in prev[0].children:
+            # need to "eval" the string because it's returned in its original form
+            docstring = literals.evalString(node[0].value, self.encoding)
+            docstring = prepare_docstring(docstring)
+            self.add_docstring(prev[0], docstring)
+
+    def visit_funcdef(self, node):
+        # don't descend into functions -- nothing interesting there
+        return
+
+    def add_docstring(self, node, docstring):
+        # add an item for each assignment target
+        for i in range(0, len(node) - 1, 2):
+            target = node[i]
+            if target.type != token.NAME:
+                # don't care about complex targets
+                continue
+            namespace = '.'.join(self.namespace)
+            if namespace.startswith(self.scope):
+                self.collected[namespace, target.value] = docstring
+
+
+class PycodeError(Exception):
+    def __str__(self):
+        res = self.args[0]
+        if len(self.args) > 1:
+            res += ' (exception was: %r)' % self.args[1]
+        return res
+
+
+class ModuleAnalyzer(object):
+    # cache for analyzer objects -- caches both by module and file name
+    cache = {}
+
+    @classmethod
+    def for_string(cls, string, modname, srcname='<string>'):
+        return cls(StringIO(string), modname, srcname)
+
+    @classmethod
+    def for_file(cls, filename, modname):
+        if ('file', filename) in cls.cache:
+            return cls.cache['file', filename]
+        try:
+            fileobj = open(filename, 'r')
+        except Exception, err:
+            raise PycodeError('error opening %r' % filename, err)
+        obj = cls(fileobj, modname, filename)
+        cls.cache['file', filename] = obj
+        return obj
+
+    @classmethod
+    def for_module(cls, modname):
+        if ('module', modname) in cls.cache:
+            entry = cls.cache['module', modname]
+            if isinstance(entry, PycodeError):
+                raise entry
+            return entry
+
+        try:
+            if modname not in sys.modules:
+                try:
+                    __import__(modname)
+                except ImportError, err:
+                    raise PycodeError('error importing %r' % modname, err)
+            mod = sys.modules[modname]
+            if hasattr(mod, '__loader__'):
+                try:
+                    source = mod.__loader__.get_source(modname)
+                except Exception, err:
+                    raise PycodeError('error getting source for %r' % modname, err)
+                obj = cls.for_string(source, modname)
+                cls.cache['module', modname] = obj
+                return obj
+            filename = getattr(mod, '__file__', None)
+            if filename is None:
+                raise PycodeError('no source found for module %r' % modname)
+            filename = path.normpath(filename)
+            lfilename = filename.lower()
+            if lfilename.endswith('.pyo') or lfilename.endswith('.pyc'):
+                filename = filename[:-1]
+            elif not lfilename.endswith('.py'):
+                raise PycodeError('source is not a .py file: %r' % filename)
+            if not path.isfile(filename):
+                raise PycodeError('source file is not present: %r' % filename)
+            obj = cls.for_file(filename, modname)
+        except PycodeError, err:
+            cls.cache['module', modname] = err
+            raise
+        cls.cache['module', modname] = obj
+        return obj
+
+    def __init__(self, source, modname, srcname):
+        # name of the module
+        self.modname = modname
+        # name of the source file
+        self.srcname = srcname
+        # file-like object yielding source lines
+        self.source = source
+
+        # will be filled by tokenize()
+        self.tokens = None
+        # will be filled by parse()
+        self.parsetree = None
+        # will be filled by find_attr_docs()
+        self.attr_docs = None
+        # will be filled by find_tags()
+        self.tags = None
+
+    def tokenize(self):
+        """Generate tokens from the source."""
+        if self.tokens is not None:
+            return
+        self.tokens = list(tokenize.generate_tokens(self.source.readline))
+        self.source.close()
+
+    def parse(self):
+        """Parse the generated source tokens."""
+        if self.parsetree is not None:
+            return
+        self.tokenize()
+        self.parsetree = pydriver.parse_tokens(self.tokens)
+        # find the source code encoding
+        encoding = sys.getdefaultencoding()
+        comments = self.parsetree.get_prefix()
+        for line in comments.splitlines()[:2]:
+            match = _coding_re.search(line)
+            if match is not None:
+                encoding = match.group(1)
+                break
+        self.encoding = encoding
+
+    def find_attr_docs(self, scope=''):
+        """Find class and module-level attributes and their documentation."""
+        if self.attr_docs is not None:
+            return self.attr_docs
+        self.parse()
+        attr_visitor = AttrDocVisitor(number2name, scope, self.encoding)
+        attr_visitor.visit(self.parsetree)
+        self.attr_docs = attr_visitor.collected
+        return attr_visitor.collected
+
+    def find_tags(self):
+        """Find class, function and method definitions and their location."""
+        if self.tags is not None:
+            return self.tags
+        self.tokenize()
+        result = {}
+        namespace = []
+        stack = []
+        indent = 0
+        defline = False
+        expect_indent = False
+        def tokeniter(ignore = (token.COMMENT, token.NL)):
+            for tokentup in self.tokens:
+                if tokentup[0] not in ignore:
+                    yield tokentup
+        tokeniter = tokeniter()
+        for type, tok, spos, epos, line in tokeniter:
+            if expect_indent:
+                if type != token.INDENT:
+                    # no suite -- one-line definition
+                    assert stack
+                    dtype, fullname, startline, _ = stack.pop()
+                    endline = epos[0]
+                    namespace.pop()
+                    result[fullname] = (dtype, startline, endline)
+                expect_indent = False
+            if tok in ('def', 'class'):
+                name = tokeniter.next()[1]
+                namespace.append(name)
+                fullname = '.'.join(namespace)
+                stack.append((tok, fullname, spos[0], indent))
+                defline = True
+            elif type == token.INDENT:
+                expect_indent = False
+                indent += 1
+            elif type == token.DEDENT:
+                indent -= 1
+                # if the stacklevel is the same as it was before the last
+                # def/class block, this dedent closes that block
+                if stack and indent == stack[-1][3]:
+                    dtype, fullname, startline, _ = stack.pop()
+                    endline = spos[0]
+                    namespace.pop()
+                    result[fullname] = (dtype, startline, endline)
+            elif type == token.NEWLINE:
+                # if this line contained a definition, expect an INDENT to start the
+                # suite; if there is no such INDENT it's a one-line definition
+                if defline:
+                    defline = False
+                    expect_indent = True
+        self.tags = result
+        return result
+
+
+if __name__ == '__main__':
+    import time, pprint
+    x0 = time.time()
+    #ma = ModuleAnalyzer.for_file(__file__.rstrip('c'), 'sphinx.builders.html')
+    ma = ModuleAnalyzer.for_file('sphinx/builders/html.py', 'sphinx.builders.html')
+    ma.tokenize()
+    x1 = time.time()
+    ma.parse()
+    x2 = time.time()
+    #for (ns, name), doc in ma.find_attr_docs().iteritems():
+    #    print '>>', ns, name
+    #    print '\n'.join(doc)
+    pprint.pprint(ma.find_tags())
+    x3 = time.time()
+    #print nodes.nice_repr(ma.parsetree, number2name)
+    print "tokenizing %.4f, parsing %.4f, finding %.4f" % (x1-x0, x2-x1, x3-x2)

Added: doctools/trunk/sphinx/pycode/nodes.py
==============================================================================
--- (empty file)
+++ doctools/trunk/sphinx/pycode/nodes.py	Sun Jan  4 21:38:57 2009
@@ -0,0 +1,202 @@
+# -*- coding: utf-8 -*-
+"""
+    sphinx.pycode.nodes
+    ~~~~~~~~~~~~~~~~~~~
+
+    Parse tree node implementations.
+
+    :copyright: Copyright 2007-2009 by the Sphinx team, see AUTHORS.
+    :license: BSD, see LICENSE for details.
+"""
+
+
+class BaseNode(object):
+    """
+    Node superclass for both terminal and nonterminal nodes.
+    """
+
+    def _eq(self, other):
+        raise NotImplementedError
+
+    def __eq__(self, other):
+        if self.__class__ is not other.__class__:
+            return NotImplemented
+        return self._eq(other)
+
+    def __ne__(self, other):
+        if self.__class__ is not other.__class__:
+            return NotImplemented
+        return not self._eq(other)
+
+    def get_prev_sibling(self):
+        """Return previous child in parent's children, or None."""
+        if self.parent is None:
+            return None
+        for i, child in enumerate(self.parent.children):
+            if child is self:
+                if i == 0:
+                    return None
+                return self.parent.children[i-1]
+
+    def get_next_sibling(self):
+        """Return next child in parent's children, or None."""
+        if self.parent is None:
+            return None
+        for i, child in enumerate(self.parent.children):
+            if child is self:
+                try:
+                    return self.parent.children[i+1]
+                except IndexError:
+                    return None
+
+    def get_prev_leaf(self):
+        """Return the leaf node that precedes this node in the parse tree."""
+        def last_child(node):
+            if isinstance(node, Leaf):
+                return node
+            elif not node.children:
+                return None
+            else:
+                return last_child(node.children[-1])
+        if self.parent is None:
+            return None
+        prev = self.get_prev_sibling()
+        if isinstance(prev, Leaf):
+            return prev
+        elif prev is not None:
+            return last_child(prev)
+        return self.parent.get_prev_leaf()
+
+    def get_next_leaf(self):
+        """Return self if leaf, otherwise the leaf node that succeeds this
+        node in the parse tree.
+        """
+        node = self
+        while not isinstance(node, Leaf):
+            assert node.children
+            node = node.children[0]
+        return node
+
+    def get_lineno(self):
+        """Return the line number which generated the invocant node."""
+        return self.get_next_leaf().lineno
+
+    def get_prefix(self):
+        """Return the prefix of the next leaf node."""
+        # only leaves carry a prefix
+        return self.get_next_leaf().prefix
+
+
+class Node(BaseNode):
+    """
+    Node implementation for nonterminals.
+    """
+
+    def __init__(self, type, children, context=None):
+        # type of nonterminals is >= 256
+        # assert type >= 256, type
+        self.type = type
+        self.children = list(children)
+        for ch in self.children:
+            # assert ch.parent is None, repr(ch)
+            ch.parent = self
+
+    def __repr__(self):
+        return '%s(%s, %r)' % (self.__class__.__name__, self.type, self.children)
+
+    def __str__(self):
+        """This reproduces the input source exactly."""
+        return ''.join(map(str, self.children))
+
+    def _eq(self, other):
+        return (self.type, self.children) == (other.type, other.children)
+
+    # support indexing the node directly instead of .children
+
+    def __getitem__(self, index):
+        return self.children[index]
+
+    def __iter__(self):
+        return iter(self.children)
+
+    def __len__(self):
+        return len(self.children)
+
+
+class Leaf(BaseNode):
+    """
+    Node implementation for leaf nodes (terminals).
+    """
+    prefix = ''  # Whitespace and comments preceding this token in the input
+    lineno = 0   # Line where this token starts in the input
+    column = 0   # Column where this token tarts in the input
+
+    def __init__(self, type, value, context=None):
+        # type of terminals is below 256
+        # assert 0 <= type < 256, type
+        self.type = type
+        self.value = value
+        if context is not None:
+            self.prefix, (self.lineno, self.column) = context
+
+    def __repr__(self):
+        return '%s(%r, %r, %r)' % (self.__class__.__name__,
+                                   self.type, self.value, self.prefix)
+
+    def __str__(self):
+        """This reproduces the input source exactly."""
+        return self.prefix + str(self.value)
+
+    def _eq(self, other):
+        """Compares two nodes for equality."""
+        return (self.type, self.value) == (other.type, other.value)
+
+
+def convert(grammar, raw_node):
+    """Convert raw node to a Node or Leaf instance."""
+    type, value, context, children = raw_node
+    if children or type in grammar.number2symbol:
+        # If there's exactly one child, return that child instead of
+        # creating a new node.
+        if len(children) == 1:
+            return children[0]
+        return Node(type, children, context=context)
+    else:
+        return Leaf(type, value, context=context)
+
+
+def nice_repr(node, number2name, prefix=False):
+    def _repr(node):
+        if isinstance(node, Leaf):
+            return "%s(%r)" % (number2name[node.type], node.value)
+        else:
+            return "%s(%s)" % (number2name[node.type],
+                               ', '.join(map(_repr, node.children)))
+    def _prepr(node):
+        if isinstance(node, Leaf):
+            return "%s(%r, %r)" % (number2name[node.type], node.prefix, node.value)
+        else:
+            return "%s(%s)" % (number2name[node.type],
+                               ', '.join(map(_prepr, node.children)))
+    return (prefix and _prepr or _repr)(node)
+
+
+class NodeVisitor(object):
+    def __init__(self, number2name, *args):
+        self.number2name = number2name
+        self.init(*args)
+
+    def init(self, *args):
+        pass
+
+    def visit(self, node):
+        """Visit a node."""
+        method = 'visit_' + self.number2name[node.type]
+        visitor = getattr(self, method, self.generic_visit)
+        return visitor(node)
+
+    def generic_visit(self, node):
+        """Called if no explicit visitor function exists for a node."""
+        if isinstance(node, Node):
+            for child in node:
+                self.visit(child)

Added: doctools/trunk/sphinx/pycode/pgen2/__init__.py
==============================================================================
--- (empty file)
+++ doctools/trunk/sphinx/pycode/pgen2/__init__.py	Sun Jan  4 21:38:57 2009
@@ -0,0 +1,4 @@
+# Copyright 2004-2005 Elemental Security, Inc. All Rights Reserved.
+# Licensed to PSF under a Contributor Agreement.
+
+"""The pgen2 package."""

Added: doctools/trunk/sphinx/pycode/pgen2/driver.py
==============================================================================
--- (empty file)
+++ doctools/trunk/sphinx/pycode/pgen2/driver.py	Sun Jan  4 21:38:57 2009
@@ -0,0 +1,145 @@
+# Copyright 2004-2005 Elemental Security, Inc. All Rights Reserved.
+# Licensed to PSF under a Contributor Agreement.
+
+# Modifications:
+# Copyright 2006 Google, Inc. All Rights Reserved.
+# Licensed to PSF under a Contributor Agreement.
+
+"""Parser driver.
+
+This provides a high-level interface to parse a file into a syntax tree.
+
+"""
+
+__author__ = "Guido van Rossum <guido at python.org>"
+
+__all__ = ["Driver", "load_grammar"]
+
+# Python imports
+import os
+import logging
+import sys
+
+# Pgen imports
+from sphinx.pycode.pgen2 import grammar, parse, token, tokenize, pgen
+
+
+class Driver(object):
+
+    def __init__(self, grammar, convert=None, logger=None):
+        self.grammar = grammar
+        if logger is None:
+            logger = logging.getLogger()
+        self.logger = logger
+        self.convert = convert
+
+    def parse_tokens(self, tokens, debug=False):
+        """Parse a series of tokens and return the syntax tree."""
+        # XXX Move the prefix computation into a wrapper around tokenize.
+        p = parse.Parser(self.grammar, self.convert)
+        p.setup()
+        lineno = 1
+        column = 0
+        type = value = start = end = line_text = None
+        prefix = ""
+        opmap = grammar.opmap
+        for type, value, start, end, line_text in tokens:
+            if start != (lineno, column):
+                assert (lineno, column) <= start, ((lineno, column), start)
+                s_lineno, s_column = start
+                if lineno < s_lineno:
+                    prefix += "\n" * (s_lineno - lineno)
+                    lineno = s_lineno
+                    column = 0
+                if column < s_column:
+                    prefix += line_text[column:s_column]
+                    column = s_column
+            if type in (tokenize.COMMENT, tokenize.NL):
+                prefix += value
+                lineno, column = end
+                if value.endswith("\n"):
+                    lineno += 1
+                    column = 0
+                continue
+            if type == token.OP:
+                type = opmap[value]
+            # if debug:
+            #     self.logger.debug("%s %r (prefix=%r)",
+            #                       token.tok_name[type], value, prefix)
+            if p.addtoken(type, value, (prefix, start)):
+                # if debug:
+                #     self.logger.debug("Stop.")
+                break
+            prefix = ""
+            lineno, column = end
+            if value.endswith("\n"):
+                lineno += 1
+                column = 0
+        else:
+            # We never broke out -- EOF is too soon (how can this happen???)
+            raise parse.ParseError("incomplete input", type, value, line_text)
+        return p.rootnode
+
+    def parse_stream_raw(self, stream, debug=False):
+        """Parse a stream and return the syntax tree."""
+        tokens = tokenize.generate_tokens(stream.readline)
+        return self.parse_tokens(tokens, debug)
+
+    def parse_stream(self, stream, debug=False):
+        """Parse a stream and return the syntax tree."""
+        return self.parse_stream_raw(stream, debug)
+
+    def parse_file(self, filename, debug=False):
+        """Parse a file and return the syntax tree."""
+        stream = open(filename)
+        try:
+            return self.parse_stream(stream, debug)
+        finally:
+            stream.close()
+
+    def parse_string(self, text, debug=False):
+        """Parse a string and return the syntax tree."""
+        tokens = tokenize.generate_tokens(generate_lines(text).next)
+        return self.parse_tokens(tokens, debug)
+
+
+def generate_lines(text):
+    """Generator that behaves like readline without using StringIO."""
+    for line in text.splitlines(True):
+        yield line
+    while True:
+        yield ""
+
+
+def load_grammar(gt="Grammar.txt", gp=None,
+                 save=True, force=False, logger=None):
+    """Load the grammar (maybe from a pickle)."""
+    if logger is None:
+        logger = logging.getLogger()
+    if gp is None:
+        head, tail = os.path.splitext(gt)
+        if tail == ".txt":
+            tail = ""
+        gp = head + tail + ".".join(map(str, sys.version_info)) + ".pickle"
+    if force or not _newer(gp, gt):
+        logger.info("Generating grammar tables from %s", gt)
+        g = pgen.generate_grammar(gt)
+        if save:
+            logger.info("Writing grammar tables to %s", gp)
+            try:
+                g.dump(gp)
+            except IOError, e:
+                logger.info("Writing failed:"+str(e))
+    else:
+        g = grammar.Grammar()
+        g.load(gp)
+    return g
+
+
+def _newer(a, b):
+    """Inquire whether file a was written since file b."""
+    if not os.path.exists(a):
+        return False
+    if not os.path.exists(b):
+        return True
+    return os.path.getmtime(a) >= os.path.getmtime(b)

Added: doctools/trunk/sphinx/pycode/pgen2/grammar.py
==============================================================================
--- (empty file)
+++ doctools/trunk/sphinx/pycode/pgen2/grammar.py	Sun Jan  4 21:38:57 2009
@@ -0,0 +1,171 @@
+# Copyright 2004-2005 Elemental Security, Inc. All Rights Reserved.
+# Licensed to PSF under a Contributor Agreement.
+
+"""This module defines the data structures used to represent a grammar.
+
+These are a bit arcane because they are derived from the data
+structures used by Python's 'pgen' parser generator.
+
+There's also a table here mapping operators to their names in the
+token module; the Python tokenize module reports all operators as the
+fallback token code OP, but the parser needs the actual token code.
+
+"""
+
+# Python imports
+import pickle
+
+# Local imports
+from sphinx.pycode.pgen2 import token, tokenize
+
+
+class Grammar(object):
+    """Pgen parsing tables tables conversion class.
+
+    Once initialized, this class supplies the grammar tables for the
+    parsing engine implemented by parse.py.  The parsing engine
+    accesses the instance variables directly.  The class here does not
+    provide initialization of the tables; several subclasses exist to
+    do this (see the conv and pgen modules).
+
+    The load() method reads the tables from a pickle file, which is
+    much faster than the other ways offered by subclasses.  The pickle
+    file is written by calling dump() (after loading the grammar
+    tables using a subclass).  The report() method prints a readable
+    representation of the tables to stdout, for debugging.
+
+    The instance variables are as follows:
+
+    symbol2number -- a dict mapping symbol names to numbers.  Symbol
+                     numbers are always 256 or higher, to distinguish
+                     them from token numbers, which are between 0 and
+                     255 (inclusive).
+
+    number2symbol -- a dict mapping numbers to symbol names;
+                     these two are each other's inverse.
+
+    states        -- a list of DFAs, where each DFA is a list of
+                     states, each state is is a list of arcs, and each
+                     arc is a (i, j) pair where i is a label and j is
+                     a state number.  The DFA number is the index into
+                     this list.  (This name is slightly confusing.)
+                     Final states are represented by a special arc of
+                     the form (0, j) where j is its own state number.
+
+    dfas          -- a dict mapping symbol numbers to (DFA, first)
+                     pairs, where DFA is an item from the states list
+                     above, and first is a set of tokens that can
+                     begin this grammar rule (represented by a dict
+                     whose values are always 1).
+
+    labels        -- a list of (x, y) pairs where x is either a token
+                     number or a symbol number, and y is either None
+                     or a string; the strings are keywords.  The label
+                     number is the index in this list; label numbers
+                     are used to mark state transitions (arcs) in the
+                     DFAs.
+
+    start         -- the number of the grammar's start symbol.
+
+    keywords      -- a dict mapping keyword strings to arc labels.
+
+    tokens        -- a dict mapping token numbers to arc labels.
+
+    """
+
+    def __init__(self):
+        self.symbol2number = {}
+        self.number2symbol = {}
+        self.states = []
+        self.dfas = {}
+        self.labels = [(0, "EMPTY")]
+        self.keywords = {}
+        self.tokens = {}
+        self.symbol2label = {}
+        self.start = 256
+
+    def dump(self, filename):
+        """Dump the grammar tables to a pickle file."""
+        f = open(filename, "wb")
+        pickle.dump(self.__dict__, f, 2)
+        f.close()
+
+    def load(self, filename):
+        """Load the grammar tables from a pickle file."""
+        f = open(filename, "rb")
+        d = pickle.load(f)
+        f.close()
+        self.__dict__.update(d)
+
+    def report(self):
+        """Dump the grammar tables to standard output, for debugging."""
+        from pprint import pprint
+        print "s2n"
+        pprint(self.symbol2number)
+        print "n2s"
+        pprint(self.number2symbol)
+        print "states"
+        pprint(self.states)
+        print "dfas"
+        pprint(self.dfas)
+        print "labels"
+        pprint(self.labels)
+        print "start", self.start
+
+
+# Map from operator to number (since tokenize doesn't do this)
+
+opmap_raw = """
+( LPAR
+) RPAR
+[ LSQB
+] RSQB
+: COLON
+, COMMA
+; SEMI
++ PLUS
+- MINUS
+* STAR
+/ SLASH
+| VBAR
+& AMPER
+< LESS
+> GREATER
+= EQUAL
+. DOT
+% PERCENT
+` BACKQUOTE
+{ LBRACE
+} RBRACE
+@ AT
+== EQEQUAL
+!= NOTEQUAL
+<> NOTEQUAL
+<= LESSEQUAL
+>= GREATEREQUAL
+~ TILDE
+^ CIRCUMFLEX
+<< LEFTSHIFT
+>> RIGHTSHIFT
+** DOUBLESTAR
++= PLUSEQUAL
+-= MINEQUAL
+*= STAREQUAL
+/= SLASHEQUAL
+%= PERCENTEQUAL
+&= AMPEREQUAL
+|= VBAREQUAL
+^= CIRCUMFLEXEQUAL
+<<= LEFTSHIFTEQUAL
+>>= RIGHTSHIFTEQUAL
+**= DOUBLESTAREQUAL
+// DOUBLESLASH
+//= DOUBLESLASHEQUAL
+-> RARROW
+"""
+
+opmap = {}
+for line in opmap_raw.splitlines():
+    if line:
+        op, name = line.split()
+        opmap[op] = getattr(token, name)

Added: doctools/trunk/sphinx/pycode/pgen2/literals.py
==============================================================================
--- (empty file)
+++ doctools/trunk/sphinx/pycode/pgen2/literals.py	Sun Jan  4 21:38:57 2009
@@ -0,0 +1,96 @@
+# Copyright 2004-2005 Elemental Security, Inc. All Rights Reserved.
+# Licensed to PSF under a Contributor Agreement.
+
+# Extended to handle raw and unicode literals by Georg Brandl.
+
+"""Safely evaluate Python string literals without using eval()."""
+
+import re
+
+simple_escapes = {"a": "\a",
+                  "b": "\b",
+                  "f": "\f",
+                  "n": "\n",
+                  "r": "\r",
+                  "t": "\t",
+                  "v": "\v",
+                  "'": "'",
+                  '"': '"',
+                  "\\": "\\"}
+
+def convert_hex(x, n):
+    if len(x) < n+1:
+        raise ValueError("invalid hex string escape ('\\%s')" % x)
+    try:
+        return int(x[1:], 16)
+    except ValueError:
+        raise ValueError("invalid hex string escape ('\\%s')" % x)
+
+def escape(m):
+    all, tail = m.group(0, 1)
+    assert all.startswith("\\")
+    esc = simple_escapes.get(tail)
+    if esc is not None:
+        return esc
+    elif tail.startswith("x"):
+        return chr(convert_hex(tail, 2))
+    elif tail.startswith('u'):
+        return unichr(convert_hex(tail, 4))
+    elif tail.startswith('U'):
+        return unichr(convert_hex(tail, 8))
+    elif tail.startswith('N'):
+        import unicodedata
+        try:
+            return unicodedata.lookup(tail[1:-1])
+        except KeyError:
+            raise ValueError("undefined character name %r" % tail[1:-1])
+    else:
+        try:
+            return chr(int(tail, 8))
+        except ValueError:
+            raise ValueError("invalid octal string escape ('\\%s')" % tail)
+
+def escaperaw(m):
+    all, tail = m.group(0, 1)
+    if tail.startswith('u'):
+        return unichr(convert_hex(tail, 4))
+    elif tail.startswith('U'):
+        return unichr(convert_hex(tail, 8))
+    else:
+        return all
+
+escape_re = re.compile(r"\\(\'|\"|\\|[abfnrtv]|x.{0,2}|[0-7]{1,3})")
+uni_escape_re = re.compile(r"\\(\'|\"|\\|[abfnrtv]|x.{0,2}|[0-7]{1,3}|"
+                           r"u[0-9a-fA-F]{0,4}|U[0-9a-fA-F]{0,8}|N\{.+?\})")
+
+def evalString(s, encoding=None):
+    regex = escape_re
+    repl = escape
+    if encoding:
+        s = s.decode(encoding)
+    if s.startswith('u') or s.startswith('U'):
+        regex = uni_escape_re
+        s = s[1:]
+    if s.startswith('r') or s.startswith('R'):
+        repl = escaperaw
+        s = s[1:]
+    assert s.startswith("'") or s.startswith('"'), repr(s[:1])
+    q = s[0]
+    if s[:3] == q*3:
+        q = q*3
+    assert s.endswith(q), repr(s[-len(q):])
+    assert len(s) >= 2*len(q)
+    s = s[len(q):-len(q)]
+    return regex.sub(repl, s)
+
+def test():
+    for i in range(256):
+        c = chr(i)
+        s = repr(c)
+        e = evalString(s)
+        if e != c:
+            print i, c, s, e
+
+
+if __name__ == "__main__":
+    test()

Added: doctools/trunk/sphinx/pycode/pgen2/parse.c
==============================================================================
--- (empty file)
+++ doctools/trunk/sphinx/pycode/pgen2/parse.c	Sun Jan  4 21:38:57 2009
@@ -0,0 +1,3261 @@
+/* Generated by Cython 0.9.8.1 on Thu Jan  1 23:45:38 2009 */
+
+#define PY_SSIZE_T_CLEAN
+#include "Python.h"
+#include "structmember.h"
+#ifndef PY_LONG_LONG
+  #define PY_LONG_LONG LONG_LONG
+#endif
+#ifndef DL_EXPORT
+  #define DL_EXPORT(t) t
+#endif
+#if PY_VERSION_HEX < 0x02040000
+  #define METH_COEXIST 0
+#endif
+#if PY_VERSION_HEX < 0x02050000
+  typedef int Py_ssize_t;
+  #define PY_SSIZE_T_MAX INT_MAX
+  #define PY_SSIZE_T_MIN INT_MIN
+  #define PyInt_FromSsize_t(z) PyInt_FromLong(z)
+  #define PyInt_AsSsize_t(o)   PyInt_AsLong(o)
+  #define PyNumber_Index(o)    PyNumber_Int(o)
+  #define PyIndex_Check(o)     PyNumber_Check(o)
+#endif
+#if PY_VERSION_HEX < 0x02060000
+  #define Py_REFCNT(ob) (((PyObject*)(ob))->ob_refcnt)
+  #define Py_TYPE(ob)   (((PyObject*)(ob))->ob_type)
+  #define Py_SIZE(ob)   (((PyVarObject*)(ob))->ob_size)
+  #define PyVarObject_HEAD_INIT(type, size) \
+          PyObject_HEAD_INIT(type) size,
+  #define PyType_Modified(t)
+
+  typedef struct {
+       void *buf;
+       Py_ssize_t len;
+       int readonly;
+       const char *format;
+       int ndim;
+       Py_ssize_t *shape;
+       Py_ssize_t *strides;
+       Py_ssize_t *suboffsets;
+       Py_ssize_t itemsize;
+       void *internal;
+  } Py_buffer;
+
+  #define PyBUF_SIMPLE 0
+  #define PyBUF_WRITABLE 0x0001
+  #define PyBUF_LOCK 0x0002
+  #define PyBUF_FORMAT 0x0004
+  #define PyBUF_ND 0x0008
+  #define PyBUF_STRIDES (0x0010 | PyBUF_ND)
+  #define PyBUF_C_CONTIGUOUS (0x0020 | PyBUF_STRIDES)
+  #define PyBUF_F_CONTIGUOUS (0x0040 | PyBUF_STRIDES)
+  #define PyBUF_ANY_CONTIGUOUS (0x0080 | PyBUF_STRIDES)
+  #define PyBUF_INDIRECT (0x0100 | PyBUF_STRIDES)
+
+#endif
+#if PY_MAJOR_VERSION < 3
+  #define __Pyx_BUILTIN_MODULE_NAME "__builtin__"
+#else
+  #define __Pyx_BUILTIN_MODULE_NAME "builtins"
+#endif
+#if PY_MAJOR_VERSION >= 3
+  #define Py_TPFLAGS_CHECKTYPES 0
+  #define Py_TPFLAGS_HAVE_INDEX 0
+#endif
+#if PY_MAJOR_VERSION >= 3
+  #define PyBaseString_Type            PyUnicode_Type
+  #define PyString_Type                PyBytes_Type
+  #define PyInt_Type                   PyLong_Type
+  #define PyInt_Check(op)              PyLong_Check(op)
+  #define PyInt_CheckExact(op)         PyLong_CheckExact(op)
+  #define PyInt_FromString             PyLong_FromString
+  #define PyInt_FromUnicode            PyLong_FromUnicode
+  #define PyInt_FromLong               PyLong_FromLong
+  #define PyInt_FromSize_t             PyLong_FromSize_t
+  #define PyInt_FromSsize_t            PyLong_FromSsize_t
+  #define PyInt_AsLong                 PyLong_AsLong
+  #define PyInt_AS_LONG                PyLong_AS_LONG
+  #define PyInt_AsSsize_t              PyLong_AsSsize_t
+  #define PyInt_AsUnsignedLongMask     PyLong_AsUnsignedLongMask
+  #define PyInt_AsUnsignedLongLongMask PyLong_AsUnsignedLongLongMask
+  #define __Pyx_PyNumber_Divide(x,y)         PyNumber_TrueDivide(x,y)
+#else
+  #define __Pyx_PyNumber_Divide(x,y)         PyNumber_Divide(x,y)
+  #define PyBytes_Type                 PyString_Type
+#endif
+#if PY_MAJOR_VERSION >= 3
+  #define PyMethod_New(func, self, klass) PyInstanceMethod_New(func)
+#endif
+#if !defined(WIN32) && !defined(MS_WINDOWS)
+  #ifndef __stdcall
+    #define __stdcall
+  #endif
+  #ifndef __cdecl
+    #define __cdecl
+  #endif
+#else
+  #define _USE_MATH_DEFINES
+#endif
+#ifdef __cplusplus
+#define __PYX_EXTERN_C extern "C"
+#else
+#define __PYX_EXTERN_C extern
+#endif
+#include <math.h>
+#define __PYX_HAVE_API__sphinx__pycode__pgen2__parse
+
+
+#ifdef __GNUC__
+#define INLINE __inline__
+#elif _WIN32
+#define INLINE __inline
+#else
+#define INLINE 
+#endif
+
+typedef struct {PyObject **p; char *s; long n; char is_unicode; char intern; char is_identifier;} __Pyx_StringTabEntry; /*proto*/
+
+
+
+static int __pyx_skip_dispatch = 0;
+
+
+/* Type Conversion Predeclarations */
+
+#if PY_MAJOR_VERSION < 3
+#define __Pyx_PyBytes_FromString PyString_FromString
+#define __Pyx_PyBytes_AsString   PyString_AsString
+#else
+#define __Pyx_PyBytes_FromString PyBytes_FromString
+#define __Pyx_PyBytes_AsString   PyBytes_AsString
+#endif
+
+#define __Pyx_PyBool_FromLong(b) ((b) ? (Py_INCREF(Py_True), Py_True) : (Py_INCREF(Py_False), Py_False))
+static INLINE int __Pyx_PyObject_IsTrue(PyObject* x);
+static INLINE PY_LONG_LONG __pyx_PyInt_AsLongLong(PyObject* x);
+static INLINE unsigned PY_LONG_LONG __pyx_PyInt_AsUnsignedLongLong(PyObject* x);
+static INLINE Py_ssize_t __pyx_PyIndex_AsSsize_t(PyObject* b);
+
+#define __pyx_PyInt_AsLong(x) (PyInt_CheckExact(x) ? PyInt_AS_LONG(x) : PyInt_AsLong(x))
+#define __pyx_PyFloat_AsDouble(x) (PyFloat_CheckExact(x) ? PyFloat_AS_DOUBLE(x) : PyFloat_AsDouble(x))
+
+static INLINE unsigned char __pyx_PyInt_unsigned_char(PyObject* x);
+static INLINE unsigned short __pyx_PyInt_unsigned_short(PyObject* x);
+static INLINE char __pyx_PyInt_char(PyObject* x);
+static INLINE short __pyx_PyInt_short(PyObject* x);
+static INLINE int __pyx_PyInt_int(PyObject* x);
+static INLINE long __pyx_PyInt_long(PyObject* x);
+static INLINE signed char __pyx_PyInt_signed_char(PyObject* x);
+static INLINE signed short __pyx_PyInt_signed_short(PyObject* x);
+static INLINE signed int __pyx_PyInt_signed_int(PyObject* x);
+static INLINE signed long __pyx_PyInt_signed_long(PyObject* x);
+static INLINE long double __pyx_PyInt_long_double(PyObject* x);
+#ifdef __GNUC__
+/* Test for GCC > 2.95 */
+#if __GNUC__ > 2 ||               (__GNUC__ == 2 && (__GNUC_MINOR__ > 95)) 
+#define likely(x)   __builtin_expect(!!(x), 1)
+#define unlikely(x) __builtin_expect(!!(x), 0)
+#else /* __GNUC__ > 2 ... */
+#define likely(x)   (x)
+#define unlikely(x) (x)
+#endif /* __GNUC__ > 2 ... */
+#else /* __GNUC__ */
+#define likely(x)   (x)
+#define unlikely(x) (x)
+#endif /* __GNUC__ */
+    
+static PyObject *__pyx_m;
+static PyObject *__pyx_b;
+static PyObject *__pyx_empty_tuple;
+static int __pyx_lineno;
+static int __pyx_clineno = 0;
+static const char * __pyx_cfilenm= __FILE__;
+static const char *__pyx_filename;
+static const char **__pyx_f;
+
+static INLINE void __Pyx_RaiseArgtupleTooLong(Py_ssize_t num_expected, Py_ssize_t num_found); /*proto*/
+
+static PyObject *__Pyx_Import(PyObject *name, PyObject *from_list); /*proto*/
+
+static PyObject *__Pyx_GetName(PyObject *dict, PyObject *name); /*proto*/
+
+static PyObject *__Pyx_CreateClass(PyObject *bases, PyObject *dict, PyObject *name, char *modname); /*proto*/
+
+static INLINE PyObject *__Pyx_GetItemInt(PyObject *o, Py_ssize_t i, int is_unsigned) {
+    PyObject *r;
+    if (PyList_CheckExact(o) && 0 <= i && i < PyList_GET_SIZE(o)) {
+        r = PyList_GET_ITEM(o, i);
+        Py_INCREF(r);
+    }
+    else if (PyTuple_CheckExact(o) && 0 <= i && i < PyTuple_GET_SIZE(o)) {
+        r = PyTuple_GET_ITEM(o, i);
+        Py_INCREF(r);
+    }
+    else if (Py_TYPE(o)->tp_as_sequence && Py_TYPE(o)->tp_as_sequence->sq_item && (likely(i >= 0) || !is_unsigned))
+        r = PySequence_GetItem(o, i);
+    else {
+        PyObject *j = (likely(i >= 0) || !is_unsigned) ? PyInt_FromLong(i) : PyLong_FromUnsignedLongLong((sizeof(unsigned long long) > sizeof(Py_ssize_t) ? (1ULL << (sizeof(Py_ssize_t)*8)) : 0) + i);
+        if (!j)
+            return 0;
+        r = PyObject_GetItem(o, j);
+        Py_DECREF(j);
+    }
+    return r;
+}
+
+static PyObject *__Pyx_UnpackItem(PyObject *, Py_ssize_t index); /*proto*/
+static int __Pyx_EndUnpack(PyObject *); /*proto*/
+
+static void __Pyx_Raise(PyObject *type, PyObject *value, PyObject *tb); /*proto*/
+
+static INLINE PyObject* __Pyx_PyObject_Append(PyObject* L, PyObject* x) {
+    if (likely(PyList_CheckExact(L))) {
+        if (PyList_Append(L, x) < 0) return NULL;
+        Py_INCREF(Py_None);
+        return Py_None; // this is just to have an accurate signature
+    }
+    else {
+        return PyObject_CallMethod(L, "append", "(O)", x);
+    }
+}
+
+static INLINE int __Pyx_SetItemInt(PyObject *o, Py_ssize_t i, PyObject *v, int is_unsigned) {
+    int r;
+    if (PyList_CheckExact(o) && 0 <= i && i < PyList_GET_SIZE(o)) {
+        Py_DECREF(PyList_GET_ITEM(o, i));
+        Py_INCREF(v);
+        PyList_SET_ITEM(o, i, v);
+        return 1;
+    }
+    else if (Py_TYPE(o)->tp_as_sequence && Py_TYPE(o)->tp_as_sequence->sq_ass_item && (likely(i >= 0) || !is_unsigned))
+        r = PySequence_SetItem(o, i, v);
+    else {
+        PyObject *j = (likely(i >= 0) || !is_unsigned) ? PyInt_FromLong(i) : PyLong_FromUnsignedLongLong((sizeof(unsigned long long) > sizeof(Py_ssize_t) ? (1ULL << (sizeof(Py_ssize_t)*8)) : 0) + i);
+        if (!j)
+            return -1;
+        r = PyObject_SetItem(o, j, v);
+        Py_DECREF(j);
+    }
+    return r;
+}
+
+static void __Pyx_WriteUnraisable(const char *name); /*proto*/
+
+static int __Pyx_SetVtable(PyObject *dict, void *vtable); /*proto*/
+
+static void __Pyx_AddTraceback(const char *funcname); /*proto*/
+
+static int __Pyx_InitStrings(__Pyx_StringTabEntry *t); /*proto*/
+
+/* Type declarations */
+
+/* "/home/gbr/devel/sphinx/sphinx/pycode/pgen2/parse.pyx":31
+ * 
+ * 
+ * cdef class Parser:             # <<<<<<<<<<<<<<
+ *     cdef public grammar, stack, rootnode, used_names
+ *     cdef _grammar_dfas, _grammar_labels, _grammar_keywords, _grammar_tokens
+ */
+
+struct __pyx_obj_6sphinx_6pycode_5pgen2_5parse_Parser {
+  PyObject_HEAD
+  struct __pyx_vtabstruct_6sphinx_6pycode_5pgen2_5parse_Parser *__pyx_vtab;
+  PyObject *grammar;
+  PyObject *stack;
+  PyObject *rootnode;
+  PyObject *used_names;
+  PyObject *_grammar_dfas;
+  PyObject *_grammar_labels;
+  PyObject *_grammar_keywords;
+  PyObject *_grammar_tokens;
+  PyObject *_grammar_number2symbol;
+};
+
+
+struct __pyx_vtabstruct_6sphinx_6pycode_5pgen2_5parse_Parser {
+  int (*classify)(struct __pyx_obj_6sphinx_6pycode_5pgen2_5parse_Parser *, PyObject *, PyObject *, PyObject *);
+  void (*shift)(struct __pyx_obj_6sphinx_6pycode_5pgen2_5parse_Parser *, PyObject *, PyObject *, PyObject *, PyObject *);
+  void (*push)(struct __pyx_obj_6sphinx_6pycode_5pgen2_5parse_Parser *, PyObject *, PyObject *, PyObject *, PyObject *);
+  void (*pop)(struct __pyx_obj_6sphinx_6pycode_5pgen2_5parse_Parser *);
+  PyObject *(*convert)(struct __pyx_obj_6sphinx_6pycode_5pgen2_5parse_Parser *, PyObject *);
+};
+static struct __pyx_vtabstruct_6sphinx_6pycode_5pgen2_5parse_Parser *__pyx_vtabptr_6sphinx_6pycode_5pgen2_5parse_Parser;
+/* Module declarations from sphinx.pycode.pgen2.parse */
+
+static PyTypeObject *__pyx_ptype_6sphinx_6pycode_5pgen2_5parse_Parser = 0;
+
+
+/* Implementation of sphinx.pycode.pgen2.parse */
+static char __pyx_k_2[] = "Exception to signal the parser is stuck.";
+static PyObject *__pyx_int_0;
+static PyObject *__pyx_int_1;
+static char __pyx_k___init__[] = "__init__";
+static PyObject *__pyx_kp___init__;
+static char __pyx_k_setup[] = "setup";
+static PyObject *__pyx_kp_setup;
+static char __pyx_k_addtoken[] = "addtoken";
+static PyObject *__pyx_kp_addtoken;
+static char __pyx_k_1[] = "sphinx.pycode.nodes";
+static PyObject *__pyx_kp_1;
+static char __pyx_k_Node[] = "Node";
+static PyObject *__pyx_kp_Node;
+static char __pyx_k_Leaf[] = "Leaf";
+static PyObject *__pyx_kp_Leaf;
+static char __pyx_k_ParseError[] = "ParseError";
+static PyObject *__pyx_kp_ParseError;
+static char __pyx_k_Exception[] = "Exception";
+static PyObject *__pyx_kp_Exception;
+static char __pyx_k_msg[] = "msg";
+static PyObject *__pyx_kp_msg;
+static char __pyx_k_type[] = "type";
+static PyObject *__pyx_kp_type;
+static char __pyx_k_value[] = "value";
+static PyObject *__pyx_kp_value;
+static char __pyx_k_context[] = "context";
+static PyObject *__pyx_kp_context;
+static char __pyx_k_dfas[] = "dfas";
+static PyObject *__pyx_kp_dfas;
+static char __pyx_k_labels[] = "labels";
+static PyObject *__pyx_kp_labels;
+static char __pyx_k_keywords[] = "keywords";
+static PyObject *__pyx_kp_keywords;
+static char __pyx_k_tokens[] = "tokens";
+static PyObject *__pyx_kp_tokens;
+static char __pyx_k_4[] = "number2symbol";
+static PyObject *__pyx_kp_4;
+static char __pyx_k_start[] = "start";
+static PyObject *__pyx_kp_start;
+static char __pyx_k_add[] = "add";
+static PyObject *__pyx_kp_add;
+static char __pyx_k_get[] = "get";
+static PyObject *__pyx_kp_get;
+static char __pyx_k_append[] = "append";
+static PyObject *__pyx_kp_append;
+static char __pyx_k_pop[] = "pop";
+static PyObject *__pyx_kp_pop;
+static char __pyx_k_used_names[] = "used_names";
+static PyObject *__pyx_kp_used_names;
+static PyObject *__pyx_kp_2;
+static PyObject *__pyx_builtin_Exception;
+static PyObject *__pyx_kp_3;
+static char __pyx_k_3[] = "%s: type=%r, value=%r, context=%r";
+static PyObject *__pyx_kp_5;
+static PyObject *__pyx_kp_6;
+static char __pyx_k_5[] = "too much input";
+static char __pyx_k_6[] = "bad input";
+static PyObject *__pyx_kp_7;
+static char __pyx_k_7[] = "bad token";
+
+/* "/home/gbr/devel/sphinx/sphinx/pycode/pgen2/parse.pyx":22
+ *     """Exception to signal the parser is stuck."""
+ * 
+ *     def __init__(self, msg, type, value, context):             # <<<<<<<<<<<<<<
+ *         Exception.__init__(self, "%s: type=%r, value=%r, context=%r" %
+ *                            (msg, type, value, context))
+ */
+
+static PyObject *__pyx_pf_6sphinx_6pycode_5pgen2_5parse_10ParseError___init__(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/
+static PyMethodDef __pyx_mdef_6sphinx_6pycode_5pgen2_5parse_10ParseError___init__ = {"__init__", (PyCFunction)__pyx_pf_6sphinx_6pycode_5pgen2_5parse_10ParseError___init__, METH_VARARGS|METH_KEYWORDS, 0};
+static PyObject *__pyx_pf_6sphinx_6pycode_5pgen2_5parse_10ParseError___init__(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds) {
+  PyObject *__pyx_v_self = 0;
+  PyObject *__pyx_v_msg = 0;
+  PyObject *__pyx_v_type = 0;
+  PyObject *__pyx_v_value = 0;
+  PyObject *__pyx_v_context = 0;
+  PyObject *__pyx_r;
+  PyObject *__pyx_1 = 0;
+  PyObject *__pyx_2 = 0;
+  PyObject *__pyx_3 = 0;
+  static char *__pyx_argnames[] = {"self","msg","type","value","context",0};
+  __pyx_self = __pyx_self;
+  if (likely(!__pyx_kwds) && likely(PyTuple_GET_SIZE(__pyx_args) == 5)) {
+    __pyx_v_self = PyTuple_GET_ITEM(__pyx_args, 0);
+    __pyx_v_msg = PyTuple_GET_ITEM(__pyx_args, 1);
+    __pyx_v_type = PyTuple_GET_ITEM(__pyx_args, 2);
+    __pyx_v_value = PyTuple_GET_ITEM(__pyx_args, 3);
+    __pyx_v_context = PyTuple_GET_ITEM(__pyx_args, 4);
+  }
+  else {
+    if (unlikely(!PyArg_ParseTupleAndKeywords(__pyx_args, __pyx_kwds, "OOOOO", __pyx_argnames, &__pyx_v_self, &__pyx_v_msg, &__pyx_v_type, &__pyx_v_value, &__pyx_v_context))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 22; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+  }
+  goto __pyx_L4;
+  __pyx_L3_error:;
+  __Pyx_AddTraceback("sphinx.pycode.pgen2.parse.ParseError.__init__");
+  return NULL;
+  __pyx_L4:;
+
+  /* "/home/gbr/devel/sphinx/sphinx/pycode/pgen2/parse.pyx":23
+ * 
+ *     def __init__(self, msg, type, value, context):
+ *         Exception.__init__(self, "%s: type=%r, value=%r, context=%r" %             # <<<<<<<<<<<<<<
+ *                            (msg, type, value, context))
+ *         self.msg = msg
+ */
+  __pyx_1 = PyObject_GetAttr(__pyx_builtin_Exception, __pyx_kp___init__); if (unlikely(!__pyx_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 23; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+
+  /* "/home/gbr/devel/sphinx/sphinx/pycode/pgen2/parse.pyx":24
+ *     def __init__(self, msg, type, value, context):
+ *         Exception.__init__(self, "%s: type=%r, value=%r, context=%r" %
+ *                            (msg, type, value, context))             # <<<<<<<<<<<<<<
+ *         self.msg = msg
+ *         self.type = type
+ */
+  __pyx_2 = PyTuple_New(4); if (unlikely(!__pyx_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 24; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  Py_INCREF(__pyx_v_msg);
+  PyTuple_SET_ITEM(__pyx_2, 0, __pyx_v_msg);
+  Py_INCREF(__pyx_v_type);
+  PyTuple_SET_ITEM(__pyx_2, 1, __pyx_v_type);
+  Py_INCREF(__pyx_v_value);
+  PyTuple_SET_ITEM(__pyx_2, 2, __pyx_v_value);
+  Py_INCREF(__pyx_v_context);
+  PyTuple_SET_ITEM(__pyx_2, 3, __pyx_v_context);
+  __pyx_3 = PyNumber_Remainder(__pyx_kp_3, ((PyObject *)__pyx_2)); if (unlikely(!__pyx_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 23; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  Py_DECREF(((PyObject *)__pyx_2)); __pyx_2 = 0;
+  __pyx_2 = PyTuple_New(2); if (unlikely(!__pyx_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 23; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  Py_INCREF(__pyx_v_self);
+  PyTuple_SET_ITEM(__pyx_2, 0, __pyx_v_self);
+  PyTuple_SET_ITEM(__pyx_2, 1, __pyx_3);
+  __pyx_3 = 0;
+  __pyx_3 = PyObject_Call(__pyx_1, ((PyObject *)__pyx_2), NULL); if (unlikely(!__pyx_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 23; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  Py_DECREF(__pyx_1); __pyx_1 = 0;
+  Py_DECREF(((PyObject *)__pyx_2)); __pyx_2 = 0;
+  Py_DECREF(__pyx_3); __pyx_3 = 0;
+
+  /* "/home/gbr/devel/sphinx/sphinx/pycode/pgen2/parse.pyx":25
+ *         Exception.__init__(self, "%s: type=%r, value=%r, context=%r" %
+ *                            (msg, type, value, context))
+ *         self.msg = msg             # <<<<<<<<<<<<<<
+ *         self.type = type
+ *         self.value = value
+ */
+  if (PyObject_SetAttr(__pyx_v_self, __pyx_kp_msg, __pyx_v_msg) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 25; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+
+  /* "/home/gbr/devel/sphinx/sphinx/pycode/pgen2/parse.pyx":26
+ *                            (msg, type, value, context))
+ *         self.msg = msg
+ *         self.type = type             # <<<<<<<<<<<<<<
+ *         self.value = value
+ *         self.context = context
+ */
+  if (PyObject_SetAttr(__pyx_v_self, __pyx_kp_type, __pyx_v_type) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 26; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+
+  /* "/home/gbr/devel/sphinx/sphinx/pycode/pgen2/parse.pyx":27
+ *         self.msg = msg
+ *         self.type = type
+ *         self.value = value             # <<<<<<<<<<<<<<
+ *         self.context = context
+ * 
+ */
+  if (PyObject_SetAttr(__pyx_v_self, __pyx_kp_value, __pyx_v_value) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 27; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+
+  /* "/home/gbr/devel/sphinx/sphinx/pycode/pgen2/parse.pyx":28
+ *         self.type = type
+ *         self.value = value
+ *         self.context = context             # <<<<<<<<<<<<<<
+ * 
+ * 
+ */
+  if (PyObject_SetAttr(__pyx_v_self, __pyx_kp_context, __pyx_v_context) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 28; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+
+  __pyx_r = Py_None; Py_INCREF(Py_None);
+  goto __pyx_L0;
+  __pyx_L1_error:;
+  Py_XDECREF(__pyx_1);
+  Py_XDECREF(__pyx_2);
+  Py_XDECREF(__pyx_3);
+  __Pyx_AddTraceback("sphinx.pycode.pgen2.parse.ParseError.__init__");
+  __pyx_r = NULL;
+  __pyx_L0:;
+  return __pyx_r;
+}
+
+/* "/home/gbr/devel/sphinx/sphinx/pycode/pgen2/parse.pyx":36
+ *     cdef _grammar_number2symbol
+ * 
+ *     def __init__(self, grammar, convert=None):             # <<<<<<<<<<<<<<
+ *         self.grammar = grammar
+ *         #self.convert = convert or noconvert
+ */
+
+static int __pyx_pf_6sphinx_6pycode_5pgen2_5parse_6Parser___init__(PyObject *__pyx_v_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/
+static int __pyx_pf_6sphinx_6pycode_5pgen2_5parse_6Parser___init__(PyObject *__pyx_v_self, PyObject *__pyx_args, PyObject *__pyx_kwds) {
+  PyObject *__pyx_v_grammar = 0;
+  PyObject *__pyx_v_convert = 0;
+  int __pyx_r;
+  PyObject *__pyx_1 = 0;
+  static char *__pyx_argnames[] = {"grammar","convert",0};
+  __pyx_v_convert = Py_None;
+  if (likely(!__pyx_kwds) && likely(1 <= PyTuple_GET_SIZE(__pyx_args)) && likely(PyTuple_GET_SIZE(__pyx_args) <= 2)) {
+    __pyx_v_grammar = PyTuple_GET_ITEM(__pyx_args, 0);
+    if (PyTuple_GET_SIZE(__pyx_args) > 1) {
+      __pyx_v_convert = PyTuple_GET_ITEM(__pyx_args, 1);
+    }
+  }
+  else {
+    if (unlikely(!PyArg_ParseTupleAndKeywords(__pyx_args, __pyx_kwds, "O|O", __pyx_argnames, &__pyx_v_grammar, &__pyx_v_convert))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 36; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+  }
+  goto __pyx_L4;
+  __pyx_L3_error:;
+  __Pyx_AddTraceback("sphinx.pycode.pgen2.parse.Parser.__init__");
+  return -1;
+  __pyx_L4:;
+
+  /* "/home/gbr/devel/sphinx/sphinx/pycode/pgen2/parse.pyx":37
+ * 
+ *     def __init__(self, grammar, convert=None):
+ *         self.grammar = grammar             # <<<<<<<<<<<<<<
+ *         #self.convert = convert or noconvert
+ * 
+ */
+  Py_INCREF(__pyx_v_grammar);
+  Py_DECREF(((struct __pyx_obj_6sphinx_6pycode_5pgen2_5parse_Parser *)__pyx_v_self)->grammar);
+  ((struct __pyx_obj_6sphinx_6pycode_5pgen2_5parse_Parser *)__pyx_v_self)->grammar = __pyx_v_grammar;
+
+  /* "/home/gbr/devel/sphinx/sphinx/pycode/pgen2/parse.pyx":40
+ *         #self.convert = convert or noconvert
+ * 
+ *         self._grammar_dfas = grammar.dfas             # <<<<<<<<<<<<<<
+ *         self._grammar_labels = grammar.labels
+ *         self._grammar_keywords = grammar.keywords
+ */
+  __pyx_1 = PyObject_GetAttr(__pyx_v_grammar, __pyx_kp_dfas); if (unlikely(!__pyx_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 40; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  Py_DECREF(((struct __pyx_obj_6sphinx_6pycode_5pgen2_5parse_Parser *)__pyx_v_self)->_grammar_dfas);
+  ((struct __pyx_obj_6sphinx_6pycode_5pgen2_5parse_Parser *)__pyx_v_self)->_grammar_dfas = __pyx_1;
+  __pyx_1 = 0;
+
+  /* "/home/gbr/devel/sphinx/sphinx/pycode/pgen2/parse.pyx":41
+ * 
+ *         self._grammar_dfas = grammar.dfas
+ *         self._grammar_labels = grammar.labels             # <<<<<<<<<<<<<<
+ *         self._grammar_keywords = grammar.keywords
+ *         self._grammar_tokens = grammar.tokens
+ */
+  __pyx_1 = PyObject_GetAttr(__pyx_v_grammar, __pyx_kp_labels); if (unlikely(!__pyx_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 41; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  Py_DECREF(((struct __pyx_obj_6sphinx_6pycode_5pgen2_5parse_Parser *)__pyx_v_self)->_grammar_labels);
+  ((struct __pyx_obj_6sphinx_6pycode_5pgen2_5parse_Parser *)__pyx_v_self)->_grammar_labels = __pyx_1;
+  __pyx_1 = 0;
+
+  /* "/home/gbr/devel/sphinx/sphinx/pycode/pgen2/parse.pyx":42
+ *         self._grammar_dfas = grammar.dfas
+ *         self._grammar_labels = grammar.labels
+ *         self._grammar_keywords = grammar.keywords             # <<<<<<<<<<<<<<
+ *         self._grammar_tokens = grammar.tokens
+ *         self._grammar_number2symbol = grammar.number2symbol
+ */
+  __pyx_1 = PyObject_GetAttr(__pyx_v_grammar, __pyx_kp_keywords); if (unlikely(!__pyx_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 42; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  Py_DECREF(((struct __pyx_obj_6sphinx_6pycode_5pgen2_5parse_Parser *)__pyx_v_self)->_grammar_keywords);
+  ((struct __pyx_obj_6sphinx_6pycode_5pgen2_5parse_Parser *)__pyx_v_self)->_grammar_keywords = __pyx_1;
+  __pyx_1 = 0;
+
+  /* "/home/gbr/devel/sphinx/sphinx/pycode/pgen2/parse.pyx":43
+ *         self._grammar_labels = grammar.labels
+ *         self._grammar_keywords = grammar.keywords
+ *         self._grammar_tokens = grammar.tokens             # <<<<<<<<<<<<<<
+ *         self._grammar_number2symbol = grammar.number2symbol
+ * 
+ */
+  __pyx_1 = PyObject_GetAttr(__pyx_v_grammar, __pyx_kp_tokens); if (unlikely(!__pyx_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 43; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  Py_DECREF(((struct __pyx_obj_6sphinx_6pycode_5pgen2_5parse_Parser *)__pyx_v_self)->_grammar_tokens);
+  ((struct __pyx_obj_6sphinx_6pycode_5pgen2_5parse_Parser *)__pyx_v_self)->_grammar_tokens = __pyx_1;
+  __pyx_1 = 0;
+
+  /* "/home/gbr/devel/sphinx/sphinx/pycode/pgen2/parse.pyx":44
+ *         self._grammar_keywords = grammar.keywords
+ *         self._grammar_tokens = grammar.tokens
+ *         self._grammar_number2symbol = grammar.number2symbol             # <<<<<<<<<<<<<<
+ * 
+ *     def setup(self, start=None):
+ */
+  __pyx_1 = PyObject_GetAttr(__pyx_v_grammar, __pyx_kp_4); if (unlikely(!__pyx_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 44; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  Py_DECREF(((struct __pyx_obj_6sphinx_6pycode_5pgen2_5parse_Parser *)__pyx_v_self)->_grammar_number2symbol);
+  ((struct __pyx_obj_6sphinx_6pycode_5pgen2_5parse_Parser *)__pyx_v_self)->_grammar_number2symbol = __pyx_1;
+  __pyx_1 = 0;
+
+  __pyx_r = 0;
+  goto __pyx_L0;
+  __pyx_L1_error:;
+  Py_XDECREF(__pyx_1);
+  __Pyx_AddTraceback("sphinx.pycode.pgen2.parse.Parser.__init__");
+  __pyx_r = -1;
+  __pyx_L0:;
+  return __pyx_r;
+}
+
+/* "/home/gbr/devel/sphinx/sphinx/pycode/pgen2/parse.pyx":46
+ *         self._grammar_number2symbol = grammar.number2symbol
+ * 
+ *     def setup(self, start=None):             # <<<<<<<<<<<<<<
+ *         if start is None:
+ *             start = self.grammar.start
+ */
+
+static PyObject *__pyx_pf_6sphinx_6pycode_5pgen2_5parse_6Parser_setup(PyObject *__pyx_v_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/
+static PyObject *__pyx_pf_6sphinx_6pycode_5pgen2_5parse_6Parser_setup(PyObject *__pyx_v_self, PyObject *__pyx_args, PyObject *__pyx_kwds) {
+  PyObject *__pyx_v_start = 0;
+  PyObject *__pyx_v_newnode;
+  PyObject *__pyx_v_stackentry;
+  PyObject *__pyx_r;
+  int __pyx_1;
+  PyObject *__pyx_2 = 0;
+  PyObject *__pyx_3 = 0;
+  static char *__pyx_argnames[] = {"start",0};
+  __pyx_v_start = Py_None;
+  if (likely(!__pyx_kwds) && likely(0 <= PyTuple_GET_SIZE(__pyx_args)) && likely(PyTuple_GET_SIZE(__pyx_args) <= 1)) {
+    if (PyTuple_GET_SIZE(__pyx_args) > 0) {
+      __pyx_v_start = PyTuple_GET_ITEM(__pyx_args, 0);
+    }
+  }
+  else {
+    if (unlikely(!PyArg_ParseTupleAndKeywords(__pyx_args, __pyx_kwds, "|O", __pyx_argnames, &__pyx_v_start))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 46; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+  }
+  goto __pyx_L4;
+  __pyx_L3_error:;
+  __Pyx_AddTraceback("sphinx.pycode.pgen2.parse.Parser.setup");
+  return NULL;
+  __pyx_L4:;
+  Py_INCREF(__pyx_v_start);
+  __pyx_v_newnode = Py_None; Py_INCREF(Py_None);
+  __pyx_v_stackentry = Py_None; Py_INCREF(Py_None);
+
+  /* "/home/gbr/devel/sphinx/sphinx/pycode/pgen2/parse.pyx":47
+ * 
+ *     def setup(self, start=None):
+ *         if start is None:             # <<<<<<<<<<<<<<
+ *             start = self.grammar.start
+ *         # Each stack entry is a tuple: (dfa, state, node).
+ */
+  __pyx_1 = (__pyx_v_start == Py_None);
+  if (__pyx_1) {
+
+    /* "/home/gbr/devel/sphinx/sphinx/pycode/pgen2/parse.pyx":48
+ *     def setup(self, start=None):
+ *         if start is None:
+ *             start = self.grammar.start             # <<<<<<<<<<<<<<
+ *         # Each stack entry is a tuple: (dfa, state, node).
+ *         # A node is a tuple: (type, value, context, children),
+ */
+    __pyx_2 = PyObject_GetAttr(((struct __pyx_obj_6sphinx_6pycode_5pgen2_5parse_Parser *)__pyx_v_self)->grammar, __pyx_kp_start); if (unlikely(!__pyx_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 48; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    Py_DECREF(__pyx_v_start);
+    __pyx_v_start = __pyx_2;
+    __pyx_2 = 0;
+    goto __pyx_L5;
+  }
+  __pyx_L5:;
+
+  /* "/home/gbr/devel/sphinx/sphinx/pycode/pgen2/parse.pyx":52
+ *         # A node is a tuple: (type, value, context, children),
+ *         # where children is a list of nodes or None, and context may be None.
+ *         newnode = (start, None, None, [])             # <<<<<<<<<<<<<<
+ *         stackentry = (self._grammar_dfas[start], 0, newnode)
+ *         self.stack = [stackentry]
+ */
+  __pyx_2 = PyList_New(0); if (unlikely(!__pyx_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 52; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_3 = PyTuple_New(4); if (unlikely(!__pyx_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 52; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  Py_INCREF(__pyx_v_start);
+  PyTuple_SET_ITEM(__pyx_3, 0, __pyx_v_start);
+  Py_INCREF(Py_None);
+  PyTuple_SET_ITEM(__pyx_3, 1, Py_None);
+  Py_INCREF(Py_None);
+  PyTuple_SET_ITEM(__pyx_3, 2, Py_None);
+  PyTuple_SET_ITEM(__pyx_3, 3, ((PyObject *)__pyx_2));
+  __pyx_2 = 0;
+  Py_DECREF(__pyx_v_newnode);
+  __pyx_v_newnode = ((PyObject *)__pyx_3);
+  __pyx_3 = 0;
+
+  /* "/home/gbr/devel/sphinx/sphinx/pycode/pgen2/parse.pyx":53
+ *         # where children is a list of nodes or None, and context may be None.
+ *         newnode = (start, None, None, [])
+ *         stackentry = (self._grammar_dfas[start], 0, newnode)             # <<<<<<<<<<<<<<
+ *         self.stack = [stackentry]
+ *         self.rootnode = None
+ */
+  __pyx_2 = PyObject_GetItem(((struct __pyx_obj_6sphinx_6pycode_5pgen2_5parse_Parser *)__pyx_v_self)->_grammar_dfas, __pyx_v_start); if (!__pyx_2) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 53; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_3 = PyTuple_New(3); if (unlikely(!__pyx_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 53; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  PyTuple_SET_ITEM(__pyx_3, 0, __pyx_2);
+  Py_INCREF(__pyx_int_0);
+  PyTuple_SET_ITEM(__pyx_3, 1, __pyx_int_0);
+  Py_INCREF(__pyx_v_newnode);
+  PyTuple_SET_ITEM(__pyx_3, 2, __pyx_v_newnode);
+  __pyx_2 = 0;
+  Py_DECREF(__pyx_v_stackentry);
+  __pyx_v_stackentry = ((PyObject *)__pyx_3);
+  __pyx_3 = 0;
+
+  /* "/home/gbr/devel/sphinx/sphinx/pycode/pgen2/parse.pyx":54
+ *         newnode = (start, None, None, [])
+ *         stackentry = (self._grammar_dfas[start], 0, newnode)
+ *         self.stack = [stackentry]             # <<<<<<<<<<<<<<
+ *         self.rootnode = None
+ *         self.used_names = set() # Aliased to self.rootnode.used_names in pop()
+ */
+  __pyx_2 = PyList_New(1); if (unlikely(!__pyx_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 54; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  Py_INCREF(__pyx_v_stackentry);
+  PyList_SET_ITEM(__pyx_2, 0, __pyx_v_stackentry);
+  Py_DECREF(((struct __pyx_obj_6sphinx_6pycode_5pgen2_5parse_Parser *)__pyx_v_self)->stack);
+  ((struct __pyx_obj_6sphinx_6pycode_5pgen2_5parse_Parser *)__pyx_v_self)->stack = ((PyObject *)__pyx_2);
+  __pyx_2 = 0;
+
+  /* "/home/gbr/devel/sphinx/sphinx/pycode/pgen2/parse.pyx":55
+ *         stackentry = (self._grammar_dfas[start], 0, newnode)
+ *         self.stack = [stackentry]
+ *         self.rootnode = None             # <<<<<<<<<<<<<<
+ *         self.used_names = set() # Aliased to self.rootnode.used_names in pop()
+ * 
+ */
+  Py_INCREF(Py_None);
+  Py_DECREF(((struct __pyx_obj_6sphinx_6pycode_5pgen2_5parse_Parser *)__pyx_v_self)->rootnode);
+  ((struct __pyx_obj_6sphinx_6pycode_5pgen2_5parse_Parser *)__pyx_v_self)->rootnode = Py_None;
+
+  /* "/home/gbr/devel/sphinx/sphinx/pycode/pgen2/parse.pyx":56
+ *         self.stack = [stackentry]
+ *         self.rootnode = None
+ *         self.used_names = set() # Aliased to self.rootnode.used_names in pop()             # <<<<<<<<<<<<<<
+ * 
+ *     def addtoken(self, type, value, context):
+ */
+  __pyx_3 = PyObject_Call(((PyObject*)&PySet_Type), ((PyObject *)__pyx_empty_tuple), NULL); if (unlikely(!__pyx_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 56; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  Py_DECREF(((struct __pyx_obj_6sphinx_6pycode_5pgen2_5parse_Parser *)__pyx_v_self)->used_names);
+  ((struct __pyx_obj_6sphinx_6pycode_5pgen2_5parse_Parser *)__pyx_v_self)->used_names = __pyx_3;
+  __pyx_3 = 0;
+
+  __pyx_r = Py_None; Py_INCREF(Py_None);
+  goto __pyx_L0;
+  __pyx_L1_error:;
+  Py_XDECREF(__pyx_2);
+  Py_XDECREF(__pyx_3);
+  __Pyx_AddTraceback("sphinx.pycode.pgen2.parse.Parser.setup");
+  __pyx_r = NULL;
+  __pyx_L0:;
+  Py_DECREF(__pyx_v_newnode);
+  Py_DECREF(__pyx_v_stackentry);
+  Py_DECREF(__pyx_v_start);
+  return __pyx_r;
+}
+
+/* "/home/gbr/devel/sphinx/sphinx/pycode/pgen2/parse.pyx":58
+ *         self.used_names = set() # Aliased to self.rootnode.used_names in pop()
+ * 
+ *     def addtoken(self, type, value, context):             # <<<<<<<<<<<<<<
+ *         """Add a token; return True iff this is the end of the program."""
+ *         cdef int ilabel, i, t, state, newstate
+ */
+
+static PyObject *__pyx_pf_6sphinx_6pycode_5pgen2_5parse_6Parser_addtoken(PyObject *__pyx_v_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/
+static char __pyx_doc_6sphinx_6pycode_5pgen2_5parse_6Parser_addtoken[] = "Add a token; return True iff this is the end of the program.";
+static PyObject *__pyx_pf_6sphinx_6pycode_5pgen2_5parse_6Parser_addtoken(PyObject *__pyx_v_self, PyObject *__pyx_args, PyObject *__pyx_kwds) {
+  PyObject *__pyx_v_type = 0;
+  PyObject *__pyx_v_value = 0;
+  PyObject *__pyx_v_context = 0;
+  int __pyx_v_ilabel;
+  int __pyx_v_i;
+  int __pyx_v_t;
+  int __pyx_v_state;
+  int __pyx_v_newstate;
+  PyObject *__pyx_v_dfa;
+  PyObject *__pyx_v_node;
+  PyObject *__pyx_v_states;
+  PyObject *__pyx_v_first;
+  PyObject *__pyx_v_arcs;
+  PyObject *__pyx_v_v;
+  PyObject *__pyx_v_itsdfa;
+  PyObject *__pyx_v_itsstates;
+  PyObject *__pyx_v_itsfirst;
+  PyObject *__pyx_r;
+  int __pyx_1;
+  PyObject *__pyx_2 = 0;
+  PyObject *__pyx_3 = 0;
+  PyObject *__pyx_4 = 0;
+  int __pyx_5;
+  Py_ssize_t __pyx_6 = 0;
+  PyObject *__pyx_7 = 0;
+  int __pyx_8;
+  static char *__pyx_argnames[] = {"type","value","context",0};
+  if (likely(!__pyx_kwds) && likely(PyTuple_GET_SIZE(__pyx_args) == 3)) {
+    __pyx_v_type = PyTuple_GET_ITEM(__pyx_args, 0);
+    __pyx_v_value = PyTuple_GET_ITEM(__pyx_args, 1);
+    __pyx_v_context = PyTuple_GET_ITEM(__pyx_args, 2);
+  }
+  else {
+    if (unlikely(!PyArg_ParseTupleAndKeywords(__pyx_args, __pyx_kwds, "OOO", __pyx_argnames, &__pyx_v_type, &__pyx_v_value, &__pyx_v_context))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 58; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+  }
+  goto __pyx_L4;
+  __pyx_L3_error:;
+  __Pyx_AddTraceback("sphinx.pycode.pgen2.parse.Parser.addtoken");
+  return NULL;
+  __pyx_L4:;
+  __pyx_v_dfa = Py_None; Py_INCREF(Py_None);
+  __pyx_v_node = Py_None; Py_INCREF(Py_None);
+  __pyx_v_states = Py_None; Py_INCREF(Py_None);
+  __pyx_v_first = Py_None; Py_INCREF(Py_None);
+  __pyx_v_arcs = Py_None; Py_INCREF(Py_None);
+  __pyx_v_v = Py_None; Py_INCREF(Py_None);
+  __pyx_v_itsdfa = Py_None; Py_INCREF(Py_None);
+  __pyx_v_itsstates = Py_None; Py_INCREF(Py_None);
+  __pyx_v_itsfirst = Py_None; Py_INCREF(Py_None);
+
+  /* "/home/gbr/devel/sphinx/sphinx/pycode/pgen2/parse.pyx":62
+ *         cdef int ilabel, i, t, state, newstate
+ *         # Map from token to label
+ *         ilabel = self.classify(type, value, context)             # <<<<<<<<<<<<<<
+ *         # Loop until the token is shifted; may raise exceptions
+ *         while True:
+ */
+  __pyx_v_ilabel = ((struct __pyx_vtabstruct_6sphinx_6pycode_5pgen2_5parse_Parser *)((struct __pyx_obj_6sphinx_6pycode_5pgen2_5parse_Parser *)__pyx_v_self)->__pyx_vtab)->classify(((struct __pyx_obj_6sphinx_6pycode_5pgen2_5parse_Parser *)__pyx_v_self), __pyx_v_type, __pyx_v_value, __pyx_v_context);
+
+  /* "/home/gbr/devel/sphinx/sphinx/pycode/pgen2/parse.pyx":64
+ *         ilabel = self.classify(type, value, context)
+ *         # Loop until the token is shifted; may raise exceptions
+ *         while True:             # <<<<<<<<<<<<<<
+ *             dfa, state, node = self.stack[-1]
+ *             states, first = dfa
+ */
+  while (1) {
+    __pyx_1 = 1;
+    if (!__pyx_1) break;
+
+    /* "/home/gbr/devel/sphinx/sphinx/pycode/pgen2/parse.pyx":65
+ *         # Loop until the token is shifted; may raise exceptions
+ *         while True:
+ *             dfa, state, node = self.stack[-1]             # <<<<<<<<<<<<<<
+ *             states, first = dfa
+ *             arcs = states[state]
+ */
+    __pyx_2 = __Pyx_GetItemInt(((struct __pyx_obj_6sphinx_6pycode_5pgen2_5parse_Parser *)__pyx_v_self)->stack, -1, 0); if (!__pyx_2) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 65; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    if (PyTuple_CheckExact(__pyx_2) && PyTuple_GET_SIZE(__pyx_2) == 3) {
+      PyObject* tuple = __pyx_2;
+      __pyx_4 = PyTuple_GET_ITEM(tuple, 0);
+      Py_INCREF(__pyx_4);
+      Py_DECREF(__pyx_v_dfa);
+      __pyx_v_dfa = __pyx_4;
+      __pyx_4 = 0;
+      __pyx_4 = PyTuple_GET_ITEM(tuple, 1);
+      Py_INCREF(__pyx_4);
+      __pyx_5 = __pyx_PyInt_int(__pyx_4); if (unlikely((__pyx_5 == (int)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 65; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      Py_DECREF(__pyx_4); __pyx_4 = 0;
+      __pyx_v_state = __pyx_5;
+      __pyx_4 = PyTuple_GET_ITEM(tuple, 2);
+      Py_INCREF(__pyx_4);
+      Py_DECREF(__pyx_v_node);
+      __pyx_v_node = __pyx_4;
+      __pyx_4 = 0;
+      Py_DECREF(__pyx_2); __pyx_2 = 0;
+    }
+    else {
+      __pyx_3 = PyObject_GetIter(__pyx_2); if (unlikely(!__pyx_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 65; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      Py_DECREF(__pyx_2); __pyx_2 = 0;
+      __pyx_4 = __Pyx_UnpackItem(__pyx_3, 0); if (unlikely(!__pyx_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 65; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      Py_DECREF(__pyx_v_dfa);
+      __pyx_v_dfa = __pyx_4;
+      __pyx_4 = 0;
+      __pyx_4 = __Pyx_UnpackItem(__pyx_3, 1); if (unlikely(!__pyx_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 65; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_5 = __pyx_PyInt_int(__pyx_4); if (unlikely((__pyx_5 == (int)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 65; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      Py_DECREF(__pyx_4); __pyx_4 = 0;
+      __pyx_v_state = __pyx_5;
+      __pyx_4 = __Pyx_UnpackItem(__pyx_3, 2); if (unlikely(!__pyx_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 65; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      Py_DECREF(__pyx_v_node);
+      __pyx_v_node = __pyx_4;
+      __pyx_4 = 0;
+      if (__Pyx_EndUnpack(__pyx_3) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 65; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      Py_DECREF(__pyx_3); __pyx_3 = 0;
+    }
+
+    /* "/home/gbr/devel/sphinx/sphinx/pycode/pgen2/parse.pyx":66
+ *         while True:
+ *             dfa, state, node = self.stack[-1]
+ *             states, first = dfa             # <<<<<<<<<<<<<<
+ *             arcs = states[state]
+ *             # Look for a state with this label
+ */
+    if (PyTuple_CheckExact(__pyx_v_dfa) && PyTuple_GET_SIZE(__pyx_v_dfa) == 2) {
+      PyObject* tuple = __pyx_v_dfa;
+      __pyx_2 = PyTuple_GET_ITEM(tuple, 0);
+      Py_INCREF(__pyx_2);
+      Py_DECREF(__pyx_v_states);
+      __pyx_v_states = __pyx_2;
+      __pyx_2 = 0;
+      __pyx_3 = PyTuple_GET_ITEM(tuple, 1);
+      Py_INCREF(__pyx_3);
+      Py_DECREF(__pyx_v_first);
+      __pyx_v_first = __pyx_3;
+      __pyx_3 = 0;
+    }
+    else {
+      __pyx_4 = PyObject_GetIter(__pyx_v_dfa); if (unlikely(!__pyx_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 66; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_2 = __Pyx_UnpackItem(__pyx_4, 0); if (unlikely(!__pyx_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 66; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      Py_DECREF(__pyx_v_states);
+      __pyx_v_states = __pyx_2;
+      __pyx_2 = 0;
+      __pyx_3 = __Pyx_UnpackItem(__pyx_4, 1); if (unlikely(!__pyx_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 66; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      Py_DECREF(__pyx_v_first);
+      __pyx_v_first = __pyx_3;
+      __pyx_3 = 0;
+      if (__Pyx_EndUnpack(__pyx_4) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 66; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      Py_DECREF(__pyx_4); __pyx_4 = 0;
+    }
+
+    /* "/home/gbr/devel/sphinx/sphinx/pycode/pgen2/parse.pyx":67
+ *             dfa, state, node = self.stack[-1]
+ *             states, first = dfa
+ *             arcs = states[state]             # <<<<<<<<<<<<<<
+ *             # Look for a state with this label
+ *             for i, newstate in arcs:
+ */
+    __pyx_2 = __Pyx_GetItemInt(__pyx_v_states, __pyx_v_state, 0); if (!__pyx_2) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 67; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    Py_DECREF(__pyx_v_arcs);
+    __pyx_v_arcs = __pyx_2;
+    __pyx_2 = 0;
+
+    /* "/home/gbr/devel/sphinx/sphinx/pycode/pgen2/parse.pyx":69
+ *             arcs = states[state]
+ *             # Look for a state with this label
+ *             for i, newstate in arcs:             # <<<<<<<<<<<<<<
+ *                 t, v = self._grammar_labels[i]
+ *                 if ilabel == i:
+ */
+    if (PyList_CheckExact(__pyx_v_arcs) || PyTuple_CheckExact(__pyx_v_arcs)) {
+      __pyx_6 = 0; __pyx_3 = __pyx_v_arcs; Py_INCREF(__pyx_3);
+    } else {
+      __pyx_6 = -1; __pyx_3 = PyObject_GetIter(__pyx_v_arcs); if (unlikely(!__pyx_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 69; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    }
+    for (;;) {
+      if (likely(PyList_CheckExact(__pyx_3))) {
+        if (__pyx_6 >= PyList_GET_SIZE(__pyx_3)) break;
+        __pyx_4 = PyList_GET_ITEM(__pyx_3, __pyx_6); Py_INCREF(__pyx_4); __pyx_6++;
+      } else if (likely(PyTuple_CheckExact(__pyx_3))) {
+        if (__pyx_6 >= PyTuple_GET_SIZE(__pyx_3)) break;
+        __pyx_4 = PyTuple_GET_ITEM(__pyx_3, __pyx_6); Py_INCREF(__pyx_4); __pyx_6++;
+      } else {
+        __pyx_4 = PyIter_Next(__pyx_3);
+        if (!__pyx_4) {
+          if (unlikely(PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 69; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+          break;
+        }
+      }
+      if (PyTuple_CheckExact(__pyx_4) && PyTuple_GET_SIZE(__pyx_4) == 2) {
+        PyObject* tuple = __pyx_4;
+        __pyx_7 = PyTuple_GET_ITEM(tuple, 0);
+        Py_INCREF(__pyx_7);
+        __pyx_5 = __pyx_PyInt_int(__pyx_7); if (unlikely((__pyx_5 == (int)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 69; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+        Py_DECREF(__pyx_7); __pyx_7 = 0;
+        __pyx_v_i = __pyx_5;
+        __pyx_7 = PyTuple_GET_ITEM(tuple, 1);
+        Py_INCREF(__pyx_7);
+        __pyx_5 = __pyx_PyInt_int(__pyx_7); if (unlikely((__pyx_5 == (int)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 69; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+        Py_DECREF(__pyx_7); __pyx_7 = 0;
+        __pyx_v_newstate = __pyx_5;
+        Py_DECREF(__pyx_4); __pyx_4 = 0;
+      }
+      else {
+        __pyx_2 = PyObject_GetIter(__pyx_4); if (unlikely(!__pyx_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 69; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+        Py_DECREF(__pyx_4); __pyx_4 = 0;
+        __pyx_7 = __Pyx_UnpackItem(__pyx_2, 0); if (unlikely(!__pyx_7)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 69; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+        __pyx_5 = __pyx_PyInt_int(__pyx_7); if (unlikely((__pyx_5 == (int)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 69; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+        Py_DECREF(__pyx_7); __pyx_7 = 0;
+        __pyx_v_i = __pyx_5;
+        __pyx_7 = __Pyx_UnpackItem(__pyx_2, 1); if (unlikely(!__pyx_7)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 69; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+        __pyx_5 = __pyx_PyInt_int(__pyx_7); if (unlikely((__pyx_5 == (int)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 69; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+        Py_DECREF(__pyx_7); __pyx_7 = 0;
+        __pyx_v_newstate = __pyx_5;
+        if (__Pyx_EndUnpack(__pyx_2) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 69; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+        Py_DECREF(__pyx_2); __pyx_2 = 0;
+      }
+
+      /* "/home/gbr/devel/sphinx/sphinx/pycode/pgen2/parse.pyx":70
+ *             # Look for a state with this label
+ *             for i, newstate in arcs:
+ *                 t, v = self._grammar_labels[i]             # <<<<<<<<<<<<<<
+ *                 if ilabel == i:
+ *                     # Look it up in the list of labels
+ */
+      __pyx_7 = __Pyx_GetItemInt(((struct __pyx_obj_6sphinx_6pycode_5pgen2_5parse_Parser *)__pyx_v_self)->_grammar_labels, __pyx_v_i, 0); if (!__pyx_7) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 70; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      if (PyTuple_CheckExact(__pyx_7) && PyTuple_GET_SIZE(__pyx_7) == 2) {
+        PyObject* tuple = __pyx_7;
+        __pyx_2 = PyTuple_GET_ITEM(tuple, 0);
+        Py_INCREF(__pyx_2);
+        __pyx_5 = __pyx_PyInt_int(__pyx_2); if (unlikely((__pyx_5 == (int)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 70; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+        Py_DECREF(__pyx_2); __pyx_2 = 0;
+        __pyx_v_t = __pyx_5;
+        __pyx_2 = PyTuple_GET_ITEM(tuple, 1);
+        Py_INCREF(__pyx_2);
+        Py_DECREF(__pyx_v_v);
+        __pyx_v_v = __pyx_2;
+        __pyx_2 = 0;
+        Py_DECREF(__pyx_7); __pyx_7 = 0;
+      }
+      else {
+        __pyx_4 = PyObject_GetIter(__pyx_7); if (unlikely(!__pyx_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 70; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+        Py_DECREF(__pyx_7); __pyx_7 = 0;
+        __pyx_2 = __Pyx_UnpackItem(__pyx_4, 0); if (unlikely(!__pyx_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 70; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+        __pyx_5 = __pyx_PyInt_int(__pyx_2); if (unlikely((__pyx_5 == (int)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 70; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+        Py_DECREF(__pyx_2); __pyx_2 = 0;
+        __pyx_v_t = __pyx_5;
+        __pyx_2 = __Pyx_UnpackItem(__pyx_4, 1); if (unlikely(!__pyx_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 70; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+        Py_DECREF(__pyx_v_v);
+        __pyx_v_v = __pyx_2;
+        __pyx_2 = 0;
+        if (__Pyx_EndUnpack(__pyx_4) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 70; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+        Py_DECREF(__pyx_4); __pyx_4 = 0;
+      }
+
+      /* "/home/gbr/devel/sphinx/sphinx/pycode/pgen2/parse.pyx":71
+ *             for i, newstate in arcs:
+ *                 t, v = self._grammar_labels[i]
+ *                 if ilabel == i:             # <<<<<<<<<<<<<<
+ *                     # Look it up in the list of labels
+ *                     ## assert t < 256
+ */
+      __pyx_1 = (__pyx_v_ilabel == __pyx_v_i);
+      if (__pyx_1) {
+
+        /* "/home/gbr/devel/sphinx/sphinx/pycode/pgen2/parse.pyx":75
+ *                     ## assert t < 256
+ *                     # Shift a token; we're done with it
+ *                     self.shift(type, value, newstate, context)             # <<<<<<<<<<<<<<
+ *                     # Pop while we are in an accept-only state
+ *                     state = newstate
+ */
+        __pyx_2 = PyInt_FromLong(__pyx_v_newstate); if (unlikely(!__pyx_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 75; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+        ((struct __pyx_vtabstruct_6sphinx_6pycode_5pgen2_5parse_Parser *)((struct __pyx_obj_6sphinx_6pycode_5pgen2_5parse_Parser *)__pyx_v_self)->__pyx_vtab)->shift(((struct __pyx_obj_6sphinx_6pycode_5pgen2_5parse_Parser *)__pyx_v_self), __pyx_v_type, __pyx_v_value, __pyx_2, __pyx_v_context);
+        Py_DECREF(__pyx_2); __pyx_2 = 0;
+
+        /* "/home/gbr/devel/sphinx/sphinx/pycode/pgen2/parse.pyx":77
+ *                     self.shift(type, value, newstate, context)
+ *                     # Pop while we are in an accept-only state
+ *                     state = newstate             # <<<<<<<<<<<<<<
+ *                     while states[state] == [(0, state)]:
+ *                         self.pop()
+ */
+        __pyx_v_state = __pyx_v_newstate;
+
+        /* "/home/gbr/devel/sphinx/sphinx/pycode/pgen2/parse.pyx":78
+ *                     # Pop while we are in an accept-only state
+ *                     state = newstate
+ *                     while states[state] == [(0, state)]:             # <<<<<<<<<<<<<<
+ *                         self.pop()
+ *                         if not self.stack:
+ */
+        while (1) {
+          __pyx_7 = __Pyx_GetItemInt(__pyx_v_states, __pyx_v_state, 0); if (!__pyx_7) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 78; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+          __pyx_4 = PyInt_FromLong(__pyx_v_state); if (unlikely(!__pyx_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 78; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+          __pyx_2 = PyTuple_New(2); if (unlikely(!__pyx_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 78; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+          Py_INCREF(__pyx_int_0);
+          PyTuple_SET_ITEM(__pyx_2, 0, __pyx_int_0);
+          PyTuple_SET_ITEM(__pyx_2, 1, __pyx_4);
+          __pyx_4 = 0;
+          __pyx_4 = PyList_New(1); if (unlikely(!__pyx_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 78; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+          PyList_SET_ITEM(__pyx_4, 0, ((PyObject *)__pyx_2));
+          __pyx_2 = 0;
+          __pyx_2 = PyObject_RichCompare(__pyx_7, ((PyObject *)__pyx_4), Py_EQ); if (unlikely(!__pyx_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 78; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+          Py_DECREF(__pyx_7); __pyx_7 = 0;
+          Py_DECREF(((PyObject *)__pyx_4)); __pyx_4 = 0;
+          __pyx_1 = __Pyx_PyObject_IsTrue(__pyx_2); if (unlikely(__pyx_1 < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 78; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+          Py_DECREF(__pyx_2); __pyx_2 = 0;
+          if (!__pyx_1) break;
+
+          /* "/home/gbr/devel/sphinx/sphinx/pycode/pgen2/parse.pyx":79
+ *                     state = newstate
+ *                     while states[state] == [(0, state)]:
+ *                         self.pop()             # <<<<<<<<<<<<<<
+ *                         if not self.stack:
+ *                             # Done parsing!
+ */
+          ((struct __pyx_vtabstruct_6sphinx_6pycode_5pgen2_5parse_Parser *)((struct __pyx_obj_6sphinx_6pycode_5pgen2_5parse_Parser *)__pyx_v_self)->__pyx_vtab)->pop(((struct __pyx_obj_6sphinx_6pycode_5pgen2_5parse_Parser *)__pyx_v_self));
+
+          /* "/home/gbr/devel/sphinx/sphinx/pycode/pgen2/parse.pyx":80
+ *                     while states[state] == [(0, state)]:
+ *                         self.pop()
+ *                         if not self.stack:             # <<<<<<<<<<<<<<
+ *                             # Done parsing!
+ *                             return True
+ */
+          __pyx_1 = __Pyx_PyObject_IsTrue(((struct __pyx_obj_6sphinx_6pycode_5pgen2_5parse_Parser *)__pyx_v_self)->stack); if (unlikely(__pyx_1 < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 80; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+          __pyx_8 = (!__pyx_1);
+          if (__pyx_8) {
+
+            /* "/home/gbr/devel/sphinx/sphinx/pycode/pgen2/parse.pyx":82
+ *                         if not self.stack:
+ *                             # Done parsing!
+ *                             return True             # <<<<<<<<<<<<<<
+ *                         dfa, state, node = self.stack[-1]
+ *                         states, first = dfa
+ */
+            __pyx_7 = __Pyx_PyBool_FromLong(1); if (unlikely(!__pyx_7)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 82; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+            __pyx_r = __pyx_7;
+            __pyx_7 = 0;
+            Py_DECREF(__pyx_3); __pyx_3 = 0;
+            goto __pyx_L0;
+            goto __pyx_L12;
+          }
+          __pyx_L12:;
+
+          /* "/home/gbr/devel/sphinx/sphinx/pycode/pgen2/parse.pyx":83
+ *                             # Done parsing!
+ *                             return True
+ *                         dfa, state, node = self.stack[-1]             # <<<<<<<<<<<<<<
+ *                         states, first = dfa
+ *                     # Done with this token
+ */
+          __pyx_4 = __Pyx_GetItemInt(((struct __pyx_obj_6sphinx_6pycode_5pgen2_5parse_Parser *)__pyx_v_self)->stack, -1, 0); if (!__pyx_4) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 83; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+          if (PyTuple_CheckExact(__pyx_4) && PyTuple_GET_SIZE(__pyx_4) == 3) {
+            PyObject* tuple = __pyx_4;
+            __pyx_7 = PyTuple_GET_ITEM(tuple, 0);
+            Py_INCREF(__pyx_7);
+            Py_DECREF(__pyx_v_dfa);
+            __pyx_v_dfa = __pyx_7;
+            __pyx_7 = 0;
+            __pyx_7 = PyTuple_GET_ITEM(tuple, 1);
+            Py_INCREF(__pyx_7);
+            __pyx_5 = __pyx_PyInt_int(__pyx_7); if (unlikely((__pyx_5 == (int)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 83; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+            Py_DECREF(__pyx_7); __pyx_7 = 0;
+            __pyx_v_state = __pyx_5;
+            __pyx_7 = PyTuple_GET_ITEM(tuple, 2);
+            Py_INCREF(__pyx_7);
+            Py_DECREF(__pyx_v_node);
+            __pyx_v_node = __pyx_7;
+            __pyx_7 = 0;
+            Py_DECREF(__pyx_4); __pyx_4 = 0;
+          }
+          else {
+            __pyx_2 = PyObject_GetIter(__pyx_4); if (unlikely(!__pyx_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 83; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+            Py_DECREF(__pyx_4); __pyx_4 = 0;
+            __pyx_7 = __Pyx_UnpackItem(__pyx_2, 0); if (unlikely(!__pyx_7)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 83; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+            Py_DECREF(__pyx_v_dfa);
+            __pyx_v_dfa = __pyx_7;
+            __pyx_7 = 0;
+            __pyx_7 = __Pyx_UnpackItem(__pyx_2, 1); if (unlikely(!__pyx_7)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 83; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+            __pyx_5 = __pyx_PyInt_int(__pyx_7); if (unlikely((__pyx_5 == (int)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 83; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+            Py_DECREF(__pyx_7); __pyx_7 = 0;
+            __pyx_v_state = __pyx_5;
+            __pyx_7 = __Pyx_UnpackItem(__pyx_2, 2); if (unlikely(!__pyx_7)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 83; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+            Py_DECREF(__pyx_v_node);
+            __pyx_v_node = __pyx_7;
+            __pyx_7 = 0;
+            if (__Pyx_EndUnpack(__pyx_2) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 83; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+            Py_DECREF(__pyx_2); __pyx_2 = 0;
+          }
+
+          /* "/home/gbr/devel/sphinx/sphinx/pycode/pgen2/parse.pyx":84
+ *                             return True
+ *                         dfa, state, node = self.stack[-1]
+ *                         states, first = dfa             # <<<<<<<<<<<<<<
+ *                     # Done with this token
+ *                     return False
+ */
+          if (PyTuple_CheckExact(__pyx_v_dfa) && PyTuple_GET_SIZE(__pyx_v_dfa) == 2) {
+            PyObject* tuple = __pyx_v_dfa;
+            __pyx_4 = PyTuple_GET_ITEM(tuple, 0);
+            Py_INCREF(__pyx_4);
+            Py_DECREF(__pyx_v_states);
+            __pyx_v_states = __pyx_4;
+            __pyx_4 = 0;
+            __pyx_2 = PyTuple_GET_ITEM(tuple, 1);
+            Py_INCREF(__pyx_2);
+            Py_DECREF(__pyx_v_first);
+            __pyx_v_first = __pyx_2;
+            __pyx_2 = 0;
+          }
+          else {
+            __pyx_7 = PyObject_GetIter(__pyx_v_dfa); if (unlikely(!__pyx_7)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 84; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+            __pyx_4 = __Pyx_UnpackItem(__pyx_7, 0); if (unlikely(!__pyx_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 84; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+            Py_DECREF(__pyx_v_states);
+            __pyx_v_states = __pyx_4;
+            __pyx_4 = 0;
+            __pyx_2 = __Pyx_UnpackItem(__pyx_7, 1); if (unlikely(!__pyx_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 84; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+            Py_DECREF(__pyx_v_first);
+            __pyx_v_first = __pyx_2;
+            __pyx_2 = 0;
+            if (__Pyx_EndUnpack(__pyx_7) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 84; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+            Py_DECREF(__pyx_7); __pyx_7 = 0;
+          }
+        }
+
+        /* "/home/gbr/devel/sphinx/sphinx/pycode/pgen2/parse.pyx":86
+ *                         states, first = dfa
+ *                     # Done with this token
+ *                     return False             # <<<<<<<<<<<<<<
+ *                 elif t >= 256:
+ *                     # See if it's a symbol and if we're in its first set
+ */
+        __pyx_4 = __Pyx_PyBool_FromLong(0); if (unlikely(!__pyx_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 86; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+        __pyx_r = __pyx_4;
+        __pyx_4 = 0;
+        Py_DECREF(__pyx_3); __pyx_3 = 0;
+        goto __pyx_L0;
+        goto __pyx_L9;
+      }
+
+      /* "/home/gbr/devel/sphinx/sphinx/pycode/pgen2/parse.pyx":87
+ *                     # Done with this token
+ *                     return False
+ *                 elif t >= 256:             # <<<<<<<<<<<<<<
+ *                     # See if it's a symbol and if we're in its first set
+ *                     itsdfa = self._grammar_dfas[t]
+ */
+      __pyx_1 = (__pyx_v_t >= 256);
+      if (__pyx_1) {
+
+        /* "/home/gbr/devel/sphinx/sphinx/pycode/pgen2/parse.pyx":89
+ *                 elif t >= 256:
+ *                     # See if it's a symbol and if we're in its first set
+ *                     itsdfa = self._grammar_dfas[t]             # <<<<<<<<<<<<<<
+ *                     itsstates, itsfirst = itsdfa
+ *                     if ilabel in itsfirst:
+ */
+        __pyx_2 = __Pyx_GetItemInt(((struct __pyx_obj_6sphinx_6pycode_5pgen2_5parse_Parser *)__pyx_v_self)->_grammar_dfas, __pyx_v_t, 0); if (!__pyx_2) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 89; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+        Py_DECREF(__pyx_v_itsdfa);
+        __pyx_v_itsdfa = __pyx_2;
+        __pyx_2 = 0;
+
+        /* "/home/gbr/devel/sphinx/sphinx/pycode/pgen2/parse.pyx":90
+ *                     # See if it's a symbol and if we're in its first set
+ *                     itsdfa = self._grammar_dfas[t]
+ *                     itsstates, itsfirst = itsdfa             # <<<<<<<<<<<<<<
+ *                     if ilabel in itsfirst:
+ *                         # Push a symbol
+ */
+        if (PyTuple_CheckExact(__pyx_v_itsdfa) && PyTuple_GET_SIZE(__pyx_v_itsdfa) == 2) {
+          PyObject* tuple = __pyx_v_itsdfa;
+          __pyx_4 = PyTuple_GET_ITEM(tuple, 0);
+          Py_INCREF(__pyx_4);
+          Py_DECREF(__pyx_v_itsstates);
+          __pyx_v_itsstates = __pyx_4;
+          __pyx_4 = 0;
+          __pyx_2 = PyTuple_GET_ITEM(tuple, 1);
+          Py_INCREF(__pyx_2);
+          Py_DECREF(__pyx_v_itsfirst);
+          __pyx_v_itsfirst = __pyx_2;
+          __pyx_2 = 0;
+        }
+        else {
+          __pyx_7 = PyObject_GetIter(__pyx_v_itsdfa); if (unlikely(!__pyx_7)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 90; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+          __pyx_4 = __Pyx_UnpackItem(__pyx_7, 0); if (unlikely(!__pyx_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 90; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+          Py_DECREF(__pyx_v_itsstates);
+          __pyx_v_itsstates = __pyx_4;
+          __pyx_4 = 0;
+          __pyx_2 = __Pyx_UnpackItem(__pyx_7, 1); if (unlikely(!__pyx_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 90; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+          Py_DECREF(__pyx_v_itsfirst);
+          __pyx_v_itsfirst = __pyx_2;
+          __pyx_2 = 0;
+          if (__Pyx_EndUnpack(__pyx_7) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 90; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+          Py_DECREF(__pyx_7); __pyx_7 = 0;
+        }
+
+        /* "/home/gbr/devel/sphinx/sphinx/pycode/pgen2/parse.pyx":91
+ *                     itsdfa = self._grammar_dfas[t]
+ *                     itsstates, itsfirst = itsdfa
+ *                     if ilabel in itsfirst:             # <<<<<<<<<<<<<<
+ *                         # Push a symbol
+ *                         self.push(t, itsdfa, newstate, context)
+ */
+        __pyx_4 = PyInt_FromLong(__pyx_v_ilabel); if (unlikely(!__pyx_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 91; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+        __pyx_8 = (PySequence_Contains(__pyx_v_itsfirst, __pyx_4)); if (unlikely(__pyx_8 < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 91; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+        Py_DECREF(__pyx_4); __pyx_4 = 0;
+        if (__pyx_8) {
+
+          /* "/home/gbr/devel/sphinx/sphinx/pycode/pgen2/parse.pyx":93
+ *                     if ilabel in itsfirst:
+ *                         # Push a symbol
+ *                         self.push(t, itsdfa, newstate, context)             # <<<<<<<<<<<<<<
+ *                         break # To continue the outer while loop
+ *             else:
+ */
+          __pyx_2 = PyInt_FromLong(__pyx_v_t); if (unlikely(!__pyx_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 93; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+          __pyx_7 = PyInt_FromLong(__pyx_v_newstate); if (unlikely(!__pyx_7)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 93; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+          ((struct __pyx_vtabstruct_6sphinx_6pycode_5pgen2_5parse_Parser *)((struct __pyx_obj_6sphinx_6pycode_5pgen2_5parse_Parser *)__pyx_v_self)->__pyx_vtab)->push(((struct __pyx_obj_6sphinx_6pycode_5pgen2_5parse_Parser *)__pyx_v_self), __pyx_2, __pyx_v_itsdfa, __pyx_7, __pyx_v_context);
+          Py_DECREF(__pyx_2); __pyx_2 = 0;
+          Py_DECREF(__pyx_7); __pyx_7 = 0;
+
+          /* "/home/gbr/devel/sphinx/sphinx/pycode/pgen2/parse.pyx":94
+ *                         # Push a symbol
+ *                         self.push(t, itsdfa, newstate, context)
+ *                         break # To continue the outer while loop             # <<<<<<<<<<<<<<
+ *             else:
+ *                 if (0, state) in arcs:
+ */
+          goto __pyx_L8;
+          goto __pyx_L13;
+        }
+        __pyx_L13:;
+        goto __pyx_L9;
+      }
+      __pyx_L9:;
+    }
+    /*else*/ {
+
+      /* "/home/gbr/devel/sphinx/sphinx/pycode/pgen2/parse.pyx":96
+ *                         break # To continue the outer while loop
+ *             else:
+ *                 if (0, state) in arcs:             # <<<<<<<<<<<<<<
+ *                     # An accepting state, pop it and try something else
+ *                     self.pop()
+ */
+      __pyx_4 = PyInt_FromLong(__pyx_v_state); if (unlikely(!__pyx_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 96; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_2 = PyTuple_New(2); if (unlikely(!__pyx_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 96; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      Py_INCREF(__pyx_int_0);
+      PyTuple_SET_ITEM(__pyx_2, 0, __pyx_int_0);
+      PyTuple_SET_ITEM(__pyx_2, 1, __pyx_4);
+      __pyx_4 = 0;
+      __pyx_1 = (PySequence_Contains(__pyx_v_arcs, ((PyObject *)__pyx_2))); if (unlikely(__pyx_1 < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 96; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      Py_DECREF(((PyObject *)__pyx_2)); __pyx_2 = 0;
+      if (__pyx_1) {
+
+        /* "/home/gbr/devel/sphinx/sphinx/pycode/pgen2/parse.pyx":98
+ *                 if (0, state) in arcs:
+ *                     # An accepting state, pop it and try something else
+ *                     self.pop()             # <<<<<<<<<<<<<<
+ *                     if not self.stack:
+ *                         # Done parsing, but another token is input
+ */
+        ((struct __pyx_vtabstruct_6sphinx_6pycode_5pgen2_5parse_Parser *)((struct __pyx_obj_6sphinx_6pycode_5pgen2_5parse_Parser *)__pyx_v_self)->__pyx_vtab)->pop(((struct __pyx_obj_6sphinx_6pycode_5pgen2_5parse_Parser *)__pyx_v_self));
+
+        /* "/home/gbr/devel/sphinx/sphinx/pycode/pgen2/parse.pyx":99
+ *                     # An accepting state, pop it and try something else
+ *                     self.pop()
+ *                     if not self.stack:             # <<<<<<<<<<<<<<
+ *                         # Done parsing, but another token is input
+ *                         raise ParseError("too much input",
+ */
+        __pyx_8 = __Pyx_PyObject_IsTrue(((struct __pyx_obj_6sphinx_6pycode_5pgen2_5parse_Parser *)__pyx_v_self)->stack); if (unlikely(__pyx_8 < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 99; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+        __pyx_1 = (!__pyx_8);
+        if (__pyx_1) {
+
+          /* "/home/gbr/devel/sphinx/sphinx/pycode/pgen2/parse.pyx":101
+ *                     if not self.stack:
+ *                         # Done parsing, but another token is input
+ *                         raise ParseError("too much input",             # <<<<<<<<<<<<<<
+ *                                          type, value, context)
+ *                 else:
+ */
+          __pyx_7 = __Pyx_GetName(__pyx_m, __pyx_kp_ParseError); if (unlikely(!__pyx_7)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 101; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+
+          /* "/home/gbr/devel/sphinx/sphinx/pycode/pgen2/parse.pyx":102
+ *                         # Done parsing, but another token is input
+ *                         raise ParseError("too much input",
+ *                                          type, value, context)             # <<<<<<<<<<<<<<
+ *                 else:
+ *                     # No success finding a transition
+ */
+          __pyx_4 = PyTuple_New(4); if (unlikely(!__pyx_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 101; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+          Py_INCREF(__pyx_kp_5);
+          PyTuple_SET_ITEM(__pyx_4, 0, __pyx_kp_5);
+          Py_INCREF(__pyx_v_type);
+          PyTuple_SET_ITEM(__pyx_4, 1, __pyx_v_type);
+          Py_INCREF(__pyx_v_value);
+          PyTuple_SET_ITEM(__pyx_4, 2, __pyx_v_value);
+          Py_INCREF(__pyx_v_context);
+          PyTuple_SET_ITEM(__pyx_4, 3, __pyx_v_context);
+          __pyx_2 = PyObject_Call(__pyx_7, ((PyObject *)__pyx_4), NULL); if (unlikely(!__pyx_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 101; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+          Py_DECREF(__pyx_7); __pyx_7 = 0;
+          Py_DECREF(((PyObject *)__pyx_4)); __pyx_4 = 0;
+          __Pyx_Raise(__pyx_2, 0, 0);
+          Py_DECREF(__pyx_2); __pyx_2 = 0;
+          {__pyx_filename = __pyx_f[0]; __pyx_lineno = 101; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+          goto __pyx_L15;
+        }
+        __pyx_L15:;
+        goto __pyx_L14;
+      }
+      /*else*/ {
+
+        /* "/home/gbr/devel/sphinx/sphinx/pycode/pgen2/parse.pyx":105
+ *                 else:
+ *                     # No success finding a transition
+ *                     raise ParseError("bad input", type, value, context)             # <<<<<<<<<<<<<<
+ * 
+ *     cdef int classify(self, type, value, context):
+ */
+        __pyx_7 = __Pyx_GetName(__pyx_m, __pyx_kp_ParseError); if (unlikely(!__pyx_7)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 105; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+        __pyx_4 = PyTuple_New(4); if (unlikely(!__pyx_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 105; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+        Py_INCREF(__pyx_kp_6);
+        PyTuple_SET_ITEM(__pyx_4, 0, __pyx_kp_6);
+        Py_INCREF(__pyx_v_type);
+        PyTuple_SET_ITEM(__pyx_4, 1, __pyx_v_type);
+        Py_INCREF(__pyx_v_value);
+        PyTuple_SET_ITEM(__pyx_4, 2, __pyx_v_value);
+        Py_INCREF(__pyx_v_context);
+        PyTuple_SET_ITEM(__pyx_4, 3, __pyx_v_context);
+        __pyx_2 = PyObject_Call(__pyx_7, ((PyObject *)__pyx_4), NULL); if (unlikely(!__pyx_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 105; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+        Py_DECREF(__pyx_7); __pyx_7 = 0;
+        Py_DECREF(((PyObject *)__pyx_4)); __pyx_4 = 0;
+        __Pyx_Raise(__pyx_2, 0, 0);
+        Py_DECREF(__pyx_2); __pyx_2 = 0;
+        {__pyx_filename = __pyx_f[0]; __pyx_lineno = 105; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      }
+      __pyx_L14:;
+    }
+    __pyx_L8:;
+    Py_DECREF(__pyx_3); __pyx_3 = 0;
+  }
+
+  __pyx_r = Py_None; Py_INCREF(Py_None);
+  goto __pyx_L0;
+  __pyx_L1_error:;
+  Py_XDECREF(__pyx_2);
+  Py_XDECREF(__pyx_3);
+  Py_XDECREF(__pyx_4);
+  Py_XDECREF(__pyx_7);
+  __Pyx_AddTraceback("sphinx.pycode.pgen2.parse.Parser.addtoken");
+  __pyx_r = NULL;
+  __pyx_L0:;
+  Py_DECREF(__pyx_v_dfa);
+  Py_DECREF(__pyx_v_node);
+  Py_DECREF(__pyx_v_states);
+  Py_DECREF(__pyx_v_first);
+  Py_DECREF(__pyx_v_arcs);
+  Py_DECREF(__pyx_v_v);
+  Py_DECREF(__pyx_v_itsdfa);
+  Py_DECREF(__pyx_v_itsstates);
+  Py_DECREF(__pyx_v_itsfirst);
+  return __pyx_r;
+}
+
+/* "/home/gbr/devel/sphinx/sphinx/pycode/pgen2/parse.pyx":107
+ *                     raise ParseError("bad input", type, value, context)
+ * 
+ *     cdef int classify(self, type, value, context):             # <<<<<<<<<<<<<<
+ *         """Turn a token into a label.  (Internal)"""
+ *         if type == NAME:
+ */
+
+static  int __pyx_f_6sphinx_6pycode_5pgen2_5parse_6Parser_classify(struct __pyx_obj_6sphinx_6pycode_5pgen2_5parse_Parser *__pyx_v_self, PyObject *__pyx_v_type, PyObject *__pyx_v_value, PyObject *__pyx_v_context) {
+  PyObject *__pyx_v_ilabel;
+  int __pyx_r;
+  PyObject *__pyx_1 = 0;
+  int __pyx_2;
+  PyObject *__pyx_3 = 0;
+  PyObject *__pyx_4 = 0;
+  int __pyx_5;
+  __pyx_v_ilabel = Py_None; Py_INCREF(Py_None);
+
+  /* "/home/gbr/devel/sphinx/sphinx/pycode/pgen2/parse.pyx":109
+ *     cdef int classify(self, type, value, context):
+ *         """Turn a token into a label.  (Internal)"""
+ *         if type == NAME:             # <<<<<<<<<<<<<<
+ *             # Keep a listing of all used names
+ *             self.used_names.add(value)
+ */
+  __pyx_1 = PyObject_RichCompare(__pyx_v_type, __pyx_int_1, Py_EQ); if (unlikely(!__pyx_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 109; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_2 = __Pyx_PyObject_IsTrue(__pyx_1); if (unlikely(__pyx_2 < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 109; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  Py_DECREF(__pyx_1); __pyx_1 = 0;
+  if (__pyx_2) {
+
+    /* "/home/gbr/devel/sphinx/sphinx/pycode/pgen2/parse.pyx":111
+ *         if type == NAME:
+ *             # Keep a listing of all used names
+ *             self.used_names.add(value)             # <<<<<<<<<<<<<<
+ *             # Check for reserved words
+ *             ilabel = self._grammar_keywords.get(value)
+ */
+    __pyx_1 = PyObject_GetAttr(__pyx_v_self->used_names, __pyx_kp_add); if (unlikely(!__pyx_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 111; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_3 = PyTuple_New(1); if (unlikely(!__pyx_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 111; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    Py_INCREF(__pyx_v_value);
+    PyTuple_SET_ITEM(__pyx_3, 0, __pyx_v_value);
+    __pyx_4 = PyObject_Call(__pyx_1, ((PyObject *)__pyx_3), NULL); if (unlikely(!__pyx_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 111; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    Py_DECREF(__pyx_1); __pyx_1 = 0;
+    Py_DECREF(((PyObject *)__pyx_3)); __pyx_3 = 0;
+    Py_DECREF(__pyx_4); __pyx_4 = 0;
+
+    /* "/home/gbr/devel/sphinx/sphinx/pycode/pgen2/parse.pyx":113
+ *             self.used_names.add(value)
+ *             # Check for reserved words
+ *             ilabel = self._grammar_keywords.get(value)             # <<<<<<<<<<<<<<
+ *             if ilabel is not None:
+ *                 return ilabel
+ */
+    __pyx_1 = PyObject_GetAttr(__pyx_v_self->_grammar_keywords, __pyx_kp_get); if (unlikely(!__pyx_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 113; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_3 = PyTuple_New(1); if (unlikely(!__pyx_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 113; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    Py_INCREF(__pyx_v_value);
+    PyTuple_SET_ITEM(__pyx_3, 0, __pyx_v_value);
+    __pyx_4 = PyObject_Call(__pyx_1, ((PyObject *)__pyx_3), NULL); if (unlikely(!__pyx_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 113; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    Py_DECREF(__pyx_1); __pyx_1 = 0;
+    Py_DECREF(((PyObject *)__pyx_3)); __pyx_3 = 0;
+    Py_DECREF(__pyx_v_ilabel);
+    __pyx_v_ilabel = __pyx_4;
+    __pyx_4 = 0;
+
+    /* "/home/gbr/devel/sphinx/sphinx/pycode/pgen2/parse.pyx":114
+ *             # Check for reserved words
+ *             ilabel = self._grammar_keywords.get(value)
+ *             if ilabel is not None:             # <<<<<<<<<<<<<<
+ *                 return ilabel
+ *         ilabel = self._grammar_tokens.get(type)
+ */
+    __pyx_2 = (__pyx_v_ilabel != Py_None);
+    if (__pyx_2) {
+
+      /* "/home/gbr/devel/sphinx/sphinx/pycode/pgen2/parse.pyx":115
+ *             ilabel = self._grammar_keywords.get(value)
+ *             if ilabel is not None:
+ *                 return ilabel             # <<<<<<<<<<<<<<
+ *         ilabel = self._grammar_tokens.get(type)
+ *         if ilabel is None:
+ */
+      __pyx_5 = __pyx_PyInt_int(__pyx_v_ilabel); if (unlikely((__pyx_5 == (int)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 115; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_r = __pyx_5;
+      goto __pyx_L0;
+      goto __pyx_L4;
+    }
+    __pyx_L4:;
+    goto __pyx_L3;
+  }
+  __pyx_L3:;
+
+  /* "/home/gbr/devel/sphinx/sphinx/pycode/pgen2/parse.pyx":116
+ *             if ilabel is not None:
+ *                 return ilabel
+ *         ilabel = self._grammar_tokens.get(type)             # <<<<<<<<<<<<<<
+ *         if ilabel is None:
+ *             raise ParseError("bad token", type, value, context)
+ */
+  __pyx_1 = PyObject_GetAttr(__pyx_v_self->_grammar_tokens, __pyx_kp_get); if (unlikely(!__pyx_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 116; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_3 = PyTuple_New(1); if (unlikely(!__pyx_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 116; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  Py_INCREF(__pyx_v_type);
+  PyTuple_SET_ITEM(__pyx_3, 0, __pyx_v_type);
+  __pyx_4 = PyObject_Call(__pyx_1, ((PyObject *)__pyx_3), NULL); if (unlikely(!__pyx_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 116; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  Py_DECREF(__pyx_1); __pyx_1 = 0;
+  Py_DECREF(((PyObject *)__pyx_3)); __pyx_3 = 0;
+  Py_DECREF(__pyx_v_ilabel);
+  __pyx_v_ilabel = __pyx_4;
+  __pyx_4 = 0;
+
+  /* "/home/gbr/devel/sphinx/sphinx/pycode/pgen2/parse.pyx":117
+ *                 return ilabel
+ *         ilabel = self._grammar_tokens.get(type)
+ *         if ilabel is None:             # <<<<<<<<<<<<<<
+ *             raise ParseError("bad token", type, value, context)
+ *         return ilabel
+ */
+  __pyx_2 = (__pyx_v_ilabel == Py_None);
+  if (__pyx_2) {
+
+    /* "/home/gbr/devel/sphinx/sphinx/pycode/pgen2/parse.pyx":118
+ *         ilabel = self._grammar_tokens.get(type)
+ *         if ilabel is None:
+ *             raise ParseError("bad token", type, value, context)             # <<<<<<<<<<<<<<
+ *         return ilabel
+ * 
+ */
+    __pyx_1 = __Pyx_GetName(__pyx_m, __pyx_kp_ParseError); if (unlikely(!__pyx_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 118; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_3 = PyTuple_New(4); if (unlikely(!__pyx_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 118; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    Py_INCREF(__pyx_kp_7);
+    PyTuple_SET_ITEM(__pyx_3, 0, __pyx_kp_7);
+    Py_INCREF(__pyx_v_type);
+    PyTuple_SET_ITEM(__pyx_3, 1, __pyx_v_type);
+    Py_INCREF(__pyx_v_value);
+    PyTuple_SET_ITEM(__pyx_3, 2, __pyx_v_value);
+    Py_INCREF(__pyx_v_context);
+    PyTuple_SET_ITEM(__pyx_3, 3, __pyx_v_context);
+    __pyx_4 = PyObject_Call(__pyx_1, ((PyObject *)__pyx_3), NULL); if (unlikely(!__pyx_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 118; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    Py_DECREF(__pyx_1); __pyx_1 = 0;
+    Py_DECREF(((PyObject *)__pyx_3)); __pyx_3 = 0;
+    __Pyx_Raise(__pyx_4, 0, 0);
+    Py_DECREF(__pyx_4); __pyx_4 = 0;
+    {__pyx_filename = __pyx_f[0]; __pyx_lineno = 118; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    goto __pyx_L5;
+  }
+  __pyx_L5:;
+
+  /* "/home/gbr/devel/sphinx/sphinx/pycode/pgen2/parse.pyx":119
+ *         if ilabel is None:
+ *             raise ParseError("bad token", type, value, context)
+ *         return ilabel             # <<<<<<<<<<<<<<
+ * 
+ *     cdef void shift(self, type, value, newstate, context):
+ */
+  __pyx_5 = __pyx_PyInt_int(__pyx_v_ilabel); if (unlikely((__pyx_5 == (int)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 119; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_r = __pyx_5;
+  goto __pyx_L0;
+
+  __pyx_r = 0;
+  goto __pyx_L0;
+  __pyx_L1_error:;
+  Py_XDECREF(__pyx_1);
+  Py_XDECREF(__pyx_3);
+  Py_XDECREF(__pyx_4);
+  __Pyx_WriteUnraisable("sphinx.pycode.pgen2.parse.Parser.classify");
+  __pyx_r = 0;
+  __pyx_L0:;
+  Py_DECREF(__pyx_v_ilabel);
+  return __pyx_r;
+}
+
+/* "/home/gbr/devel/sphinx/sphinx/pycode/pgen2/parse.pyx":121
+ *         return ilabel
+ * 
+ *     cdef void shift(self, type, value, newstate, context):             # <<<<<<<<<<<<<<
+ *         """Shift a token.  (Internal)"""
+ *         dfa, state, node = self.stack[-1]
+ */
+
+static  void __pyx_f_6sphinx_6pycode_5pgen2_5parse_6Parser_shift(struct __pyx_obj_6sphinx_6pycode_5pgen2_5parse_Parser *__pyx_v_self, PyObject *__pyx_v_type, PyObject *__pyx_v_value, PyObject *__pyx_v_newstate, PyObject *__pyx_v_context) {
+  PyObject *__pyx_v_dfa;
+  PyObject *__pyx_v_state;
+  PyObject *__pyx_v_node;
+  PyObject *__pyx_v_newnode;
+  PyObject *__pyx_1 = 0;
+  PyObject *__pyx_2 = 0;
+  PyObject *__pyx_3 = 0;
+  int __pyx_4;
+  __pyx_v_dfa = Py_None; Py_INCREF(Py_None);
+  __pyx_v_state = Py_None; Py_INCREF(Py_None);
+  __pyx_v_node = Py_None; Py_INCREF(Py_None);
+  __pyx_v_newnode = Py_None; Py_INCREF(Py_None);
+
+  /* "/home/gbr/devel/sphinx/sphinx/pycode/pgen2/parse.pyx":123
+ *     cdef void shift(self, type, value, newstate, context):
+ *         """Shift a token.  (Internal)"""
+ *         dfa, state, node = self.stack[-1]             # <<<<<<<<<<<<<<
+ *         newnode = (type, value, context, None)
+ *         newnode = self.convert(newnode)
+ */
+  __pyx_1 = __Pyx_GetItemInt(__pyx_v_self->stack, -1, 0); if (!__pyx_1) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 123; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  if (PyTuple_CheckExact(__pyx_1) && PyTuple_GET_SIZE(__pyx_1) == 3) {
+    PyObject* tuple = __pyx_1;
+    __pyx_3 = PyTuple_GET_ITEM(tuple, 0);
+    Py_INCREF(__pyx_3);
+    Py_DECREF(__pyx_v_dfa);
+    __pyx_v_dfa = __pyx_3;
+    __pyx_3 = 0;
+    __pyx_3 = PyTuple_GET_ITEM(tuple, 1);
+    Py_INCREF(__pyx_3);
+    Py_DECREF(__pyx_v_state);
+    __pyx_v_state = __pyx_3;
+    __pyx_3 = 0;
+    __pyx_3 = PyTuple_GET_ITEM(tuple, 2);
+    Py_INCREF(__pyx_3);
+    Py_DECREF(__pyx_v_node);
+    __pyx_v_node = __pyx_3;
+    __pyx_3 = 0;
+    Py_DECREF(__pyx_1); __pyx_1 = 0;
+  }
+  else {
+    __pyx_2 = PyObject_GetIter(__pyx_1); if (unlikely(!__pyx_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 123; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    Py_DECREF(__pyx_1); __pyx_1 = 0;
+    __pyx_3 = __Pyx_UnpackItem(__pyx_2, 0); if (unlikely(!__pyx_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 123; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    Py_DECREF(__pyx_v_dfa);
+    __pyx_v_dfa = __pyx_3;
+    __pyx_3 = 0;
+    __pyx_3 = __Pyx_UnpackItem(__pyx_2, 1); if (unlikely(!__pyx_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 123; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    Py_DECREF(__pyx_v_state);
+    __pyx_v_state = __pyx_3;
+    __pyx_3 = 0;
+    __pyx_3 = __Pyx_UnpackItem(__pyx_2, 2); if (unlikely(!__pyx_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 123; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    Py_DECREF(__pyx_v_node);
+    __pyx_v_node = __pyx_3;
+    __pyx_3 = 0;
+    if (__Pyx_EndUnpack(__pyx_2) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 123; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    Py_DECREF(__pyx_2); __pyx_2 = 0;
+  }
+
+  /* "/home/gbr/devel/sphinx/sphinx/pycode/pgen2/parse.pyx":124
+ *         """Shift a token.  (Internal)"""
+ *         dfa, state, node = self.stack[-1]
+ *         newnode = (type, value, context, None)             # <<<<<<<<<<<<<<
+ *         newnode = self.convert(newnode)
+ *         if newnode is not None:
+ */
+  __pyx_3 = PyTuple_New(4); if (unlikely(!__pyx_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 124; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  Py_INCREF(__pyx_v_type);
+  PyTuple_SET_ITEM(__pyx_3, 0, __pyx_v_type);
+  Py_INCREF(__pyx_v_value);
+  PyTuple_SET_ITEM(__pyx_3, 1, __pyx_v_value);
+  Py_INCREF(__pyx_v_context);
+  PyTuple_SET_ITEM(__pyx_3, 2, __pyx_v_context);
+  Py_INCREF(Py_None);
+  PyTuple_SET_ITEM(__pyx_3, 3, Py_None);
+  Py_DECREF(__pyx_v_newnode);
+  __pyx_v_newnode = ((PyObject *)__pyx_3);
+  __pyx_3 = 0;
+
+  /* "/home/gbr/devel/sphinx/sphinx/pycode/pgen2/parse.pyx":125
+ *         dfa, state, node = self.stack[-1]
+ *         newnode = (type, value, context, None)
+ *         newnode = self.convert(newnode)             # <<<<<<<<<<<<<<
+ *         if newnode is not None:
+ *             node[-1].append(newnode)
+ */
+  __pyx_1 = ((struct __pyx_vtabstruct_6sphinx_6pycode_5pgen2_5parse_Parser *)__pyx_v_self->__pyx_vtab)->convert(__pyx_v_self, __pyx_v_newnode); if (unlikely(!__pyx_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 125; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  Py_DECREF(__pyx_v_newnode);
+  __pyx_v_newnode = __pyx_1;
+  __pyx_1 = 0;
+
+  /* "/home/gbr/devel/sphinx/sphinx/pycode/pgen2/parse.pyx":126
+ *         newnode = (type, value, context, None)
+ *         newnode = self.convert(newnode)
+ *         if newnode is not None:             # <<<<<<<<<<<<<<
+ *             node[-1].append(newnode)
+ *         self.stack[-1] = (dfa, newstate, node)
+ */
+  __pyx_4 = (__pyx_v_newnode != Py_None);
+  if (__pyx_4) {
+
+    /* "/home/gbr/devel/sphinx/sphinx/pycode/pgen2/parse.pyx":127
+ *         newnode = self.convert(newnode)
+ *         if newnode is not None:
+ *             node[-1].append(newnode)             # <<<<<<<<<<<<<<
+ *         self.stack[-1] = (dfa, newstate, node)
+ * 
+ */
+    __pyx_2 = __Pyx_GetItemInt(__pyx_v_node, -1, 0); if (!__pyx_2) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 127; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_3 = __Pyx_PyObject_Append(__pyx_2, __pyx_v_newnode); if (unlikely(!__pyx_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 127; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    Py_DECREF(__pyx_2); __pyx_2 = 0;
+    Py_DECREF(__pyx_3); __pyx_3 = 0;
+    goto __pyx_L3;
+  }
+  __pyx_L3:;
+
+  /* "/home/gbr/devel/sphinx/sphinx/pycode/pgen2/parse.pyx":128
+ *         if newnode is not None:
+ *             node[-1].append(newnode)
+ *         self.stack[-1] = (dfa, newstate, node)             # <<<<<<<<<<<<<<
+ * 
+ *     cdef void push(self, type, newdfa, newstate, context):
+ */
+  __pyx_1 = PyTuple_New(3); if (unlikely(!__pyx_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 128; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  Py_INCREF(__pyx_v_dfa);
+  PyTuple_SET_ITEM(__pyx_1, 0, __pyx_v_dfa);
+  Py_INCREF(__pyx_v_newstate);
+  PyTuple_SET_ITEM(__pyx_1, 1, __pyx_v_newstate);
+  Py_INCREF(__pyx_v_node);
+  PyTuple_SET_ITEM(__pyx_1, 2, __pyx_v_node);
+  if (__Pyx_SetItemInt(__pyx_v_self->stack, -1, ((PyObject *)__pyx_1), 0) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 128; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  Py_DECREF(((PyObject *)__pyx_1)); __pyx_1 = 0;
+
+  goto __pyx_L0;
+  __pyx_L1_error:;
+  Py_XDECREF(__pyx_1);
+  Py_XDECREF(__pyx_2);
+  Py_XDECREF(__pyx_3);
+  __Pyx_WriteUnraisable("sphinx.pycode.pgen2.parse.Parser.shift");
+  __pyx_L0:;
+  Py_DECREF(__pyx_v_dfa);
+  Py_DECREF(__pyx_v_state);
+  Py_DECREF(__pyx_v_node);
+  Py_DECREF(__pyx_v_newnode);
+}
+
+/* "/home/gbr/devel/sphinx/sphinx/pycode/pgen2/parse.pyx":130
+ *         self.stack[-1] = (dfa, newstate, node)
+ * 
+ *     cdef void push(self, type, newdfa, newstate, context):             # <<<<<<<<<<<<<<
+ *         """Push a nonterminal.  (Internal)"""
+ *         dfa, state, node = self.stack[-1]
+ */
+
+static  void __pyx_f_6sphinx_6pycode_5pgen2_5parse_6Parser_push(struct __pyx_obj_6sphinx_6pycode_5pgen2_5parse_Parser *__pyx_v_self, PyObject *__pyx_v_type, PyObject *__pyx_v_newdfa, PyObject *__pyx_v_newstate, PyObject *__pyx_v_context) {
+  PyObject *__pyx_v_dfa;
+  PyObject *__pyx_v_state;
+  PyObject *__pyx_v_node;
+  PyObject *__pyx_v_newnode;
+  PyObject *__pyx_1 = 0;
+  PyObject *__pyx_2 = 0;
+  PyObject *__pyx_3 = 0;
+  __pyx_v_dfa = Py_None; Py_INCREF(Py_None);
+  __pyx_v_state = Py_None; Py_INCREF(Py_None);
+  __pyx_v_node = Py_None; Py_INCREF(Py_None);
+  __pyx_v_newnode = Py_None; Py_INCREF(Py_None);
+
+  /* "/home/gbr/devel/sphinx/sphinx/pycode/pgen2/parse.pyx":132
+ *     cdef void push(self, type, newdfa, newstate, context):
+ *         """Push a nonterminal.  (Internal)"""
+ *         dfa, state, node = self.stack[-1]             # <<<<<<<<<<<<<<
+ *         newnode = (type, None, context, [])
+ *         self.stack[-1] = (dfa, newstate, node)
+ */
+  __pyx_1 = __Pyx_GetItemInt(__pyx_v_self->stack, -1, 0); if (!__pyx_1) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 132; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  if (PyTuple_CheckExact(__pyx_1) && PyTuple_GET_SIZE(__pyx_1) == 3) {
+    PyObject* tuple = __pyx_1;
+    __pyx_3 = PyTuple_GET_ITEM(tuple, 0);
+    Py_INCREF(__pyx_3);
+    Py_DECREF(__pyx_v_dfa);
+    __pyx_v_dfa = __pyx_3;
+    __pyx_3 = 0;
+    __pyx_3 = PyTuple_GET_ITEM(tuple, 1);
+    Py_INCREF(__pyx_3);
+    Py_DECREF(__pyx_v_state);
+    __pyx_v_state = __pyx_3;
+    __pyx_3 = 0;
+    __pyx_3 = PyTuple_GET_ITEM(tuple, 2);
+    Py_INCREF(__pyx_3);
+    Py_DECREF(__pyx_v_node);
+    __pyx_v_node = __pyx_3;
+    __pyx_3 = 0;
+    Py_DECREF(__pyx_1); __pyx_1 = 0;
+  }
+  else {
+    __pyx_2 = PyObject_GetIter(__pyx_1); if (unlikely(!__pyx_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 132; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    Py_DECREF(__pyx_1); __pyx_1 = 0;
+    __pyx_3 = __Pyx_UnpackItem(__pyx_2, 0); if (unlikely(!__pyx_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 132; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    Py_DECREF(__pyx_v_dfa);
+    __pyx_v_dfa = __pyx_3;
+    __pyx_3 = 0;
+    __pyx_3 = __Pyx_UnpackItem(__pyx_2, 1); if (unlikely(!__pyx_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 132; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    Py_DECREF(__pyx_v_state);
+    __pyx_v_state = __pyx_3;
+    __pyx_3 = 0;
+    __pyx_3 = __Pyx_UnpackItem(__pyx_2, 2); if (unlikely(!__pyx_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 132; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    Py_DECREF(__pyx_v_node);
+    __pyx_v_node = __pyx_3;
+    __pyx_3 = 0;
+    if (__Pyx_EndUnpack(__pyx_2) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 132; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    Py_DECREF(__pyx_2); __pyx_2 = 0;
+  }
+
+  /* "/home/gbr/devel/sphinx/sphinx/pycode/pgen2/parse.pyx":133
+ *         """Push a nonterminal.  (Internal)"""
+ *         dfa, state, node = self.stack[-1]
+ *         newnode = (type, None, context, [])             # <<<<<<<<<<<<<<
+ *         self.stack[-1] = (dfa, newstate, node)
+ *         self.stack.append((newdfa, 0, newnode))
+ */
+  __pyx_3 = PyList_New(0); if (unlikely(!__pyx_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 133; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_1 = PyTuple_New(4); if (unlikely(!__pyx_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 133; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  Py_INCREF(__pyx_v_type);
+  PyTuple_SET_ITEM(__pyx_1, 0, __pyx_v_type);
+  Py_INCREF(Py_None);
+  PyTuple_SET_ITEM(__pyx_1, 1, Py_None);
+  Py_INCREF(__pyx_v_context);
+  PyTuple_SET_ITEM(__pyx_1, 2, __pyx_v_context);
+  PyTuple_SET_ITEM(__pyx_1, 3, ((PyObject *)__pyx_3));
+  __pyx_3 = 0;
+  Py_DECREF(__pyx_v_newnode);
+  __pyx_v_newnode = ((PyObject *)__pyx_1);
+  __pyx_1 = 0;
+
+  /* "/home/gbr/devel/sphinx/sphinx/pycode/pgen2/parse.pyx":134
+ *         dfa, state, node = self.stack[-1]
+ *         newnode = (type, None, context, [])
+ *         self.stack[-1] = (dfa, newstate, node)             # <<<<<<<<<<<<<<
+ *         self.stack.append((newdfa, 0, newnode))
+ * 
+ */
+  __pyx_2 = PyTuple_New(3); if (unlikely(!__pyx_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 134; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  Py_INCREF(__pyx_v_dfa);
+  PyTuple_SET_ITEM(__pyx_2, 0, __pyx_v_dfa);
+  Py_INCREF(__pyx_v_newstate);
+  PyTuple_SET_ITEM(__pyx_2, 1, __pyx_v_newstate);
+  Py_INCREF(__pyx_v_node);
+  PyTuple_SET_ITEM(__pyx_2, 2, __pyx_v_node);
+  if (__Pyx_SetItemInt(__pyx_v_self->stack, -1, ((PyObject *)__pyx_2), 0) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 134; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  Py_DECREF(((PyObject *)__pyx_2)); __pyx_2 = 0;
+
+  /* "/home/gbr/devel/sphinx/sphinx/pycode/pgen2/parse.pyx":135
+ *         newnode = (type, None, context, [])
+ *         self.stack[-1] = (dfa, newstate, node)
+ *         self.stack.append((newdfa, 0, newnode))             # <<<<<<<<<<<<<<
+ * 
+ *     cdef void pop(self):
+ */
+  __pyx_3 = PyTuple_New(3); if (unlikely(!__pyx_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 135; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  Py_INCREF(__pyx_v_newdfa);
+  PyTuple_SET_ITEM(__pyx_3, 0, __pyx_v_newdfa);
+  Py_INCREF(__pyx_int_0);
+  PyTuple_SET_ITEM(__pyx_3, 1, __pyx_int_0);
+  Py_INCREF(__pyx_v_newnode);
+  PyTuple_SET_ITEM(__pyx_3, 2, __pyx_v_newnode);
+  __pyx_1 = __Pyx_PyObject_Append(__pyx_v_self->stack, ((PyObject *)__pyx_3)); if (unlikely(!__pyx_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 135; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  Py_DECREF(((PyObject *)__pyx_3)); __pyx_3 = 0;
+  Py_DECREF(__pyx_1); __pyx_1 = 0;
+
+  goto __pyx_L0;
+  __pyx_L1_error:;
+  Py_XDECREF(__pyx_1);
+  Py_XDECREF(__pyx_2);
+  Py_XDECREF(__pyx_3);
+  __Pyx_WriteUnraisable("sphinx.pycode.pgen2.parse.Parser.push");
+  __pyx_L0:;
+  Py_DECREF(__pyx_v_dfa);
+  Py_DECREF(__pyx_v_state);
+  Py_DECREF(__pyx_v_node);
+  Py_DECREF(__pyx_v_newnode);
+}
+
+/* "/home/gbr/devel/sphinx/sphinx/pycode/pgen2/parse.pyx":137
+ *         self.stack.append((newdfa, 0, newnode))
+ * 
+ *     cdef void pop(self):             # <<<<<<<<<<<<<<
+ *         """Pop a nonterminal.  (Internal)"""
+ *         popdfa, popstate, popnode = self.stack.pop()
+ */
+
+static  void __pyx_f_6sphinx_6pycode_5pgen2_5parse_6Parser_pop(struct __pyx_obj_6sphinx_6pycode_5pgen2_5parse_Parser *__pyx_v_self) {
+  PyObject *__pyx_v_popdfa;
+  PyObject *__pyx_v_popstate;
+  PyObject *__pyx_v_popnode;
+  PyObject *__pyx_v_newnode;
+  PyObject *__pyx_v_dfa;
+  PyObject *__pyx_v_state;
+  PyObject *__pyx_v_node;
+  PyObject *__pyx_1 = 0;
+  PyObject *__pyx_2 = 0;
+  PyObject *__pyx_3 = 0;
+  int __pyx_4;
+  __pyx_v_popdfa = Py_None; Py_INCREF(Py_None);
+  __pyx_v_popstate = Py_None; Py_INCREF(Py_None);
+  __pyx_v_popnode = Py_None; Py_INCREF(Py_None);
+  __pyx_v_newnode = Py_None; Py_INCREF(Py_None);
+  __pyx_v_dfa = Py_None; Py_INCREF(Py_None);
+  __pyx_v_state = Py_None; Py_INCREF(Py_None);
+  __pyx_v_node = Py_None; Py_INCREF(Py_None);
+
+  /* "/home/gbr/devel/sphinx/sphinx/pycode/pgen2/parse.pyx":139
+ *     cdef void pop(self):
+ *         """Pop a nonterminal.  (Internal)"""
+ *         popdfa, popstate, popnode = self.stack.pop()             # <<<<<<<<<<<<<<
+ *         newnode = self.convert(popnode)
+ *         if newnode is not None:
+ */
+  __pyx_1 = PyObject_GetAttr(__pyx_v_self->stack, __pyx_kp_pop); if (unlikely(!__pyx_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 139; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_2 = PyObject_Call(__pyx_1, ((PyObject *)__pyx_empty_tuple), NULL); if (unlikely(!__pyx_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 139; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  Py_DECREF(__pyx_1); __pyx_1 = 0;
+  if (PyTuple_CheckExact(__pyx_2) && PyTuple_GET_SIZE(__pyx_2) == 3) {
+    PyObject* tuple = __pyx_2;
+    __pyx_3 = PyTuple_GET_ITEM(tuple, 0);
+    Py_INCREF(__pyx_3);
+    Py_DECREF(__pyx_v_popdfa);
+    __pyx_v_popdfa = __pyx_3;
+    __pyx_3 = 0;
+    __pyx_3 = PyTuple_GET_ITEM(tuple, 1);
+    Py_INCREF(__pyx_3);
+    Py_DECREF(__pyx_v_popstate);
+    __pyx_v_popstate = __pyx_3;
+    __pyx_3 = 0;
+    __pyx_3 = PyTuple_GET_ITEM(tuple, 2);
+    Py_INCREF(__pyx_3);
+    Py_DECREF(__pyx_v_popnode);
+    __pyx_v_popnode = __pyx_3;
+    __pyx_3 = 0;
+    Py_DECREF(__pyx_2); __pyx_2 = 0;
+  }
+  else {
+    __pyx_1 = PyObject_GetIter(__pyx_2); if (unlikely(!__pyx_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 139; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    Py_DECREF(__pyx_2); __pyx_2 = 0;
+    __pyx_3 = __Pyx_UnpackItem(__pyx_1, 0); if (unlikely(!__pyx_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 139; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    Py_DECREF(__pyx_v_popdfa);
+    __pyx_v_popdfa = __pyx_3;
+    __pyx_3 = 0;
+    __pyx_3 = __Pyx_UnpackItem(__pyx_1, 1); if (unlikely(!__pyx_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 139; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    Py_DECREF(__pyx_v_popstate);
+    __pyx_v_popstate = __pyx_3;
+    __pyx_3 = 0;
+    __pyx_3 = __Pyx_UnpackItem(__pyx_1, 2); if (unlikely(!__pyx_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 139; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    Py_DECREF(__pyx_v_popnode);
+    __pyx_v_popnode = __pyx_3;
+    __pyx_3 = 0;
+    if (__Pyx_EndUnpack(__pyx_1) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 139; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    Py_DECREF(__pyx_1); __pyx_1 = 0;
+  }
+
+  /* "/home/gbr/devel/sphinx/sphinx/pycode/pgen2/parse.pyx":140
+ *         """Pop a nonterminal.  (Internal)"""
+ *         popdfa, popstate, popnode = self.stack.pop()
+ *         newnode = self.convert(popnode)             # <<<<<<<<<<<<<<
+ *         if newnode is not None:
+ *             if self.stack:
+ */
+  __pyx_3 = ((struct __pyx_vtabstruct_6sphinx_6pycode_5pgen2_5parse_Parser *)__pyx_v_self->__pyx_vtab)->convert(__pyx_v_self, __pyx_v_popnode); if (unlikely(!__pyx_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 140; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  Py_DECREF(__pyx_v_newnode);
+  __pyx_v_newnode = __pyx_3;
+  __pyx_3 = 0;
+
+  /* "/home/gbr/devel/sphinx/sphinx/pycode/pgen2/parse.pyx":141
+ *         popdfa, popstate, popnode = self.stack.pop()
+ *         newnode = self.convert(popnode)
+ *         if newnode is not None:             # <<<<<<<<<<<<<<
+ *             if self.stack:
+ *                 dfa, state, node = self.stack[-1]
+ */
+  __pyx_4 = (__pyx_v_newnode != Py_None);
+  if (__pyx_4) {
+
+    /* "/home/gbr/devel/sphinx/sphinx/pycode/pgen2/parse.pyx":142
+ *         newnode = self.convert(popnode)
+ *         if newnode is not None:
+ *             if self.stack:             # <<<<<<<<<<<<<<
+ *                 dfa, state, node = self.stack[-1]
+ *                 node[-1].append(newnode)
+ */
+    __pyx_4 = __Pyx_PyObject_IsTrue(__pyx_v_self->stack); if (unlikely(__pyx_4 < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 142; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    if (__pyx_4) {
+
+      /* "/home/gbr/devel/sphinx/sphinx/pycode/pgen2/parse.pyx":143
+ *         if newnode is not None:
+ *             if self.stack:
+ *                 dfa, state, node = self.stack[-1]             # <<<<<<<<<<<<<<
+ *                 node[-1].append(newnode)
+ *             else:
+ */
+      __pyx_2 = __Pyx_GetItemInt(__pyx_v_self->stack, -1, 0); if (!__pyx_2) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 143; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      if (PyTuple_CheckExact(__pyx_2) && PyTuple_GET_SIZE(__pyx_2) == 3) {
+        PyObject* tuple = __pyx_2;
+        __pyx_3 = PyTuple_GET_ITEM(tuple, 0);
+        Py_INCREF(__pyx_3);
+        Py_DECREF(__pyx_v_dfa);
+        __pyx_v_dfa = __pyx_3;
+        __pyx_3 = 0;
+        __pyx_3 = PyTuple_GET_ITEM(tuple, 1);
+        Py_INCREF(__pyx_3);
+        Py_DECREF(__pyx_v_state);
+        __pyx_v_state = __pyx_3;
+        __pyx_3 = 0;
+        __pyx_3 = PyTuple_GET_ITEM(tuple, 2);
+        Py_INCREF(__pyx_3);
+        Py_DECREF(__pyx_v_node);
+        __pyx_v_node = __pyx_3;
+        __pyx_3 = 0;
+        Py_DECREF(__pyx_2); __pyx_2 = 0;
+      }
+      else {
+        __pyx_1 = PyObject_GetIter(__pyx_2); if (unlikely(!__pyx_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 143; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+        Py_DECREF(__pyx_2); __pyx_2 = 0;
+        __pyx_3 = __Pyx_UnpackItem(__pyx_1, 0); if (unlikely(!__pyx_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 143; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+        Py_DECREF(__pyx_v_dfa);
+        __pyx_v_dfa = __pyx_3;
+        __pyx_3 = 0;
+        __pyx_3 = __Pyx_UnpackItem(__pyx_1, 1); if (unlikely(!__pyx_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 143; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+        Py_DECREF(__pyx_v_state);
+        __pyx_v_state = __pyx_3;
+        __pyx_3 = 0;
+        __pyx_3 = __Pyx_UnpackItem(__pyx_1, 2); if (unlikely(!__pyx_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 143; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+        Py_DECREF(__pyx_v_node);
+        __pyx_v_node = __pyx_3;
+        __pyx_3 = 0;
+        if (__Pyx_EndUnpack(__pyx_1) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 143; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+        Py_DECREF(__pyx_1); __pyx_1 = 0;
+      }
+
+      /* "/home/gbr/devel/sphinx/sphinx/pycode/pgen2/parse.pyx":144
+ *             if self.stack:
+ *                 dfa, state, node = self.stack[-1]
+ *                 node[-1].append(newnode)             # <<<<<<<<<<<<<<
+ *             else:
+ *                 self.rootnode = newnode
+ */
+      __pyx_3 = __Pyx_GetItemInt(__pyx_v_node, -1, 0); if (!__pyx_3) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 144; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_2 = __Pyx_PyObject_Append(__pyx_3, __pyx_v_newnode); if (unlikely(!__pyx_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 144; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      Py_DECREF(__pyx_3); __pyx_3 = 0;
+      Py_DECREF(__pyx_2); __pyx_2 = 0;
+      goto __pyx_L4;
+    }
+    /*else*/ {
+
+      /* "/home/gbr/devel/sphinx/sphinx/pycode/pgen2/parse.pyx":146
+ *                 node[-1].append(newnode)
+ *             else:
+ *                 self.rootnode = newnode             # <<<<<<<<<<<<<<
+ *                 self.rootnode.used_names = self.used_names
+ * 
+ */
+      Py_INCREF(__pyx_v_newnode);
+      Py_DECREF(__pyx_v_self->rootnode);
+      __pyx_v_self->rootnode = __pyx_v_newnode;
+
+      /* "/home/gbr/devel/sphinx/sphinx/pycode/pgen2/parse.pyx":147
+ *             else:
+ *                 self.rootnode = newnode
+ *                 self.rootnode.used_names = self.used_names             # <<<<<<<<<<<<<<
+ * 
+ *     cdef convert(self, raw_node):
+ */
+      if (PyObject_SetAttr(__pyx_v_self->rootnode, __pyx_kp_used_names, __pyx_v_self->used_names) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 147; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    }
+    __pyx_L4:;
+    goto __pyx_L3;
+  }
+  __pyx_L3:;
+
+  goto __pyx_L0;
+  __pyx_L1_error:;
+  Py_XDECREF(__pyx_1);
+  Py_XDECREF(__pyx_2);
+  Py_XDECREF(__pyx_3);
+  __Pyx_WriteUnraisable("sphinx.pycode.pgen2.parse.Parser.pop");
+  __pyx_L0:;
+  Py_DECREF(__pyx_v_popdfa);
+  Py_DECREF(__pyx_v_popstate);
+  Py_DECREF(__pyx_v_popnode);
+  Py_DECREF(__pyx_v_newnode);
+  Py_DECREF(__pyx_v_dfa);
+  Py_DECREF(__pyx_v_state);
+  Py_DECREF(__pyx_v_node);
+}
+
+/* "/home/gbr/devel/sphinx/sphinx/pycode/pgen2/parse.pyx":149
+ *                 self.rootnode.used_names = self.used_names
+ * 
+ *     cdef convert(self, raw_node):             # <<<<<<<<<<<<<<
+ *         type, value, context, children = raw_node
+ *         if children or type in self._grammar_number2symbol:
+ */
+
+static  PyObject *__pyx_f_6sphinx_6pycode_5pgen2_5parse_6Parser_convert(struct __pyx_obj_6sphinx_6pycode_5pgen2_5parse_Parser *__pyx_v_self, PyObject *__pyx_v_raw_node) {
+  PyObject *__pyx_v_type;
+  PyObject *__pyx_v_value;
+  PyObject *__pyx_v_context;
+  PyObject *__pyx_v_children;
+  PyObject *__pyx_r;
+  PyObject *__pyx_1 = 0;
+  PyObject *__pyx_2 = 0;
+  int __pyx_3;
+  Py_ssize_t __pyx_4 = 0;
+  PyObject *__pyx_5 = 0;
+  PyObject *__pyx_6 = 0;
+  __pyx_v_type = Py_None; Py_INCREF(Py_None);
+  __pyx_v_value = Py_None; Py_INCREF(Py_None);
+  __pyx_v_context = Py_None; Py_INCREF(Py_None);
+  __pyx_v_children = Py_None; Py_INCREF(Py_None);
+
+  /* "/home/gbr/devel/sphinx/sphinx/pycode/pgen2/parse.pyx":150
+ * 
+ *     cdef convert(self, raw_node):
+ *         type, value, context, children = raw_node             # <<<<<<<<<<<<<<
+ *         if children or type in self._grammar_number2symbol:
+ *             # If there's exactly one child, return that child instead of
+ */
+  if (PyTuple_CheckExact(__pyx_v_raw_node) && PyTuple_GET_SIZE(__pyx_v_raw_node) == 4) {
+    PyObject* tuple = __pyx_v_raw_node;
+    __pyx_2 = PyTuple_GET_ITEM(tuple, 0);
+    Py_INCREF(__pyx_2);
+    Py_DECREF(__pyx_v_type);
+    __pyx_v_type = __pyx_2;
+    __pyx_2 = 0;
+    __pyx_2 = PyTuple_GET_ITEM(tuple, 1);
+    Py_INCREF(__pyx_2);
+    Py_DECREF(__pyx_v_value);
+    __pyx_v_value = __pyx_2;
+    __pyx_2 = 0;
+    __pyx_2 = PyTuple_GET_ITEM(tuple, 2);
+    Py_INCREF(__pyx_2);
+    Py_DECREF(__pyx_v_context);
+    __pyx_v_context = __pyx_2;
+    __pyx_2 = 0;
+    __pyx_2 = PyTuple_GET_ITEM(tuple, 3);
+    Py_INCREF(__pyx_2);
+    Py_DECREF(__pyx_v_children);
+    __pyx_v_children = __pyx_2;
+    __pyx_2 = 0;
+  }
+  else {
+    __pyx_1 = PyObject_GetIter(__pyx_v_raw_node); if (unlikely(!__pyx_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 150; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_2 = __Pyx_UnpackItem(__pyx_1, 0); if (unlikely(!__pyx_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 150; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    Py_DECREF(__pyx_v_type);
+    __pyx_v_type = __pyx_2;
+    __pyx_2 = 0;
+    __pyx_2 = __Pyx_UnpackItem(__pyx_1, 1); if (unlikely(!__pyx_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 150; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    Py_DECREF(__pyx_v_value);
+    __pyx_v_value = __pyx_2;
+    __pyx_2 = 0;
+    __pyx_2 = __Pyx_UnpackItem(__pyx_1, 2); if (unlikely(!__pyx_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 150; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    Py_DECREF(__pyx_v_context);
+    __pyx_v_context = __pyx_2;
+    __pyx_2 = 0;
+    __pyx_2 = __Pyx_UnpackItem(__pyx_1, 3); if (unlikely(!__pyx_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 150; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    Py_DECREF(__pyx_v_children);
+    __pyx_v_children = __pyx_2;
+    __pyx_2 = 0;
+    if (__Pyx_EndUnpack(__pyx_1) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 150; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    Py_DECREF(__pyx_1); __pyx_1 = 0;
+  }
+
+  /* "/home/gbr/devel/sphinx/sphinx/pycode/pgen2/parse.pyx":151
+ *     cdef convert(self, raw_node):
+ *         type, value, context, children = raw_node
+ *         if children or type in self._grammar_number2symbol:             # <<<<<<<<<<<<<<
+ *             # If there's exactly one child, return that child instead of
+ *             # creating a new node.
+ */
+  __pyx_2 = __pyx_v_children;
+  Py_INCREF(__pyx_2);
+  __pyx_3 = __Pyx_PyObject_IsTrue(__pyx_2); if (unlikely(__pyx_3 < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 151; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  if (!__pyx_3) {
+    Py_DECREF(__pyx_2); __pyx_2 = 0;
+    __pyx_3 = (PySequence_Contains(__pyx_v_self->_grammar_number2symbol, __pyx_v_type)); if (unlikely(__pyx_3 < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 151; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_2 = __Pyx_PyBool_FromLong(__pyx_3); if (unlikely(!__pyx_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 151; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  }
+  __pyx_3 = __Pyx_PyObject_IsTrue(__pyx_2); if (unlikely(__pyx_3 < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 151; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  Py_DECREF(__pyx_2); __pyx_2 = 0;
+  if (__pyx_3) {
+
+    /* "/home/gbr/devel/sphinx/sphinx/pycode/pgen2/parse.pyx":154
+ *             # If there's exactly one child, return that child instead of
+ *             # creating a new node.
+ *             if len(children) == 1:             # <<<<<<<<<<<<<<
+ *                 return children[0]
+ *             return Node(type, children, context=context)
+ */
+    __pyx_4 = PyObject_Length(__pyx_v_children); if (unlikely(__pyx_4 == -1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 154; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_3 = (__pyx_4 == 1);
+    if (__pyx_3) {
+
+      /* "/home/gbr/devel/sphinx/sphinx/pycode/pgen2/parse.pyx":155
+ *             # creating a new node.
+ *             if len(children) == 1:
+ *                 return children[0]             # <<<<<<<<<<<<<<
+ *             return Node(type, children, context=context)
+ *         else:
+ */
+      __pyx_1 = __Pyx_GetItemInt(__pyx_v_children, 0, 0); if (!__pyx_1) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 155; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_r = __pyx_1;
+      __pyx_1 = 0;
+      goto __pyx_L0;
+      goto __pyx_L4;
+    }
+    __pyx_L4:;
+
+    /* "/home/gbr/devel/sphinx/sphinx/pycode/pgen2/parse.pyx":156
+ *             if len(children) == 1:
+ *                 return children[0]
+ *             return Node(type, children, context=context)             # <<<<<<<<<<<<<<
+ *         else:
+ *             return Leaf(type, value, context=context)
+ */
+    __pyx_2 = __Pyx_GetName(__pyx_m, __pyx_kp_Node); if (unlikely(!__pyx_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 156; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_1 = PyTuple_New(2); if (unlikely(!__pyx_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 156; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    Py_INCREF(__pyx_v_type);
+    PyTuple_SET_ITEM(__pyx_1, 0, __pyx_v_type);
+    Py_INCREF(__pyx_v_children);
+    PyTuple_SET_ITEM(__pyx_1, 1, __pyx_v_children);
+    __pyx_5 = PyDict_New(); if (unlikely(!__pyx_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 156; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    if (PyDict_SetItem(__pyx_5, __pyx_kp_context, __pyx_v_context) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 156; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_6 = PyEval_CallObjectWithKeywords(__pyx_2, ((PyObject *)__pyx_1), ((PyObject *)__pyx_5)); if (unlikely(!__pyx_6)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 156; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    Py_DECREF(__pyx_2); __pyx_2 = 0;
+    Py_DECREF(((PyObject *)__pyx_1)); __pyx_1 = 0;
+    Py_DECREF(((PyObject *)__pyx_5)); __pyx_5 = 0;
+    __pyx_r = __pyx_6;
+    __pyx_6 = 0;
+    goto __pyx_L0;
+    goto __pyx_L3;
+  }
+  /*else*/ {
+
+    /* "/home/gbr/devel/sphinx/sphinx/pycode/pgen2/parse.pyx":158
+ *             return Node(type, children, context=context)
+ *         else:
+ *             return Leaf(type, value, context=context)             # <<<<<<<<<<<<<<
+ */
+    __pyx_2 = __Pyx_GetName(__pyx_m, __pyx_kp_Leaf); if (unlikely(!__pyx_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 158; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_1 = PyTuple_New(2); if (unlikely(!__pyx_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 158; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    Py_INCREF(__pyx_v_type);
+    PyTuple_SET_ITEM(__pyx_1, 0, __pyx_v_type);
+    Py_INCREF(__pyx_v_value);
+    PyTuple_SET_ITEM(__pyx_1, 1, __pyx_v_value);
+    __pyx_5 = PyDict_New(); if (unlikely(!__pyx_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 158; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    if (PyDict_SetItem(__pyx_5, __pyx_kp_context, __pyx_v_context) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 158; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_6 = PyEval_CallObjectWithKeywords(__pyx_2, ((PyObject *)__pyx_1), ((PyObject *)__pyx_5)); if (unlikely(!__pyx_6)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 158; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    Py_DECREF(__pyx_2); __pyx_2 = 0;
+    Py_DECREF(((PyObject *)__pyx_1)); __pyx_1 = 0;
+    Py_DECREF(((PyObject *)__pyx_5)); __pyx_5 = 0;
+    __pyx_r = __pyx_6;
+    __pyx_6 = 0;
+    goto __pyx_L0;
+  }
+  __pyx_L3:;
+
+  __pyx_r = Py_None; Py_INCREF(Py_None);
+  goto __pyx_L0;
+  __pyx_L1_error:;
+  Py_XDECREF(__pyx_1);
+  Py_XDECREF(__pyx_2);
+  Py_XDECREF(__pyx_5);
+  Py_XDECREF(__pyx_6);
+  __Pyx_AddTraceback("sphinx.pycode.pgen2.parse.Parser.convert");
+  __pyx_r = 0;
+  __pyx_L0:;
+  Py_DECREF(__pyx_v_type);
+  Py_DECREF(__pyx_v_value);
+  Py_DECREF(__pyx_v_context);
+  Py_DECREF(__pyx_v_children);
+  return __pyx_r;
+}
+static struct __pyx_vtabstruct_6sphinx_6pycode_5pgen2_5parse_Parser __pyx_vtable_6sphinx_6pycode_5pgen2_5parse_Parser;
+
+static PyObject *__pyx_tp_new_6sphinx_6pycode_5pgen2_5parse_Parser(PyTypeObject *t, PyObject *a, PyObject *k) {
+  struct __pyx_obj_6sphinx_6pycode_5pgen2_5parse_Parser *p;
+  PyObject *o = (*t->tp_alloc)(t, 0);
+  if (!o) return 0;
+  p = ((struct __pyx_obj_6sphinx_6pycode_5pgen2_5parse_Parser *)o);
+  p->__pyx_vtab = __pyx_vtabptr_6sphinx_6pycode_5pgen2_5parse_Parser;
+  p->grammar = Py_None; Py_INCREF(Py_None);
+  p->stack = Py_None; Py_INCREF(Py_None);
+  p->rootnode = Py_None; Py_INCREF(Py_None);
+  p->used_names = Py_None; Py_INCREF(Py_None);
+  p->_grammar_dfas = Py_None; Py_INCREF(Py_None);
+  p->_grammar_labels = Py_None; Py_INCREF(Py_None);
+  p->_grammar_keywords = Py_None; Py_INCREF(Py_None);
+  p->_grammar_tokens = Py_None; Py_INCREF(Py_None);
+  p->_grammar_number2symbol = Py_None; Py_INCREF(Py_None);
+  return o;
+}
+
+static void __pyx_tp_dealloc_6sphinx_6pycode_5pgen2_5parse_Parser(PyObject *o) {
+  struct __pyx_obj_6sphinx_6pycode_5pgen2_5parse_Parser *p = (struct __pyx_obj_6sphinx_6pycode_5pgen2_5parse_Parser *)o;
+  Py_XDECREF(p->grammar);
+  Py_XDECREF(p->stack);
+  Py_XDECREF(p->rootnode);
+  Py_XDECREF(p->used_names);
+  Py_XDECREF(p->_grammar_dfas);
+  Py_XDECREF(p->_grammar_labels);
+  Py_XDECREF(p->_grammar_keywords);
+  Py_XDECREF(p->_grammar_tokens);
+  Py_XDECREF(p->_grammar_number2symbol);
+  (*Py_TYPE(o)->tp_free)(o);
+}
+
+static int __pyx_tp_traverse_6sphinx_6pycode_5pgen2_5parse_Parser(PyObject *o, visitproc v, void *a) {
+  int e;
+  struct __pyx_obj_6sphinx_6pycode_5pgen2_5parse_Parser *p = (struct __pyx_obj_6sphinx_6pycode_5pgen2_5parse_Parser *)o;
+  if (p->grammar) {
+    e = (*v)(p->grammar, a); if (e) return e;
+  }
+  if (p->stack) {
+    e = (*v)(p->stack, a); if (e) return e;
+  }
+  if (p->rootnode) {
+    e = (*v)(p->rootnode, a); if (e) return e;
+  }
+  if (p->used_names) {
+    e = (*v)(p->used_names, a); if (e) return e;
+  }
+  if (p->_grammar_dfas) {
+    e = (*v)(p->_grammar_dfas, a); if (e) return e;
+  }
+  if (p->_grammar_labels) {
+    e = (*v)(p->_grammar_labels, a); if (e) return e;
+  }
+  if (p->_grammar_keywords) {
+    e = (*v)(p->_grammar_keywords, a); if (e) return e;
+  }
+  if (p->_grammar_tokens) {
+    e = (*v)(p->_grammar_tokens, a); if (e) return e;
+  }
+  if (p->_grammar_number2symbol) {
+    e = (*v)(p->_grammar_number2symbol, a); if (e) return e;
+  }
+  return 0;
+}
+
+static int __pyx_tp_clear_6sphinx_6pycode_5pgen2_5parse_Parser(PyObject *o) {
+  struct __pyx_obj_6sphinx_6pycode_5pgen2_5parse_Parser *p = (struct __pyx_obj_6sphinx_6pycode_5pgen2_5parse_Parser *)o;
+  PyObject* tmp;
+  tmp = ((PyObject*)p->grammar);
+  p->grammar = Py_None; Py_INCREF(Py_None);
+  Py_XDECREF(tmp);
+  tmp = ((PyObject*)p->stack);
+  p->stack = Py_None; Py_INCREF(Py_None);
+  Py_XDECREF(tmp);
+  tmp = ((PyObject*)p->rootnode);
+  p->rootnode = Py_None; Py_INCREF(Py_None);
+  Py_XDECREF(tmp);
+  tmp = ((PyObject*)p->used_names);
+  p->used_names = Py_None; Py_INCREF(Py_None);
+  Py_XDECREF(tmp);
+  tmp = ((PyObject*)p->_grammar_dfas);
+  p->_grammar_dfas = Py_None; Py_INCREF(Py_None);
+  Py_XDECREF(tmp);
+  tmp = ((PyObject*)p->_grammar_labels);
+  p->_grammar_labels = Py_None; Py_INCREF(Py_None);
+  Py_XDECREF(tmp);
+  tmp = ((PyObject*)p->_grammar_keywords);
+  p->_grammar_keywords = Py_None; Py_INCREF(Py_None);
+  Py_XDECREF(tmp);
+  tmp = ((PyObject*)p->_grammar_tokens);
+  p->_grammar_tokens = Py_None; Py_INCREF(Py_None);
+  Py_XDECREF(tmp);
+  tmp = ((PyObject*)p->_grammar_number2symbol);
+  p->_grammar_number2symbol = Py_None; Py_INCREF(Py_None);
+  Py_XDECREF(tmp);
+  return 0;
+}
+
+static struct PyMethodDef __pyx_methods_6sphinx_6pycode_5pgen2_5parse_Parser[] = {
+  {"setup", (PyCFunction)__pyx_pf_6sphinx_6pycode_5pgen2_5parse_6Parser_setup, METH_VARARGS|METH_KEYWORDS, 0},
+  {"addtoken", (PyCFunction)__pyx_pf_6sphinx_6pycode_5pgen2_5parse_6Parser_addtoken, METH_VARARGS|METH_KEYWORDS, __pyx_doc_6sphinx_6pycode_5pgen2_5parse_6Parser_addtoken},
+  {0, 0, 0, 0}
+};
+
+static struct PyMemberDef __pyx_members_6sphinx_6pycode_5pgen2_5parse_Parser[] = {
+  {"grammar", T_OBJECT, offsetof(struct __pyx_obj_6sphinx_6pycode_5pgen2_5parse_Parser, grammar), 0, 0},
+  {"stack", T_OBJECT, offsetof(struct __pyx_obj_6sphinx_6pycode_5pgen2_5parse_Parser, stack), 0, 0},
+  {"rootnode", T_OBJECT, offsetof(struct __pyx_obj_6sphinx_6pycode_5pgen2_5parse_Parser, rootnode), 0, 0},
+  {"used_names", T_OBJECT, offsetof(struct __pyx_obj_6sphinx_6pycode_5pgen2_5parse_Parser, used_names), 0, 0},
+  {0, 0, 0, 0, 0}
+};
+
+static PyNumberMethods __pyx_tp_as_number_Parser = {
+  0, /*nb_add*/
+  0, /*nb_subtract*/
+  0, /*nb_multiply*/
+  #if PY_MAJOR_VERSION < 3
+  0, /*nb_divide*/
+  #endif
+  0, /*nb_remainder*/
+  0, /*nb_divmod*/
+  0, /*nb_power*/
+  0, /*nb_negative*/
+  0, /*nb_positive*/
+  0, /*nb_absolute*/
+  0, /*nb_nonzero*/
+  0, /*nb_invert*/
+  0, /*nb_lshift*/
+  0, /*nb_rshift*/
+  0, /*nb_and*/
+  0, /*nb_xor*/
+  0, /*nb_or*/
+  #if PY_MAJOR_VERSION < 3
+  0, /*nb_coerce*/
+  #endif
+  0, /*nb_int*/
+  0, /*nb_long*/
+  0, /*nb_float*/
+  #if PY_MAJOR_VERSION < 3
+  0, /*nb_oct*/
+  #endif
+  #if PY_MAJOR_VERSION < 3
+  0, /*nb_hex*/
+  #endif
+  0, /*nb_inplace_add*/
+  0, /*nb_inplace_subtract*/
+  0, /*nb_inplace_multiply*/
+  #if PY_MAJOR_VERSION < 3
+  0, /*nb_inplace_divide*/
+  #endif
+  0, /*nb_inplace_remainder*/
+  0, /*nb_inplace_power*/
+  0, /*nb_inplace_lshift*/
+  0, /*nb_inplace_rshift*/
+  0, /*nb_inplace_and*/
+  0, /*nb_inplace_xor*/
+  0, /*nb_inplace_or*/
+  0, /*nb_floor_divide*/
+  0, /*nb_true_divide*/
+  0, /*nb_inplace_floor_divide*/
+  0, /*nb_inplace_true_divide*/
+  #if (PY_MAJOR_VERSION >= 3) || (Py_TPFLAGS_DEFAULT & Py_TPFLAGS_HAVE_INDEX)
+  0, /*nb_index*/
+  #endif
+};
+
+static PySequenceMethods __pyx_tp_as_sequence_Parser = {
+  0, /*sq_length*/
+  0, /*sq_concat*/
+  0, /*sq_repeat*/
+  0, /*sq_item*/
+  0, /*sq_slice*/
+  0, /*sq_ass_item*/
+  0, /*sq_ass_slice*/
+  0, /*sq_contains*/
+  0, /*sq_inplace_concat*/
+  0, /*sq_inplace_repeat*/
+};
+
+static PyMappingMethods __pyx_tp_as_mapping_Parser = {
+  0, /*mp_length*/
+  0, /*mp_subscript*/
+  0, /*mp_ass_subscript*/
+};
+
+static PyBufferProcs __pyx_tp_as_buffer_Parser = {
+  #if PY_MAJOR_VERSION < 3
+  0, /*bf_getreadbuffer*/
+  #endif
+  #if PY_MAJOR_VERSION < 3
+  0, /*bf_getwritebuffer*/
+  #endif
+  #if PY_MAJOR_VERSION < 3
+  0, /*bf_getsegcount*/
+  #endif
+  #if PY_MAJOR_VERSION < 3
+  0, /*bf_getcharbuffer*/
+  #endif
+  #if (PY_MAJOR_VERSION >= 3) || (Py_TPFLAGS_DEFAULT & Py_TPFLAGS_HAVE_NEWBUFFER)
+  0, /*bf_getbuffer*/
+  #endif
+  #if (PY_MAJOR_VERSION >= 3) || (Py_TPFLAGS_DEFAULT & Py_TPFLAGS_HAVE_NEWBUFFER)
+  0, /*bf_releasebuffer*/
+  #endif
+};
+
+PyTypeObject __pyx_type_6sphinx_6pycode_5pgen2_5parse_Parser = {
+  PyVarObject_HEAD_INIT(0, 0)
+  "sphinx.pycode.pgen2.parse.Parser", /*tp_name*/
+  sizeof(struct __pyx_obj_6sphinx_6pycode_5pgen2_5parse_Parser), /*tp_basicsize*/
+  0, /*tp_itemsize*/
+  __pyx_tp_dealloc_6sphinx_6pycode_5pgen2_5parse_Parser, /*tp_dealloc*/
+  0, /*tp_print*/
+  0, /*tp_getattr*/
+  0, /*tp_setattr*/
+  0, /*tp_compare*/
+  0, /*tp_repr*/
+  &__pyx_tp_as_number_Parser, /*tp_as_number*/
+  &__pyx_tp_as_sequence_Parser, /*tp_as_sequence*/
+  &__pyx_tp_as_mapping_Parser, /*tp_as_mapping*/
+  0, /*tp_hash*/
+  0, /*tp_call*/
+  0, /*tp_str*/
+  0, /*tp_getattro*/
+  0, /*tp_setattro*/
+  &__pyx_tp_as_buffer_Parser, /*tp_as_buffer*/
+  Py_TPFLAGS_DEFAULT|Py_TPFLAGS_CHECKTYPES|Py_TPFLAGS_BASETYPE|Py_TPFLAGS_HAVE_GC, /*tp_flags*/
+  0, /*tp_doc*/
+  __pyx_tp_traverse_6sphinx_6pycode_5pgen2_5parse_Parser, /*tp_traverse*/
+  __pyx_tp_clear_6sphinx_6pycode_5pgen2_5parse_Parser, /*tp_clear*/
+  0, /*tp_richcompare*/
+  0, /*tp_weaklistoffset*/
+  0, /*tp_iter*/
+  0, /*tp_iternext*/
+  __pyx_methods_6sphinx_6pycode_5pgen2_5parse_Parser, /*tp_methods*/
+  __pyx_members_6sphinx_6pycode_5pgen2_5parse_Parser, /*tp_members*/
+  0, /*tp_getset*/
+  0, /*tp_base*/
+  0, /*tp_dict*/
+  0, /*tp_descr_get*/
+  0, /*tp_descr_set*/
+  0, /*tp_dictoffset*/
+  __pyx_pf_6sphinx_6pycode_5pgen2_5parse_6Parser___init__, /*tp_init*/
+  0, /*tp_alloc*/
+  __pyx_tp_new_6sphinx_6pycode_5pgen2_5parse_Parser, /*tp_new*/
+  0, /*tp_free*/
+  0, /*tp_is_gc*/
+  0, /*tp_bases*/
+  0, /*tp_mro*/
+  0, /*tp_cache*/
+  0, /*tp_subclasses*/
+  0, /*tp_weaklist*/
+};
+
+static struct PyMethodDef __pyx_methods[] = {
+  {0, 0, 0, 0}
+};
+
+static void __pyx_init_filenames(void); /*proto*/
+
+#if PY_MAJOR_VERSION >= 3
+static struct PyModuleDef __pyx_moduledef = {
+    PyModuleDef_HEAD_INIT,
+    "parse",
+    0, /* m_doc */
+    -1, /* m_size */
+    __pyx_methods /* m_methods */,
+    NULL, /* m_reload */
+    NULL, /* m_traverse */
+    NULL, /* m_clear */
+    NULL /* m_free */
+};
+#endif
+
+static __Pyx_StringTabEntry __pyx_string_tab[] = {
+  {&__pyx_kp___init__, __pyx_k___init__, sizeof(__pyx_k___init__), 0, 1, 1},
+  {&__pyx_kp_setup, __pyx_k_setup, sizeof(__pyx_k_setup), 0, 1, 1},
+  {&__pyx_kp_addtoken, __pyx_k_addtoken, sizeof(__pyx_k_addtoken), 0, 1, 1},
+  {&__pyx_kp_1, __pyx_k_1, sizeof(__pyx_k_1), 1, 1, 1},
+  {&__pyx_kp_Node, __pyx_k_Node, sizeof(__pyx_k_Node), 1, 1, 1},
+  {&__pyx_kp_Leaf, __pyx_k_Leaf, sizeof(__pyx_k_Leaf), 1, 1, 1},
+  {&__pyx_kp_ParseError, __pyx_k_ParseError, sizeof(__pyx_k_ParseError), 0, 1, 1},
+  {&__pyx_kp_Exception, __pyx_k_Exception, sizeof(__pyx_k_Exception), 1, 1, 1},
+  {&__pyx_kp_msg, __pyx_k_msg, sizeof(__pyx_k_msg), 1, 1, 1},
+  {&__pyx_kp_type, __pyx_k_type, sizeof(__pyx_k_type), 1, 1, 1},
+  {&__pyx_kp_value, __pyx_k_value, sizeof(__pyx_k_value), 1, 1, 1},
+  {&__pyx_kp_context, __pyx_k_context, sizeof(__pyx_k_context), 1, 1, 1},
+  {&__pyx_kp_dfas, __pyx_k_dfas, sizeof(__pyx_k_dfas), 1, 1, 1},
+  {&__pyx_kp_labels, __pyx_k_labels, sizeof(__pyx_k_labels), 1, 1, 1},
+  {&__pyx_kp_keywords, __pyx_k_keywords, sizeof(__pyx_k_keywords), 1, 1, 1},
+  {&__pyx_kp_tokens, __pyx_k_tokens, sizeof(__pyx_k_tokens), 1, 1, 1},
+  {&__pyx_kp_4, __pyx_k_4, sizeof(__pyx_k_4), 1, 1, 1},
+  {&__pyx_kp_start, __pyx_k_start, sizeof(__pyx_k_start), 1, 1, 1},
+  {&__pyx_kp_add, __pyx_k_add, sizeof(__pyx_k_add), 1, 1, 1},
+  {&__pyx_kp_get, __pyx_k_get, sizeof(__pyx_k_get), 1, 1, 1},
+  {&__pyx_kp_append, __pyx_k_append, sizeof(__pyx_k_append), 1, 1, 1},
+  {&__pyx_kp_pop, __pyx_k_pop, sizeof(__pyx_k_pop), 1, 1, 1},
+  {&__pyx_kp_used_names, __pyx_k_used_names, sizeof(__pyx_k_used_names), 1, 1, 1},
+  {&__pyx_kp_2, __pyx_k_2, sizeof(__pyx_k_2), 0, 0, 0},
+  {&__pyx_kp_3, __pyx_k_3, sizeof(__pyx_k_3), 0, 0, 0},
+  {&__pyx_kp_5, __pyx_k_5, sizeof(__pyx_k_5), 0, 0, 0},
+  {&__pyx_kp_6, __pyx_k_6, sizeof(__pyx_k_6), 0, 0, 0},
+  {&__pyx_kp_7, __pyx_k_7, sizeof(__pyx_k_7), 0, 0, 0},
+  {0, 0, 0, 0, 0, 0}
+};
+static int __Pyx_InitCachedBuiltins(void) {
+  __pyx_builtin_Exception = __Pyx_GetName(__pyx_b, __pyx_kp_Exception); if (!__pyx_builtin_Exception) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 19; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  return 0;
+  __pyx_L1_error:;
+  return -1;
+}
+
+static int __Pyx_InitGlobals(void) {
+  __pyx_int_0 = PyInt_FromLong(0); if (unlikely(!__pyx_int_0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;};
+  __pyx_int_1 = PyInt_FromLong(1); if (unlikely(!__pyx_int_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;};
+  if (__Pyx_InitStrings(__pyx_string_tab) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;};
+  return 0;
+  __pyx_L1_error:;
+  return -1;
+}
+
+#if PY_MAJOR_VERSION < 3
+PyMODINIT_FUNC initparse(void); /*proto*/
+PyMODINIT_FUNC initparse(void)
+#else
+PyMODINIT_FUNC PyInit_parse(void); /*proto*/
+PyMODINIT_FUNC PyInit_parse(void)
+#endif
+{
+  PyObject *__pyx_1 = 0;
+  PyObject *__pyx_2 = 0;
+  PyObject *__pyx_3 = 0;
+  PyObject *__pyx_4 = 0;
+  __pyx_empty_tuple = PyTuple_New(0); if (unlikely(!__pyx_empty_tuple)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  /*--- Libary function declarations ---*/
+  __pyx_init_filenames();
+  /*--- Initialize various global constants etc. ---*/
+  if (unlikely(__Pyx_InitGlobals() < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  /*--- Module creation code ---*/
+  #if PY_MAJOR_VERSION < 3
+  __pyx_m = Py_InitModule4("parse", __pyx_methods, 0, 0, PYTHON_API_VERSION);
+  #else
+  __pyx_m = PyModule_Create(&__pyx_moduledef);
+  #endif
+  if (!__pyx_m) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;};
+  #if PY_MAJOR_VERSION < 3
+  Py_INCREF(__pyx_m);
+  #endif
+  __pyx_b = PyImport_AddModule(__Pyx_BUILTIN_MODULE_NAME);
+  if (!__pyx_b) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;};
+  if (PyObject_SetAttrString(__pyx_m, "__builtins__", __pyx_b) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;};
+  /*--- Builtin init code ---*/
+  if (unlikely(__Pyx_InitCachedBuiltins() < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_skip_dispatch = 0;
+  /*--- Global init code ---*/
+  /*--- Function export code ---*/
+  /*--- Type init code ---*/
+  __pyx_vtabptr_6sphinx_6pycode_5pgen2_5parse_Parser = &__pyx_vtable_6sphinx_6pycode_5pgen2_5parse_Parser;
+  *(void(**)(void))&__pyx_vtable_6sphinx_6pycode_5pgen2_5parse_Parser.classify = (void(*)(void))__pyx_f_6sphinx_6pycode_5pgen2_5parse_6Parser_classify;
+  *(void(**)(void))&__pyx_vtable_6sphinx_6pycode_5pgen2_5parse_Parser.shift = (void(*)(void))__pyx_f_6sphinx_6pycode_5pgen2_5parse_6Parser_shift;
+  *(void(**)(void))&__pyx_vtable_6sphinx_6pycode_5pgen2_5parse_Parser.push = (void(*)(void))__pyx_f_6sphinx_6pycode_5pgen2_5parse_6Parser_push;
+  *(void(**)(void))&__pyx_vtable_6sphinx_6pycode_5pgen2_5parse_Parser.pop = (void(*)(void))__pyx_f_6sphinx_6pycode_5pgen2_5parse_6Parser_pop;
+  *(void(**)(void))&__pyx_vtable_6sphinx_6pycode_5pgen2_5parse_Parser.convert = (void(*)(void))__pyx_f_6sphinx_6pycode_5pgen2_5parse_6Parser_convert;
+  if (PyType_Ready(&__pyx_type_6sphinx_6pycode_5pgen2_5parse_Parser) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 31; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  if (__Pyx_SetVtable(__pyx_type_6sphinx_6pycode_5pgen2_5parse_Parser.tp_dict, __pyx_vtabptr_6sphinx_6pycode_5pgen2_5parse_Parser) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 31; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  if (PyObject_SetAttrString(__pyx_m, "Parser", (PyObject *)&__pyx_type_6sphinx_6pycode_5pgen2_5parse_Parser) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 31; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_ptype_6sphinx_6pycode_5pgen2_5parse_Parser = &__pyx_type_6sphinx_6pycode_5pgen2_5parse_Parser;
+  /*--- Type import code ---*/
+  /*--- Function import code ---*/
+  /*--- Execution code ---*/
+
+  /* "/home/gbr/devel/sphinx/sphinx/pycode/pgen2/parse.pyx":15
+ * """
+ * 
+ * from sphinx.pycode.nodes import Node, Leaf             # <<<<<<<<<<<<<<
+ * 
+ * DEF NAME = 1
+ */
+  __pyx_1 = PyList_New(2); if (unlikely(!__pyx_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 15; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  Py_INCREF(__pyx_kp_Node);
+  PyList_SET_ITEM(__pyx_1, 0, __pyx_kp_Node);
+  Py_INCREF(__pyx_kp_Leaf);
+  PyList_SET_ITEM(__pyx_1, 1, __pyx_kp_Leaf);
+  __pyx_2 = __Pyx_Import(__pyx_kp_1, ((PyObject *)__pyx_1)); if (unlikely(!__pyx_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 15; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  Py_DECREF(((PyObject *)__pyx_1)); __pyx_1 = 0;
+  __pyx_1 = PyObject_GetAttr(__pyx_2, __pyx_kp_Node); if (unlikely(!__pyx_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 15; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  if (PyObject_SetAttr(__pyx_m, __pyx_kp_Node, __pyx_1) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 15; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  Py_DECREF(__pyx_1); __pyx_1 = 0;
+  __pyx_1 = PyObject_GetAttr(__pyx_2, __pyx_kp_Leaf); if (unlikely(!__pyx_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 15; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  if (PyObject_SetAttr(__pyx_m, __pyx_kp_Leaf, __pyx_1) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 15; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  Py_DECREF(__pyx_1); __pyx_1 = 0;
+  Py_DECREF(__pyx_2); __pyx_2 = 0;
+
+  /* "/home/gbr/devel/sphinx/sphinx/pycode/pgen2/parse.pyx":19
+ * DEF NAME = 1
+ * 
+ * class ParseError(Exception):             # <<<<<<<<<<<<<<
+ *     """Exception to signal the parser is stuck."""
+ * 
+ */
+  __pyx_2 = PyDict_New(); if (unlikely(!__pyx_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 19; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_1 = PyTuple_New(1); if (unlikely(!__pyx_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 19; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  Py_INCREF(__pyx_builtin_Exception);
+  PyTuple_SET_ITEM(__pyx_1, 0, __pyx_builtin_Exception);
+  if (PyDict_SetItemString(((PyObject *)__pyx_2), "__doc__", __pyx_kp_2) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 19; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_3 = __Pyx_CreateClass(((PyObject *)__pyx_1), ((PyObject *)__pyx_2), __pyx_kp_ParseError, "sphinx.pycode.pgen2.parse"); if (unlikely(!__pyx_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 19; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  Py_DECREF(((PyObject *)__pyx_1)); __pyx_1 = 0;
+
+  /* "/home/gbr/devel/sphinx/sphinx/pycode/pgen2/parse.pyx":22
+ *     """Exception to signal the parser is stuck."""
+ * 
+ *     def __init__(self, msg, type, value, context):             # <<<<<<<<<<<<<<
+ *         Exception.__init__(self, "%s: type=%r, value=%r, context=%r" %
+ *                            (msg, type, value, context))
+ */
+  __pyx_1 = PyCFunction_New(&__pyx_mdef_6sphinx_6pycode_5pgen2_5parse_10ParseError___init__, 0); if (unlikely(!__pyx_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 22; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_4 = PyMethod_New(__pyx_1, 0, __pyx_3); if (unlikely(!__pyx_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 22; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  Py_DECREF(__pyx_1); __pyx_1 = 0;
+  if (PyObject_SetAttr(__pyx_3, __pyx_kp___init__, __pyx_4) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 22; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  Py_DECREF(__pyx_4); __pyx_4 = 0;
+  if (PyObject_SetAttr(__pyx_m, __pyx_kp_ParseError, __pyx_3) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 19; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  Py_DECREF(__pyx_3); __pyx_3 = 0;
+  Py_DECREF(((PyObject *)__pyx_2)); __pyx_2 = 0;
+
+  /* "/home/gbr/devel/sphinx/sphinx/pycode/pgen2/parse.pyx":149
+ *                 self.rootnode.used_names = self.used_names
+ * 
+ *     cdef convert(self, raw_node):             # <<<<<<<<<<<<<<
+ *         type, value, context, children = raw_node
+ *         if children or type in self._grammar_number2symbol:
+ */
+  #if PY_MAJOR_VERSION < 3
+  return;
+  #else
+  return __pyx_m;
+  #endif
+  __pyx_L1_error:;
+  Py_XDECREF(__pyx_1);
+  Py_XDECREF(__pyx_2);
+  Py_XDECREF(__pyx_3);
+  Py_XDECREF(__pyx_4);
+  __Pyx_AddTraceback("sphinx.pycode.pgen2.parse");
+  #if PY_MAJOR_VERSION >= 3
+  return NULL;
+  #endif
+}
+
+static const char *__pyx_filenames[] = {
+  "parse.pyx",
+};
+
+/* Runtime support code */
+
+static void __pyx_init_filenames(void) {
+  __pyx_f = __pyx_filenames;
+}
+
+static INLINE void __Pyx_RaiseArgtupleTooLong(
+    Py_ssize_t num_expected,
+    Py_ssize_t num_found)
+{
+    const char* error_message =
+    #if PY_VERSION_HEX < 0x02050000
+        "function takes at most %d positional arguments (%d given)";
+    #else
+        "function takes at most %zd positional arguments (%zd given)";
+    #endif
+    PyErr_Format(PyExc_TypeError, error_message, num_expected, num_found);
+}
+
+static PyObject *__Pyx_Import(PyObject *name, PyObject *from_list) {
+    PyObject *__import__ = 0;
+    PyObject *empty_list = 0;
+    PyObject *module = 0;
+    PyObject *global_dict = 0;
+    PyObject *empty_dict = 0;
+    PyObject *list;
+    __import__ = PyObject_GetAttrString(__pyx_b, "__import__");
+    if (!__import__)
+        goto bad;
+    if (from_list)
+        list = from_list;
+    else {
+        empty_list = PyList_New(0);
+        if (!empty_list)
+            goto bad;
+        list = empty_list;
+    }
+    global_dict = PyModule_GetDict(__pyx_m);
+    if (!global_dict)
+        goto bad;
+    empty_dict = PyDict_New();
+    if (!empty_dict)
+        goto bad;
+    module = PyObject_CallFunction(__import__, "OOOO",
+        name, global_dict, empty_dict, list);
+bad:
+    Py_XDECREF(empty_list);
+    Py_XDECREF(__import__);
+    Py_XDECREF(empty_dict);
+    return module;
+}
+
+static PyObject *__Pyx_GetName(PyObject *dict, PyObject *name) {
+    PyObject *result;
+    result = PyObject_GetAttr(dict, name);
+    if (!result)
+        PyErr_SetObject(PyExc_NameError, name);
+    return result;
+}
+
+static PyObject *__Pyx_CreateClass(
+    PyObject *bases, PyObject *dict, PyObject *name, char *modname)
+{
+    PyObject *py_modname;
+    PyObject *result = 0;
+
+    #if PY_MAJOR_VERSION < 3
+    py_modname = PyString_FromString(modname);
+    #else
+    py_modname = PyUnicode_FromString(modname);
+    #endif
+    if (!py_modname)
+        goto bad;
+    if (PyDict_SetItemString(dict, "__module__", py_modname) < 0)
+        goto bad;
+    #if PY_MAJOR_VERSION < 3
+    result = PyClass_New(bases, dict, name);
+    #else
+    result = PyObject_CallFunctionObjArgs((PyObject *)&PyType_Type, name, bases, dict, NULL);
+    #endif
+bad:
+    Py_XDECREF(py_modname);
+    return result;
+}
+
+
+static PyObject *__Pyx_UnpackItem(PyObject *iter, Py_ssize_t index) {
+    PyObject *item;
+    if (!(item = PyIter_Next(iter))) {
+        if (!PyErr_Occurred()) {
+            PyErr_Format(PyExc_ValueError,
+                #if PY_VERSION_HEX < 0x02050000
+                    "need more than %d values to unpack", (int)index);
+                #else
+                    "need more than %zd values to unpack", index);
+                #endif
+        }
+    }
+    return item;
+}
+
+static int __Pyx_EndUnpack(PyObject *iter) {
+    PyObject *item;
+    if ((item = PyIter_Next(iter))) {
+        Py_DECREF(item);
+        PyErr_SetString(PyExc_ValueError, "too many values to unpack");
+        return -1;
+    }
+    else if (!PyErr_Occurred())
+        return 0;
+    else
+        return -1;
+}
+
+static void __Pyx_Raise(PyObject *type, PyObject *value, PyObject *tb) {
+    Py_XINCREF(type);
+    Py_XINCREF(value);
+    Py_XINCREF(tb);
+    /* First, check the traceback argument, replacing None with NULL. */
+    if (tb == Py_None) {
+        Py_DECREF(tb);
+        tb = 0;
+    }
+    else if (tb != NULL && !PyTraceBack_Check(tb)) {
+        PyErr_SetString(PyExc_TypeError,
+            "raise: arg 3 must be a traceback or None");
+        goto raise_error;
+    }
+    /* Next, replace a missing value with None */
+    if (value == NULL) {
+        value = Py_None;
+        Py_INCREF(value);
+    }
+    #if PY_VERSION_HEX < 0x02050000
+    if (!PyClass_Check(type))
+    #else
+    if (!PyType_Check(type))
+    #endif
+    {
+        /* Raising an instance.  The value should be a dummy. */
+        if (value != Py_None) {
+            PyErr_SetString(PyExc_TypeError,
+                "instance exception may not have a separate value");
+            goto raise_error;
+        }
+        /* Normalize to raise <class>, <instance> */
+        Py_DECREF(value);
+        value = type;
+        #if PY_VERSION_HEX < 0x02050000
+            if (PyInstance_Check(type)) {
+                type = (PyObject*) ((PyInstanceObject*)type)->in_class;
+                Py_INCREF(type);
+            }
+            else {
+                type = 0;
+                PyErr_SetString(PyExc_TypeError,
+                    "raise: exception must be an old-style class or instance");
+                goto raise_error;
+            }
+        #else
+            type = (PyObject*) Py_TYPE(type);
+            Py_INCREF(type);
+            if (!PyType_IsSubtype((PyTypeObject *)type, (PyTypeObject *)PyExc_BaseException)) {
+                PyErr_SetString(PyExc_TypeError,
+                    "raise: exception class must be a subclass of BaseException");
+                goto raise_error;
+            }
+        #endif
+    }
+    PyErr_Restore(type, value, tb);
+    return;
+raise_error:
+    Py_XDECREF(value);
+    Py_XDECREF(type);
+    Py_XDECREF(tb);
+    return;
+}
+
+
+static void __Pyx_WriteUnraisable(const char *name) {
+    PyObject *old_exc, *old_val, *old_tb;
+    PyObject *ctx;
+    PyErr_Fetch(&old_exc, &old_val, &old_tb);
+    #if PY_MAJOR_VERSION < 3
+    ctx = PyString_FromString(name);
+    #else
+    ctx = PyUnicode_FromString(name);
+    #endif
+    PyErr_Restore(old_exc, old_val, old_tb);
+    if (!ctx)
+        ctx = Py_None;
+    PyErr_WriteUnraisable(ctx);
+}
+
+static int __Pyx_SetVtable(PyObject *dict, void *vtable) {
+    PyObject *pycobj = 0;
+    int result;
+    
+    pycobj = PyCObject_FromVoidPtr(vtable, 0);
+    if (!pycobj)
+        goto bad;
+    if (PyDict_SetItemString(dict, "__pyx_vtable__", pycobj) < 0)
+        goto bad;
+    result = 0;
+    goto done;
+
+bad:
+    result = -1;
+done:
+    Py_XDECREF(pycobj);
+    return result;
+}
+
+#include "compile.h"
+#include "frameobject.h"
+#include "traceback.h"
+
+static void __Pyx_AddTraceback(const char *funcname) {
+    PyObject *py_srcfile = 0;
+    PyObject *py_funcname = 0;
+    PyObject *py_globals = 0;
+    PyObject *empty_string = 0;
+    PyCodeObject *py_code = 0;
+    PyFrameObject *py_frame = 0;
+
+    #if PY_MAJOR_VERSION < 3
+    py_srcfile = PyString_FromString(__pyx_filename);
+    #else
+    py_srcfile = PyUnicode_FromString(__pyx_filename);
+    #endif
+    if (!py_srcfile) goto bad;
+    if (__pyx_clineno) {
+        #if PY_MAJOR_VERSION < 3
+        py_funcname = PyString_FromFormat( "%s (%s:%d)", funcname, __pyx_cfilenm, __pyx_clineno);
+        #else
+        py_funcname = PyUnicode_FromFormat( "%s (%s:%d)", funcname, __pyx_cfilenm, __pyx_clineno);
+        #endif
+    }
+    else {
+        #if PY_MAJOR_VERSION < 3
+        py_funcname = PyString_FromString(funcname);
+        #else
+        py_funcname = PyUnicode_FromString(funcname);
+        #endif
+    }
+    if (!py_funcname) goto bad;
+    py_globals = PyModule_GetDict(__pyx_m);
+    if (!py_globals) goto bad;
+    #if PY_MAJOR_VERSION < 3
+    empty_string = PyString_FromStringAndSize("", 0);
+    #else
+    empty_string = PyBytes_FromStringAndSize("", 0);
+    #endif
+    if (!empty_string) goto bad;
+    py_code = PyCode_New(
+        0,            /*int argcount,*/
+        #if PY_MAJOR_VERSION >= 3
+        0,            /*int kwonlyargcount,*/
+        #endif
+        0,            /*int nlocals,*/
+        0,            /*int stacksize,*/
+        0,            /*int flags,*/
+        empty_string, /*PyObject *code,*/
+        __pyx_empty_tuple,  /*PyObject *consts,*/
+        __pyx_empty_tuple,  /*PyObject *names,*/
+        __pyx_empty_tuple,  /*PyObject *varnames,*/
+        __pyx_empty_tuple,  /*PyObject *freevars,*/
+        __pyx_empty_tuple,  /*PyObject *cellvars,*/
+        py_srcfile,   /*PyObject *filename,*/
+        py_funcname,  /*PyObject *name,*/
+        __pyx_lineno,   /*int firstlineno,*/
+        empty_string  /*PyObject *lnotab*/
+    );
+    if (!py_code) goto bad;
+    py_frame = PyFrame_New(
+        PyThreadState_Get(), /*PyThreadState *tstate,*/
+        py_code,             /*PyCodeObject *code,*/
+        py_globals,          /*PyObject *globals,*/
+        0                    /*PyObject *locals*/
+    );
+    if (!py_frame) goto bad;
+    py_frame->f_lineno = __pyx_lineno;
+    PyTraceBack_Here(py_frame);
+bad:
+    Py_XDECREF(py_srcfile);
+    Py_XDECREF(py_funcname);
+    Py_XDECREF(empty_string);
+    Py_XDECREF(py_code);
+    Py_XDECREF(py_frame);
+}
+
+static int __Pyx_InitStrings(__Pyx_StringTabEntry *t) {
+    while (t->p) {
+        #if PY_MAJOR_VERSION < 3
+        if (t->is_unicode && (!t->is_identifier)) {
+            *t->p = PyUnicode_DecodeUTF8(t->s, t->n - 1, NULL);
+        } else if (t->intern) {
+            *t->p = PyString_InternFromString(t->s);
+        } else {
+            *t->p = PyString_FromStringAndSize(t->s, t->n - 1);
+        }
+        #else  /* Python 3+ has unicode identifiers */
+        if (t->is_identifier || (t->is_unicode && t->intern)) {
+            *t->p = PyUnicode_InternFromString(t->s);
+        } else if (t->is_unicode) {
+            *t->p = PyUnicode_FromStringAndSize(t->s, t->n - 1);
+        } else {
+            *t->p = PyBytes_FromStringAndSize(t->s, t->n - 1);
+        }
+        #endif
+        if (!*t->p)
+            return -1;
+        ++t;
+    }
+    return 0;
+}
+
+/* Type Conversion Functions */
+
+static INLINE Py_ssize_t __pyx_PyIndex_AsSsize_t(PyObject* b) {
+  Py_ssize_t ival;
+  PyObject* x = PyNumber_Index(b);
+  if (!x) return -1;
+  ival = PyInt_AsSsize_t(x);
+  Py_DECREF(x);
+  return ival;
+}
+
+static INLINE int __Pyx_PyObject_IsTrue(PyObject* x) {
+   if (x == Py_True) return 1;
+   else if (x == Py_False) return 0;
+   else return PyObject_IsTrue(x);
+}
+
+static INLINE PY_LONG_LONG __pyx_PyInt_AsLongLong(PyObject* x) {
+    if (PyInt_CheckExact(x)) {
+        return PyInt_AS_LONG(x);
+    }
+    else if (PyLong_CheckExact(x)) {
+        return PyLong_AsLongLong(x);
+    }
+    else {
+        PY_LONG_LONG val;
+        PyObject* tmp = PyNumber_Int(x); if (!tmp) return (PY_LONG_LONG)-1;
+        val = __pyx_PyInt_AsLongLong(tmp);
+        Py_DECREF(tmp);
+        return val;
+    }
+}
+
+static INLINE unsigned PY_LONG_LONG __pyx_PyInt_AsUnsignedLongLong(PyObject* x) {
+    if (PyInt_CheckExact(x)) {
+        long val = PyInt_AS_LONG(x);
+        if (unlikely(val < 0)) {
+            PyErr_SetString(PyExc_TypeError, "Negative assignment to unsigned type.");
+            return (unsigned PY_LONG_LONG)-1;
+        }
+        return val;
+    }
+    else if (PyLong_CheckExact(x)) {
+        return PyLong_AsUnsignedLongLong(x);
+    }
+    else {
+        PY_LONG_LONG val;
+        PyObject* tmp = PyNumber_Int(x); if (!tmp) return (PY_LONG_LONG)-1;
+        val = __pyx_PyInt_AsUnsignedLongLong(tmp);
+        Py_DECREF(tmp);
+        return val;
+    }
+}
+
+
+static INLINE unsigned char __pyx_PyInt_unsigned_char(PyObject* x) {
+    if (sizeof(unsigned char) < sizeof(long)) {
+        long long_val = __pyx_PyInt_AsLong(x);
+        unsigned char val = (unsigned char)long_val;
+        if (unlikely((val != long_val)  || (long_val < 0))) {
+            PyErr_SetString(PyExc_OverflowError, "value too large to convert to unsigned char");
+            return (unsigned char)-1;
+        }
+        return val;
+    }
+    else {
+        return __pyx_PyInt_AsLong(x);
+    }
+}
+
+static INLINE unsigned short __pyx_PyInt_unsigned_short(PyObject* x) {
+    if (sizeof(unsigned short) < sizeof(long)) {
+        long long_val = __pyx_PyInt_AsLong(x);
+        unsigned short val = (unsigned short)long_val;
+        if (unlikely((val != long_val)  || (long_val < 0))) {
+            PyErr_SetString(PyExc_OverflowError, "value too large to convert to unsigned short");
+            return (unsigned short)-1;
+        }
+        return val;
+    }
+    else {
+        return __pyx_PyInt_AsLong(x);
+    }
+}
+
+static INLINE char __pyx_PyInt_char(PyObject* x) {
+    if (sizeof(char) < sizeof(long)) {
+        long long_val = __pyx_PyInt_AsLong(x);
+        char val = (char)long_val;
+        if (unlikely((val != long_val) )) {
+            PyErr_SetString(PyExc_OverflowError, "value too large to convert to char");
+            return (char)-1;
+        }
+        return val;
+    }
+    else {
+        return __pyx_PyInt_AsLong(x);
+    }
+}
+
+static INLINE short __pyx_PyInt_short(PyObject* x) {
+    if (sizeof(short) < sizeof(long)) {
+        long long_val = __pyx_PyInt_AsLong(x);
+        short val = (short)long_val;
+        if (unlikely((val != long_val) )) {
+            PyErr_SetString(PyExc_OverflowError, "value too large to convert to short");
+            return (short)-1;
+        }
+        return val;
+    }
+    else {
+        return __pyx_PyInt_AsLong(x);
+    }
+}
+
+static INLINE int __pyx_PyInt_int(PyObject* x) {
+    if (sizeof(int) < sizeof(long)) {
+        long long_val = __pyx_PyInt_AsLong(x);
+        int val = (int)long_val;
+        if (unlikely((val != long_val) )) {
+            PyErr_SetString(PyExc_OverflowError, "value too large to convert to int");
+            return (int)-1;
+        }
+        return val;
+    }
+    else {
+        return __pyx_PyInt_AsLong(x);
+    }
+}
+
+static INLINE long __pyx_PyInt_long(PyObject* x) {
+    if (sizeof(long) < sizeof(long)) {
+        long long_val = __pyx_PyInt_AsLong(x);
+        long val = (long)long_val;
+        if (unlikely((val != long_val) )) {
+            PyErr_SetString(PyExc_OverflowError, "value too large to convert to long");
+            return (long)-1;
+        }
+        return val;
+    }
+    else {
+        return __pyx_PyInt_AsLong(x);
+    }
+}
+
+static INLINE signed char __pyx_PyInt_signed_char(PyObject* x) {
+    if (sizeof(signed char) < sizeof(long)) {
+        long long_val = __pyx_PyInt_AsLong(x);
+        signed char val = (signed char)long_val;
+        if (unlikely((val != long_val) )) {
+            PyErr_SetString(PyExc_OverflowError, "value too large to convert to signed char");
+            return (signed char)-1;
+        }
+        return val;
+    }
+    else {
+        return __pyx_PyInt_AsLong(x);
+    }
+}
+
+static INLINE signed short __pyx_PyInt_signed_short(PyObject* x) {
+    if (sizeof(signed short) < sizeof(long)) {
+        long long_val = __pyx_PyInt_AsLong(x);
+        signed short val = (signed short)long_val;
+        if (unlikely((val != long_val) )) {
+            PyErr_SetString(PyExc_OverflowError, "value too large to convert to signed short");
+            return (signed short)-1;
+        }
+        return val;
+    }
+    else {
+        return __pyx_PyInt_AsLong(x);
+    }
+}
+
+static INLINE signed int __pyx_PyInt_signed_int(PyObject* x) {
+    if (sizeof(signed int) < sizeof(long)) {
+        long long_val = __pyx_PyInt_AsLong(x);
+        signed int val = (signed int)long_val;
+        if (unlikely((val != long_val) )) {
+            PyErr_SetString(PyExc_OverflowError, "value too large to convert to signed int");
+            return (signed int)-1;
+        }
+        return val;
+    }
+    else {
+        return __pyx_PyInt_AsLong(x);
+    }
+}
+
+static INLINE signed long __pyx_PyInt_signed_long(PyObject* x) {
+    if (sizeof(signed long) < sizeof(long)) {
+        long long_val = __pyx_PyInt_AsLong(x);
+        signed long val = (signed long)long_val;
+        if (unlikely((val != long_val) )) {
+            PyErr_SetString(PyExc_OverflowError, "value too large to convert to signed long");
+            return (signed long)-1;
+        }
+        return val;
+    }
+    else {
+        return __pyx_PyInt_AsLong(x);
+    }
+}
+
+static INLINE long double __pyx_PyInt_long_double(PyObject* x) {
+    if (sizeof(long double) < sizeof(long)) {
+        long long_val = __pyx_PyInt_AsLong(x);
+        long double val = (long double)long_val;
+        if (unlikely((val != long_val) )) {
+            PyErr_SetString(PyExc_OverflowError, "value too large to convert to long double");
+            return (long double)-1;
+        }
+        return val;
+    }
+    else {
+        return __pyx_PyInt_AsLong(x);
+    }
+}
+

Added: doctools/trunk/sphinx/pycode/pgen2/parse.py
==============================================================================
--- (empty file)
+++ doctools/trunk/sphinx/pycode/pgen2/parse.py	Sun Jan  4 21:38:57 2009
@@ -0,0 +1,201 @@
+# Copyright 2004-2005 Elemental Security, Inc. All Rights Reserved.
+# Licensed to PSF under a Contributor Agreement.
+
+"""Parser engine for the grammar tables generated by pgen.
+
+The grammar table must be loaded first.
+
+See Parser/parser.c in the Python distribution for additional info on
+how this parsing engine works.
+
+"""
+
+# Local imports
+from sphinx.pycode.pgen2 import token
+
+class ParseError(Exception):
+    """Exception to signal the parser is stuck."""
+
+    def __init__(self, msg, type, value, context):
+        Exception.__init__(self, "%s: type=%r, value=%r, context=%r" %
+                           (msg, type, value, context))
+        self.msg = msg
+        self.type = type
+        self.value = value
+        self.context = context
+
+class Parser(object):
+    """Parser engine.
+
+    The proper usage sequence is:
+
+    p = Parser(grammar, [converter])  # create instance
+    p.setup([start])                  # prepare for parsing
+    <for each input token>:
+        if p.addtoken(...):           # parse a token; may raise ParseError
+            break
+    root = p.rootnode                 # root of abstract syntax tree
+
+    A Parser instance may be reused by calling setup() repeatedly.
+
+    A Parser instance contains state pertaining to the current token
+    sequence, and should not be used concurrently by different threads
+    to parse separate token sequences.
+
+    See driver.py for how to get input tokens by tokenizing a file or
+    string.
+
+    Parsing is complete when addtoken() returns True; the root of the
+    abstract syntax tree can then be retrieved from the rootnode
+    instance variable.  When a syntax error occurs, addtoken() raises
+    the ParseError exception.  There is no error recovery; the parser
+    cannot be used after a syntax error was reported (but it can be
+    reinitialized by calling setup()).
+
+    """
+
+    def __init__(self, grammar, convert=None):
+        """Constructor.
+
+        The grammar argument is a grammar.Grammar instance; see the
+        grammar module for more information.
+
+        The parser is not ready yet for parsing; you must call the
+        setup() method to get it started.
+
+        The optional convert argument is a function mapping concrete
+        syntax tree nodes to abstract syntax tree nodes.  If not
+        given, no conversion is done and the syntax tree produced is
+        the concrete syntax tree.  If given, it must be a function of
+        two arguments, the first being the grammar (a grammar.Grammar
+        instance), and the second being the concrete syntax tree node
+        to be converted.  The syntax tree is converted from the bottom
+        up.
+
+        A concrete syntax tree node is a (type, value, context, nodes)
+        tuple, where type is the node type (a token or symbol number),
+        value is None for symbols and a string for tokens, context is
+        None or an opaque value used for error reporting (typically a
+        (lineno, offset) pair), and nodes is a list of children for
+        symbols, and None for tokens.
+
+        An abstract syntax tree node may be anything; this is entirely
+        up to the converter function.
+
+        """
+        self.grammar = grammar
+        self.convert = convert or (lambda grammar, node: node)
+
+    def setup(self, start=None):
+        """Prepare for parsing.
+
+        This *must* be called before starting to parse.
+
+        The optional argument is an alternative start symbol; it
+        defaults to the grammar's start symbol.
+
+        You can use a Parser instance to parse any number of programs;
+        each time you call setup() the parser is reset to an initial
+        state determined by the (implicit or explicit) start symbol.
+
+        """
+        if start is None:
+            start = self.grammar.start
+        # Each stack entry is a tuple: (dfa, state, node).
+        # A node is a tuple: (type, value, context, children),
+        # where children is a list of nodes or None, and context may be None.
+        newnode = (start, None, None, [])
+        stackentry = (self.grammar.dfas[start], 0, newnode)
+        self.stack = [stackentry]
+        self.rootnode = None
+        self.used_names = set() # Aliased to self.rootnode.used_names in pop()
+
+    def addtoken(self, type, value, context):
+        """Add a token; return True iff this is the end of the program."""
+        # Map from token to label
+        ilabel = self.classify(type, value, context)
+        # Loop until the token is shifted; may raise exceptions
+        while True:
+            dfa, state, node = self.stack[-1]
+            states, first = dfa
+            arcs = states[state]
+            # Look for a state with this label
+            for i, newstate in arcs:
+                t, v = self.grammar.labels[i]
+                if ilabel == i:
+                    # Look it up in the list of labels
+                    assert t < 256
+                    # Shift a token; we're done with it
+                    self.shift(type, value, newstate, context)
+                    # Pop while we are in an accept-only state
+                    state = newstate
+                    while states[state] == [(0, state)]:
+                        self.pop()
+                        if not self.stack:
+                            # Done parsing!
+                            return True
+                        dfa, state, node = self.stack[-1]
+                        states, first = dfa
+                    # Done with this token
+                    return False
+                elif t >= 256:
+                    # See if it's a symbol and if we're in its first set
+                    itsdfa = self.grammar.dfas[t]
+                    itsstates, itsfirst = itsdfa
+                    if ilabel in itsfirst:
+                        # Push a symbol
+                        self.push(t, self.grammar.dfas[t], newstate, context)
+                        break # To continue the outer while loop
+            else:
+                if (0, state) in arcs:
+                    # An accepting state, pop it and try something else
+                    self.pop()
+                    if not self.stack:
+                        # Done parsing, but another token is input
+                        raise ParseError("too much input",
+                                         type, value, context)
+                else:
+                    # No success finding a transition
+                    raise ParseError("bad input", type, value, context)
+
+    def classify(self, type, value, context):
+        """Turn a token into a label.  (Internal)"""
+        if type == token.NAME:
+            # Keep a listing of all used names
+            self.used_names.add(value)
+            # Check for reserved words
+            ilabel = self.grammar.keywords.get(value)
+            if ilabel is not None:
+                return ilabel
+        ilabel = self.grammar.tokens.get(type)
+        if ilabel is None:
+            raise ParseError("bad token", type, value, context)
+        return ilabel
+
+    def shift(self, type, value, newstate, context):
+        """Shift a token.  (Internal)"""
+        dfa, state, node = self.stack[-1]
+        newnode = (type, value, context, None)
+        newnode = self.convert(self.grammar, newnode)
+        if newnode is not None:
+            node[-1].append(newnode)
+        self.stack[-1] = (dfa, newstate, node)
+
+    def push(self, type, newdfa, newstate, context):
+        """Push a nonterminal.  (Internal)"""
+        dfa, state, node = self.stack[-1]
+        newnode = (type, None, context, [])
+        self.stack[-1] = (dfa, newstate, node)
+        self.stack.append((newdfa, 0, newnode))
+
+    def pop(self):
+        """Pop a nonterminal.  (Internal)"""
+        popdfa, popstate, popnode = self.stack.pop()
+        newnode = self.convert(self.grammar, popnode)
+        if newnode is not None:
+            if self.stack:
+                dfa, state, node = self.stack[-1]
+                node[-1].append(newnode)
+            else:
+                self.rootnode = newnode
+                self.rootnode.used_names = self.used_names

Added: doctools/trunk/sphinx/pycode/pgen2/parse.pyx
==============================================================================
--- (empty file)
+++ doctools/trunk/sphinx/pycode/pgen2/parse.pyx	Sun Jan  4 21:38:57 2009
@@ -0,0 +1,158 @@
+# Copyright 2004-2005 Elemental Security, Inc. All Rights Reserved.
+# Licensed to PSF under a Contributor Agreement.
+
+# Adapted from parse.py to be compiled with Cython by Georg Brandl.
+
+"""Parser engine for the grammar tables generated by pgen.
+
+The grammar table must be loaded first.
+
+See Parser/parser.c in the Python distribution for additional info on
+how this parsing engine works.
+
+"""
+
+from sphinx.pycode.nodes import Node, Leaf
+
+DEF NAME = 1
+
+class ParseError(Exception):
+    """Exception to signal the parser is stuck."""
+
+    def __init__(self, msg, type, value, context):
+        Exception.__init__(self, "%s: type=%r, value=%r, context=%r" %
+                           (msg, type, value, context))
+        self.msg = msg
+        self.type = type
+        self.value = value
+        self.context = context
+
+
+cdef class Parser:
+    cdef public grammar, stack, rootnode, used_names
+    cdef _grammar_dfas, _grammar_labels, _grammar_keywords, _grammar_tokens
+    cdef _grammar_number2symbol
+
+    def __init__(self, grammar, convert=None):
+        self.grammar = grammar
+        #self.convert = convert or noconvert
+
+        self._grammar_dfas = grammar.dfas
+        self._grammar_labels = grammar.labels
+        self._grammar_keywords = grammar.keywords
+        self._grammar_tokens = grammar.tokens
+        self._grammar_number2symbol = grammar.number2symbol
+
+    def setup(self, start=None):
+        if start is None:
+            start = self.grammar.start
+        # Each stack entry is a tuple: (dfa, state, node).
+        # A node is a tuple: (type, value, context, children),
+        # where children is a list of nodes or None, and context may be None.
+        newnode = (start, None, None, [])
+        stackentry = (self._grammar_dfas[start], 0, newnode)
+        self.stack = [stackentry]
+        self.rootnode = None
+        self.used_names = set() # Aliased to self.rootnode.used_names in pop()
+
+    def addtoken(self, type, value, context):
+        """Add a token; return True iff this is the end of the program."""
+        cdef int ilabel, i, t, state, newstate
+        # Map from token to label
+        ilabel = self.classify(type, value, context)
+        # Loop until the token is shifted; may raise exceptions
+        while True:
+            dfa, state, node = self.stack[-1]
+            states, first = dfa
+            arcs = states[state]
+            # Look for a state with this label
+            for i, newstate in arcs:
+                t, v = self._grammar_labels[i]
+                if ilabel == i:
+                    # Look it up in the list of labels
+                    ## assert t < 256
+                    # Shift a token; we're done with it
+                    self.shift(type, value, newstate, context)
+                    # Pop while we are in an accept-only state
+                    state = newstate
+                    while states[state] == [(0, state)]:
+                        self.pop()
+                        if not self.stack:
+                            # Done parsing!
+                            return True
+                        dfa, state, node = self.stack[-1]
+                        states, first = dfa
+                    # Done with this token
+                    return False
+                elif t >= 256:
+                    # See if it's a symbol and if we're in its first set
+                    itsdfa = self._grammar_dfas[t]
+                    itsstates, itsfirst = itsdfa
+                    if ilabel in itsfirst:
+                        # Push a symbol
+                        self.push(t, itsdfa, newstate, context)
+                        break # To continue the outer while loop
+            else:
+                if (0, state) in arcs:
+                    # An accepting state, pop it and try something else
+                    self.pop()
+                    if not self.stack:
+                        # Done parsing, but another token is input
+                        raise ParseError("too much input",
+                                         type, value, context)
+                else:
+                    # No success finding a transition
+                    raise ParseError("bad input", type, value, context)
+
+    cdef int classify(self, type, value, context):
+        """Turn a token into a label.  (Internal)"""
+        if type == NAME:
+            # Keep a listing of all used names
+            self.used_names.add(value)
+            # Check for reserved words
+            ilabel = self._grammar_keywords.get(value)
+            if ilabel is not None:
+                return ilabel
+        ilabel = self._grammar_tokens.get(type)
+        if ilabel is None:
+            raise ParseError("bad token", type, value, context)
+        return ilabel
+
+    cdef void shift(self, type, value, newstate, context):
+        """Shift a token.  (Internal)"""
+        dfa, state, node = self.stack[-1]
+        newnode = (type, value, context, None)
+        newnode = self.convert(newnode)
+        if newnode is not None:
+            node[-1].append(newnode)
+        self.stack[-1] = (dfa, newstate, node)
+
+    cdef void push(self, type, newdfa, newstate, context):
+        """Push a nonterminal.  (Internal)"""
+        dfa, state, node = self.stack[-1]
+        newnode = (type, None, context, [])
+        self.stack[-1] = (dfa, newstate, node)
+        self.stack.append((newdfa, 0, newnode))
+
+    cdef void pop(self):
+        """Pop a nonterminal.  (Internal)"""
+        popdfa, popstate, popnode = self.stack.pop()
+        newnode = self.convert(popnode)
+        if newnode is not None:
+            if self.stack:
+                dfa, state, node = self.stack[-1]
+                node[-1].append(newnode)
+            else:
+                self.rootnode = newnode
+                self.rootnode.used_names = self.used_names
+
+    cdef convert(self, raw_node):
+        type, value, context, children = raw_node
+        if children or type in self._grammar_number2symbol:
+            # If there's exactly one child, return that child instead of
+            # creating a new node.
+            if len(children) == 1:
+                return children[0]
+            return Node(type, children, context=context)
+        else:
+            return Leaf(type, value, context=context)

Added: doctools/trunk/sphinx/pycode/pgen2/pgen.py
==============================================================================
--- (empty file)
+++ doctools/trunk/sphinx/pycode/pgen2/pgen.py	Sun Jan  4 21:38:57 2009
@@ -0,0 +1,384 @@
+# Copyright 2004-2005 Elemental Security, Inc. All Rights Reserved.
+# Licensed to PSF under a Contributor Agreement.
+
+# Pgen imports
+from sphinx.pycode.pgen2 import grammar, token, tokenize
+
+class PgenGrammar(grammar.Grammar):
+    pass
+
+class ParserGenerator(object):
+
+    def __init__(self, filename, stream=None):
+        close_stream = None
+        if stream is None:
+            stream = open(filename)
+            close_stream = stream.close
+        self.filename = filename
+        self.stream = stream
+        self.generator = tokenize.generate_tokens(stream.readline)
+        self.gettoken() # Initialize lookahead
+        self.dfas, self.startsymbol = self.parse()
+        if close_stream is not None:
+            close_stream()
+        self.first = {} # map from symbol name to set of tokens
+        self.addfirstsets()
+
+    def make_grammar(self):
+        c = PgenGrammar()
+        names = self.dfas.keys()
+        names.sort()
+        names.remove(self.startsymbol)
+        names.insert(0, self.startsymbol)
+        for name in names:
+            i = 256 + len(c.symbol2number)
+            c.symbol2number[name] = i
+            c.number2symbol[i] = name
+        for name in names:
+            dfa = self.dfas[name]
+            states = []
+            for state in dfa:
+                arcs = []
+                for label, next in state.arcs.iteritems():
+                    arcs.append((self.make_label(c, label), dfa.index(next)))
+                if state.isfinal:
+                    arcs.append((0, dfa.index(state)))
+                states.append(arcs)
+            c.states.append(states)
+            c.dfas[c.symbol2number[name]] = (states, self.make_first(c, name))
+        c.start = c.symbol2number[self.startsymbol]
+        return c
+
+    def make_first(self, c, name):
+        rawfirst = self.first[name]
+        first = {}
+        for label in rawfirst:
+            ilabel = self.make_label(c, label)
+            ##assert ilabel not in first # XXX failed on <> ... !=
+            first[ilabel] = 1
+        return first
+
+    def make_label(self, c, label):
+        # XXX Maybe this should be a method on a subclass of converter?
+        ilabel = len(c.labels)
+        if label[0].isalpha():
+            # Either a symbol name or a named token
+            if label in c.symbol2number:
+                # A symbol name (a non-terminal)
+                if label in c.symbol2label:
+                    return c.symbol2label[label]
+                else:
+                    c.labels.append((c.symbol2number[label], None))
+                    c.symbol2label[label] = ilabel
+                    return ilabel
+            else:
+                # A named token (NAME, NUMBER, STRING)
+                itoken = getattr(token, label, None)
+                assert isinstance(itoken, int), label
+                assert itoken in token.tok_name, label
+                if itoken in c.tokens:
+                    return c.tokens[itoken]
+                else:
+                    c.labels.append((itoken, None))
+                    c.tokens[itoken] = ilabel
+                    return ilabel
+        else:
+            # Either a keyword or an operator
+            assert label[0] in ('"', "'"), label
+            value = eval(label)
+            if value[0].isalpha():
+                # A keyword
+                if value in c.keywords:
+                    return c.keywords[value]
+                else:
+                    c.labels.append((token.NAME, value))
+                    c.keywords[value] = ilabel
+                    return ilabel
+            else:
+                # An operator (any non-numeric token)
+                itoken = grammar.opmap[value] # Fails if unknown token
+                if itoken in c.tokens:
+                    return c.tokens[itoken]
+                else:
+                    c.labels.append((itoken, None))
+                    c.tokens[itoken] = ilabel
+                    return ilabel
+
+    def addfirstsets(self):
+        names = self.dfas.keys()
+        names.sort()
+        for name in names:
+            if name not in self.first:
+                self.calcfirst(name)
+            #print name, self.first[name].keys()
+
+    def calcfirst(self, name):
+        dfa = self.dfas[name]
+        self.first[name] = None # dummy to detect left recursion
+        state = dfa[0]
+        totalset = {}
+        overlapcheck = {}
+        for label, next in state.arcs.iteritems():
+            if label in self.dfas:
+                if label in self.first:
+                    fset = self.first[label]
+                    if fset is None:
+                        raise ValueError("recursion for rule %r" % name)
+                else:
+                    self.calcfirst(label)
+                    fset = self.first[label]
+                totalset.update(fset)
+                overlapcheck[label] = fset
+            else:
+                totalset[label] = 1
+                overlapcheck[label] = {label: 1}
+        inverse = {}
+        for label, itsfirst in overlapcheck.iteritems():
+            for symbol in itsfirst:
+                if symbol in inverse:
+                    raise ValueError("rule %s is ambiguous; %s is in the"
+                                     " first sets of %s as well as %s" %
+                                     (name, symbol, label, inverse[symbol]))
+                inverse[symbol] = label
+        self.first[name] = totalset
+
+    def parse(self):
+        dfas = {}
+        startsymbol = None
+        # MSTART: (NEWLINE | RULE)* ENDMARKER
+        while self.type != token.ENDMARKER:
+            while self.type == token.NEWLINE:
+                self.gettoken()
+            # RULE: NAME ':' RHS NEWLINE
+            name = self.expect(token.NAME)
+            self.expect(token.OP, ":")
+            a, z = self.parse_rhs()
+            self.expect(token.NEWLINE)
+            #self.dump_nfa(name, a, z)
+            dfa = self.make_dfa(a, z)
+            #self.dump_dfa(name, dfa)
+            oldlen = len(dfa)
+            self.simplify_dfa(dfa)
+            newlen = len(dfa)
+            dfas[name] = dfa
+            #print name, oldlen, newlen
+            if startsymbol is None:
+                startsymbol = name
+        return dfas, startsymbol
+
+    def make_dfa(self, start, finish):
+        # To turn an NFA into a DFA, we define the states of the DFA
+        # to correspond to *sets* of states of the NFA.  Then do some
+        # state reduction.  Let's represent sets as dicts with 1 for
+        # values.
+        assert isinstance(start, NFAState)
+        assert isinstance(finish, NFAState)
+        def closure(state):
+            base = {}
+            addclosure(state, base)
+            return base
+        def addclosure(state, base):
+            assert isinstance(state, NFAState)
+            if state in base:
+                return
+            base[state] = 1
+            for label, next in state.arcs:
+                if label is None:
+                    addclosure(next, base)
+        states = [DFAState(closure(start), finish)]
+        for state in states: # NB states grows while we're iterating
+            arcs = {}
+            for nfastate in state.nfaset:
+                for label, next in nfastate.arcs:
+                    if label is not None:
+                        addclosure(next, arcs.setdefault(label, {}))
+            for label, nfaset in arcs.iteritems():
+                for st in states:
+                    if st.nfaset == nfaset:
+                        break
+                else:
+                    st = DFAState(nfaset, finish)
+                    states.append(st)
+                state.addarc(st, label)
+        return states # List of DFAState instances; first one is start
+
+    def dump_nfa(self, name, start, finish):
+        print "Dump of NFA for", name
+        todo = [start]
+        for i, state in enumerate(todo):
+            print "  State", i, state is finish and "(final)" or ""
+            for label, next in state.arcs:
+                if next in todo:
+                    j = todo.index(next)
+                else:
+                    j = len(todo)
+                    todo.append(next)
+                if label is None:
+                    print "    -> %d" % j
+                else:
+                    print "    %s -> %d" % (label, j)
+
+    def dump_dfa(self, name, dfa):
+        print "Dump of DFA for", name
+        for i, state in enumerate(dfa):
+            print "  State", i, state.isfinal and "(final)" or ""
+            for label, next in state.arcs.iteritems():
+                print "    %s -> %d" % (label, dfa.index(next))
+
+    def simplify_dfa(self, dfa):
+        # This is not theoretically optimal, but works well enough.
+        # Algorithm: repeatedly look for two states that have the same
+        # set of arcs (same labels pointing to the same nodes) and
+        # unify them, until things stop changing.
+
+        # dfa is a list of DFAState instances
+        changes = True
+        while changes:
+            changes = False
+            for i, state_i in enumerate(dfa):
+                for j in range(i+1, len(dfa)):
+                    state_j = dfa[j]
+                    if state_i == state_j:
+                        #print "  unify", i, j
+                        del dfa[j]
+                        for state in dfa:
+                            state.unifystate(state_j, state_i)
+                        changes = True
+                        break
+
+    def parse_rhs(self):
+        # RHS: ALT ('|' ALT)*
+        a, z = self.parse_alt()
+        if self.value != "|":
+            return a, z
+        else:
+            aa = NFAState()
+            zz = NFAState()
+            aa.addarc(a)
+            z.addarc(zz)
+            while self.value == "|":
+                self.gettoken()
+                a, z = self.parse_alt()
+                aa.addarc(a)
+                z.addarc(zz)
+            return aa, zz
+
+    def parse_alt(self):
+        # ALT: ITEM+
+        a, b = self.parse_item()
+        while (self.value in ("(", "[") or
+               self.type in (token.NAME, token.STRING)):
+            c, d = self.parse_item()
+            b.addarc(c)
+            b = d
+        return a, b
+
+    def parse_item(self):
+        # ITEM: '[' RHS ']' | ATOM ['+' | '*']
+        if self.value == "[":
+            self.gettoken()
+            a, z = self.parse_rhs()
+            self.expect(token.OP, "]")
+            a.addarc(z)
+            return a, z
+        else:
+            a, z = self.parse_atom()
+            value = self.value
+            if value not in ("+", "*"):
+                return a, z
+            self.gettoken()
+            z.addarc(a)
+            if value == "+":
+                return a, z
+            else:
+                return a, a
+
+    def parse_atom(self):
+        # ATOM: '(' RHS ')' | NAME | STRING
+        if self.value == "(":
+            self.gettoken()
+            a, z = self.parse_rhs()
+            self.expect(token.OP, ")")
+            return a, z
+        elif self.type in (token.NAME, token.STRING):
+            a = NFAState()
+            z = NFAState()
+            a.addarc(z, self.value)
+            self.gettoken()
+            return a, z
+        else:
+            self.raise_error("expected (...) or NAME or STRING, got %s/%s",
+                             self.type, self.value)
+
+    def expect(self, type, value=None):
+        if self.type != type or (value is not None and self.value != value):
+            self.raise_error("expected %s/%s, got %s/%s",
+                             type, value, self.type, self.value)
+        value = self.value
+        self.gettoken()
+        return value
+
+    def gettoken(self):
+        tup = self.generator.next()
+        while tup[0] in (tokenize.COMMENT, tokenize.NL):
+            tup = self.generator.next()
+        self.type, self.value, self.begin, self.end, self.line = tup
+        #print token.tok_name[self.type], repr(self.value)
+
+    def raise_error(self, msg, *args):
+        if args:
+            try:
+                msg = msg % args
+            except:
+                msg = " ".join([msg] + map(str, args))
+        raise SyntaxError(msg, (self.filename, self.end[0],
+                                self.end[1], self.line))
+
+class NFAState(object):
+
+    def __init__(self):
+        self.arcs = [] # list of (label, NFAState) pairs
+
+    def addarc(self, next, label=None):
+        assert label is None or isinstance(label, str)
+        assert isinstance(next, NFAState)
+        self.arcs.append((label, next))
+
+class DFAState(object):
+
+    def __init__(self, nfaset, final):
+        assert isinstance(nfaset, dict)
+        assert isinstance(iter(nfaset).next(), NFAState)
+        assert isinstance(final, NFAState)
+        self.nfaset = nfaset
+        self.isfinal = final in nfaset
+        self.arcs = {} # map from label to DFAState
+
+    def addarc(self, next, label):
+        assert isinstance(label, str)
+        assert label not in self.arcs
+        assert isinstance(next, DFAState)
+        self.arcs[label] = next
+
+    def unifystate(self, old, new):
+        for label, next in self.arcs.iteritems():
+            if next is old:
+                self.arcs[label] = new
+
+    def __eq__(self, other):
+        # Equality test -- ignore the nfaset instance variable
+        assert isinstance(other, DFAState)
+        if self.isfinal != other.isfinal:
+            return False
+        # Can't just return self.arcs == other.arcs, because that
+        # would invoke this method recursively, with cycles...
+        if len(self.arcs) != len(other.arcs):
+            return False
+        for label, next in self.arcs.iteritems():
+            if next is not other.arcs.get(label):
+                return False
+        return True
+
+def generate_grammar(filename="Grammar.txt"):
+    p = ParserGenerator(filename)
+    return p.make_grammar()

Added: doctools/trunk/sphinx/pycode/pgen2/token.py
==============================================================================
--- (empty file)
+++ doctools/trunk/sphinx/pycode/pgen2/token.py	Sun Jan  4 21:38:57 2009
@@ -0,0 +1,82 @@
+#! /usr/bin/env python
+
+"""Token constants (from "token.h")."""
+
+#  Taken from Python (r53757) and modified to include some tokens
+#   originally monkeypatched in by pgen2.tokenize
+
+#--start constants--
+ENDMARKER = 0
+NAME = 1
+NUMBER = 2
+STRING = 3
+NEWLINE = 4
+INDENT = 5
+DEDENT = 6
+LPAR = 7
+RPAR = 8
+LSQB = 9
+RSQB = 10
+COLON = 11
+COMMA = 12
+SEMI = 13
+PLUS = 14
+MINUS = 15
+STAR = 16
+SLASH = 17
+VBAR = 18
+AMPER = 19
+LESS = 20
+GREATER = 21
+EQUAL = 22
+DOT = 23
+PERCENT = 24
+BACKQUOTE = 25
+LBRACE = 26
+RBRACE = 27
+EQEQUAL = 28
+NOTEQUAL = 29
+LESSEQUAL = 30
+GREATEREQUAL = 31
+TILDE = 32
+CIRCUMFLEX = 33
+LEFTSHIFT = 34
+RIGHTSHIFT = 35
+DOUBLESTAR = 36
+PLUSEQUAL = 37
+MINEQUAL = 38
+STAREQUAL = 39
+SLASHEQUAL = 40
+PERCENTEQUAL = 41
+AMPEREQUAL = 42
+VBAREQUAL = 43
+CIRCUMFLEXEQUAL = 44
+LEFTSHIFTEQUAL = 45
+RIGHTSHIFTEQUAL = 46
+DOUBLESTAREQUAL = 47
+DOUBLESLASH = 48
+DOUBLESLASHEQUAL = 49
+AT = 50
+OP = 51
+COMMENT = 52
+NL = 53
+RARROW = 54
+ERRORTOKEN = 55
+N_TOKENS = 56
+NT_OFFSET = 256
+#--end constants--
+
+tok_name = {}
+for _name, _value in globals().items():
+    if type(_value) is type(0):
+        tok_name[_value] = _name
+
+
+def ISTERMINAL(x):
+    return x < NT_OFFSET
+
+def ISNONTERMINAL(x):
+    return x >= NT_OFFSET
+
+def ISEOF(x):
+    return x == ENDMARKER

Added: doctools/trunk/sphinx/pycode/pgen2/tokenize.py
==============================================================================
--- (empty file)
+++ doctools/trunk/sphinx/pycode/pgen2/tokenize.py	Sun Jan  4 21:38:57 2009
@@ -0,0 +1,405 @@
+# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006 Python Software Foundation.
+# All rights reserved.
+
+"""Tokenization help for Python programs.
+
+generate_tokens(readline) is a generator that breaks a stream of
+text into Python tokens.  It accepts a readline-like method which is called
+repeatedly to get the next line of input (or "" for EOF).  It generates
+5-tuples with these members:
+
+    the token type (see token.py)
+    the token (a string)
+    the starting (row, column) indices of the token (a 2-tuple of ints)
+    the ending (row, column) indices of the token (a 2-tuple of ints)
+    the original line (string)
+
+It is designed to match the working of the Python tokenizer exactly, except
+that it produces COMMENT tokens for comments and gives type OP for all
+operators
+
+Older entry points
+    tokenize_loop(readline, tokeneater)
+    tokenize(readline, tokeneater=printtoken)
+are the same, except instead of generating tokens, tokeneater is a callback
+function to which the 5 fields described above are passed as 5 arguments,
+each time a new token is found."""
+
+__author__ = 'Ka-Ping Yee <ping at lfw.org>'
+__credits__ = \
+    'GvR, ESR, Tim Peters, Thomas Wouters, Fred Drake, Skip Montanaro'
+
+import string, re
+from sphinx.pycode.pgen2.token import *
+from sphinx.pycode.pgen2 import token
+
+__all__ = [x for x in dir(token) if x[0] != '_'] + ["tokenize",
+           "generate_tokens", "untokenize"]
+del token
+
+def group(*choices): return '(' + '|'.join(choices) + ')'
+def any(*choices): return group(*choices) + '*'
+def maybe(*choices): return group(*choices) + '?'
+
+Whitespace = r'[ \f\t]*'
+Comment = r'#[^\r\n]*'
+Ignore = Whitespace + any(r'\\\r?\n' + Whitespace) + maybe(Comment)
+Name = r'[a-zA-Z_]\w*'
+
+Binnumber = r'0[bB][01]*'
+Hexnumber = r'0[xX][\da-fA-F]*[lL]?'
+Octnumber = r'0[oO]?[0-7]*[lL]?'
+Decnumber = r'[1-9]\d*[lL]?'
+Intnumber = group(Binnumber, Hexnumber, Octnumber, Decnumber)
+Exponent = r'[eE][-+]?\d+'
+Pointfloat = group(r'\d+\.\d*', r'\.\d+') + maybe(Exponent)
+Expfloat = r'\d+' + Exponent
+Floatnumber = group(Pointfloat, Expfloat)
+Imagnumber = group(r'\d+[jJ]', Floatnumber + r'[jJ]')
+Number = group(Imagnumber, Floatnumber, Intnumber)
+
+# Tail end of ' string.
+Single = r"[^'\\]*(?:\\.[^'\\]*)*'"
+# Tail end of " string.
+Double = r'[^"\\]*(?:\\.[^"\\]*)*"'
+# Tail end of ''' string.
+Single3 = r"[^'\\]*(?:(?:\\.|'(?!''))[^'\\]*)*'''"
+# Tail end of """ string.
+Double3 = r'[^"\\]*(?:(?:\\.|"(?!""))[^"\\]*)*"""'
+Triple = group("[ubUB]?[rR]?'''", '[ubUB]?[rR]?"""')
+# Single-line ' or " string.
+String = group(r"[uU]?[rR]?'[^\n'\\]*(?:\\.[^\n'\\]*)*'",
+               r'[uU]?[rR]?"[^\n"\\]*(?:\\.[^\n"\\]*)*"')
+
+# Because of leftmost-then-longest match semantics, be sure to put the
+# longest operators first (e.g., if = came before ==, == would get
+# recognized as two instances of =).
+Operator = group(r"\*\*=?", r">>=?", r"<<=?", r"<>", r"!=",
+                 r"//=?", r"->",
+                 r"[+\-*/%&|^=<>]=?",
+                 r"~")
+
+Bracket = '[][(){}]'
+Special = group(r'\r?\n', r'[:;.,`@]')
+Funny = group(Operator, Bracket, Special)
+
+PlainToken = group(Number, Funny, String, Name)
+Token = Ignore + PlainToken
+
+# First (or only) line of ' or " string.
+ContStr = group(r"[uUbB]?[rR]?'[^\n'\\]*(?:\\.[^\n'\\]*)*" +
+                group("'", r'\\\r?\n'),
+                r'[uUbB]?[rR]?"[^\n"\\]*(?:\\.[^\n"\\]*)*' +
+                group('"', r'\\\r?\n'))
+PseudoExtras = group(r'\\\r?\n', Comment, Triple)
+PseudoToken = Whitespace + group(PseudoExtras, Number, Funny, ContStr, Name)
+
+tokenprog, pseudoprog, single3prog, double3prog = map(
+    re.compile, (Token, PseudoToken, Single3, Double3))
+endprogs = {"'": re.compile(Single), '"': re.compile(Double),
+            "'''": single3prog, '"""': double3prog,
+            "r'''": single3prog, 'r"""': double3prog,
+            "u'''": single3prog, 'u"""': double3prog,
+            "b'''": single3prog, 'b"""': double3prog,
+            "ur'''": single3prog, 'ur"""': double3prog,
+            "br'''": single3prog, 'br"""': double3prog,
+            "R'''": single3prog, 'R"""': double3prog,
+            "U'''": single3prog, 'U"""': double3prog,
+            "B'''": single3prog, 'B"""': double3prog,
+            "uR'''": single3prog, 'uR"""': double3prog,
+            "Ur'''": single3prog, 'Ur"""': double3prog,
+            "UR'''": single3prog, 'UR"""': double3prog,
+            "bR'''": single3prog, 'bR"""': double3prog,
+            "Br'''": single3prog, 'Br"""': double3prog,
+            "BR'''": single3prog, 'BR"""': double3prog,
+            'r': None, 'R': None,
+            'u': None, 'U': None,
+            'b': None, 'B': None}
+
+triple_quoted = {}
+for t in ("'''", '"""',
+          "r'''", 'r"""', "R'''", 'R"""',
+          "u'''", 'u"""', "U'''", 'U"""',
+          "b'''", 'b"""', "B'''", 'B"""',
+          "ur'''", 'ur"""', "Ur'''", 'Ur"""',
+          "uR'''", 'uR"""', "UR'''", 'UR"""',
+          "br'''", 'br"""', "Br'''", 'Br"""',
+          "bR'''", 'bR"""', "BR'''", 'BR"""',):
+    triple_quoted[t] = t
+single_quoted = {}
+for t in ("'", '"',
+          "r'", 'r"', "R'", 'R"',
+          "u'", 'u"', "U'", 'U"',
+          "b'", 'b"', "B'", 'B"',
+          "ur'", 'ur"', "Ur'", 'Ur"',
+          "uR'", 'uR"', "UR'", 'UR"',
+          "br'", 'br"', "Br'", 'Br"',
+          "bR'", 'bR"', "BR'", 'BR"', ):
+    single_quoted[t] = t
+
+tabsize = 8
+
+class TokenError(Exception): pass
+
+class StopTokenizing(Exception): pass
+
+def printtoken(type, token, (srow, scol), (erow, ecol), line): # for testing
+    print "%d,%d-%d,%d:\t%s\t%s" % \
+        (srow, scol, erow, ecol, tok_name[type], repr(token))
+
+def tokenize(readline, tokeneater=printtoken):
+    """
+    The tokenize() function accepts two parameters: one representing the
+    input stream, and one providing an output mechanism for tokenize().
+
+    The first parameter, readline, must be a callable object which provides
+    the same interface as the readline() method of built-in file objects.
+    Each call to the function should return one line of input as a string.
+
+    The second parameter, tokeneater, must also be a callable object. It is
+    called once for each token, with five arguments, corresponding to the
+    tuples generated by generate_tokens().
+    """
+    try:
+        tokenize_loop(readline, tokeneater)
+    except StopTokenizing:
+        pass
+
+# backwards compatible interface
+def tokenize_loop(readline, tokeneater):
+    for token_info in generate_tokens(readline):
+        tokeneater(*token_info)
+
+class Untokenizer:
+
+    def __init__(self):
+        self.tokens = []
+        self.prev_row = 1
+        self.prev_col = 0
+
+    def add_whitespace(self, start):
+        row, col = start
+        assert row <= self.prev_row
+        col_offset = col - self.prev_col
+        if col_offset:
+            self.tokens.append(" " * col_offset)
+
+    def untokenize(self, iterable):
+        for t in iterable:
+            if len(t) == 2:
+                self.compat(t, iterable)
+                break
+            tok_type, token, start, end, line = t
+            self.add_whitespace(start)
+            self.tokens.append(token)
+            self.prev_row, self.prev_col = end
+            if tok_type in (NEWLINE, NL):
+                self.prev_row += 1
+                self.prev_col = 0
+        return "".join(self.tokens)
+
+    def compat(self, token, iterable):
+        startline = False
+        indents = []
+        toks_append = self.tokens.append
+        toknum, tokval = token
+        if toknum in (NAME, NUMBER):
+            tokval += ' '
+        if toknum in (NEWLINE, NL):
+            startline = True
+        for tok in iterable:
+            toknum, tokval = tok[:2]
+
+            if toknum in (NAME, NUMBER):
+                tokval += ' '
+
+            if toknum == INDENT:
+                indents.append(tokval)
+                continue
+            elif toknum == DEDENT:
+                indents.pop()
+                continue
+            elif toknum in (NEWLINE, NL):
+                startline = True
+            elif startline and indents:
+                toks_append(indents[-1])
+                startline = False
+            toks_append(tokval)
+
+def untokenize(iterable):
+    """Transform tokens back into Python source code.
+
+    Each element returned by the iterable must be a token sequence
+    with at least two elements, a token number and token value.  If
+    only two tokens are passed, the resulting output is poor.
+
+    Round-trip invariant for full input:
+        Untokenized source will match input source exactly
+
+    Round-trip invariant for limited intput:
+        # Output text will tokenize the back to the input
+        t1 = [tok[:2] for tok in generate_tokens(f.readline)]
+        newcode = untokenize(t1)
+        readline = iter(newcode.splitlines(1)).next
+        t2 = [tok[:2] for tokin generate_tokens(readline)]
+        assert t1 == t2
+    """
+    ut = Untokenizer()
+    return ut.untokenize(iterable)
+
+def generate_tokens(readline):
+    """
+    The generate_tokens() generator requires one argment, readline, which
+    must be a callable object which provides the same interface as the
+    readline() method of built-in file objects. Each call to the function
+    should return one line of input as a string.  Alternately, readline
+    can be a callable function terminating with StopIteration:
+        readline = open(myfile).next    # Example of alternate readline
+
+    The generator produces 5-tuples with these members: the token type; the
+    token string; a 2-tuple (srow, scol) of ints specifying the row and
+    column where the token begins in the source; a 2-tuple (erow, ecol) of
+    ints specifying the row and column where the token ends in the source;
+    and the line on which the token was found. The line passed is the
+    logical line; continuation lines are included.
+    """
+    lnum = parenlev = continued = 0
+    namechars, numchars = string.ascii_letters + '_', '0123456789'
+    contstr, needcont = '', 0
+    contline = None
+    indents = [0]
+
+    while 1:                                   # loop over lines in stream
+        try:
+            line = readline()
+        except StopIteration:
+            line = ''
+        lnum = lnum + 1
+        pos, max = 0, len(line)
+
+        if contstr:                            # continued string
+            if not line:
+                raise TokenError, ("EOF in multi-line string", strstart)
+            endmatch = endprog.match(line)
+            if endmatch:
+                pos = end = endmatch.end(0)
+                yield (STRING, contstr + line[:end],
+                       strstart, (lnum, end), contline + line)
+                contstr, needcont = '', 0
+                contline = None
+            elif needcont and line[-2:] != '\\\n' and line[-3:] != '\\\r\n':
+                yield (ERRORTOKEN, contstr + line,
+                           strstart, (lnum, len(line)), contline)
+                contstr = ''
+                contline = None
+                continue
+            else:
+                contstr = contstr + line
+                contline = contline + line
+                continue
+
+        elif parenlev == 0 and not continued:  # new statement
+            if not line: break
+            column = 0
+            while pos < max:                   # measure leading whitespace
+                if line[pos] == ' ': column = column + 1
+                elif line[pos] == '\t': column = (column/tabsize + 1)*tabsize
+                elif line[pos] == '\f': column = 0
+                else: break
+                pos = pos + 1
+            if pos == max: break
+
+            if line[pos] in '#\r\n':           # skip comments or blank lines
+                if line[pos] == '#':
+                    comment_token = line[pos:].rstrip('\r\n')
+                    nl_pos = pos + len(comment_token)
+                    yield (COMMENT, comment_token,
+                           (lnum, pos), (lnum, pos + len(comment_token)), line)
+                    yield (NL, line[nl_pos:],
+                           (lnum, nl_pos), (lnum, len(line)), line)
+                else:
+                    yield ((NL, COMMENT)[line[pos] == '#'], line[pos:],
+                           (lnum, pos), (lnum, len(line)), line)
+                continue
+
+            if column > indents[-1]:           # count indents or dedents
+                indents.append(column)
+                yield (INDENT, line[:pos], (lnum, 0), (lnum, pos), line)
+            while column < indents[-1]:
+                if column not in indents:
+                    raise IndentationError(
+                        "unindent does not match any outer indentation level",
+                        ("<tokenize>", lnum, pos, line))
+                indents = indents[:-1]
+                yield (DEDENT, '', (lnum, pos), (lnum, pos), line)
+
+        else:                                  # continued statement
+            if not line:
+                raise TokenError, ("EOF in multi-line statement", (lnum, 0))
+            continued = 0
+
+        while pos < max:
+            pseudomatch = pseudoprog.match(line, pos)
+            if pseudomatch:                                # scan for tokens
+                start, end = pseudomatch.span(1)
+                spos, epos, pos = (lnum, start), (lnum, end), end
+                token, initial = line[start:end], line[start]
+
+                if initial in numchars or \
+                   (initial == '.' and token != '.'):      # ordinary number
+                    yield (NUMBER, token, spos, epos, line)
+                elif initial in '\r\n':
+                    newline = NEWLINE
+                    if parenlev > 0:
+                        newline = NL
+                    yield (newline, token, spos, epos, line)
+                elif initial == '#':
+                    assert not token.endswith("\n")
+                    yield (COMMENT, token, spos, epos, line)
+                elif token in triple_quoted:
+                    endprog = endprogs[token]
+                    endmatch = endprog.match(line, pos)
+                    if endmatch:                           # all on one line
+                        pos = endmatch.end(0)
+                        token = line[start:pos]
+                        yield (STRING, token, spos, (lnum, pos), line)
+                    else:
+                        strstart = (lnum, start)           # multiple lines
+                        contstr = line[start:]
+                        contline = line
+                        break
+                elif initial in single_quoted or \
+                    token[:2] in single_quoted or \
+                    token[:3] in single_quoted:
+                    if token[-1] == '\n':                  # continued string
+                        strstart = (lnum, start)
+                        endprog = (endprogs[initial] or endprogs[token[1]] or
+                                   endprogs[token[2]])
+                        contstr, needcont = line[start:], 1
+                        contline = line
+                        break
+                    else:                                  # ordinary string
+                        yield (STRING, token, spos, epos, line)
+                elif initial in namechars:                 # ordinary name
+                    yield (NAME, token, spos, epos, line)
+                elif initial == '\\':                      # continued stmt
+                    # This yield is new; needed for better idempotency:
+                    yield (NL, token, spos, (lnum, pos), line)
+                    continued = 1
+                else:
+                    if initial in '([{': parenlev = parenlev + 1
+                    elif initial in ')]}': parenlev = parenlev - 1
+                    yield (OP, token, spos, epos, line)
+            else:
+                yield (ERRORTOKEN, line[pos],
+                           (lnum, pos), (lnum, pos+1), line)
+                pos = pos + 1
+
+    for indent in indents[1:]:                 # pop remaining indent levels
+        yield (DEDENT, '', (lnum, 0), (lnum, 0), '')
+    yield (ENDMARKER, '', (lnum, 0), (lnum, 0), '')
+
+if __name__ == '__main__':                     # testing
+    import sys
+    if len(sys.argv) > 1: tokenize(open(sys.argv[1]).readline)
+    else: tokenize(sys.stdin.readline)

Modified: doctools/trunk/sphinx/quickstart.py
==============================================================================
--- doctools/trunk/sphinx/quickstart.py	(original)
+++ doctools/trunk/sphinx/quickstart.py	Sun Jan  4 21:38:57 2009
@@ -5,8 +5,8 @@
 
     Quickly setup documentation source to work with Sphinx.
 
-    :copyright: 2008 by Georg Brandl.
-    :license: BSD.
+    :copyright: Copyright 2007-2009 by the Sphinx team, see AUTHORS.
+    :license: BSD, see LICENSE for details.
 """
 
 import sys, os, time
@@ -165,8 +165,8 @@
 # If true, the index is split into individual pages for each letter.
 #html_split_index = False
 
-# If true, the reST sources are included in the HTML build as _sources/<name>.
-#html_copy_source = True
+# If true, links to the reST sources are added to the pages.
+#html_show_sourcelink = True
 
 # If true, an OpenSearch description file will be output, and all pages will
 # contain a <link> tag referring to it.  The value of this option must be the
@@ -257,7 +257,7 @@
 ALLSPHINXOPTS   = -d %(rbuilddir)s/doctrees $(PAPEROPT_$(PAPER)) \
 $(SPHINXOPTS) %(rsrcdir)s
 
-.PHONY: help clean html web pickle htmlhelp latex changes linkcheck
+.PHONY: help clean html pickle json htmlhelp qthelp latex changes linkcheck
 
 help:
 \t at echo "Please use \\`make <target>' where <target> is one of"
@@ -265,6 +265,7 @@
 \t at echo "  pickle    to make pickle files"
 \t at echo "  json      to make JSON files"
 \t at echo "  htmlhelp  to make HTML files and a HTML help project"
+\t at echo "  qthelp    to make HTML files and a qthelp project"
 \t at echo "  latex     to make LaTeX files, you can set PAPER=a4 or PAPER=letter"
 \t at echo "  changes   to make an overview over all changed/added/deprecated items"
 \t at echo "  linkcheck to check all external links for integrity"
@@ -284,8 +285,6 @@
 \t at echo
 \t at echo "Build finished; now you can process the pickle files."
 
-web: pickle
-
 json:
 \tmkdir -p %(rbuilddir)s/json %(rbuilddir)s/doctrees
 \t$(SPHINXBUILD) -b json $(ALLSPHINXOPTS) %(rbuilddir)s/json
@@ -299,6 +298,16 @@
 \t at echo "Build finished; now you can run HTML Help Workshop with the" \\
 \t      ".hhp project file in %(rbuilddir)s/htmlhelp."
 
+qthelp:
+\tmkdir -p %(rbuilddir)s/qthelp %(rbuilddir)s/doctrees
+\t$(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) %(rbuilddir)s/qthelp
+\t at echo
+\t at echo "Build finished; now you can run "qcollectiongenerator" with the" \\
+\t      ".qhcp project file in %(rbuilddir)s/qthelp, like this:"
+\t at echo "# qcollectiongenerator %(rbuilddir)s/qthelp/Sphinx.qhcp"
+\t at echo "To view the help file:"
+\t at echo "# assistant -collectionFile %(rbuilddir)s/qthelp/%(project)s.qhc"
+
 latex:
 \tmkdir -p %(rbuilddir)s/latex %(rbuilddir)s/doctrees
 \t$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) %(rbuilddir)s/latex

Modified: doctools/trunk/sphinx/roles.py
==============================================================================
--- doctools/trunk/sphinx/roles.py	(original)
+++ doctools/trunk/sphinx/roles.py	Sun Jan  4 21:38:57 2009
@@ -5,8 +5,8 @@
 
     Handlers for additional ReST roles.
 
-    :copyright: 2007-2008 by Georg Brandl.
-    :license: BSD.
+    :copyright: Copyright 2007-2009 by the Sphinx team, see AUTHORS.
+    :license: BSD, see LICENSE for details.
 """
 
 import re
@@ -24,7 +24,7 @@
     'guilabel' : nodes.strong,
     'kbd' : nodes.literal,
     'mailheader' : addnodes.literal_emphasis,
-    'makevar' : nodes.Text,
+    'makevar' : nodes.strong,
     'manpage' : addnodes.literal_emphasis,
     'mimetype' : addnodes.literal_emphasis,
     'newsgroup' : addnodes.literal_emphasis,
@@ -96,6 +96,7 @@
     'term': nodes.emphasis,
     'token': nodes.strong,
     'envvar': nodes.strong,
+    'download': nodes.strong,
     'option': addnodes.literal_emphasis,
 }
 
@@ -122,8 +123,10 @@
         return [innernodetypes.get(typ, nodes.literal)(
             rawtext, text, classes=['xref'])], []
     # we want a cross-reference, create the reference node
-    pnode = addnodes.pending_xref(rawtext, reftype=typ, refcaption=False,
-                                  modname=env.currmodule, classname=env.currclass)
+    nodeclass = (typ == 'download') and addnodes.download_reference or \
+                addnodes.pending_xref
+    pnode = nodeclass(rawtext, reftype=typ, refcaption=False,
+                      modname=env.currmodule, classname=env.currclass)
     # we may need the line number for warnings
     pnode.line = lineno
     # the link title may differ from the target, but by default they are the same
@@ -235,6 +238,8 @@
     'token': xfileref_role,
     'term': xfileref_role,
     'option': xfileref_role,
+    'doc': xfileref_role,
+    'download': xfileref_role,
 
     'menuselection': menusel_role,
     'file': emph_literal_role,

Modified: doctools/trunk/sphinx/search.py
==============================================================================
--- doctools/trunk/sphinx/search.py	(original)
+++ doctools/trunk/sphinx/search.py	Sun Jan  4 21:38:57 2009
@@ -5,8 +5,8 @@
 
     Create a search index for offline search.
 
-    :copyright: 2007-2008 by Armin Ronacher.
-    :license: BSD.
+    :copyright: Copyright 2007-2009 by the Sphinx team, see AUTHORS.
+    :license: BSD, see LICENSE for details.
 """
 import re
 import cPickle as pickle

Modified: doctools/trunk/sphinx/setup_command.py
==============================================================================
--- doctools/trunk/sphinx/setup_command.py	(original)
+++ doctools/trunk/sphinx/setup_command.py	Sun Jan  4 21:38:57 2009
@@ -8,8 +8,8 @@
 
     :author: Sebastian Wiesner
     :contact: basti.wiesner at gmx.net
-    :copyright: 2008 by Sebastian Wiesner.
-    :license: MIT.
+    :copyright: Copyright 2007-2009 by the Sphinx team, see AUTHORS.
+    :license: BSD, see LICENSE for details.
 """
 
 import sys

Modified: doctools/trunk/sphinx/static/searchtools.js
==============================================================================
--- doctools/trunk/sphinx/static/searchtools.js	(original)
+++ doctools/trunk/sphinx/static/searchtools.js	Sun Jan  4 21:38:57 2009
@@ -239,7 +239,7 @@
   },
 
   hasIndex : function() {
-      return self._index !== null;
+      return this._index !== null;
   },
 
   deferQuery : function(query) {
@@ -431,7 +431,7 @@
           listItem.slideDown(5, function() {
             displayNextItem();
           });
-        } else {
+        } else if (DOCUMENTATION_OPTIONS.HAS_SOURCE) {
           $.get('_sources/' + item[0] + '.txt', function(data) {
             listItem.append($.makeSearchSummary(data, searchterms, hlterms));
             Search.output.append(listItem);
@@ -439,6 +439,12 @@
               displayNextItem();
             });
           });
+        } else {
+          // no source available, just display title
+          Search.output.append(listItem);
+          listItem.slideDown(5, function() {
+            displayNextItem();
+          });
         }
       }
       // search finished, update title and status message

Modified: doctools/trunk/sphinx/templates/changes/versionchanges.html
==============================================================================
--- doctools/trunk/sphinx/templates/changes/versionchanges.html	(original)
+++ doctools/trunk/sphinx/templates/changes/versionchanges.html	Sun Jan  4 21:38:57 2009
@@ -1,4 +1,4 @@
-{% macro entries changes %}
+{% macro entries(changes) %}
 <ul>{% for entry, docname, lineno in changes %}
 <li><a href="rst/{{ docname }}.html#L{{ lineno-10 }}" target="src">{{ entry }}</a></li>
 {% endfor %}</ul>

Modified: doctools/trunk/sphinx/templates/layout.html
==============================================================================
--- doctools/trunk/sphinx/templates/layout.html	(original)
+++ doctools/trunk/sphinx/templates/layout.html	Sun Jan  4 21:38:57 2009
@@ -4,7 +4,7 @@
 {%- endblock %}
 {%- set reldelim1 = reldelim1 is not defined and ' &raquo;' or reldelim1 %}
 {%- set reldelim2 = reldelim2 is not defined and ' |' or reldelim2 %}
-{%- macro relbar %}
+{%- macro relbar() %}
     <div class="related">
       <h3>{{ _('Navigation') }}</h3>
       <ul>
@@ -24,8 +24,8 @@
       </ul>
     </div>
 {%- endmacro %}
-{%- macro sidebar %}
-      {%- if builder != 'htmlhelp' %}
+{%- macro sidebar() %}
+      {%- if not embedded %}
       <div class="sphinxsidebar">
         <div class="sphinxsidebarwrapper">
           {%- block sidebarlogo %}
@@ -51,64 +51,53 @@
             <p class="topless"><a href="{{ next.link|e }}" title="{{ _('next chapter') }}">{{ next.title }}</a></p>
           {%- endif %}
           {%- endblock %}
-          {%- if sourcename %}
+          {%- block sidebarsourcelink %}
+          {%- if show_source and has_source and sourcename %}
             <h3>{{ _('This Page') }}</h3>
             <ul class="this-page-menu">
-            {%- if builder == 'web' %}
-              <li><a href="#comments">Comments ({{ comments|length }} so far)</a></li>
-              <li><a href="{{ pathto('@edit/' + sourcename)|e }}">{{ _('Suggest Change') }}</a></li>
-              <li><a href="{{ pathto('@source/' + sourcename)|e }}">{{ _('Show Source') }}</a></li>
-            {%- elif builder == 'html' %}
-              <li><a href="{{ pathto('_sources/' + sourcename, true)|e }}">{{ _('Show Source') }}</a></li>
-            {%- endif %}
+              <li><a href="{{ pathto('_sources/' + sourcename, true)|e }}" rel="nofollow">{{ _('Show Source') }}</a></li>
             </ul>
           {%- endif %}
+          {%- endblock %}
           {%- if customsidebar %}
-          {{ rendertemplate(customsidebar) }}
+          {% include customsidebar %}
           {%- endif %}
           {%- block sidebarsearch %}
           {%- if pagename != "search" %}
-          <h3>{% if builder == 'web' %}{{ _('Keyword search')}}{% else %}{{ _('Quick search') }}{% endif %}</h3>
+          <h3>{{ _('Quick search') }}</h3>
             <form class="search" action="{{ pathto('search') }}" method="get">
               <input type="text" name="q" size="18" /> <input type="submit" value="{{ _('Go') }}" />
               <input type="hidden" name="check_keywords" value="yes" />
               <input type="hidden" name="area" value="default" />
             </form>
-            {%- if builder == 'web' %}
-            <p style="font-size: 90%">{{ _('Enter a module, class or function name.') }}</p>
-            {%- endif %}
+            <p style="font-size: 90%">{{ _('Enter search terms or a module, class or function name.') }}</p>
           {%- endif %}
           {%- endblock %}
         </div>
       </div>
       {%- endif %}
-{%- endmacro -%}
+{%- endmacro %}
 
 <html xmlns="http://www.w3.org/1999/xhtml">
   <head>
     <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
     {{ metatags }}
-    {%- if builder != 'htmlhelp' %}
-      {%- set titlesuffix = " &mdash; " + docstitle|e %}
+    {%- if not embedded %}
+      {%- set titlesuffix = " &mdash; "|safe + docstitle|e %}
+    {%- else %}
+      {%- set titlesuffix = "" %}
     {%- endif %}
     <title>{{ title|striptags }}{{ titlesuffix }}</title>
-    {%- if builder == 'web' %}
-    <link rel="stylesheet" href="{{ pathto('index') }}?do=stylesheet{%
-      if in_admin_panel %}&admin=yes{% endif %}" type="text/css" />
-    {%- for link, type, title in page_links %}
-    <link rel="alternate" type="{{ type|e(true) }}" title="{{ title|e(true) }}" href="{{ link|e(true) }}" />
-    {%- endfor %}
-    {%- else %}
     <link rel="stylesheet" href="{{ pathto('_static/' + style, 1) }}" type="text/css" />
     <link rel="stylesheet" href="{{ pathto('_static/pygments.css', 1) }}" type="text/css" />
-    {%- endif %}
-    {%- if builder != 'htmlhelp' %}
+    {%- if not embedded %}
     <script type="text/javascript">
       var DOCUMENTATION_OPTIONS = {
-          URL_ROOT:    '{{ pathto("", 1) }}',
-          VERSION:     '{{ release|e }}',
-          COLLAPSE_MODINDEX: false,
-          FILE_SUFFIX: '{{ file_suffix }}'
+        URL_ROOT:    '{{ pathto("", 1) }}',
+        VERSION:     '{{ release|e }}',
+        COLLAPSE_MODINDEX: false,
+        FILE_SUFFIX: '{{ file_suffix }}',
+        HAS_SOURCE:  {{ has_source|lower }}
       };
     </script>
     {%- for scriptfile in script_files %}
@@ -154,13 +143,13 @@
 {%- block document %}
     <div class="document">
       <div class="documentwrapper">
-      {%- if builder != 'htmlhelp' %}
+      {%- if not embedded %}
         <div class="bodywrapper">
       {%- endif %}
           <div class="body">
             {% block body %} {% endblock %}
           </div>
-      {%- if builder != 'htmlhelp' %}
+      {%- if not embedded %}
         </div>
       {%- endif %}
       </div>

Modified: doctools/trunk/sphinx/templates/modindex.html
==============================================================================
--- doctools/trunk/sphinx/templates/modindex.html	(original)
+++ doctools/trunk/sphinx/templates/modindex.html	Sun Jan  4 21:38:57 2009
@@ -2,7 +2,7 @@
 {% set title = _('Global Module Index') %}
 {% block extrahead %}
 {{ super() }}
-{% if builder != 'htmlhelp' and collapse_modindex %}
+{% if not embedded and collapse_modindex %}
     <script type="text/javascript">
       DOCUMENTATION_OPTIONS.COLLAPSE_MODINDEX = true;
     </script>
@@ -11,26 +11,6 @@
 {% block body %}
 
    <h1 id="global-module-index">{{ _('Global Module Index') }}</h1>
-{% if builder == 'web' and freqentries %}
-   <p>{{ _('Most popular modules:') }}</p>
-   <div class="modulecloud">
-   {%- for module in freqentries %}
-     <a href="../q/{{ module.name|e }}/" style="font-size: {{ module.size }}%">{{ module.name|e }}</a>
-   {%- endfor %}
-   </div>
-{% endif %}
-{% if builder == 'web' %}
-   <form class="pfform" action="" method="get">
-     {{ _('Show modules only available on these platforms') }}:<br>
-     {% for pl in platforms -%}
-     <input type="checkbox" name="pf" value="{{ pl }}" id="pl-{{ pl }}"
-            {%- if pl in showpf %} checked="checked"{% endif %}>
-     <label for="pl-{{ pl }}">{{ pl }}</label>
-     {% endfor %}
-     <input type="hidden" name="newpf" value="true">
-     <input type="submit" value="Apply">
-   </form>
-{% endif %}
 
    {%- for letter in letters %}
    <a href="#cap-{{ letter }}"><strong>{{ letter }}</strong></a> {% if not loop.last %}| {% endif %}
@@ -52,7 +32,7 @@
      {% if fname %}<a href="{{ fname }}">{% endif -%}
      <tt class="xref">{{ modname|e }}</tt>
      {%- if fname %}</a>{% endif %}
-   {%- if pform[0] %} <em>({{ pform|join(', ') }})</em>{% endif -%}
+   {%- if pform and pform[0] %} <em>({{ pform|join(', ') }})</em>{% endif -%}
    </td><td>{% if dep %}<strong>{{ _('Deprecated')}}:</strong>{% endif %}
      <em>{{ synops|e }}</em></td></tr>
    {%- endif -%}

Modified: doctools/trunk/sphinx/templates/page.html
==============================================================================
--- doctools/trunk/sphinx/templates/page.html	(original)
+++ doctools/trunk/sphinx/templates/page.html	Sun Jan  4 21:38:57 2009
@@ -1,12 +1,4 @@
 {% extends "layout.html" %}
-{% set page_links = [
-  (pathto('@rss/' + sourcename), 'application/rss+xml', 'Page Comments'),
-] %}
 {% block body %}
-  {% if oldurl %}
-  <div class="docwarning">
-    {% trans %}<strong>Note:</strong> You requested an out-of-date URL from this server. We've tried to redirect you to the new location of this page, but it may not be the right one.{% endtrans %}
-  </div>
-  {% endif %}
   {{ body }}
 {% endblock %}

Modified: doctools/trunk/sphinx/texinputs/sphinx.sty
==============================================================================
--- doctools/trunk/sphinx/texinputs/sphinx.sty	(original)
+++ doctools/trunk/sphinx/texinputs/sphinx.sty	Sun Jan  4 21:38:57 2009
@@ -451,6 +451,35 @@
     \fi
 }{\end{fulllineitems}}
 
+% class method ----------------------------------------------------------
+% \begin{classmethoddesc}[classname]{methodname}{args}
+\newcommand{\classmethodline}[3][\@undefined]{
+  \classmethodlineni{#2}{#3}
+  \ifx\@undefined#1\relax
+    \index{#2@{\py at idxcode{#2()}} (\py at thisclass\ class method)}
+  \else
+    \index{#2@{\py at idxcode{#2()}} (#1 class method)}
+  \fi
+}
+\newenvironment{classmethoddesc}[3][\@undefined]{
+  \begin{fulllineitems}
+    \ifx\@undefined#1\relax
+      \classmethodline{#2}{#3}
+    \else
+      \def\py at thisclass{#1}
+      \classmethodline{#2}{#3}
+    \fi
+}{\end{fulllineitems}}
+
+% similar to {classmethoddesc}, but doesn't add to the index
+% (never actually uses the optional argument)
+\newcommand{\classmethodlineni}[3][\py at classbadkey]{%
+  \py at sigline{class \bfcode{#2}}{#3}}
+\newenvironment{classmethoddescni}[3][\py at classbadkey]{
+  \begin{fulllineitems}
+    \classmethodlineni{#2}{#3}
+}{\end{fulllineitems}}
+
 % object data attribute --------------------------------------------------
 % \begin{memberdesc}[classname]{membername}
 \newcommand{\memberline}[2][\py at classbadkey]{%

Modified: doctools/trunk/sphinx/util/__init__.py
==============================================================================
--- doctools/trunk/sphinx/util/__init__.py	(original)
+++ doctools/trunk/sphinx/util/__init__.py	Sun Jan  4 21:38:57 2009
@@ -5,8 +5,8 @@
 
     Utility functions for Sphinx.
 
-    :copyright: 2007-2008 by Georg Brandl.
-    :license: BSD.
+    :copyright: Copyright 2007-2009 by the Sphinx team, see AUTHORS.
+    :license: BSD, see LICENSE for details.
 """
 
 import os
@@ -15,6 +15,7 @@
 import time
 import fnmatch
 import tempfile
+import posixpath
 import traceback
 from os import path
 
@@ -48,6 +49,11 @@
     return ('..' + SEP) * (len(b2)-1) + SEP.join(t2)
 
 
+def docname_join(basedocname, docname):
+    return posixpath.normpath(
+        posixpath.join('/' + basedocname, '..', docname))[1:]
+
+
 def ensuredir(path):
     """Ensure that a path exists."""
     try:
@@ -282,3 +288,76 @@
 def ustrftime(format, *args):
     # strftime for unicode strings
     return time.strftime(unicode(format).encode('utf-8'), *args).decode('utf-8')
+
+
+class FilenameUniqDict(dict):
+    """
+    A dictionary that automatically generates unique names for its keys,
+    interpreted as filenames, and keeps track of a set of docnames they
+    appear in.  Used for images and downloadable files in the environment.
+    """
+    def __init__(self):
+        self._existing = set()
+
+    def add_file(self, docname, newfile):
+        if newfile in self:
+            self[newfile][0].add(docname)
+            return
+        uniquename = path.basename(newfile)
+        base, ext = path.splitext(uniquename)
+        i = 0
+        while uniquename in self._existing:
+            i += 1
+            uniquename = '%s%s%s' % (base, i, ext)
+        self[newfile] = (set([docname]), uniquename)
+        self._existing.add(uniquename)
+        return uniquename
+
+    def purge_doc(self, docname):
+        for filename, (docs, _) in self.items():
+            docs.discard(docname)
+            if not docs:
+                del self[filename]
+
+    def __getstate__(self):
+        return self._existing
+
+    def __setstate__(self, state):
+        self._existing = state
+
+
+def parselinenos(spec, total):
+    """
+    Parse a line number spec (such as "1,2,4-6") and return a list of
+    wanted line numbers.
+    """
+    items = list()
+    parts = spec.split(',')
+    for part in parts:
+        try:
+            begend = part.strip().split('-')
+            if len(begend) > 2:
+                raise ValueError
+            if len(begend) == 1:
+                items.append(int(begend[0])-1)
+            else:
+                start = (begend[0] == '') and 0 or int(begend[0])-1
+                end = (begend[1] == '') and total or int(begend[1])
+                items.extend(xrange(start, end))
+        except Exception, err:
+            raise ValueError('invalid line number spec: %r' % spec)
+    return items
+
+
+def force_decode(string, encoding):
+    if isinstance(string, str):
+        if encoding:
+            string = string.decode(encoding)
+        else:
+            try:
+                # try decoding with utf-8, should only work for real UTF-8
+                string = string.decode('utf-8')
+            except UnicodeError:
+                # last resort -- can't fail
+                string = string.decode('latin1')
+    return string

Modified: doctools/trunk/sphinx/util/compat.py
==============================================================================
--- doctools/trunk/sphinx/util/compat.py	(original)
+++ doctools/trunk/sphinx/util/compat.py	Sun Jan  4 21:38:57 2009
@@ -5,8 +5,8 @@
 
     Stuff for docutils compatibility.
 
-    :copyright: 2008 by Georg Brandl.
-    :license: BSD.
+    :copyright: Copyright 2007-2009 by the Sphinx team, see AUTHORS.
+    :license: BSD, see LICENSE for details.
 """
 
 from docutils import nodes

Modified: doctools/trunk/sphinx/util/console.py
==============================================================================
--- doctools/trunk/sphinx/util/console.py	(original)
+++ doctools/trunk/sphinx/util/console.py	Sun Jan  4 21:38:57 2009
@@ -5,8 +5,8 @@
 
     Format colored console output.
 
-    :copyright: 2007-2008 by Georg Brandl.
-    :license: BSD.
+    :copyright: Copyright 2007-2009 by the Sphinx team, see AUTHORS.
+    :license: BSD, see LICENSE for details.
 """
 
 import os

Added: doctools/trunk/sphinx/util/docstrings.py
==============================================================================
--- (empty file)
+++ doctools/trunk/sphinx/util/docstrings.py	Sun Jan  4 21:38:57 2009
@@ -0,0 +1,56 @@
+# -*- coding: utf-8 -*-
+"""
+    sphinx.util.docstrings
+    ~~~~~~~~~~~~~~~~~~~~~~
+
+    Utilities for docstring processing.
+
+    :copyright: Copyright 2007-2009 by the Sphinx team, see AUTHORS.
+    :license: BSD, see LICENSE for details.
+"""
+
+import sys
+
+
+def prepare_docstring(s):
+    """
+    Convert a docstring into lines of parseable reST.  Return it as a list of
+    lines usable for inserting into a docutils ViewList (used as argument
+    of nested_parse().)  An empty line is added to act as a separator between
+    this docstring and following content.
+    """
+    lines = s.expandtabs().splitlines()
+    # Find minimum indentation of any non-blank lines after first line.
+    margin = sys.maxint
+    for line in lines[1:]:
+        content = len(line.lstrip())
+        if content:
+            indent = len(line) - content
+            margin = min(margin, indent)
+    # Remove indentation.
+    if lines:
+        lines[0] = lines[0].lstrip()
+    if margin < sys.maxint:
+        for i in range(1, len(lines)): lines[i] = lines[i][margin:]
+    # Remove any leading blank lines.
+    while lines and not lines[0]:
+        lines.pop(0)
+    # make sure there is an empty line at the end
+    if lines and lines[-1]:
+        lines.append('')
+    return lines
+
+
+def prepare_commentdoc(s):
+    """
+    Extract documentation comment lines (starting with #:) and return them as a
+    list of lines.  Returns an empty list if there is no documentation.
+    """
+    result = []
+    lines = [line.strip() for line in s.expandtabs().splitlines()]
+    for line in lines:
+        if line.startswith('#: '):
+            result.append(line[3:])
+    if result and result[-1]:
+        result.append('')
+    return result

Modified: doctools/trunk/sphinx/util/jsdump.py
==============================================================================
--- doctools/trunk/sphinx/util/jsdump.py	(original)
+++ doctools/trunk/sphinx/util/jsdump.py	Sun Jan  4 21:38:57 2009
@@ -4,10 +4,10 @@
     ~~~~~~~~~~~~~~~~~~
 
     This module implements a simple JavaScript serializer.
-    Uses the basestring encode function from simplejson.
+    Uses the basestring encode function from simplejson by Bob Ippolito.
 
-    :copyright: 2008 by Armin Ronacher, Bob Ippolito, Georg Brandl.
-    :license: BSD.
+    :copyright: Copyright 2007-2009 by the Sphinx team, see AUTHORS.
+    :license: BSD, see LICENSE for details.
 """
 
 import re

Added: doctools/trunk/sphinx/util/png.py
==============================================================================
--- (empty file)
+++ doctools/trunk/sphinx/util/png.py	Sun Jan  4 21:38:57 2009
@@ -0,0 +1,58 @@
+# -*- coding: utf-8 -*-
+"""
+    sphinx.util.png
+    ~~~~~~~~~~~~~~~
+
+    PNG image manipulation helpers.
+
+    :copyright: Copyright 2007-2009 by the Sphinx team, see AUTHORS.
+    :license: BSD, see LICENSE for details.
+"""
+
+import struct
+import binascii
+
+LEN_IEND = 12
+LEN_DEPTH = 22
+
+DEPTH_CHUNK_LEN = struct.pack('!i', 10)
+DEPTH_CHUNK_START = 'tEXtDepth\x00'
+IEND_CHUNK = '\x00\x00\x00\x00IEND\xAE\x42\x60\x82'
+
+
+def read_png_depth(filename):
+    """
+    Read the special tEXt chunk indicating the depth from a PNG file.
+    """
+    result = None
+    f = open(filename, 'rb')
+    try:
+        f.seek(- (LEN_IEND + LEN_DEPTH), 2)
+        depthchunk = f.read(LEN_DEPTH)
+        if not depthchunk.startswith(DEPTH_CHUNK_LEN + DEPTH_CHUNK_START):
+            # either not a PNG file or not containing the depth chunk
+            return None
+        result = struct.unpack('!i', depthchunk[14:18])[0]
+    finally:
+        f.close()
+    return result
+
+
+def write_png_depth(filename, depth):
+    """
+    Write the special tEXt chunk indicating the depth to a PNG file.
+    The chunk is placed immediately before the special IEND chunk.
+    """
+    data = struct.pack('!i', depth)
+    f = open(filename, 'r+b')
+    try:
+        # seek to the beginning of the IEND chunk
+        f.seek(-LEN_IEND, 2)
+        # overwrite it with the depth chunk
+        f.write(DEPTH_CHUNK_LEN + DEPTH_CHUNK_START + data)
+        # calculate the checksum over chunk name and data
+        f.write(struct.pack('!i', binascii.crc32(DEPTH_CHUNK_START + data)))
+        # replace the IEND chunk
+        f.write(IEND_CHUNK)
+    finally:
+        f.close()

Modified: doctools/trunk/sphinx/util/stemmer.py
==============================================================================
--- doctools/trunk/sphinx/util/stemmer.py	(original)
+++ doctools/trunk/sphinx/util/stemmer.py	Sun Jan  4 21:38:57 2009
@@ -24,7 +24,7 @@
 
     Release 1: January 2001
 
-    :copyright: 2001 by Vivake Gupta <v at nano.com>.
+    :copyright: Copyright 2001 by Vivake Gupta <v at nano.com>.
     :license: Public Domain ("can be used free of charge for any purpose").
 """
 

Modified: doctools/trunk/sphinx/util/texescape.py
==============================================================================
--- doctools/trunk/sphinx/util/texescape.py	(original)
+++ doctools/trunk/sphinx/util/texescape.py	Sun Jan  4 21:38:57 2009
@@ -5,8 +5,8 @@
 
     TeX escaping helper.
 
-    :copyright: 2008 by Georg Brandl.
-    :license: BSD.
+    :copyright: Copyright 2007-2009 by the Sphinx team, see AUTHORS.
+    :license: BSD, see LICENSE for details.
 """
 
 tex_replacements = [

Added: doctools/trunk/sphinx/writers/__init__.py
==============================================================================
--- (empty file)
+++ doctools/trunk/sphinx/writers/__init__.py	Sun Jan  4 21:38:57 2009
@@ -0,0 +1,10 @@
+# -*- coding: utf-8 -*-
+"""
+    sphinx.writers
+    ~~~~~~~~~~~~~~
+
+    Custom docutils writers.
+
+    :copyright: Copyright 2007-2009 by the Sphinx team, see AUTHORS.
+    :license: BSD, see LICENSE for details.
+"""

Added: doctools/trunk/sphinx/writers/html.py
==============================================================================
--- (empty file)
+++ doctools/trunk/sphinx/writers/html.py	Sun Jan  4 21:38:57 2009
@@ -0,0 +1,473 @@
+# -*- coding: utf-8 -*-
+"""
+    sphinx.writers.html
+    ~~~~~~~~~~~~~~~~~~~
+
+    docutils writers handling Sphinx' custom nodes.
+
+    :copyright: Copyright 2007-2009 by the Sphinx team, see AUTHORS.
+    :license: BSD, see LICENSE for details.
+"""
+
+import sys
+import posixpath
+import os
+
+from docutils import nodes
+from docutils.writers.html4css1 import Writer, HTMLTranslator as BaseTranslator
+
+from sphinx.locale import admonitionlabels, versionlabels
+from sphinx.highlighting import PygmentsBridge
+from sphinx.util.smartypants import sphinx_smarty_pants
+
+try:
+    import Image                        # check for the Python Imaging Library
+except ImportError:
+    Image = None
+
+class HTMLWriter(Writer):
+    def __init__(self, builder):
+        Writer.__init__(self)
+        self.builder = builder
+
+    def translate(self):
+        # sadly, this is mostly copied from parent class
+        self.visitor = visitor = self.builder.translator_class(self.builder,
+                                                               self.document)
+        self.document.walkabout(visitor)
+        self.output = visitor.astext()
+        for attr in ('head_prefix', 'stylesheet', 'head', 'body_prefix',
+                     'body_pre_docinfo', 'docinfo', 'body', 'fragment',
+                     'body_suffix', 'meta', 'title', 'subtitle', 'header',
+                     'footer', 'html_prolog', 'html_head', 'html_title',
+                     'html_subtitle', 'html_body', ):
+            setattr(self, attr, getattr(visitor, attr, None))
+        self.clean_meta = ''.join(visitor.meta[2:])
+
+
+class HTMLTranslator(BaseTranslator):
+    """
+    Our custom HTML translator.
+    """
+
+    def __init__(self, builder, *args, **kwds):
+        BaseTranslator.__init__(self, *args, **kwds)
+        self.highlighter = PygmentsBridge('html', builder.config.pygments_style)
+        self.no_smarty = 0
+        self.builder = builder
+        self.highlightlang = builder.config.highlight_language
+        self.highlightlinenothreshold = sys.maxint
+        self.protect_literal_text = 0
+        self.add_permalinks = builder.config.html_add_permalinks
+
+    def visit_desc(self, node):
+        self.body.append(self.starttag(node, 'dl', CLASS=node['desctype']))
+    def depart_desc(self, node):
+        self.body.append('</dl>\n\n')
+
+    def visit_desc_signature(self, node):
+        # the id is set automatically
+        self.body.append(self.starttag(node, 'dt'))
+        # anchor for per-desc interactive data
+        if node.parent['desctype'] != 'describe' and node['ids'] and node['first']:
+            self.body.append('<!--[%s]-->' % node['ids'][0])
+        if node.parent['desctype'] in ('class', 'exception'):
+            self.body.append('%s ' % node.parent['desctype'])
+    def depart_desc_signature(self, node):
+        if node['ids'] and self.add_permalinks and self.builder.add_permalinks:
+            self.body.append(u'<a class="headerlink" href="#%s" ' % node['ids'][0] +
+                             u'title="%s">\u00B6</a>' %
+                             _('Permalink to this definition'))
+        self.body.append('</dt>\n')
+
+    def visit_desc_addname(self, node):
+        self.body.append(self.starttag(node, 'tt', '', CLASS='descclassname'))
+    def depart_desc_addname(self, node):
+        self.body.append('</tt>')
+
+    def visit_desc_type(self, node):
+        pass
+    def depart_desc_type(self, node):
+        pass
+
+    def visit_desc_returns(self, node):
+        self.body.append(' &rarr; ')
+    def depart_desc_returns(self, node):
+        pass
+
+    def visit_desc_name(self, node):
+        self.body.append(self.starttag(node, 'tt', '', CLASS='descname'))
+    def depart_desc_name(self, node):
+        self.body.append('</tt>')
+
+    def visit_desc_parameterlist(self, node):
+        self.body.append('<big>(</big>')
+        self.first_param = 1
+    def depart_desc_parameterlist(self, node):
+        self.body.append('<big>)</big>')
+
+    def visit_desc_parameter(self, node):
+        if not self.first_param:
+            self.body.append(', ')
+        else:
+            self.first_param = 0
+        if not node.hasattr('noemph'):
+            self.body.append('<em>')
+    def depart_desc_parameter(self, node):
+        if not node.hasattr('noemph'):
+            self.body.append('</em>')
+
+    def visit_desc_optional(self, node):
+        self.body.append('<span class="optional">[</span>')
+    def depart_desc_optional(self, node):
+        self.body.append('<span class="optional">]</span>')
+
+    def visit_desc_annotation(self, node):
+        self.body.append(self.starttag(node, 'em', CLASS='property'))
+    def depart_desc_annotation(self, node):
+        self.body.append('</em>')
+
+    def visit_desc_content(self, node):
+        self.body.append(self.starttag(node, 'dd', ''))
+    def depart_desc_content(self, node):
+        self.body.append('</dd>')
+
+    def visit_refcount(self, node):
+        self.body.append(self.starttag(node, 'em', '', CLASS='refcount'))
+    def depart_refcount(self, node):
+        self.body.append('</em>')
+
+    def visit_versionmodified(self, node):
+        self.body.append(self.starttag(node, 'p'))
+        text = versionlabels[node['type']] % node['version']
+        if len(node):
+            text += ': '
+        else:
+            text += '.'
+        self.body.append('<span class="versionmodified">%s</span>' % text)
+    def depart_versionmodified(self, node):
+        self.body.append('</p>\n')
+
+    # overwritten
+    def visit_reference(self, node):
+        BaseTranslator.visit_reference(self, node)
+        if node.hasattr('reftitle'):
+            # ugly hack to add a title attribute
+            starttag = self.body[-1]
+            if not starttag.startswith('<a '):
+                return
+            self.body[-1] = '<a title="%s"' % self.attval(node['reftitle']) + \
+                            starttag[2:]
+
+    # overwritten -- we don't want source comments to show up in the HTML
+    def visit_comment(self, node):
+        raise nodes.SkipNode
+
+    # overwritten
+    def visit_admonition(self, node, name=''):
+        self.body.append(self.starttag(
+            node, 'div', CLASS=('admonition ' + name)))
+        if name and name != 'seealso':
+            node.insert(0, nodes.title(name, admonitionlabels[name]))
+        self.set_first_last(node)
+
+    def visit_seealso(self, node):
+        self.visit_admonition(node, 'seealso')
+    def depart_seealso(self, node):
+        self.depart_admonition(node)
+
+    # overwritten for docutils 0.4
+    if hasattr(BaseTranslator, 'start_tag_with_title'):
+        def visit_section(self, node):
+            # the 0.5 version, to get the id attribute in the <div> tag
+            self.section_level += 1
+            self.body.append(self.starttag(node, 'div', CLASS='section'))
+
+        def visit_title(self, node):
+            # don't move the id attribute inside the <h> tag
+            BaseTranslator.visit_title(self, node, move_ids=0)
+
+    # overwritten
+    def visit_literal_block(self, node):
+        if node.rawsource != node.astext():
+            # most probably a parsed-literal block -- don't highlight
+            return BaseTranslator.visit_literal_block(self, node)
+        lang = self.highlightlang
+        linenos = node.rawsource.count('\n') >= self.highlightlinenothreshold - 1
+        if node.has_key('language'):
+            # code-block directives
+            lang = node['language']
+        if node.has_key('linenos'):
+            linenos = node['linenos']
+        highlighted = self.highlighter.highlight_block(node.rawsource, lang, linenos)
+        starttag = self.starttag(node, 'div', suffix='', CLASS='highlight-%s' % lang)
+        self.body.append(starttag + highlighted + '</div>\n')
+        raise nodes.SkipNode
+
+    def visit_doctest_block(self, node):
+        self.visit_literal_block(node)
+
+    # overwritten
+    def visit_literal(self, node):
+        if len(node.children) == 1 and \
+               node.children[0] in ('None', 'True', 'False'):
+            node['classes'].append('xref')
+        self.body.append(self.starttag(node, 'tt', '', CLASS='docutils literal'))
+        self.protect_literal_text += 1
+    def depart_literal(self, node):
+        self.protect_literal_text -= 1
+        self.body.append('</tt>')
+
+    def visit_productionlist(self, node):
+        self.body.append(self.starttag(node, 'pre'))
+        names = []
+        for production in node:
+            names.append(production['tokenname'])
+        maxlen = max(len(name) for name in names)
+        for production in node:
+            if production['tokenname']:
+                lastname = production['tokenname'].ljust(maxlen)
+                self.body.append(self.starttag(production, 'strong', ''))
+                self.body.append(lastname + '</strong> ::= ')
+            else:
+                self.body.append('%s     ' % (' '*len(lastname)))
+            production.walkabout(self)
+            self.body.append('\n')
+        self.body.append('</pre>\n')
+        raise nodes.SkipNode
+    def depart_productionlist(self, node):
+        pass
+
+    def visit_production(self, node):
+        pass
+    def depart_production(self, node):
+        pass
+
+    def visit_centered(self, node):
+        self.body.append(self.starttag(node, 'p', CLASS="centered") + '<strong>')
+    def depart_centered(self, node):
+        self.body.append('</strong></p>')
+
+    def visit_compact_paragraph(self, node):
+        pass
+    def depart_compact_paragraph(self, node):
+        pass
+
+    def visit_highlightlang(self, node):
+        self.highlightlang = node['lang']
+        self.highlightlinenothreshold = node['linenothreshold']
+    def depart_highlightlang(self, node):
+        pass
+
+    def visit_download_reference(self, node):
+        if node.hasattr('filename'):
+            self.body.append('<a href="%s">' % posixpath.join(
+                self.builder.dlpath, node['filename']))
+            self.context.append('</a>')
+        else:
+            self.context.append('')
+    def depart_download_reference(self, node):
+        self.body.append(self.context.pop())
+
+    # overwritten
+    def visit_image(self, node):
+        olduri = node['uri']
+        # rewrite the URI if the environment knows about it
+        if olduri in self.builder.images:
+            node['uri'] = posixpath.join(self.builder.imgpath,
+                                         self.builder.images[olduri])
+
+        if node.has_key('scale'):
+            if Image and not (node.has_key('width')
+                              and node.has_key('height')):
+                try:
+                    im = Image.open(os.path.join(self.builder.srcdir,
+                                                    olduri))
+                except (IOError, # Source image can't be found or opened
+                        UnicodeError):  # PIL doesn't like Unicode paths.
+                    print olduri
+                    pass
+                else:
+                    if not node.has_key('width'):
+                        node['width'] = str(im.size[0])
+                    if not node.has_key('height'):
+                        node['height'] = str(im.size[1])
+                    del im
+        BaseTranslator.visit_image(self, node)
+
+    def visit_toctree(self, node):
+        # this only happens when formatting a toc from env.tocs -- in this
+        # case we don't want to include the subtree
+        raise nodes.SkipNode
+
+    def visit_index(self, node):
+        raise nodes.SkipNode
+
+    def visit_tabular_col_spec(self, node):
+        raise nodes.SkipNode
+
+    def visit_glossary(self, node):
+        pass
+    def depart_glossary(self, node):
+        pass
+
+    def visit_acks(self, node):
+        pass
+    def depart_acks(self, node):
+        pass
+
+    def visit_module(self, node):
+        pass
+    def depart_module(self, node):
+        pass
+
+    def bulk_text_processor(self, text):
+        return text
+
+    # overwritten
+    def visit_Text(self, node):
+        text = node.astext()
+        encoded = self.encode(text)
+        if self.protect_literal_text:
+            # moved here from base class's visit_literal to support
+            # more formatting in literal nodes
+            for token in self.words_and_spaces.findall(encoded):
+                if token.strip():
+                    # protect literal text from line wrapping
+                    self.body.append('<span class="pre">%s</span>' % token)
+                elif token in ' \n':
+                    # allow breaks at whitespace
+                    self.body.append(token)
+                else:
+                    # protect runs of multiple spaces; the last one can wrap
+                    self.body.append('&nbsp;' * (len(token)-1) + ' ')
+        else:
+            if self.in_mailto and self.settings.cloak_email_addresses:
+                encoded = self.cloak_email(encoded)
+            else:
+                encoded = self.bulk_text_processor(encoded)
+            self.body.append(encoded)
+
+    # these are all for docutils 0.5 compatibility
+
+    def visit_note(self, node):
+        self.visit_admonition(node, 'note')
+    def depart_note(self, node):
+        self.depart_admonition(node)
+
+    def visit_warning(self, node):
+        self.visit_admonition(node, 'warning')
+    def depart_warning(self, node):
+        self.depart_admonition(node)
+
+    def visit_attention(self, node):
+        self.visit_admonition(node, 'attention')
+
+    def depart_attention(self, node):
+        self.depart_admonition()
+
+    def visit_caution(self, node):
+        self.visit_admonition(node, 'caution')
+    def depart_caution(self, node):
+        self.depart_admonition()
+
+    def visit_danger(self, node):
+        self.visit_admonition(node, 'danger')
+    def depart_danger(self, node):
+        self.depart_admonition()
+
+    def visit_error(self, node):
+        self.visit_admonition(node, 'error')
+    def depart_error(self, node):
+        self.depart_admonition()
+
+    def visit_hint(self, node):
+        self.visit_admonition(node, 'hint')
+    def depart_hint(self, node):
+        self.depart_admonition()
+
+    def visit_important(self, node):
+        self.visit_admonition(node, 'important')
+    def depart_important(self, node):
+        self.depart_admonition()
+
+    def visit_tip(self, node):
+        self.visit_admonition(node, 'tip')
+    def depart_tip(self, node):
+        self.depart_admonition()
+
+    # these are only handled specially in the SmartyPantsHTMLTranslator
+    def visit_literal_emphasis(self, node):
+        return self.visit_emphasis(node)
+    def depart_literal_emphasis(self, node):
+        return self.depart_emphasis(node)
+
+    def depart_title(self, node):
+        close_tag = self.context[-1]
+        if self.add_permalinks and self.builder.add_permalinks and \
+               (close_tag.startswith('</h') or
+                close_tag.startswith('</a></h')) and \
+               node.parent.hasattr('ids') and node.parent['ids']:
+            aname = node.parent['ids'][0]
+            # add permalink anchor
+            self.body.append(u'<a class="headerlink" href="#%s" ' % aname +
+                             u'title="%s">\u00B6</a>' %
+                             _('Permalink to this headline'))
+        BaseTranslator.depart_title(self, node)
+
+    def unknown_visit(self, node):
+        raise NotImplementedError('Unknown node: ' + node.__class__.__name__)
+
+
+class SmartyPantsHTMLTranslator(HTMLTranslator):
+    """
+    Handle ordinary text via smartypants, converting quotes and dashes
+    to the correct entities.
+    """
+
+    def __init__(self, *args, **kwds):
+        self.no_smarty = 0
+        HTMLTranslator.__init__(self, *args, **kwds)
+
+    def visit_literal(self, node):
+        self.no_smarty += 1
+        try:
+            # this raises SkipNode
+            HTMLTranslator.visit_literal(self, node)
+        finally:
+            self.no_smarty -= 1
+
+    def visit_literal_emphasis(self, node):
+        self.no_smarty += 1
+        self.visit_emphasis(node)
+
+    def depart_literal_emphasis(self, node):
+        self.depart_emphasis(node)
+        self.no_smarty -= 1
+
+    def visit_desc_signature(self, node):
+        self.no_smarty += 1
+        HTMLTranslator.visit_desc_signature(self, node)
+
+    def depart_desc_signature(self, node):
+        self.no_smarty -= 1
+        HTMLTranslator.depart_desc_signature(self, node)
+
+    def visit_productionlist(self, node):
+        self.no_smarty += 1
+        try:
+            HTMLTranslator.visit_productionlist(self, node)
+        finally:
+            self.no_smarty -= 1
+
+    def visit_option(self, node):
+        self.no_smarty += 1
+        HTMLTranslator.visit_option(self, node)
+    def depart_option(self, node):
+        self.no_smarty -= 1
+        HTMLTranslator.depart_option(self, node)
+
+    def bulk_text_processor(self, text):
+        if self.no_smarty <= 0:
+            return sphinx_smarty_pants(text)
+        return text

Added: doctools/trunk/sphinx/writers/latex.py
==============================================================================
--- (empty file)
+++ doctools/trunk/sphinx/writers/latex.py	Sun Jan  4 21:38:57 2009
@@ -0,0 +1,1216 @@
+# -*- coding: utf-8 -*-
+"""
+    sphinx.writers.latex
+    ~~~~~~~~~~~~~~~~~~~~
+
+    Custom docutils writer for LaTeX.
+
+    Much of this code is adapted from Dave Kuhlman's "docpy" writer from his
+    docutils sandbox.
+
+    :copyright: Copyright 2007-2009 by the Sphinx team, see AUTHORS.
+    :license: BSD, see LICENSE for details.
+"""
+
+import re
+import sys
+from os import path
+
+from docutils import nodes, writers
+from docutils.writers.latex2e import Babel
+
+from sphinx import addnodes
+from sphinx import highlighting
+from sphinx.locale import admonitionlabels, versionlabels
+from sphinx.util import ustrftime
+from sphinx.util.texescape import tex_escape_map
+from sphinx.util.smartypants import educateQuotesLatex
+
+HEADER = r'''%% Generated by Sphinx.
+\documentclass[%(papersize)s,%(pointsize)s%(classoptions)s]{%(docclass)s}
+%(inputenc)s
+%(fontenc)s
+%(babel)s
+%(fontpkg)s
+%(fncychap)s
+\usepackage{sphinx}
+%(preamble)s
+
+\title{%(title)s}
+\date{%(date)s}
+\release{%(release)s}
+\author{%(author)s}
+\newcommand{\sphinxlogo}{%(logo)s}
+\renewcommand{\releasename}{%(releasename)s}
+%(makeindex)s
+%(makemodindex)s
+'''
+
+BEGIN_DOC = r'''
+\begin{document}
+%(shorthandoff)s
+%(maketitle)s
+%(tableofcontents)s
+'''
+
+FOOTER = r'''
+%(footer)s
+\renewcommand{\indexname}{%(modindexname)s}
+%(printmodindex)s
+\renewcommand{\indexname}{%(indexname)s}
+%(printindex)s
+\end{document}
+'''
+
+
+class LaTeXWriter(writers.Writer):
+
+    supported = ('sphinxlatex',)
+
+    settings_spec = ('LaTeX writer options', '', (
+        ('Document name', ['--docname'], {'default': ''}),
+        ('Document class', ['--docclass'], {'default': 'manual'}),
+        ('Author', ['--author'], {'default': ''}),
+        ))
+    settings_defaults = {}
+
+    output = None
+
+    def __init__(self, builder):
+        writers.Writer.__init__(self)
+        self.builder = builder
+
+    def translate(self):
+        visitor = LaTeXTranslator(self.document, self.builder)
+        self.document.walkabout(visitor)
+        self.output = visitor.astext()
+
+
+# Helper classes
+
+class ExtBabel(Babel):
+    def get_shorthandoff(self):
+        shortlang = self.language.split('_')[0]
+        if shortlang in ('de', 'sl', 'pt', 'es', 'nl', 'pl', 'it'):
+            return '\\shorthandoff{"}'
+        return ''
+
+    _ISO639_TO_BABEL = Babel._ISO639_TO_BABEL.copy()
+    _ISO639_TO_BABEL['sl'] = 'slovene'
+
+
+class Table(object):
+    def __init__(self):
+        self.col = 0
+        self.colcount = 0
+        self.colspec = None
+        self.had_head = False
+        self.has_verbatim = False
+        self.caption = None
+
+
+class Desc(object):
+    def __init__(self, node):
+        self.env = LaTeXTranslator.desc_map.get(node['desctype'], 'describe')
+        self.type = self.cls = self.name = self.params = \
+                    self.annotation = self.returns = ''
+        self.count = 0
+
+
+class LaTeXTranslator(nodes.NodeVisitor):
+    sectionnames = ["part", "chapter", "section", "subsection",
+                    "subsubsection", "paragraph", "subparagraph"]
+
+    ignore_missing_images = False
+
+    default_elements = {
+        'docclass':        'manual',
+        'papersize':       'letterpaper',
+        'pointsize':       '10pt',
+        'classoptions':    '',
+        'inputenc':        '\\usepackage[utf8]{inputenc}',
+        'fontenc':         '\\usepackage[T1]{fontenc}',
+        'babel':           '\\usepackage{babel}',
+        'fontpkg':         '\\usepackage{times}',
+        'fncychap':        '\\usepackage[Bjarne]{fncychap}',
+        'preamble':        '',
+        'title':           '',
+        'date':            '',
+        'release':         '',
+        'author':          '',
+        'logo':            '',
+        'releasename':     'Release',
+        'makeindex':       '\\makeindex',
+        'makemodindex':    '\\makemodindex',
+        'shorthandoff':    '',
+        'maketitle':       '\\maketitle',
+        'tableofcontents': '\\tableofcontents',
+        'footer':          '',
+        'printmodindex':   '\\printmodindex',
+        'printindex':      '\\printindex',
+    }
+
+    def __init__(self, document, builder):
+        nodes.NodeVisitor.__init__(self, document)
+        self.builder = builder
+        self.body = []
+
+        # sort out some elements
+        papersize = builder.config.latex_paper_size + 'paper'
+        if papersize == 'paper': # e.g. command line "-D latex_paper_size="
+            papersize = 'letterpaper'
+
+        self.elements = self.default_elements.copy()
+        self.elements.update({
+            'docclass':     document.settings.docclass,
+            'papersize':    papersize,
+            'pointsize':    builder.config.latex_font_size,
+            # if empty, the title is set to the first section title
+            'title':        document.settings.title,
+            'date':         ustrftime(builder.config.today_fmt or _('%B %d, %Y')),
+            'release':      builder.config.release,
+            'author':       document.settings.author,
+            'releasename':  _('Release'),
+            'preamble':     builder.config.latex_preamble,
+            'modindexname': _('Module Index'),
+            'indexname':    _('Index'),
+        })
+        if builder.config.latex_logo:
+            self.elements['logo'] = '\\includegraphics{%s}\\par' % \
+                                    path.basename(builder.config.latex_logo)
+        if builder.config.language:
+            babel = ExtBabel(builder.config.language)
+            lang = babel.get_language()
+            if lang:
+                self.elements['classoptions'] += ',' + babel.get_language()
+            else:
+                self.builder.warn('no Babel option known for language %r' %
+                                  builder.config.language)
+            self.elements['shorthandoff'] = babel.get_shorthandoff()
+            self.elements['fncychap'] = '\\usepackage[Sonny]{fncychap}'
+        else:
+            self.elements['classoptions'] += ',english'
+        if not builder.config.latex_use_modindex:
+            self.elements['makemodindex'] = ''
+            self.elements['printmodindex'] = ''
+        # allow the user to override them all
+        self.elements.update(builder.config.latex_elements)
+
+        self.highlighter = highlighting.PygmentsBridge(
+            'latex', builder.config.pygments_style)
+        self.context = []
+        self.descstack = []
+        self.bibitems = []
+        self.table = None
+        self.next_table_colspec = None
+        self.highlightlang = builder.config.highlight_language
+        self.highlightlinenothreshold = sys.maxint
+        self.written_ids = set()
+        self.footnotestack = []
+        if self.elements['docclass'] == 'manual':
+            if builder.config.latex_use_parts:
+                self.top_sectionlevel = 0
+            else:
+                self.top_sectionlevel = 1
+        else:
+            self.top_sectionlevel = 2
+        self.next_section_target = None
+        # flags
+        self.verbatim = None
+        self.in_title = 0
+        self.in_production_list = 0
+        self.first_document = 1
+        self.this_is_the_title = 1
+        self.literal_whitespace = 0
+        self.no_contractions = 0
+
+    def astext(self):
+        return (HEADER % self.elements + self.highlighter.get_stylesheet() +
+                u''.join(self.body) + FOOTER % self.elements)
+
+    def visit_document(self, node):
+        self.footnotestack.append(self.collect_footnotes(node))
+        if self.first_document == 1:
+            # the first document is all the regular content ...
+            self.body.append(BEGIN_DOC % self.elements)
+            self.first_document = 0
+        elif self.first_document == 0:
+            # ... and all others are the appendices
+            self.body.append('\n\\appendix\n')
+            self.first_document = -1
+        if 'docname' in node:
+            self.body.append('\\hypertarget{--doc-%s}{}' % node['docname'])
+        # "- 1" because the level is increased before the title is visited
+        self.sectionlevel = self.top_sectionlevel - 1
+    def depart_document(self, node):
+        if self.bibitems:
+            widest_label = ""
+            for bi in self.bibitems:
+                if len(widest_label) < len(bi[0]):
+                    widest_label = bi[0]
+            self.body.append('\n\\begin{thebibliography}{%s}\n' % widest_label)
+            for bi in self.bibitems:
+                # cite_key: underscores must not be escaped
+                cite_key = bi[0].replace(r"\_", "_")
+                self.body.append('\\bibitem[%s]{%s}{%s}\n' % (bi[0], cite_key, bi[1]))
+            self.body.append('\\end{thebibliography}\n')
+            self.bibitems = []
+
+    def visit_start_of_file(self, node):
+        # This marks the begin of a new file; therefore the current module and
+        # class must be reset
+        self.body.append('\n\\resetcurrentobjects\n')
+        # and also, new footnotes
+        self.footnotestack.append(self.collect_footnotes(node))
+        # also add a document target
+        self.body.append('\\hypertarget{--doc-%s}{}' % node['docname'])
+
+    def collect_footnotes(self, node):
+        fnotes = {}
+        def footnotes_under(n):
+            if isinstance(n, nodes.footnote):
+                yield n
+            else:
+                for c in n.children:
+                    if isinstance(c, addnodes.start_of_file):
+                        continue
+                    for k in footnotes_under(c):
+                        yield k
+        for fn in footnotes_under(node):
+            num = fn.children[0].astext().strip()
+            fnotes[num] = fn
+            fn.parent.remove(fn)
+        return fnotes
+
+    def depart_start_of_file(self, node):
+        self.footnotestack.pop()
+
+    def visit_highlightlang(self, node):
+        self.highlightlang = node['lang']
+        self.highlightlinenothreshold = node['linenothreshold']
+        raise nodes.SkipNode
+
+    def visit_section(self, node):
+        if not self.this_is_the_title:
+            self.sectionlevel += 1
+        self.body.append('\n\n')
+        if self.next_section_target:
+            self.body.append(r'\hypertarget{%s}{}' % self.next_section_target)
+            self.next_section_target = None
+        #if node.get('ids'):
+        #    for id in node['ids']:
+        #        if id not in self.written_ids:
+        #            self.body.append(r'\hypertarget{%s}{}' % id)
+        #            self.written_ids.add(id)
+    def depart_section(self, node):
+        self.sectionlevel = max(self.sectionlevel - 1, self.top_sectionlevel - 1)
+
+    def visit_problematic(self, node):
+        self.body.append(r'{\color{red}\bfseries{}')
+    def depart_problematic(self, node):
+        self.body.append('}')
+
+    def visit_topic(self, node):
+        self.body.append('\\setbox0\\vbox{\n'
+                         '\\begin{minipage}{0.95\\textwidth}\n')
+    def depart_topic(self, node):
+        self.body.append('\\end{minipage}}\n'
+                         '\\begin{center}\\setlength{\\fboxsep}{5pt}'
+                         '\\shadowbox{\\box0}\\end{center}\n')
+    visit_sidebar = visit_topic
+    depart_sidebar = depart_topic
+
+    def visit_glossary(self, node):
+        pass
+    def depart_glossary(self, node):
+        pass
+
+    def visit_productionlist(self, node):
+        self.body.append('\n\n\\begin{productionlist}\n')
+        self.in_production_list = 1
+    def depart_productionlist(self, node):
+        self.body.append('\\end{productionlist}\n\n')
+        self.in_production_list = 0
+
+    def visit_production(self, node):
+        if node['tokenname']:
+            self.body.append('\\production{%s}{' % self.encode(node['tokenname']))
+        else:
+            self.body.append('\\productioncont{')
+    def depart_production(self, node):
+        self.body.append('}\n')
+
+    def visit_transition(self, node):
+        self.body.append('\n\n\\bigskip\\hrule{}\\bigskip\n\n')
+    def depart_transition(self, node):
+        pass
+
+    def visit_title(self, node):
+        parent = node.parent
+        if isinstance(parent, addnodes.seealso):
+            # the environment already handles this
+            raise nodes.SkipNode
+        elif self.this_is_the_title:
+            if len(node.children) != 1 and not isinstance(node.children[0], nodes.Text):
+                self.builder.warn('document title is not a single Text node')
+            if not self.elements['title']:
+                # text needs to be escaped since it is inserted into
+                # the output literally
+                self.elements['title'] = node.astext().translate(tex_escape_map)
+            self.this_is_the_title = 0
+            raise nodes.SkipNode
+        elif isinstance(parent, nodes.section):
+            try:
+                self.body.append(r'\%s{' % self.sectionnames[self.sectionlevel])
+            except IndexError:
+                from sphinx.application import SphinxError
+                raise SphinxError('too many nesting section levels for LaTeX, '
+                                  'at heading: %s' % node.astext())
+            self.context.append('}\n')
+        elif isinstance(parent, (nodes.topic, nodes.sidebar)):
+            self.body.append(r'\textbf{')
+            self.context.append('}\n\n\medskip\n\n')
+        elif isinstance(parent, nodes.Admonition):
+            self.body.append('{')
+            self.context.append('}\n')
+        elif isinstance(parent, nodes.table):
+            self.table.caption = self.encode(node.astext())
+            raise nodes.SkipNode
+        else:
+            self.builder.warn('encountered title node not in section, topic, '
+                              'table, admonition or sidebar')
+            self.body.append('\\textbf{')
+            self.context.append('}\n')
+        self.in_title = 1
+    def depart_title(self, node):
+        self.in_title = 0
+        self.body.append(self.context.pop())
+
+    def visit_subtitle(self, node):
+        if isinstance(node.parent, nodes.sidebar):
+            self.body.append('~\\\\\n\\textbf{')
+            self.context.append('}\n\\smallskip\n')
+        else:
+            self.context.append('')
+    def depart_subtitle(self, node):
+        self.body.append(self.context.pop())
+
+    desc_map = {
+        'function' : 'funcdesc',
+        'class': 'classdesc',
+        'method': 'methoddesc',
+        'classmethod': 'classmethoddesc',
+        'staticmethod': 'staticmethoddesc',
+        'exception': 'excdesc',
+        'data': 'datadesc',
+        'attribute': 'memberdesc',
+        'opcode': 'opcodedesc',
+
+        'cfunction': 'cfuncdesc',
+        'cmember': 'cmemberdesc',
+        'cmacro': 'csimplemacrodesc',
+        'ctype': 'ctypedesc',
+        'cvar': 'cvardesc',
+
+        'describe': 'describe',
+        # and all others are 'describe' too
+    }
+
+    def visit_desc(self, node):
+        self.descstack.append(Desc(node))
+    def depart_desc(self, node):
+        d = self.descstack.pop()
+        self.body.append("\\end{%s}\n" % d.env)
+
+    def visit_desc_signature(self, node):
+        d = self.descstack[-1]
+        # reset these for every signature
+        d.type = d.cls = d.name = d.params = ''
+    def depart_desc_signature(self, node):
+        d = self.descstack[-1]
+        d.cls = d.cls.rstrip('.')
+        if node.parent['desctype'] != 'describe' and node['ids']:
+            hyper = '\\hypertarget{%s}{}' % node['ids'][0]
+        else:
+            hyper = ''
+        if d.count == 0:
+            t1 = "\n\n%s\\begin{%s}" % (hyper, d.env)
+        else:
+            t1 = "\n%s\\%sline" % (hyper, d.env[:-4])
+        d.count += 1
+        if d.env in ('funcdesc', 'classdesc', 'excclassdesc'):
+            t2 = "{%s}{%s}" % (d.name, d.params)
+        elif d.env in ('datadesc', 'excdesc', 'csimplemacrodesc'):
+            t2 = "{%s}" % (d.name)
+        elif d.env in ('methoddesc', 'classmethoddesc', 'staticmethoddesc'):
+            if d.cls:
+                t2 = "[%s]{%s}{%s}" % (d.cls, d.name, d.params)
+            else:
+                t2 = "{%s}{%s}" % (d.name, d.params)
+        elif d.env == 'memberdesc':
+            if d.cls:
+                t2 = "[%s]{%s}" % (d.cls, d.name)
+            else:
+                t2 = "{%s}" % d.name
+        elif d.env == 'cfuncdesc':
+            if d.cls:
+                # C++ class names
+                d.name = '%s::%s' % (d.cls, d.name)
+            t2 = "{%s}{%s}{%s}" % (d.type, d.name, d.params)
+        elif d.env == 'cmemberdesc':
+            try:
+                type, container = d.type.rsplit(' ', 1)
+                container = container.rstrip('.')
+            except ValueError:
+                container = ''
+                type = d.type
+            t2 = "{%s}{%s}{%s}" % (container, type, d.name)
+        elif d.env == 'cvardesc':
+            t2 = "{%s}{%s}" % (d.type, d.name)
+        elif d.env == 'ctypedesc':
+            t2 = "{%s}" % (d.name)
+        elif d.env == 'opcodedesc':
+            t2 = "{%s}{%s}" % (d.name, d.params)
+        elif d.env == 'describe':
+            t2 = "{%s}" % d.name
+        self.body.append(t1 + t2)
+
+    def visit_desc_type(self, node):
+        d = self.descstack[-1]
+        if d.env == 'describe':
+            d.name += self.encode(node.astext())
+        else:
+            self.descstack[-1].type = self.encode(node.astext().strip())
+        raise nodes.SkipNode
+
+    def visit_desc_returns(self, node):
+        d = self.descstack[-1]
+        if d.env == 'describe':
+            d.name += ' $\\rightarrow$ ' + self.encode(node.astext())
+        else:
+            self.descstack[-1].returns = self.encode(node.astext().strip())
+        raise nodes.SkipNode
+
+    def visit_desc_name(self, node):
+        d = self.descstack[-1]
+        if d.env == 'describe':
+            d.name += self.encode(node.astext())
+        else:
+            self.descstack[-1].name = self.encode(node.astext().strip())
+        raise nodes.SkipNode
+
+    def visit_desc_addname(self, node):
+        d = self.descstack[-1]
+        if d.env == 'describe':
+            d.name += self.encode(node.astext())
+        else:
+            self.descstack[-1].cls = self.encode(node.astext().strip())
+        raise nodes.SkipNode
+
+    def visit_desc_parameterlist(self, node):
+        d = self.descstack[-1]
+        if d.env == 'describe':
+            d.name += self.encode(node.astext())
+        else:
+            self.descstack[-1].params = self.encode(node.astext().strip())
+        raise nodes.SkipNode
+
+    def visit_desc_annotation(self, node):
+        d = self.descstack[-1]
+        if d.env == 'describe':
+            d.name += self.encode(node.astext())
+        else:
+            self.descstack[-1].annotation = self.encode(node.astext().strip())
+        raise nodes.SkipNode
+
+    def visit_refcount(self, node):
+        self.body.append("\\emph{")
+    def depart_refcount(self, node):
+        self.body.append("}\\\\")
+
+    def visit_desc_content(self, node):
+        if node.children and not isinstance(node.children[0], nodes.paragraph):
+            # avoid empty desc environment which causes a formatting bug
+            self.body.append('~')
+    def depart_desc_content(self, node):
+        pass
+
+    def visit_seealso(self, node):
+        self.body.append("\n\n\\strong{%s:}\n\n" % admonitionlabels['seealso'])
+    def depart_seealso(self, node):
+        self.body.append("\n\n")
+
+    def visit_rubric(self, node):
+        if len(node.children) == 1 and node.children[0].astext() == 'Footnotes':
+            raise nodes.SkipNode
+        self.body.append('\\paragraph{')
+        self.context.append('}\n')
+    def depart_rubric(self, node):
+        self.body.append(self.context.pop())
+
+    def visit_footnote(self, node):
+        pass
+    def depart_footnote(self, node):
+        pass
+
+    def visit_label(self, node):
+        if isinstance(node.parent, nodes.citation):
+            self.bibitems[-1][0] = node.astext()
+        raise nodes.SkipNode
+
+    def visit_tabular_col_spec(self, node):
+        self.next_table_colspec = node['spec']
+        raise nodes.SkipNode
+
+    def visit_table(self, node):
+        if self.table:
+            raise NotImplementedError('Nested tables are not supported.')
+        self.table = Table()
+        self.tablebody = []
+        # Redirect body output until table is finished.
+        self._body = self.body
+        self.body = self.tablebody
+    def depart_table(self, node):
+        self.body = self._body
+        if self.table.caption is not None:
+            self.body.append('\n\\begin{threeparttable}\n'
+                             '\\caption{%s}\n' % self.table.caption)
+        if self.table.has_verbatim:
+            self.body.append('\n\\begin{tabular}')
+        else:
+            self.body.append('\n\\begin{tabulary}{\\textwidth}')
+        if self.table.colspec:
+            self.body.append(self.table.colspec)
+        else:
+            if self.table.has_verbatim:
+                colwidth = 0.95 / self.table.colcount
+                colspec = ('p{%.3f\\textwidth}|' % colwidth) * self.table.colcount
+                self.body.append('{|' + colspec + '}\n')
+            else:
+                self.body.append('{|' + ('L|' * self.table.colcount) + '}\n')
+        self.body.extend(self.tablebody)
+        if self.table.has_verbatim:
+            self.body.append('\\end{tabular}\n\n')
+        else:
+            self.body.append('\\end{tabulary}\n\n')
+        if self.table.caption is not None:
+            self.body.append('\\end{threeparttable}\n\n')
+        self.table = None
+        self.tablebody = None
+
+    def visit_colspec(self, node):
+        self.table.colcount += 1
+    def depart_colspec(self, node):
+        pass
+
+    def visit_tgroup(self, node):
+        pass
+    def depart_tgroup(self, node):
+        pass
+
+    def visit_thead(self, node):
+        if self.next_table_colspec:
+            self.table.colspec = '{%s}\n' % self.next_table_colspec
+        self.next_table_colspec = None
+        self.body.append('\\hline\n')
+        self.table.had_head = True
+    def depart_thead(self, node):
+        self.body.append('\\hline\n')
+
+    def visit_tbody(self, node):
+        if not self.table.had_head:
+            self.visit_thead(node)
+    def depart_tbody(self, node):
+        self.body.append('\\hline\n')
+
+    def visit_row(self, node):
+        self.table.col = 0
+    def depart_row(self, node):
+        self.body.append('\\\\\n')
+
+    def visit_entry(self, node):
+        if node.has_key('morerows') or node.has_key('morecols'):
+            raise NotImplementedError('Column or row spanning cells are '
+                                      'not implemented.')
+        if self.table.col > 0:
+            self.body.append(' & ')
+        self.table.col += 1
+        if isinstance(node.parent.parent, nodes.thead):
+            self.body.append('\\textbf{')
+            self.context.append('}')
+        else:
+            self.context.append('')
+    def depart_entry(self, node):
+        self.body.append(self.context.pop()) # header
+
+    def visit_acks(self, node):
+        # this is a list in the source, but should be rendered as a
+        # comma-separated list here
+        self.body.append('\n\n')
+        self.body.append(', '.join(n.astext() for n in node.children[0].children) + '.')
+        self.body.append('\n\n')
+        raise nodes.SkipNode
+
+    def visit_bullet_list(self, node):
+        self.body.append('\\begin{itemize}\n' )
+    def depart_bullet_list(self, node):
+        self.body.append('\\end{itemize}\n' )
+
+    def visit_enumerated_list(self, node):
+        self.body.append('\\begin{enumerate}\n' )
+    def depart_enumerated_list(self, node):
+        self.body.append('\\end{enumerate}\n' )
+
+    def visit_list_item(self, node):
+        # Append "{}" in case the next character is "[", which would break
+        # LaTeX's list environment (no numbering and the "[" is not printed).
+        self.body.append(r'\item {} ')
+    def depart_list_item(self, node):
+        self.body.append('\n')
+
+    def visit_definition_list(self, node):
+        self.body.append('\\begin{description}\n')
+    def depart_definition_list(self, node):
+        self.body.append('\\end{description}\n')
+
+    def visit_definition_list_item(self, node):
+        pass
+    def depart_definition_list_item(self, node):
+        pass
+
+    def visit_term(self, node):
+        ctx = ']'
+        if node.has_key('ids') and node['ids']:
+            ctx += '\\hypertarget{%s}{}' % node['ids'][0]
+        self.body.append('\\item[')
+        self.context.append(ctx)
+    def depart_term(self, node):
+        self.body.append(self.context.pop())
+
+    def visit_classifier(self, node):
+        self.body.append('{[}')
+    def depart_classifier(self, node):
+        self.body.append('{]}')
+
+    def visit_definition(self, node):
+        pass
+    def depart_definition(self, node):
+        self.body.append('\n')
+
+    def visit_field_list(self, node):
+        self.body.append('\\begin{quote}\\begin{description}\n')
+    def depart_field_list(self, node):
+        self.body.append('\\end{description}\\end{quote}\n')
+
+    def visit_field(self, node):
+        pass
+    def depart_field(self, node):
+        pass
+
+    visit_field_name = visit_term
+    depart_field_name = depart_term
+
+    visit_field_body = visit_definition
+    depart_field_body = depart_definition
+
+    def visit_paragraph(self, node):
+        self.body.append('\n')
+    def depart_paragraph(self, node):
+        self.body.append('\n')
+
+    def visit_centered(self, node):
+        self.body.append('\n\\begin{centering}')
+    def depart_centered(self, node):
+        self.body.append('\n\\end{centering}')
+
+    def visit_module(self, node):
+        modname = node['modname']
+        self.body.append('\n\\declaremodule[%s]{}{%s}' % (modname.replace('_', ''),
+                                                          self.encode(modname)))
+        self.body.append('\n\\modulesynopsis{%s}' % self.encode(node['synopsis']))
+        if node.has_key('platform'):
+            self.body.append('\\platform{%s}' % self.encode(node['platform']))
+    def depart_module(self, node):
+        pass
+
+    def latex_image_length(self, width_str):
+        match = re.match('(\d*\.?\d*)\s*(\S*)', width_str)
+        if not match:
+            # fallback
+            return width_str
+        res = width_str
+        amount, unit = match.groups()[:2]
+        if not unit or unit == "px":
+            # pixels: let LaTeX alone
+            return None
+        elif unit == "%":
+            res = "%.3f\\linewidth" % (float(amount) / 100.0)
+        return res
+
+    def visit_image(self, node):
+        attrs = node.attributes
+        pre = []                        # in reverse order
+        post = []
+        include_graphics_options = []
+        inline = isinstance(node.parent, nodes.TextElement)
+        if attrs.has_key('scale'):
+            # Could also be done with ``scale`` option to
+            # ``\includegraphics``; doing it this way for consistency.
+            pre.append('\\scalebox{%f}{' % (attrs['scale'] / 100.0,))
+            post.append('}')
+        if attrs.has_key('width'):
+            w = self.latex_image_length(attrs['width'])
+            if w:
+                include_graphics_options.append('width=%s' % w)
+        if attrs.has_key('height'):
+            h = self.latex_image_length(attrs['height'])
+            if h:
+                include_graphics_options.append('height=%s' % h)
+        if attrs.has_key('align'):
+            align_prepost = {
+                # By default latex aligns the top of an image.
+                (1, 'top'): ('', ''),
+                (1, 'middle'): ('\\raisebox{-0.5\\height}{', '}'),
+                (1, 'bottom'): ('\\raisebox{-\\height}{', '}'),
+                (0, 'center'): ('{\\hfill', '\\hfill}'),
+                # These 2 don't exactly do the right thing.  The image should
+                # be floated alongside the paragraph.  See
+                # http://www.w3.org/TR/html4/struct/objects.html#adef-align-IMG
+                (0, 'left'): ('{', '\\hfill}'),
+                (0, 'right'): ('{\\hfill', '}'),}
+            try:
+                pre.append(align_prepost[inline, attrs['align']][0])
+                post.append(align_prepost[inline, attrs['align']][1])
+            except KeyError:
+                pass                    # XXX complain here?
+        if not inline:
+            pre.append('\n')
+            post.append('\n')
+        pre.reverse()
+        if node['uri'] in self.builder.images:
+            uri = self.builder.images[node['uri']]
+        else:
+            # missing image!
+            if self.ignore_missing_images:
+                return
+            uri = node['uri']
+        if uri.find('://') != -1:
+            # ignore remote images
+            return
+        self.body.extend(pre)
+        options = ''
+        if include_graphics_options:
+            options = '[%s]' % ','.join(include_graphics_options)
+        self.body.append('\\includegraphics%s{%s}' % (options, uri))
+        self.body.extend(post)
+    def depart_image(self, node):
+        pass
+
+    def visit_figure(self, node):
+        if (not node.attributes.has_key('align') or
+            node.attributes['align'] == 'center'):
+            # centering does not add vertical space like center.
+            align = '\n\\centering'
+            align_end = ''
+        else:
+            # TODO non vertical space for other alignments.
+            align = '\\begin{flush%s}' % node.attributes['align']
+            align_end = '\\end{flush%s}' % node.attributes['align']
+        self.body.append('\\begin{figure}[htbp]%s\n' % align)
+        self.context.append('%s\\end{figure}\n' % align_end)
+    def depart_figure(self, node):
+        self.body.append(self.context.pop())
+
+    def visit_caption(self, node):
+        self.body.append('\\caption{')
+    def depart_caption(self, node):
+        self.body.append('}')
+
+    def visit_legend(self, node):
+        self.body.append('{\\small ')
+    def depart_legend(self, node):
+        self.body.append('}')
+
+    def visit_admonition(self, node):
+        self.body.append('\n\\begin{notice}{note}')
+    def depart_admonition(self, node):
+        self.body.append('\\end{notice}\n')
+
+    def _make_visit_admonition(name):
+        def visit_admonition(self, node):
+            self.body.append('\n\\begin{notice}{%s}{%s:}' %
+                             (name, admonitionlabels[name]))
+        return visit_admonition
+    def _depart_named_admonition(self, node):
+        self.body.append('\\end{notice}\n')
+
+    visit_attention = _make_visit_admonition('attention')
+    depart_attention = _depart_named_admonition
+    visit_caution = _make_visit_admonition('caution')
+    depart_caution = _depart_named_admonition
+    visit_danger = _make_visit_admonition('danger')
+    depart_danger = _depart_named_admonition
+    visit_error = _make_visit_admonition('error')
+    depart_error = _depart_named_admonition
+    visit_hint = _make_visit_admonition('hint')
+    depart_hint = _depart_named_admonition
+    visit_important = _make_visit_admonition('important')
+    depart_important = _depart_named_admonition
+    visit_note = _make_visit_admonition('note')
+    depart_note = _depart_named_admonition
+    visit_tip = _make_visit_admonition('tip')
+    depart_tip = _depart_named_admonition
+    visit_warning = _make_visit_admonition('warning')
+    depart_warning = _depart_named_admonition
+
+    def visit_versionmodified(self, node):
+        intro = versionlabels[node['type']] % node['version']
+        if node.children:
+            intro += ': '
+        else:
+            intro += '.'
+        self.body.append(intro)
+    def depart_versionmodified(self, node):
+        pass
+
+    def visit_target(self, node):
+        def add_target(id):
+            # indexing uses standard LaTeX index markup, so the targets
+            # will be generated differently
+            if not id.startswith('index-'):
+                self.body.append(r'\hypertarget{%s}{}' % id)
+
+        if node.has_key('refid') and node['refid'] not in self.written_ids:
+            parindex = node.parent.index(node)
+            try:
+                next = node.parent[parindex+1]
+                if isinstance(next, nodes.section):
+                    self.next_section_target = node['refid']
+                    return
+            except IndexError:
+                pass
+            add_target(node['refid'])
+            self.written_ids.add(node['refid'])
+    def depart_target(self, node):
+        pass
+
+    def visit_attribution(self, node):
+        self.body.append('\n\\begin{flushright}\n')
+        self.body.append('---')
+    def depart_attribution(self, node):
+        self.body.append('\n\\end{flushright}\n')
+
+    def visit_index(self, node, scre=re.compile(r';\s*')):
+        entries = node['entries']
+        for type, string, tid, _ in entries:
+            if type == 'single':
+                self.body.append(r'\index{%s}' % scre.sub('!', self.encode(string)))
+            elif type == 'pair':
+                parts = tuple(self.encode(x.strip()) for x in string.split(';', 1))
+                try:
+                    self.body.append(r'\indexii{%s}{%s}' % parts)
+                except TypeError:
+                    self.builder.warn('invalid pair index entry %r' % string)
+            elif type == 'triple':
+                parts = tuple(self.encode(x.strip()) for x in string.split(';', 2))
+                try:
+                    self.body.append(r'\indexiii{%s}{%s}{%s}' % parts)
+                except TypeError:
+                    self.builder.warn('invalid triple index entry %r' % string)
+            else:
+                self.builder.warn('unknown index entry type %s found' % type)
+        raise nodes.SkipNode
+
+    def visit_raw(self, node):
+        if 'latex' in node.get('format', '').split():
+            self.body.append(node.astext())
+        raise nodes.SkipNode
+
+    def visit_reference(self, node):
+        uri = node.get('refuri', '')
+        if self.in_title or not uri:
+            self.context.append('')
+        elif uri.startswith('mailto:') or uri.startswith('http:') or \
+             uri.startswith('https:') or uri.startswith('ftp:'):
+            self.body.append('\\href{%s}{' % self.encode(uri))
+            self.context.append('}')
+        elif uri.startswith('#'):
+            self.body.append('\\hyperlink{%s}{' % uri[1:])
+            self.context.append('}')
+        elif uri.startswith('%'):
+            hashindex = uri.find('#')
+            targetname = (hashindex == -1) and '--doc-' + uri[1:] or uri[hashindex+1:]
+            self.body.append('\\hyperlink{%s}{' % targetname)
+            self.context.append('}')
+        elif uri.startswith('@token'):
+            if self.in_production_list:
+                self.body.append('\\token{')
+            else:
+                self.body.append('\\grammartoken{')
+            self.context.append('}')
+        else:
+            self.builder.warn('unusable reference target found: %s' % uri)
+            self.context.append('')
+    def depart_reference(self, node):
+        self.body.append(self.context.pop())
+
+    def visit_download_reference(self, node):
+        pass
+    def depart_download_reference(self, node):
+        pass
+
+    def visit_pending_xref(self, node):
+        pass
+    def depart_pending_xref(self, node):
+        pass
+
+    def visit_emphasis(self, node):
+        self.body.append(r'\emph{')
+    def depart_emphasis(self, node):
+        self.body.append('}')
+
+    def visit_literal_emphasis(self, node):
+        self.body.append(r'\emph{\texttt{')
+        self.no_contractions += 1
+    def depart_literal_emphasis(self, node):
+        self.body.append('}}')
+        self.no_contractions -= 1
+
+    def visit_strong(self, node):
+        self.body.append(r'\textbf{')
+    def depart_strong(self, node):
+        self.body.append('}')
+
+    def visit_title_reference(self, node):
+        self.body.append(r'\emph{')
+    def depart_title_reference(self, node):
+        self.body.append('}')
+
+    def visit_citation(self, node):
+        # TODO maybe use cite bibitems
+        self.bibitems.append(['', ''])
+        self.context.append(len(self.body))
+    def depart_citation(self, node):
+        size = self.context.pop()
+        text = ''.join(self.body[size:])
+        del self.body[size:]
+        self.bibitems[-1][1] = text
+
+    def visit_citation_reference(self, node):
+        citeid = node.astext()
+        self.body.append('\\cite{%s}' % citeid)
+        raise nodes.SkipNode
+
+    def visit_literal(self, node):
+        content = self.encode(node.astext().strip())
+        if self.in_title:
+            self.body.append(r'\texttt{%s}' % content)
+        elif node.has_key('role') and node['role'] == 'samp':
+            self.body.append(r'\samp{%s}' % content)
+        else:
+            self.body.append(r'\code{%s}' % content)
+        raise nodes.SkipNode
+
+    def visit_footnote_reference(self, node):
+        num = node.astext().strip()
+        try:
+            fn = self.footnotestack[-1][num]
+        except (KeyError, IndexError):
+            raise nodes.SkipNode
+        self.body.append('\\footnote{')
+        fn.walkabout(self)
+        raise nodes.SkipChildren
+    def depart_footnote_reference(self, node):
+        self.body.append('}')
+
+    def visit_literal_block(self, node):
+        self.verbatim = ''
+    def depart_literal_block(self, node):
+        code = self.verbatim.rstrip('\n')
+        lang = self.highlightlang
+        linenos = code.count('\n') >= self.highlightlinenothreshold - 1
+        if node.has_key('language'):
+            # code-block directives
+            lang = node['language']
+        if node.has_key('linenos'):
+            linenos = node['linenos']
+        hlcode = self.highlighter.highlight_block(code, lang, linenos)
+        # workaround for Unicode issue
+        hlcode = hlcode.replace(u'€', u'@texteuro[]')
+        # must use original Verbatim environment and "tabular" environment
+        if self.table:
+            hlcode = hlcode.replace('\\begin{Verbatim}',
+                                    '\\begin{OriginalVerbatim}')
+            self.table.has_verbatim = True
+        # get consistent trailer
+        hlcode = hlcode.rstrip()[:-14] # strip \end{Verbatim}
+        hlcode = hlcode.rstrip() + '\n'
+        self.body.append('\n' + hlcode + '\\end{%sVerbatim}\n' %
+                         (self.table and 'Original' or ''))
+        self.verbatim = None
+    visit_doctest_block = visit_literal_block
+    depart_doctest_block = depart_literal_block
+
+    def visit_line_block(self, node):
+        """line-block:
+        * whitespace (including linebreaks) is significant
+        * inline markup is supported.
+        * serif typeface
+        """
+        self.body.append('{\\raggedright{}')
+        self.literal_whitespace = 1
+    def depart_line_block(self, node):
+        self.literal_whitespace = 0
+        # remove the last \\
+        del self.body[-1]
+        self.body.append('}\n')
+
+    def visit_line(self, node):
+        self._line_start = len(self.body)
+    def depart_line(self, node):
+        if self._line_start == len(self.body):
+            # no output in this line -- add a nonbreaking space, else the
+            # \\ command will give an error
+            self.body.append('~')
+        if self.table is not None:
+            self.body.append('\\newline\n')
+        else:
+            self.body.append('\\\\\n')
+
+    def visit_block_quote(self, node):
+        # If the block quote contains a single object and that object
+        # is a list, then generate a list not a block quote.
+        # This lets us indent lists.
+        done = 0
+        if len(node.children) == 1:
+            child = node.children[0]
+            if isinstance(child, nodes.bullet_list) or \
+                    isinstance(child, nodes.enumerated_list):
+                done = 1
+        if not done:
+            self.body.append('\\begin{quote}\n')
+    def depart_block_quote(self, node):
+        done = 0
+        if len(node.children) == 1:
+            child = node.children[0]
+            if isinstance(child, nodes.bullet_list) or \
+                    isinstance(child, nodes.enumerated_list):
+                done = 1
+        if not done:
+            self.body.append('\\end{quote}\n')
+
+    # option node handling copied from docutils' latex writer
+
+    def visit_option(self, node):
+        if self.context[-1]:
+            # this is not the first option
+            self.body.append(', ')
+    def depart_option(self, node):
+        # flag that the first option is done.
+        self.context[-1] += 1
+
+    def visit_option_argument(self, node):
+        """The delimiter betweeen an option and its argument."""
+        self.body.append(node.get('delimiter', ' '))
+    def depart_option_argument(self, node):
+        pass
+
+    def visit_option_group(self, node):
+        self.body.append('\\item [')
+        # flag for first option
+        self.context.append(0)
+    def depart_option_group(self, node):
+        self.context.pop() # the flag
+        self.body.append('] ')
+
+    def visit_option_list(self, node):
+        self.body.append('\\begin{optionlist}{3cm}\n')
+    def depart_option_list(self, node):
+        self.body.append('\\end{optionlist}\n')
+
+    def visit_option_list_item(self, node):
+        pass
+    def depart_option_list_item(self, node):
+        pass
+
+    def visit_option_string(self, node):
+        ostring = node.astext()
+        self.body.append(self.encode(ostring.replace('--', u'-{-}')))
+        raise nodes.SkipNode
+
+    def visit_description(self, node):
+        self.body.append( ' ' )
+    def depart_description(self, node):
+        pass
+
+    def visit_superscript(self, node):
+        self.body.append('$^{\\text{')
+    def depart_superscript(self, node):
+        self.body.append('}}$')
+
+    def visit_subscript(self, node):
+        self.body.append('$_{\\text{')
+    def depart_subscript(self, node):
+        self.body.append('}}$')
+
+    def visit_substitution_definition(self, node):
+        raise nodes.SkipNode
+
+    def visit_substitution_reference(self, node):
+        raise nodes.SkipNode
+
+    def visit_generated(self, node):
+        pass
+    def depart_generated(self, node):
+        pass
+
+    def visit_compound(self, node):
+        pass
+    def depart_compound(self, node):
+        pass
+
+    def visit_container(self, node):
+        pass
+    def depart_container(self, node):
+        pass
+
+    def visit_decoration(self, node):
+        pass
+    def depart_decoration(self, node):
+        pass
+
+    # text handling
+
+    def encode(self, text):
+        text = unicode(text).translate(tex_escape_map)
+        if self.literal_whitespace:
+            # Insert a blank before the newline, to avoid
+            # ! LaTeX Error: There's no line here to end.
+            text = text.replace(u'\n', u'~\\\\\n').replace(u' ', u'~')
+        if self.no_contractions:
+            text = text.replace('--', u'-{-}')
+        return text
+
+    def visit_Text(self, node):
+        if self.verbatim is not None:
+            self.verbatim += node.astext()
+        else:
+            text = self.encode(node.astext())
+            self.body.append(educateQuotesLatex(text))
+    def depart_Text(self, node):
+        pass
+
+    def visit_comment(self, node):
+        raise nodes.SkipNode
+
+    def visit_meta(self, node):
+        # only valid for HTML
+        raise nodes.SkipNode
+
+    def visit_system_message(self, node):
+        pass
+    def depart_system_message(self, node):
+        self.body.append('\n')
+
+    def unknown_visit(self, node):
+        raise NotImplementedError('Unknown node: ' + node.__class__.__name__)

Added: doctools/trunk/sphinx/writers/text.py
==============================================================================
--- (empty file)
+++ doctools/trunk/sphinx/writers/text.py	Sun Jan  4 21:38:57 2009
@@ -0,0 +1,689 @@
+# -*- coding: utf-8 -*-
+"""
+    sphinx.writers.text
+    ~~~~~~~~~~~~~~~~~~~
+
+    Custom docutils writer for plain text.
+
+    :copyright: Copyright 2007-2009 by the Sphinx team, see AUTHORS.
+    :license: BSD, see LICENSE for details.
+"""
+
+import re
+import textwrap
+
+from docutils import nodes, writers
+
+from sphinx import addnodes
+from sphinx.locale import admonitionlabels, versionlabels
+
+
+class TextWriter(writers.Writer):
+    supported = ('text',)
+    settings_spec = ('No options here.', '', ())
+    settings_defaults = {}
+
+    output = None
+
+    def __init__(self, builder):
+        writers.Writer.__init__(self)
+        self.builder = builder
+
+    def translate(self):
+        visitor = TextTranslator(self.document, self.builder)
+        self.document.walkabout(visitor)
+        self.output = visitor.body
+
+# monkey-patch...
+new_wordsep_re = re.compile(
+        r'(\s+|'                                  # any whitespace
+        r'(?<=\s)(?::[a-z-]+:)?`\S+|'             # interpreted text start
+        r'[^\s\w]*\w+[a-zA-Z]-(?=\w+[a-zA-Z])|'   # hyphenated words
+        r'(?<=[\w\!\"\'\&\.\,\?])-{2,}(?=\w))')   # em-dash
+textwrap.TextWrapper.wordsep_re = new_wordsep_re
+
+MAXWIDTH = 70
+STDINDENT = 3
+
+
+class TextTranslator(nodes.NodeVisitor):
+    sectionchars = '*=-~"+'
+
+    def __init__(self, document, builder):
+        nodes.NodeVisitor.__init__(self, document)
+
+        self.states = [[]]
+        self.stateindent = [0]
+        self.sectionlevel = 0
+        self.table = None
+
+    def add_text(self, text):
+        self.states[-1].append((-1, text))
+    def new_state(self, indent=STDINDENT):
+        self.states.append([])
+        self.stateindent.append(indent)
+    def end_state(self, wrap=True, end=[''], first=None):
+        content = self.states.pop()
+        maxindent = sum(self.stateindent)
+        indent = self.stateindent.pop()
+        result = []
+        toformat = []
+        def do_format():
+            if not toformat:
+                return
+            if wrap:
+                res = textwrap.wrap(''.join(toformat), width=MAXWIDTH-maxindent)
+            else:
+                res = ''.join(toformat).splitlines()
+            if end:
+                res += end
+            result.append((indent, res))
+        for itemindent, item in content:
+            if itemindent == -1:
+                toformat.append(item)
+            else:
+                do_format()
+                result.append((indent + itemindent, item))
+                toformat = []
+        do_format()
+        if first is not None and result:
+            itemindent, item = result[0]
+            if item:
+                result.insert(0, (itemindent - indent, [first + item[0]]))
+                result[1] = (itemindent, item[1:])
+        self.states[-1].extend(result)
+
+    def visit_document(self, node):
+        self.new_state(0)
+    def depart_document(self, node):
+        self.end_state()
+        self.body = '\n'.join(line and (' '*indent + line)
+                              for indent, lines in self.states[0]
+                              for line in lines)
+        # XXX header/footer?
+
+    def visit_highlightlang(self, node):
+        raise nodes.SkipNode
+
+    def visit_section(self, node):
+        self._title_char = self.sectionchars[self.sectionlevel]
+        self.sectionlevel += 1
+    def depart_section(self, node):
+        self.sectionlevel -= 1
+
+    def visit_topic(self, node):
+        self.new_state(0)
+    def depart_topic(self, node):
+        self.end_state()
+
+    visit_sidebar = visit_topic
+    depart_sidebar = depart_topic
+
+    def visit_rubric(self, node):
+        self.new_state(0)
+        self.add_text('-[ ')
+    def depart_rubric(self, node):
+        self.add_text(' ]-')
+        self.end_state()
+
+    def visit_compound(self, node):
+        pass
+    def depart_compound(self, node):
+        pass
+
+    def visit_glossary(self, node):
+        pass
+    def depart_glossary(self, node):
+        pass
+
+    def visit_title(self, node):
+        if isinstance(node.parent, nodes.Admonition):
+            self.add_text(node.astext()+': ')
+            raise nodes.SkipNode
+        self.new_state(0)
+    def depart_title(self, node):
+        if isinstance(node.parent, nodes.section):
+            char = self._title_char
+        else:
+            char = '^'
+        text = ''.join(x[1] for x in self.states.pop() if x[0] == -1)
+        self.stateindent.pop()
+        self.states[-1].append((0, ['', text, '%s' % (char * len(text)), '']))
+
+    def visit_subtitle(self, node):
+        pass
+    def depart_subtitle(self, node):
+        pass
+
+    def visit_attribution(self, node):
+        self.add_text('-- ')
+    def depart_attribution(self, node):
+        pass
+
+    def visit_module(self, node):
+        if node.has_key('platform'):
+            self.new_state(0)
+            self.add_text(_('Platform: %s') % node['platform'])
+            self.end_state()
+        raise nodes.SkipNode
+
+    def visit_desc(self, node):
+        pass
+    def depart_desc(self, node):
+        pass
+
+    def visit_desc_signature(self, node):
+        self.new_state(0)
+        if node.parent['desctype'] in ('class', 'exception'):
+            self.add_text('%s ' % node.parent['desctype'])
+    def depart_desc_signature(self, node):
+        # XXX: wrap signatures in a way that makes sense
+        self.end_state(wrap=False, end=None)
+
+    def visit_desc_name(self, node):
+        pass
+    def depart_desc_name(self, node):
+        pass
+
+    def visit_desc_addname(self, node):
+        pass
+    def depart_desc_addname(self, node):
+        pass
+
+    def visit_desc_type(self, node):
+        pass
+    def depart_desc_type(self, node):
+        pass
+
+    def visit_desc_returns(self, node):
+        self.add_text(' -> ')
+    def depart_desc_returns(self, node):
+        pass
+
+    def visit_desc_parameterlist(self, node):
+        self.add_text('(')
+        self.first_param = 1
+    def depart_desc_parameterlist(self, node):
+        self.add_text(')')
+
+    def visit_desc_parameter(self, node):
+        if not self.first_param:
+            self.add_text(', ')
+        else:
+            self.first_param = 0
+        self.add_text(node.astext())
+        raise nodes.SkipNode
+
+    def visit_desc_optional(self, node):
+        self.add_text('[')
+    def depart_desc_optional(self, node):
+        self.add_text(']')
+
+    def visit_desc_annotation(self, node):
+        pass
+    def depart_desc_annotation(self, node):
+        pass
+
+    def visit_refcount(self, node):
+        pass
+    def depart_refcount(self, node):
+        pass
+
+    def visit_desc_content(self, node):
+        self.new_state()
+        self.add_text('\n')
+    def depart_desc_content(self, node):
+        self.end_state()
+
+    def visit_figure(self, node):
+        self.new_state()
+    def depart_figure(self, node):
+        self.end_state()
+
+    def visit_caption(self, node):
+        pass
+    def depart_caption(self, node):
+        pass
+
+    def visit_productionlist(self, node):
+        self.new_state()
+        names = []
+        for production in node:
+            names.append(production['tokenname'])
+        maxlen = max(len(name) for name in names)
+        for production in node:
+            if production['tokenname']:
+                self.add_text(production['tokenname'].ljust(maxlen) + ' ::=')
+                lastname = production['tokenname']
+            else:
+                self.add_text('%s    ' % (' '*len(lastname)))
+            self.add_text(production.astext() + '\n')
+        self.end_state(wrap=False)
+        raise nodes.SkipNode
+
+    def visit_seealso(self, node):
+        self.new_state()
+    def depart_seealso(self, node):
+        self.end_state(first='')
+
+    def visit_footnote(self, node):
+        self._footnote = node.children[0].astext().strip()
+        self.new_state(len(self._footnote) + 3)
+    def depart_footnote(self, node):
+        self.end_state(first='[%s] ' % self._footnote)
+
+    def visit_citation(self, node):
+        if len(node) and isinstance(node[0], nodes.label):
+            self._citlabel = node[0].astext()
+        else:
+            self._citlabel = ''
+        self.new_state(len(self._citlabel) + 3)
+    def depart_citation(self, node):
+        self.end_state(first='[%s] ' % self._citlabel)
+
+    def visit_label(self, node):
+        raise nodes.SkipNode
+
+    # XXX: option list could use some better styling
+
+    def visit_option_list(self, node):
+        pass
+    def depart_option_list(self, node):
+        pass
+
+    def visit_option_list_item(self, node):
+        self.new_state(0)
+    def depart_option_list_item(self, node):
+        self.end_state()
+
+    def visit_option_group(self, node):
+        self._firstoption = True
+    def depart_option_group(self, node):
+        self.add_text('     ')
+
+    def visit_option(self, node):
+        if self._firstoption:
+            self._firstoption = False
+        else:
+            self.add_text(', ')
+    def depart_option(self, node):
+        pass
+
+    def visit_option_string(self, node):
+        pass
+    def depart_option_string(self, node):
+        pass
+
+    def visit_option_argument(self, node):
+        self.add_text(node['delimiter'])
+    def depart_option_argument(self, node):
+        pass
+
+    def visit_description(self, node):
+        pass
+    def depart_description(self, node):
+        pass
+
+    def visit_tabular_col_spec(self, node):
+        raise nodes.SkipNode
+
+    def visit_colspec(self, node):
+        self.table[0].append(node['colwidth'])
+        raise nodes.SkipNode
+
+    def visit_tgroup(self, node):
+        pass
+    def depart_tgroup(self, node):
+        pass
+
+    def visit_thead(self, node):
+        pass
+    def depart_thead(self, node):
+        pass
+
+    def visit_tbody(self, node):
+        self.table.append('sep')
+    def depart_tbody(self, node):
+        pass
+
+    def visit_row(self, node):
+        self.table.append([])
+    def depart_row(self, node):
+        pass
+
+    def visit_entry(self, node):
+        if node.has_key('morerows') or node.has_key('morecols'):
+            raise NotImplementedError('Column or row spanning cells are '
+                                      'not implemented.')
+        self.new_state(0)
+    def depart_entry(self, node):
+        text = '\n'.join('\n'.join(x[1]) for x in self.states.pop())
+        self.stateindent.pop()
+        self.table[-1].append(text)
+
+    def visit_table(self, node):
+        if self.table:
+            raise NotImplementedError('Nested tables are not supported.')
+        self.new_state(0)
+        self.table = [[]]
+    def depart_table(self, node):
+        lines = self.table[1:]
+        fmted_rows = []
+        colwidths = self.table[0]
+        realwidths = colwidths[:]
+        separator = 0
+        # don't allow paragraphs in table cells for now
+        for line in lines:
+            if line == 'sep':
+                separator = len(fmted_rows)
+            else:
+                cells = []
+                for i, cell in enumerate(line):
+                    par = textwrap.wrap(cell, width=colwidths[i])
+                    if par:
+                        maxwidth = max(map(len, par))
+                    else:
+                        maxwidth = 0
+                    realwidths[i] = max(realwidths[i], maxwidth)
+                    cells.append(par)
+                fmted_rows.append(cells)
+
+        def writesep(char='-'):
+            out = ['+']
+            for width in realwidths:
+                out.append(char * (width+2))
+                out.append('+')
+            self.add_text(''.join(out) + '\n')
+
+        def writerow(row):
+            lines = map(None, *row)
+            for line in lines:
+                out = ['|']
+                for i, cell in enumerate(line):
+                    if cell:
+                        out.append(' ' + cell.ljust(realwidths[i]+1))
+                    else:
+                        out.append(' ' * (realwidths[i] + 2))
+                    out.append('|')
+                self.add_text(''.join(out) + '\n')
+
+        for i, row in enumerate(fmted_rows):
+            if separator and i == separator:
+                writesep('=')
+            else:
+                writesep('-')
+            writerow(row)
+        writesep('-')
+        self.table = None
+        self.end_state(wrap=False)
+
+    def visit_acks(self, node):
+        self.new_state(0)
+        self.add_text(', '.join(n.astext() for n in node.children[0].children) + '.')
+        self.end_state()
+        raise nodes.SkipNode
+
+    def visit_image(self, node):
+        self.add_text(_('[image]'))
+        raise nodes.SkipNode
+
+    def visit_transition(self, node):
+        indent = sum(self.stateindent)
+        self.new_state(0)
+        self.add_text('=' * (MAXWIDTH - indent))
+        self.end_state()
+        raise nodes.SkipNode
+
+    def visit_bullet_list(self, node):
+        self._list_counter = -1
+    def depart_bullet_list(self, node):
+        pass
+
+    def visit_enumerated_list(self, node):
+        self._list_counter = 0
+    def depart_enumerated_list(self, node):
+        pass
+
+    def visit_definition_list(self, node):
+        self._list_counter = -2
+    def depart_definition_list(self, node):
+        pass
+
+    def visit_list_item(self, node):
+        if self._list_counter == -1:
+            # bullet list
+            self.new_state(2)
+        elif self._list_counter == -2:
+            # definition list
+            pass
+        else:
+            # enumerated list
+            self._list_counter += 1
+            self.new_state(len(str(self._list_counter)) + 2)
+    def depart_list_item(self, node):
+        if self._list_counter == -1:
+            self.end_state(first='* ', end=None)
+        elif self._list_counter == -2:
+            pass
+        else:
+            self.end_state(first='%s. ' % self._list_counter, end=None)
+
+    def visit_definition_list_item(self, node):
+        self._li_has_classifier = len(node) >= 2 and \
+                                  isinstance(node[1], nodes.classifier)
+    def depart_definition_list_item(self, node):
+        pass
+
+    def visit_term(self, node):
+        self.new_state(0)
+    def depart_term(self, node):
+        if not self._li_has_classifier:
+            self.end_state(end=None)
+
+    def visit_classifier(self, node):
+        self.add_text(' : ')
+    def depart_classifier(self, node):
+        self.end_state(end=None)
+
+    def visit_definition(self, node):
+        self.new_state()
+    def depart_definition(self, node):
+        self.end_state()
+
+    def visit_field_list(self, node):
+        pass
+    def depart_field_list(self, node):
+        pass
+
+    def visit_field(self, node):
+        pass
+    def depart_field(self, node):
+        pass
+
+    def visit_field_name(self, node):
+        self.new_state(0)
+    def depart_field_name(self, node):
+        self.add_text(':')
+        self.end_state(end=None)
+
+    def visit_field_body(self, node):
+        self.new_state()
+    def depart_field_body(self, node):
+        self.end_state()
+
+    def visit_centered(self, node):
+        pass
+    def depart_centered(self, node):
+        pass
+
+    def visit_admonition(self, node):
+        self.new_state(0)
+    def depart_admonition(self, node):
+        self.end_state()
+
+    def _visit_admonition(self, node):
+        self.new_state(2)
+    def _make_depart_admonition(name):
+        def depart_admonition(self, node):
+            self.end_state(first=admonitionlabels[name] + ': ')
+        return depart_admonition
+
+    visit_attention = _visit_admonition
+    depart_attention = _make_depart_admonition('attention')
+    visit_caution = _visit_admonition
+    depart_caution = _make_depart_admonition('caution')
+    visit_danger = _visit_admonition
+    depart_danger = _make_depart_admonition('danger')
+    visit_error = _visit_admonition
+    depart_error = _make_depart_admonition('error')
+    visit_hint = _visit_admonition
+    depart_hint = _make_depart_admonition('hint')
+    visit_important = _visit_admonition
+    depart_important = _make_depart_admonition('important')
+    visit_note = _visit_admonition
+    depart_note = _make_depart_admonition('note')
+    visit_tip = _visit_admonition
+    depart_tip = _make_depart_admonition('tip')
+    visit_warning = _visit_admonition
+    depart_warning = _make_depart_admonition('warning')
+
+    def visit_versionmodified(self, node):
+        self.new_state(0)
+        if node.children:
+            self.add_text(versionlabels[node['type']] % node['version'] + ': ')
+        else:
+            self.add_text(versionlabels[node['type']] % node['version'] + '.')
+    def depart_versionmodified(self, node):
+        self.end_state()
+
+    def visit_literal_block(self, node):
+        self.new_state()
+    def depart_literal_block(self, node):
+        self.end_state(wrap=False)
+
+    def visit_doctest_block(self, node):
+        self.new_state(0)
+    def depart_doctest_block(self, node):
+        self.end_state(wrap=False)
+
+    def visit_line_block(self, node):
+        self.new_state(0)
+    def depart_line_block(self, node):
+        self.end_state(wrap=False)
+
+    def visit_line(self, node):
+        pass
+    def depart_line(self, node):
+        pass
+
+    def visit_block_quote(self, node):
+        self.new_state()
+    def depart_block_quote(self, node):
+        self.end_state()
+
+    def visit_compact_paragraph(self, node):
+        pass
+    def depart_compact_paragraph(self, node):
+        pass
+
+    def visit_paragraph(self, node):
+        if not isinstance(node.parent, nodes.Admonition) or \
+               isinstance(node.parent, addnodes.seealso):
+            self.new_state(0)
+    def depart_paragraph(self, node):
+        if not isinstance(node.parent, nodes.Admonition) or \
+               isinstance(node.parent, addnodes.seealso):
+            self.end_state()
+
+    def visit_target(self, node):
+        raise nodes.SkipNode
+
+    def visit_index(self, node):
+        raise nodes.SkipNode
+
+    def visit_substitution_definition(self, node):
+        raise nodes.SkipNode
+
+    def visit_pending_xref(self, node):
+        pass
+    def depart_pending_xref(self, node):
+        pass
+
+    def visit_reference(self, node):
+        pass
+    def depart_reference(self, node):
+        pass
+
+    def visit_download_reference(self, node):
+        pass
+    def depart_download_reference(self, node):
+        pass
+
+    def visit_emphasis(self, node):
+        self.add_text('*')
+    def depart_emphasis(self, node):
+        self.add_text('*')
+
+    def visit_literal_emphasis(self, node):
+        self.add_text('*')
+    def depart_literal_emphasis(self, node):
+        self.add_text('*')
+
+    def visit_strong(self, node):
+        self.add_text('**')
+    def depart_strong(self, node):
+        self.add_text('**')
+
+    def visit_title_reference(self, node):
+        self.add_text('*')
+    def depart_title_reference(self, node):
+        self.add_text('*')
+
+    def visit_literal(self, node):
+        self.add_text('``')
+    def depart_literal(self, node):
+        self.add_text('``')
+
+    def visit_subscript(self, node):
+        self.add_text('_')
+    def depart_subscript(self, node):
+        pass
+
+    def visit_superscript(self, node):
+        self.add_text('^')
+    def depart_superscript(self, node):
+        pass
+
+    def visit_footnote_reference(self, node):
+        self.add_text('[%s]' % node.astext())
+        raise nodes.SkipNode
+
+    def visit_citation_reference(self, node):
+        self.add_text('[%s]' % node.astext())
+        raise nodes.SkipNode
+
+    def visit_Text(self, node):
+        self.add_text(node.astext())
+    def depart_Text(self, node):
+        pass
+
+    def visit_problematic(self, node):
+        self.add_text('>>')
+    def depart_problematic(self, node):
+        self.add_text('<<')
+
+    def visit_system_message(self, node):
+        self.new_state(0)
+        self.add_text('<SYSTEM MESSAGE: %s>' % node.astext())
+        self.end_state()
+        raise nodes.SkipNode
+
+    def visit_comment(self, node):
+        raise nodes.SkipNode
+
+    def visit_meta(self, node):
+        # only valid for HTML
+        raise nodes.SkipNode
+
+    def unknown_visit(self, node):
+        raise NotImplementedError('Unknown node: ' + node.__class__.__name__)

Added: doctools/trunk/tests/root/_static/README
==============================================================================
--- (empty file)
+++ doctools/trunk/tests/root/_static/README	Sun Jan  4 21:38:57 2009
@@ -0,0 +1 @@
+This placeholder file is there because Mercurial ignores empty directories.

Added: doctools/trunk/tests/root/_templates/layout.html
==============================================================================
--- (empty file)
+++ doctools/trunk/tests/root/_templates/layout.html	Sun Jan  4 21:38:57 2009
@@ -0,0 +1,4 @@
+{% extends "!layout.html" %}
+{% block extrahead %}
+<meta name="hc" content="{{ hckey }}" />
+{% endblock %}

Modified: doctools/trunk/tests/root/conf.py
==============================================================================
--- doctools/trunk/tests/root/conf.py	(original)
+++ doctools/trunk/tests/root/conf.py	Sun Jan  4 21:38:57 2009
@@ -23,7 +23,8 @@
 
 # Add any Sphinx extension module names here, as strings. They can be extensions
 # coming with Sphinx (named 'sphinx.ext.*') or your custom ones.
-extensions = ['ext', 'sphinx.ext.autodoc', 'sphinx.ext.jsmath', 'sphinx.ext.coverage']
+extensions = ['ext', 'sphinx.ext.autodoc', 'sphinx.ext.jsmath',
+              'sphinx.ext.coverage', 'sphinx.ext.todo']
 jsmath_path = 'dummy.js'
 
 # Add any paths that contain templates here, relative to this directory.
@@ -36,8 +37,8 @@
 master_doc = 'contents'
 
 # General substitutions.
-project = 'Sphinx Tests'
-copyright = '2008, Georg Brandl'
+project = 'Sphinx <Tests>'
+copyright = '2008, Georg Brandl & Team'
 
 # The default replacements for |version| and |release|, also used in various
 # other places throughout the built documents.
@@ -133,6 +134,8 @@
 # If nonempty, this is the file name suffix for HTML files (e.g. ".xhtml").
 #html_file_suffix = ''
 
+html_context = {'hckey': 'hcval'}
+
 # Output file base name for HTML help builder.
 htmlhelp_basename = 'SphinxTestsdoc'
 

Modified: doctools/trunk/tests/root/contents.txt
==============================================================================
--- doctools/trunk/tests/root/contents.txt	(original)
+++ doctools/trunk/tests/root/contents.txt	Sun Jan  4 21:38:57 2009
@@ -11,6 +11,7 @@
    :maxdepth: 2
 
    images
+   subdir/images
    includes
    markup
    desc

Added: doctools/trunk/tests/root/ext.pyc
==============================================================================
Binary file. No diff available.

Modified: doctools/trunk/tests/root/images.txt
==============================================================================
--- doctools/trunk/tests/root/images.txt	(original)
+++ doctools/trunk/tests/root/images.txt	Sun Jan  4 21:38:57 2009
@@ -9,6 +9,8 @@
 
 .. an image with path name (relative to this directory!)
 .. image:: subdir/img.png
+   :height: 100
+   :width: 200
 
 .. an image with unspecified extension
 .. image:: img.*
@@ -18,3 +20,6 @@
 
 .. a non-local image URI
 .. image:: http://www.python.org/logo.png
+
+.. an image with subdir and unspecified extension
+.. image:: subdir/simg.*

Modified: doctools/trunk/tests/root/includes.txt
==============================================================================
--- doctools/trunk/tests/root/includes.txt	(original)
+++ doctools/trunk/tests/root/includes.txt	Sun Jan  4 21:38:57 2009
@@ -14,3 +14,33 @@
    :encoding: latin-1
 .. include:: wrongenc.inc
    :encoding: latin-1
+
+Literalinclude options
+======================
+
+.. highlight:: text
+
+.. cssclass:: inc-pyobj1
+.. literalinclude:: literal.inc
+   :pyobject: Foo
+
+.. cssclass:: inc-pyobj2
+.. literalinclude:: literal.inc
+   :pyobject: Bar.baz
+
+.. cssclass:: inc-lines
+.. literalinclude:: literal.inc
+   :lines: 6-7,9
+
+.. cssclass:: inc-startend
+.. literalinclude:: literal.inc
+   :start-after: coding: utf-8
+   :end-before: class Foo
+
+
+Testing downloadable files
+==========================
+
+Download :download:`img.png` here.
+Download :download:`this <subdir/img.png>` there.
+Don't download :download:`this <nonexisting.png>`.

Modified: doctools/trunk/tests/root/literal.inc
==============================================================================
--- doctools/trunk/tests/root/literal.inc	(original)
+++ doctools/trunk/tests/root/literal.inc	Sun Jan  4 21:38:57 2009
@@ -2,3 +2,12 @@
 # -*- coding: utf-8 -*-
 
 foo = u"Including Unicode characters: üöä"
+
+class Foo:
+    pass
+
+class Bar:
+    def baz():
+        pass
+
+def bar(): pass

Modified: doctools/trunk/tests/root/markup.txt
==============================================================================
--- doctools/trunk/tests/root/markup.txt	(original)
+++ doctools/trunk/tests/root/markup.txt	Sun Jan  4 21:38:57 2009
@@ -99,7 +99,7 @@
 
 Reference lookup: [Ref1]_ (defined in another file).
 
-.. seealso::
+.. seealso:: something, something else, something more
 
    `Google <http://www.google.com>`_
        For everything.
@@ -110,6 +110,11 @@
 
 This tests :CLASS:`role names in uppercase`.
 
+Option list:
+
+-h              help
+--help          also help
+
 .. centered:: LICENSE AGREEMENT
 
 .. acks::
@@ -143,6 +148,14 @@
    single: entry
    pair: entry; pair
    triple: index; entry; triple
+   keyword: with
+
+Invalid index markup...
+
+.. index::
+   single:
+   pair:
+   keyword:
 
 
 Ö... Some strange characters

Added: doctools/trunk/tests/root/subdir/images.txt
==============================================================================
--- (empty file)
+++ doctools/trunk/tests/root/subdir/images.txt	Sun Jan  4 21:38:57 2009
@@ -0,0 +1,4 @@
+Image including source in subdir
+================================
+
+.. image:: img.*

Added: doctools/trunk/tests/root/subdir/simg.png
==============================================================================
Binary file. No diff available.

Modified: doctools/trunk/tests/run.py
==============================================================================
--- doctools/trunk/tests/run.py	(original)
+++ doctools/trunk/tests/run.py	Sun Jan  4 21:38:57 2009
@@ -6,8 +6,8 @@
 
     This script runs the Sphinx unit test suite.
 
-    :copyright: 2008 by Georg Brandl.
-    :license: BSD.
+    :copyright: Copyright 2007-2009 by the Sphinx team, see AUTHORS.
+    :license: BSD, see LICENSE for details.
 """
 
 import sys

Modified: doctools/trunk/tests/test_application.py
==============================================================================
--- doctools/trunk/tests/test_application.py	(original)
+++ doctools/trunk/tests/test_application.py	Sun Jan  4 21:38:57 2009
@@ -5,8 +5,8 @@
 
     Test the Sphinx class.
 
-    :copyright: 2008 by Benjamin Peterson.
-    :license: BSD.
+    :copyright: Copyright 2007-2009 by the Sphinx team, see AUTHORS.
+    :license: BSD, see LICENSE for details.
 """
 
 from StringIO import StringIO

Modified: doctools/trunk/tests/test_autodoc.py
==============================================================================
--- doctools/trunk/tests/test_autodoc.py	(original)
+++ doctools/trunk/tests/test_autodoc.py	Sun Jan  4 21:38:57 2009
@@ -6,8 +6,8 @@
     Test the autodoc extension.  This tests mainly the RstGenerator; the auto
     directives are tested in a test source file translated by test_build.
 
-    :copyright: 2008 by Georg Brandl.
-    :license: BSD.
+    :copyright: Copyright 2007-2009 by the Sphinx team, see AUTHORS.
+    :license: BSD, see LICENSE for details.
 """
 
 from util import *
@@ -24,6 +24,7 @@
     app.builder.env.app = app
     app.connect('autodoc-process-docstring', process_docstring)
     app.connect('autodoc-process-signature', process_signature)
+    app.connect('autodoc-skip-member', skip_member)
 
     options = Struct(
         inherited_members = False,
@@ -71,44 +72,51 @@
         return '42', None
 
 
+def skip_member(app, what, name, obj, skip, options):
+    if name.startswith('_'):
+        return True
+    if name == 'skipmeth':
+        return True
+
+
 def test_resolve_name():
     # for modules
     assert gen.resolve_name('module', 'test_autodoc') == \
-           ('test_autodoc', 'test_autodoc', [], None, None)
+           ('test_autodoc', [], None, None)
     assert gen.resolve_name('module', 'test.test_autodoc') == \
-           ('test.test_autodoc', 'test.test_autodoc', [], None, None)
+           ('test.test_autodoc', [], None, None)
 
     assert gen.resolve_name('module', 'test(arg)') == \
-           ('test', 'test', [], None, None)
+           ('test', [], None, None)
     assert 'ignoring signature arguments' in gen.warnings[0]
     del gen.warnings[:]
 
     # for functions/classes
     assert gen.resolve_name('function', 'util.raises') == \
-           ('util.raises', 'util', ['raises'], None, None)
+           ('util', ['raises'], None, None)
     assert gen.resolve_name('function', 'util.raises(exc) -> None') == \
-           ('util.raises', 'util', ['raises'], 'exc', ' -> None')
+           ('util', ['raises'], 'exc', 'None')
     gen.env.autodoc_current_module = 'util'
     assert gen.resolve_name('function', 'raises') == \
-           ('raises', 'util', ['raises'], None, None)
+           ('util', ['raises'], None, None)
     gen.env.autodoc_current_module = None
     gen.env.currmodule = 'util'
     assert gen.resolve_name('function', 'raises') == \
-           ('raises', 'util', ['raises'], None, None)
+           ('util', ['raises'], None, None)
     assert gen.resolve_name('class', 'TestApp') == \
-           ('TestApp', 'util', ['TestApp'], None, None)
+           ('util', ['TestApp'], None, None)
 
     # for members
     gen.env.currmodule = 'foo'
     assert gen.resolve_name('method', 'util.TestApp.cleanup') == \
-           ('util.TestApp.cleanup', 'util', ['TestApp', 'cleanup'], None, None)
+           ('util', ['TestApp', 'cleanup'], None, None)
     gen.env.currmodule = 'util'
     gen.env.currclass = 'Foo'
     gen.env.autodoc_current_class = 'TestApp'
     assert gen.resolve_name('method', 'cleanup') == \
-           ('cleanup', 'util', ['TestApp', 'cleanup'], None, None)
+           ('util', ['TestApp', 'cleanup'], None, None)
     assert gen.resolve_name('method', 'TestApp.cleanup') == \
-           ('TestApp.cleanup', 'util', ['TestApp', 'cleanup'], None, None)
+           ('util', ['TestApp', 'cleanup'], None, None)
 
     # and clean up
     gen.env.currmodule = None
@@ -126,7 +134,7 @@
     assert gen.format_signature('function', 'f', f, None, None) == '(a, b, c=1, **d)'
     assert gen.format_signature('function', 'f', f, 'a, b, c, d', None) == \
            '(a, b, c, d)'
-    assert gen.format_signature('function', 'f', f, None, ' -> None') == \
+    assert gen.format_signature('function', 'f', f, None, 'None') == \
            '(a, b, c=1, **d) -> None'
 
     # test for classes
@@ -144,7 +152,7 @@
         pass
     for C in (F, G):
         assert gen.format_signature('class', 'C', C, None, None) == '(a, b=None)'
-    assert gen.format_signature('class', 'C', D, 'a, b', ' -> X') == '(a, b) -> X'
+    assert gen.format_signature('class', 'C', D, 'a, b', 'X') == '(a, b) -> X'
 
     # test for methods
     class H:
@@ -165,13 +173,14 @@
 
 def test_get_doc():
     def getdocl(*args):
-        # strip the empty line at the end
-        return list(gen.get_doc(*args))[:-1]
+        ds = gen.get_doc(*args)
+        # for testing purposes, concat them and strip the empty line at the end
+        return sum(ds, [])[:-1]
 
     # objects without docstring
     def f():
         pass
-    assert getdocl('function', 'f', f) == []
+    assert getdocl('function', f) == []
 
     # standard function, diverse docstring styles...
     def f():
@@ -181,7 +190,7 @@
         Docstring
         """
     for func in (f, g):
-        assert getdocl('function', 'f', func) == ['Docstring']
+        assert getdocl('function', func) == ['Docstring']
 
     # first line vs. other lines indentation
     def f():
@@ -190,17 +199,17 @@
         Other
           lines
         """
-    assert getdocl('function', 'f', f) == ['First line', '', 'Other', '  lines']
+    assert getdocl('function', f) == ['First line', '', 'Other', '  lines']
 
     # charset guessing (this module is encoded in utf-8)
     def f():
         """Döcstring"""
-    assert getdocl('function', 'f', f) == [u'Döcstring']
+    assert getdocl('function', f) == [u'Döcstring']
 
     # already-unicode docstrings must be taken literally
     def f():
         u"""Döcstring"""
-    assert getdocl('function', 'f', f) == [u'Döcstring']
+    assert getdocl('function', f) == [u'Döcstring']
 
     # class docstring: depends on config value which one is taken
     class C:
@@ -208,21 +217,37 @@
         def __init__(self):
             """Init docstring"""
     gen.env.config.autoclass_content = 'class'
-    assert getdocl('class', 'C', C) == ['Class docstring']
+    assert getdocl('class', C) == ['Class docstring']
     gen.env.config.autoclass_content = 'init'
-    assert getdocl('class', 'C', C) == ['Init docstring']
+    assert getdocl('class', C) == ['Init docstring']
     gen.env.config.autoclass_content = 'both'
-    assert getdocl('class', 'C', C) == ['Class docstring', '', 'Init docstring']
+    assert getdocl('class', C) == ['Class docstring', '', 'Init docstring']
 
     class D:
+        """Class docstring"""
+        def __init__(self):
+            """Init docstring
+
+            Other
+             lines
+            """
+
+    # Indentation is normalized for 'both'
+    assert getdocl('class', D) == ['Class docstring', '', 'Init docstring',
+                                   '', 'Other', ' lines']
+
+
+def test_docstring_processing():
+    def process(what, name, obj):
+        return list(gen.process_doc(gen.get_doc(what, obj), what, name, obj))
+
+    class E:
         def __init__(self):
             """Init docstring"""
 
     # docstring processing by event handler
-    assert getdocl('class', 'bar', D) == ['Init docstring', '', '42']
+    assert process('class', 'bar', E) == ['Init docstring', '', '42', '']
 
-
-def test_docstring_processing_functions():
     lid = app.connect('autodoc-process-docstring', cut_lines(1, 1, ['function']))
     def f():
         """
@@ -230,7 +255,7 @@
         second line
         third line
         """
-    assert list(gen.get_doc('function', 'f', f)) == ['second line', '']
+    assert process('function', 'f', f) == ['second line', '']
     app.disconnect(lid)
 
     lid = app.connect('autodoc-process-docstring', between('---', ['function']))
@@ -242,7 +267,7 @@
         ---
         third line
         """
-    assert list(gen.get_doc('function', 'f', f)) == ['second line', '']
+    assert process('function', 'f', f) == ['second line', '']
     app.disconnect(lid)
 
 
@@ -268,7 +293,7 @@
 
     def assert_result_contains(item, *args):
         gen.generate(*args)
-        print '\n'.join(gen.result)
+        #print '\n'.join(gen.result)
         assert len(gen.warnings) == 0, gen.warnings
         assert item in gen.result
         del gen.result[:]
@@ -300,17 +325,20 @@
     assert_works('exception', 'test_autodoc.CustomEx', [], None)
 
     # test diverse inclusion settings for members
-    should = [('class', 'Class')]
+    should = [('class', 'test_autodoc.Class')]
     assert_processes(should, 'class', 'Class', [], None)
-    should.extend([('method', 'Class.meth')])
+    should.extend([('method', 'test_autodoc.Class.meth')])
     assert_processes(should, 'class', 'Class', ['meth'], None)
-    should.extend([('attribute', 'Class.prop')])
+    should.extend([('attribute', 'test_autodoc.Class.prop'),
+                   ('attribute', 'test_autodoc.Class.attr'),
+                   ('attribute', 'test_autodoc.Class.docattr'),
+                   ('attribute', 'test_autodoc.Class.udocattr')])
     assert_processes(should, 'class', 'Class', ['__all__'], None)
     options.undoc_members = True
-    should.append(('method', 'Class.undocmeth'))
+    should.append(('method', 'test_autodoc.Class.undocmeth'))
     assert_processes(should, 'class', 'Class', ['__all__'], None)
     options.inherited_members = True
-    should.append(('method', 'Class.inheritedmeth'))
+    should.append(('method', 'test_autodoc.Class.inheritedmeth'))
     assert_processes(should, 'class', 'Class', ['__all__'], None)
 
     # test module flags
@@ -342,6 +370,17 @@
     assert_result_contains('.. class:: CustomDict', 'class', 'CustomDict',
                            ['__all__'], None)
 
+    # test inner class handling
+    assert_processes([('class', 'test_autodoc.Outer'),
+                      ('class', 'test_autodoc.Outer.Inner'),
+                      ('method', 'test_autodoc.Outer.Inner.meth')],
+                     'class', 'Outer', ['__all__'], None)
+
+    # test generation for C modules (which have no source file)
+    gen.env.currmodule = 'time'
+    assert_processes([('function', 'time.asctime')], 'function', 'asctime', [], None)
+    assert_processes([('function', 'time.asctime')], 'function', 'asctime', [], None)
+
 
 # --- generate fodder ------------
 
@@ -367,10 +406,26 @@
     def undocmeth(self):
         pass
 
+    def skipmeth(self):
+        """Method that should be skipped."""
+        pass
+
+    # should not be documented
+    skipattr = 'foo'
+
+    #: should be documented -- süß
+    attr = 'bar'
+
     @property
     def prop(self):
         """Property."""
 
+    docattr = 'baz'
+    """should likewise be documented -- süß"""
+
+    udocattr = 'quux'
+    u"""should be documented as well - süß"""
+
 class CustomDict(dict):
     """Docstring."""
 
@@ -379,3 +434,16 @@
     Return spam.
     """
     pass
+
+
+class Outer(object):
+    """Foo"""
+
+    class Inner(object):
+        """Foo"""
+
+        def meth(self):
+            """Foo"""
+
+    # should be documented as an alias
+    factory = dict

Modified: doctools/trunk/tests/test_build.py
==============================================================================
--- doctools/trunk/tests/test_build.py	(original)
+++ doctools/trunk/tests/test_build.py	Sun Jan  4 21:38:57 2009
@@ -5,11 +5,13 @@
 
     Test the entire build process with the test root.
 
-    :copyright: 2008 by Georg Brandl.
-    :license: BSD.
+    :copyright: Copyright 2007-2009 by the Sphinx team, see AUTHORS.
+    :license: BSD, see LICENSE for details.
 """
 
 import os
+import re
+import sys
 import difflib
 import htmlentitydefs
 from StringIO import StringIO
@@ -18,8 +20,9 @@
 from util import *
 from etree13 import ElementTree as ET
 
-from sphinx.builder import StandaloneHTMLBuilder, LaTeXBuilder
-from sphinx.latexwriter import LaTeXTranslator
+from sphinx.builders.html import StandaloneHTMLBuilder
+from sphinx.builders.latex import LaTeXBuilder
+from sphinx.writers.latex import LaTeXTranslator
 
 
 html_warnfile = StringIO()
@@ -27,38 +30,58 @@
 
 ENV_WARNINGS = """\
 WARNING: %(root)s/images.txt:9: Image file not readable: foo.png
-WARNING: %(root)s/images.txt:20: Nonlocal image URI found: http://www.python.org/logo.png
+WARNING: %(root)s/images.txt:23: Nonlocal image URI found: http://www.python.org/logo.png
 WARNING: %(root)s/includes.txt:: (WARNING/2) Encoding 'utf-8' used for reading included \
 file u'wrongenc.inc' seems to be wrong, try giving an :encoding: option
+WARNING: %(root)s/includes.txt:56: Download file not readable: nonexisting.png
 """
 
 HTML_WARNINGS = ENV_WARNINGS + """\
 WARNING: %(root)s/images.txt:: no matching candidate for image URI u'foo.*'
+WARNING: %(root)s/markup.txt:: invalid index entry u''
+WARNING: %(root)s/markup.txt:: invalid pair index entry u''
+WARNING: %(root)s/markup.txt:: invalid pair index entry u'keyword; '
 """
 
 LATEX_WARNINGS = ENV_WARNINGS + """\
 WARNING: None:: no matching candidate for image URI u'foo.*'
+WARNING: invalid pair index entry u''
 """
 
 HTML_XPATH = {
     'images.html': {
         ".//img[@src='_images/img.png']": '',
         ".//img[@src='_images/img1.png']": '',
+        ".//img[@src='_images/simg.png']": '',
+    },
+    'subdir/images.html': {
+        ".//img[@src='../_images/img1.png']": '',
     },
     'includes.html': {
         ".//pre/span[@class='s']": u'üöä',
         ".//pre": u'Max Strauß',
+        ".//a[@href='_downloads/img.png']": '',
+        ".//a[@href='_downloads/img1.png']": '',
+        ".//div[@class='inc-pyobj1 highlight-text']/div/pre":
+            r'^class Foo:\n    pass\n\s*$',
+        ".//div[@class='inc-pyobj2 highlight-text']/div/pre":
+            r'^    def baz\(\):\n        pass\n\s*$',
+        ".//div[@class='inc-lines highlight-text']/div/pre":
+            r'^class Foo:\n    pass\nclass Bar:\n$',
+        ".//div[@class='inc-startend highlight-text']/div/pre":
+            ur'^foo = u"Including Unicode characters: üöä"\n$',
     },
     'autodoc.html': {
         ".//dt[@id='test_autodoc.Class']": '',
-        ".//dt[@id='test_autodoc.function']/em": '**kwds',
-        ".//dd": 'Return spam.',
+        ".//dt[@id='test_autodoc.function']/em": r'\*\*kwds',
+        ".//dd": r'Return spam\.',
     },
     'markup.html': {
         ".//meta[@name='author'][@content='Me']": '',
         ".//meta[@name='keywords'][@content='docs, sphinx']": '',
         ".//a[@href='contents.html#ref1']": '',
         ".//div[@id='label']": '',
+        ".//span[@class='option']": '--help',
     },
     'desc.html': {
         ".//dt[@id='mod.Cls.meth1']": '',
@@ -66,7 +89,12 @@
         ".//a[@href='#mod.Cls']": '',
     },
     'contents.html': {
-        ".//td[@class='label']": '[Ref1]',
+        ".//meta[@name='hc'][@content='hcval']": '',
+        ".//td[@class='label']": r'\[Ref1\]',
+        ".//li[@class='toctree-l1']/a": 'Testing various markup',
+        ".//li[@class='toctree-l2']/a": 'Admonitions',
+        ".//title": 'Sphinx <Tests>',
+        ".//div[@class='footer']": 'Georg Brandl & Team',
     },
 }
 
@@ -98,18 +126,23 @@
         parser = NslessParser()
         parser.entity.update(htmlentitydefs.entitydefs)
         etree = ET.parse(os.path.join(app.outdir, fname), parser)
-        for path, text in paths.iteritems():
+        for path, check in paths.iteritems():
             nodes = list(etree.findall(path))
             assert nodes != []
-            if not text:
+            if callable(check):
+                check(nodes)
+            elif not check:
                 # only check for node presence
                 continue
-            for node in nodes:
-                if node.text and text in node.text:
-                    break
             else:
-                assert False, ('%r not found in any node matching '
-                               'path %s in %s' % (text, path, fname))
+                rex = re.compile(check)
+                for node in nodes:
+                    if node.text and rex.search(node.text):
+                        break
+                else:
+                    assert False, ('%r not found in any node matching '
+                                   'path %s in %s: %r' % (check, path, fname,
+                                   [node.text for node in nodes]))
 
 
 @with_app(buildername='latex', warning=latex_warnfile)
@@ -122,6 +155,32 @@
            '\n'.join(difflib.ndiff(latex_warnings_exp.splitlines(),
                                    latex_warnings.splitlines()))
 
+    # only run latex if all needed packages are there
+    def kpsetest(filename):
+        try:
+            p = Popen(['kpsewhich', filename], stdout=PIPE)
+        except OSError, err:
+            # no kpsewhich... either no tex distribution is installed or it is
+            # a "strange" one -- don't bother running latex
+            return None
+        else:
+            p.communicate()
+            if p.returncode != 0:
+                # not found
+                return False
+            # found
+            return True
+
+    if kpsetest('article.sty') is None:
+        print >>sys.stderr, 'info: not running latex, it doesn\'t seem to be installed'
+        return
+    for filename in ['fancyhdr.sty', 'fancybox.sty', 'titlesec.sty', 'amsmath.sty',
+                     'framed.sty', 'color.sty', 'fancyvrb.sty', 'threeparttable.sty']:
+        if not kpsetest(filename):
+            print >>sys.stderr, 'info: not running latex, the %s package doesn\'t ' \
+                  'seem to be installed' % filename
+            return
+
     # now, try to run latex over it
     cwd = os.getcwd()
     os.chdir(app.outdir)

Modified: doctools/trunk/tests/test_config.py
==============================================================================
--- doctools/trunk/tests/test_config.py	(original)
+++ doctools/trunk/tests/test_config.py	Sun Jan  4 21:38:57 2009
@@ -6,8 +6,8 @@
     Test the sphinx.config.Config class and its handling in the
     Application class.
 
-    :copyright: 2008 by Georg Brandl.
-    :license: BSD.
+    :copyright: Copyright 2007-2009 by the Sphinx team, see AUTHORS.
+    :license: BSD, see LICENSE for details.
 """
 
 from util import *
@@ -15,17 +15,19 @@
 from sphinx.application import ExtensionError
 
 
- at with_app(confoverrides={'master_doc': 'master', 'nonexisting_value': 'True'})
+ at with_app(confoverrides={'master_doc': 'master', 'nonexisting_value': 'True',
+                         'latex_elements.docclass': 'scrartcl'})
 def test_core_config(app):
     cfg = app.config
 
     # simple values
     assert 'project' in cfg.__dict__
-    assert cfg.project == 'Sphinx Tests'
+    assert cfg.project == 'Sphinx <Tests>'
     assert cfg.templates_path == ['_templates']
 
     # overrides
     assert cfg.master_doc == 'master'
+    assert cfg.latex_elements['docclass'] == 'scrartcl'
 
     # simple default values
     assert 'exclude_dirs' not in cfg.__dict__
@@ -34,7 +36,7 @@
 
     # complex default values
     assert 'html_title' not in cfg.__dict__
-    assert cfg.html_title == 'Sphinx Tests v0.4alpha1 documentation'
+    assert cfg.html_title == 'Sphinx <Tests> v0.4alpha1 documentation'
 
     # complex default values mustn't raise
     for valuename in cfg.config_values:

Modified: doctools/trunk/tests/test_coverage.py
==============================================================================
--- doctools/trunk/tests/test_coverage.py	(original)
+++ doctools/trunk/tests/test_coverage.py	Sun Jan  4 21:38:57 2009
@@ -5,8 +5,8 @@
 
     Test the coverage builder.
 
-    :copyright: 2008 by Georg Brandl.
-    :license: BSD.
+    :copyright: Copyright 2007-2009 by the Sphinx team, see AUTHORS.
+    :license: BSD, see LICENSE for details.
 """
 
 import pickle

Modified: doctools/trunk/tests/test_env.py
==============================================================================
--- doctools/trunk/tests/test_env.py	(original)
+++ doctools/trunk/tests/test_env.py	Sun Jan  4 21:38:57 2009
@@ -5,14 +5,15 @@
 
     Test the BuildEnvironment class.
 
-    :copyright: 2008 by Georg Brandl.
-    :license: BSD.
+    :copyright: Copyright 2007-2009 by the Sphinx team, see AUTHORS.
+    :license: BSD, see LICENSE for details.
 """
 
 from util import *
 
 from sphinx.environment import BuildEnvironment
-from sphinx.builder import StandaloneHTMLBuilder, LaTeXBuilder
+from sphinx.builders.html import StandaloneHTMLBuilder
+from sphinx.builders.latex import LaTeXBuilder
 
 app = env = None
 warnings = []
@@ -54,16 +55,19 @@
     htmlbuilder = StandaloneHTMLBuilder(app, env)
     htmlbuilder.post_process_images(tree)
     assert "no matching candidate for image URI u'foo.*'" in app._warning.content[-1]
-    assert set(htmlbuilder.images.keys()) == set(['subdir/img.png', 'img.png'])
-    assert set(htmlbuilder.images.values()) == set(['img.png', 'img1.png'])
+    assert set(htmlbuilder.images.keys()) == set(['subdir/img.png', 'img.png',
+                                                  'subdir/simg.png'])
+    assert set(htmlbuilder.images.values()) == set(['img.png', 'img1.png',
+                                                    'simg.png'])
 
     app._warning.reset()
     latexbuilder = LaTeXBuilder(app, env)
     latexbuilder.post_process_images(tree)
     assert "no matching candidate for image URI u'foo.*'" in app._warning.content[-1]
-    assert set(latexbuilder.images.keys()) == set(['subdir/img.png',
+    assert set(latexbuilder.images.keys()) == set(['subdir/img.png', 'subdir/simg.png',
                                                    'img.png', 'img.pdf'])
-    assert set(latexbuilder.images.values()) == set(['img.pdf', 'img.png', 'img1.png'])
+    assert set(latexbuilder.images.values()) == set(['img.pdf', 'img.png',
+                                                     'img1.png', 'simg.png'])
 
 def test_second_update():
     # delete, add and "edit" (change saved mtime) some files and update again
@@ -73,11 +77,13 @@
     (root / 'new.txt').write_text('New file\n========\n')
     it = env.update(app.config, app.srcdir, app.doctreedir, app)
     msg = it.next()
-    assert '1 added, 1 changed, 1 removed' in msg
+    assert '1 added, 2 changed, 1 removed' in msg
     docnames = set()
     for docname in it:
         docnames.add(docname)
-    assert docnames == set(['contents', 'new'])
+    # "includes" is in there because it contains a reference to a nonexisting
+    # downloadable file, which is given another chance to exist
+    assert docnames == set(['contents', 'new', 'includes'])
     assert 'images' not in env.all_docs
     assert 'images' not in env.found_docs
 

Added: doctools/trunk/tests/test_highlighting.py
==============================================================================
--- (empty file)
+++ doctools/trunk/tests/test_highlighting.py	Sun Jan  4 21:38:57 2009
@@ -0,0 +1,68 @@
+# -*- coding: utf-8 -*-
+"""
+    test_highlighting
+    ~~~~~~~~~~~~~~~~~
+
+    Test the Pygments highlighting bridge.
+
+    :copyright: Copyright 2007-2009 by the Sphinx team, see AUTHORS.
+    :license: BSD, see LICENSE for details.
+"""
+
+from util import *
+
+from pygments.lexer import RegexLexer
+from pygments.token import Text, Name
+from pygments.formatters.html import HtmlFormatter
+
+from sphinx.highlighting import PygmentsBridge
+
+
+class MyLexer(RegexLexer):
+    name = 'testlexer'
+
+    tokens = {
+        'root': [
+            ('a', Name),
+            ('b', Text),
+        ],
+    }
+
+class ComplainOnUnhighlighted(PygmentsBridge):
+
+    def unhighlighted(self, source):
+        raise AssertionError("should highlight %r" % source)
+
+class MyFormatter(HtmlFormatter):
+    def format(self, tokensource, outfile):
+        outfile.write('test')
+
+
+ at with_app()
+def test_add_lexer(app):
+    app.add_lexer('test', MyLexer())
+
+    bridge = PygmentsBridge('html')
+    ret = bridge.highlight_block('ab', 'test')
+    assert '<span class="n">a</span>b' in ret
+
+def test_detect_interactive():
+    bridge = ComplainOnUnhighlighted('html')
+    blocks = [
+        """
+        >>> testing()
+        True
+        """,
+        ]
+    for block in blocks:
+        ret = bridge.highlight_block(block.lstrip(), 'python')
+        assert ret.startswith("<div class=\"highlight\">")
+
+def test_set_formatter():
+    PygmentsBridge.html_formatter = MyFormatter
+    try:
+        bridge = PygmentsBridge('html')
+        ret = bridge.highlight_block('foo', 'python')
+        assert ret == 'test'
+    finally:
+        PygmentsBridge.html_formatter = HtmlFormatter

Modified: doctools/trunk/tests/test_i18n.py
==============================================================================
--- doctools/trunk/tests/test_i18n.py	(original)
+++ doctools/trunk/tests/test_i18n.py	Sun Jan  4 21:38:57 2009
@@ -5,8 +5,8 @@
 
     Test locale features.
 
-    :copyright: 2008 by Georg Brandl.
-    :license: BSD.
+    :copyright: Copyright 2007-2009 by the Sphinx team, see AUTHORS.
+    :license: BSD, see LICENSE for details.
 """
 
 from util import *

Modified: doctools/trunk/tests/test_markup.py
==============================================================================
--- doctools/trunk/tests/test_markup.py	(original)
+++ doctools/trunk/tests/test_markup.py	Sun Jan  4 21:38:57 2009
@@ -5,8 +5,8 @@
 
     Test various Sphinx-specific markup extensions.
 
-    :copyright: 2008 by Georg Brandl.
-    :license: BSD.
+    :copyright: Copyright 2007-2009 by the Sphinx team, see AUTHORS.
+    :license: BSD, see LICENSE for details.
 """
 
 import re
@@ -17,11 +17,13 @@
 from docutils.parsers import rst
 
 from sphinx import addnodes
-from sphinx.htmlwriter import HTMLWriter, SmartyPantsHTMLTranslator
-from sphinx.latexwriter import LaTeXWriter, LaTeXTranslator
+from sphinx.util import texescape
+from sphinx.writers.html import HTMLWriter, SmartyPantsHTMLTranslator
+from sphinx.writers.latex import LaTeXWriter, LaTeXTranslator
 
 def setup_module():
     global app, settings, parser
+    texescape.init()  # otherwise done by the latex builder
     app = TestApp(cleanenv=True)
     optparser = frontend.OptionParser(components=(rst.Parser, HTMLWriter, LaTeXWriter))
     settings = optparser.get_default_values()
@@ -94,7 +96,7 @@
     # non-interpolation of dashes in option role
     verify_re(':option:`--with-option`',
               '<p><em( class="xref")?>--with-option</em></p>$',
-              r'\\emph{\\texttt{--with-option}}$')
+              r'\\emph{\\texttt{-{-}with-option}}$')
 
     # verify smarty-pants quotes
     verify('"John"', '<p>&#8220;John&#8221;</p>', "``John''")

Modified: doctools/trunk/tests/test_quickstart.py
==============================================================================
--- doctools/trunk/tests/test_quickstart.py	(original)
+++ doctools/trunk/tests/test_quickstart.py	Sun Jan  4 21:38:57 2009
@@ -5,8 +5,8 @@
 
     Test the sphinx.quickstart module.
 
-    :copyright: 2008 by Georg Brandl.
-    :license: BSD.
+    :copyright: Copyright 2007-2009 by the Sphinx team, see AUTHORS.
+    :license: BSD, see LICENSE for details.
 """
 
 import sys

Modified: doctools/trunk/tests/util.py
==============================================================================
--- doctools/trunk/tests/util.py	(original)
+++ doctools/trunk/tests/util.py	Sun Jan  4 21:38:57 2009
@@ -3,8 +3,8 @@
     Sphinx test suite utilities
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
-    :copyright: 2008 by Georg Brandl.
-    :license: BSD.
+    :copyright: Copyright 2007-2009 by the Sphinx team, see AUTHORS.
+    :license: BSD, see LICENSE for details.
 """
 
 import sys
@@ -13,9 +13,13 @@
 import tempfile
 import shutil
 
-from functools import wraps
+try:
+    from functools import wraps
+except ImportError:
+    # functools is new in 2.4
+    wraps = lambda f: (lambda w: w)
 
-from sphinx import application, builder
+from sphinx import application
 
 from path import path
 

Modified: doctools/trunk/utils/check_sources.py
==============================================================================
--- doctools/trunk/utils/check_sources.py	(original)
+++ doctools/trunk/utils/check_sources.py	Sun Jan  4 21:38:57 2009
@@ -7,7 +7,7 @@
     Make sure each Python file has a correct file header
     including copyright and license information.
 
-    :copyright: 2006-2008 by Georg Brandl.
+    :copyright: Copyright 2006-2009 by Georg Brandl.
     :license: GNU GPL, see LICENSE for more details.
 """
 
@@ -30,7 +30,8 @@
 
 
 name_mail_re = r'[\w ]+(<.*?>)?'
-copyright_re = re.compile(r'^    :copyright: 200\d(-200\d)? by %s(, %s)*[,.]$' %
+copyright_re = re.compile(r'^    :copyright: Copyright 200\d(-200\d)?'
+                          r'by %s(, %s)*[,.]$' %
                           (name_mail_re, name_mail_re))
 license_re = re.compile(r"    :license: (.*?).\n")
 copyright_2_re = re.compile(r'^                %s(, %s)*[,.]$' %


More information about the Python-checkins mailing list