summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGeorg Brandl <georg@python.org>2014-01-19 11:15:24 +0100
committerGeorg Brandl <georg@python.org>2014-01-19 11:15:24 +0100
commit6a5de08f929ef4dc58f68122dea364af4ed212e5 (patch)
treefc43faa61088ceb82e3a7e8025240d8c685111b1
parentd413fd5731de449c1f69a6c8f4898fd7645fd494 (diff)
parent88a6b565ac65a33f2798b8cbc504eb147b9a9d87 (diff)
downloadsphinx-6a5de08f929ef4dc58f68122dea364af4ed212e5.tar.gz
Merged in saschpe/sphinx (pull request #193)
BuildDoc shouldn't fail on Unicode paths.
-rw-r--r--CHANGES168
-rw-r--r--EXAMPLES6
-rw-r--r--MANIFEST.in5
-rw-r--r--doc/_templates/index.html15
-rw-r--r--doc/builders.rst10
-rw-r--r--doc/config.rst14
-rw-r--r--doc/develop.rst26
-rw-r--r--doc/devguide.rst8
-rw-r--r--doc/domains.rst134
-rw-r--r--doc/ext/appapi.rst11
-rw-r--r--doc/ext/autodoc.rst14
-rw-r--r--doc/ext/oldcmarkup.rst35
-rw-r--r--doc/extensions.rst7
-rw-r--r--doc/faq.rst16
-rw-r--r--doc/install.rst10
-rw-r--r--doc/intl.rst42
-rw-r--r--doc/intro.rst10
-rw-r--r--doc/invocation.rst20
-rw-r--r--doc/man/sphinx-build.rst19
-rw-r--r--doc/markup/code.rst43
-rw-r--r--doc/markup/misc.rst12
-rw-r--r--doc/markup/toctree.rst10
-rw-r--r--doc/rest.rst2
-rw-r--r--doc/templating.rst3
-rw-r--r--doc/tutorial.rst31
-rw-r--r--setup.py12
-rw-r--r--sphinx/__init__.py12
-rw-r--r--sphinx/addnodes.py5
-rw-r--r--sphinx/apidoc.py52
-rw-r--r--sphinx/application.py6
-rw-r--r--sphinx/builders/epub.py8
-rw-r--r--sphinx/builders/gettext.py5
-rw-r--r--sphinx/builders/html.py17
-rw-r--r--sphinx/builders/linkcheck.py93
-rw-r--r--sphinx/builders/text.py1
-rw-r--r--sphinx/cmdline.py13
-rw-r--r--sphinx/config.py35
-rw-r--r--sphinx/directives/__init__.py19
-rw-r--r--sphinx/directives/code.py29
-rw-r--r--sphinx/domains/c.py24
-rw-r--r--sphinx/domains/python.py23
-rw-r--r--sphinx/domains/std.py38
-rw-r--r--sphinx/environment.py13
-rw-r--r--sphinx/ext/autodoc.py84
-rw-r--r--sphinx/ext/autosummary/__init__.py5
-rw-r--r--sphinx/ext/autosummary/generate.py17
-rw-r--r--sphinx/ext/mathbase.py6
-rw-r--r--sphinx/ext/oldcmarkup.py67
-rw-r--r--sphinx/ext/pngmath.py17
-rw-r--r--sphinx/ext/todo.py1
-rw-r--r--sphinx/ext/viewcode.py22
-rw-r--r--sphinx/highlighting.py40
-rw-r--r--sphinx/jinja2glue.py20
-rw-r--r--sphinx/locale/__init__.py2
-rw-r--r--sphinx/locale/cs/LC_MESSAGES/sphinx.mobin10472 -> 10669 bytes
-rw-r--r--sphinx/locale/cs/LC_MESSAGES/sphinx.po178
-rw-r--r--sphinx/locale/ja/LC_MESSAGES/sphinx.mobin11311 -> 11311 bytes
-rw-r--r--sphinx/locale/ja/LC_MESSAGES/sphinx.po4
-rw-r--r--sphinx/pycode/Grammar-py2.txt (renamed from sphinx/pycode/Grammar.txt)80
-rw-r--r--sphinx/pycode/Grammar-py3.txt126
-rw-r--r--sphinx/pycode/__init__.py6
-rw-r--r--sphinx/pycode/pgen2/driver.py7
-rw-r--r--sphinx/pycode/pgen2/grammar.py1
-rw-r--r--sphinx/pycode/pgen2/parse.c89
-rwxr-xr-xsphinx/pycode/pgen2/token.py3
-rw-r--r--sphinx/quickstart.py50
-rw-r--r--sphinx/roles.py6
-rw-r--r--sphinx/search/__init__.py17
-rw-r--r--sphinx/search/ja.py4
-rw-r--r--sphinx/texinputs/Makefile28
-rw-r--r--sphinx/texinputs/sphinx.sty20
-rw-r--r--sphinx/texinputs/sphinxmanual.cls3
-rw-r--r--sphinx/texinputs/tabulary.sty9
-rw-r--r--sphinx/themes/agogo/layout.html50
-rw-r--r--sphinx/themes/agogo/static/agogo.css_t7
-rw-r--r--sphinx/themes/basic/layout.html10
-rw-r--r--sphinx/themes/basic/searchbox.html2
-rw-r--r--sphinx/themes/basic/sourcelink.html12
-rw-r--r--sphinx/themes/basic/static/basic.css_t15
-rw-r--r--sphinx/themes/basic/static/doctools.js3
-rw-r--r--sphinx/themes/basic/static/searchtools.js_t4
-rw-r--r--sphinx/themes/default/static/default.css_t5
-rw-r--r--sphinx/themes/epub/static/epub.css1
-rw-r--r--sphinx/themes/haiku/layout.html8
-rw-r--r--sphinx/themes/nature/static/nature.css_t6
-rw-r--r--sphinx/themes/pyramid/layout.html2
-rw-r--r--sphinx/themes/pyramid/static/pyramid.css_t5
-rw-r--r--sphinx/themes/scrolls/layout.html4
-rw-r--r--sphinx/themes/scrolls/static/print.css12
-rw-r--r--sphinx/themes/sphinxdoc/static/sphinxdoc.css_t6
-rw-r--r--sphinx/themes/traditional/static/traditional.css_t4
-rw-r--r--sphinx/transforms.py1
-rw-r--r--sphinx/util/docfields.py6
-rw-r--r--sphinx/util/inspect.py26
-rw-r--r--sphinx/util/jsonimpl.py20
-rw-r--r--sphinx/util/osutil.py9
-rw-r--r--sphinx/util/pycompat.py192
-rw-r--r--sphinx/versioning.py3
-rw-r--r--sphinx/writers/html.py45
-rw-r--r--sphinx/writers/latex.py96
-rw-r--r--sphinx/writers/manpage.py13
-rw-r--r--sphinx/writers/texinfo.py13
-rw-r--r--sphinx/writers/text.py15
-rw-r--r--tests/root/autodoc.txt2
-rw-r--r--tests/root/autodoc_missing_imports.py9
-rw-r--r--tests/root/conf.py9
-rw-r--r--tests/root/includes.txt1
-rw-r--r--tests/root/markup.txt5
-rw-r--r--tests/root/objects.txt9
-rw-r--r--tests/roots/test-templating/_templates/autosummary/class.rst8
-rw-r--r--tests/roots/test-templating/_templates/layout.html6
-rw-r--r--tests/roots/test-templating/autosummary_templating.txt13
-rw-r--r--tests/roots/test-templating/conf.py11
-rw-r--r--tests/roots/test-templating/contents.txt7
-rw-r--r--tests/test_autodoc.py58
-rw-r--r--tests/test_build_html.py19
-rw-r--r--tests/test_config.py8
-rw-r--r--tests/test_intersphinx.py4
-rw-r--r--tests/test_intl.py6
-rw-r--r--tests/test_linkcode.py7
-rw-r--r--tests/test_markup.py2
-rw-r--r--tests/test_metadata.py6
-rw-r--r--tests/test_quickstart.py1
-rw-r--r--tests/test_setup_command.py7
-rw-r--r--tests/test_templating.py36
-rw-r--r--tests/test_versioning.py1
-rw-r--r--tests/test_websupport.py7
-rw-r--r--tests/util.py7
-rw-r--r--tox.ini10
-rw-r--r--utils/release-checklist21
130 files changed, 1715 insertions, 1148 deletions
diff --git a/CHANGES b/CHANGES
index cc5d6955..42d544b0 100644
--- a/CHANGES
+++ b/CHANGES
@@ -1,6 +1,153 @@
-Release 1.2 (in development)
+Release 1.3 (in development)
============================
+Incompatible changes
+--------------------
+
+* Dropped support for Python 2.5 and 3.1.
+
+* Removed the ``sphinx.ext.oldcmarkup`` extension.
+
+* A new node, ``sphinx.addnodes.literal_strong``, has been added, for text that
+ should appear literally (i.e. no smart quotes) in strong font. Custom writers
+ will have to be adapted to handle this node.
+
+New features
+------------
+
+* PR#202: Allow "." and "~" prefixed references in ``:param:`` doc fields
+ for Python.
+
+* PR#184: Add :confval:`autodoc_mock_imports`, allowing to mock imports of
+ external modules that need not be present when autodocumenting.
+
+* #925: Allow list-typed config values to be provided on the command line,
+ like ``-D key=val1,val2``.
+
+* #668: Allow line numbering of ``code-block`` and ``literalinclude`` directives
+ to start at an arbitrary line number, with a new ``lineno-start`` option.
+
+* PR#172: The :rst:dir:`code-block` and :rst:dir:`literalinclude` directives now
+ can have a ``filename`` option that shows a filename before the code in the
+ output.
+
+* Prompt for the document language in sphinx-quickstart.
+
+Bugs fixed
+----------
+
+* #1174: Fix smart quotes being applied inside roles like :rst:role:`program` or
+ :rst:role:`makevar`.
+
+* #1335: Fix autosummary template overloading with exclamation prefix like
+ ``{% extends "!autosummary/class.rst" %}`` cause infinite recursive function
+ call. This caused by PR#181.
+
+* #1337: Fix autodoc with ``autoclass_content="both"`` uses useless
+ ``object.__init__`` docstring when class does not have ``__init__``.
+ This was caused by a change for #1138.
+
+* #1340: Can't search alphabetical words on the HTML quick search generated
+ with language='ja'.
+
+* #1319: Do not crash if the :confval:`html_logo` file does not exist.
+
+* #603: Do not use the HTML-ized title for building the search index (that
+ resulted in "literal" being found on every page with a literal in the
+ title).
+
+* #751: Allow production lists longer than a page in LaTeX by using longtable.
+
+* #764: Always look for stopwords lowercased in JS search.
+
+* #814: autodoc: Guard against strange type objects that don't have
+ ``__bases__``.
+
+* #932: autodoc: Do not crash if ``__doc__`` is not a string.
+
+* #933: Do not crash if an :rst:role:`option` value is malformed (contains
+ spaces but no option name).
+
+* #908: On Python 3, handle error messages from LaTeX correctly in the pngmath
+ extension.
+
+* #943: In autosummary, recognize "first sentences" to pull from the docstring
+ if they contain uppercase letters.
+
+* #923: Take the entire LaTeX document into account when caching
+ pngmath-generated images. This rebuilds them correctly when
+ :confval:`pngmath_latex_preamble` changes.
+
+* #901: Emit a warning when using docutils' new "math" markup without a Sphinx
+ math extension active.
+
+* #845: In code blocks, when the selected lexer fails, display line numbers
+ nevertheless if configured.
+
+* #929: Support parsed-literal blocks in LaTeX output correctly.
+
+* #949: Update the tabulary.sty packed with Sphinx.
+
+* #1050: Add anonymous labels into ``objects.inv`` to be referenced via
+ :mod:`~sphinx.ext.intersphinx`.
+
+* #1095: Fix print-media stylesheet being included always in the "scrolls"
+ theme.
+
+* #1085: Fix current classname not getting set if class description has
+ ``:noindex:`` set.
+
+* #1181: Report option errors in autodoc directives more gracefully.
+
+* #1155: Fix autodocumenting C-defined methods as attributes in Python 3.
+
+* #1233: Allow finding both Python classes and exceptions with the "class" and
+ "exc" roles in intersphinx.
+
+* #1198: Allow "image" for the "figwidth" option of the :rst:dir:`figure`
+ directive as documented by docutils.
+
+* #1152: Fix pycode parsing errors of Python 3 code by including two grammar
+ versions for Python 2 and 3, and loading the appropriate version for the
+ running Python version.
+
+* #1017: Be helpful and tell the user when the argument to :rst:dir:`option`
+ does not match the required format.
+
+* #1345: Fix two bugs with :confval:`nitpick_ignore`; now you don't have to
+ remove the store environment for changes to have effect.
+
+* #1072: In the JS search, fix issues searching for upper-cased words by
+ lowercasing words before stemming.
+
+* #1299: Make behavior of the :rst:dir:`math` directive more consistent and
+ avoid producing empty environments in LaTeX output.
+
+* #1308: Strip HTML tags from the content of "raw" nodes before feeding it
+ to the search indexer.
+
+* #1249: Fix duplicate LaTeX page numbering for manual documents.
+
+* #1292: In the linkchecker, retry HEAD requests when denied by HTTP 405.
+ Also make the redirect code apparent and tweak the output a bit to be
+ more obvious.
+
+* #1285: Avoid name clashes between C domain objects and section titles.
+
+* #848: Always take the newest code in incremental rebuilds with the
+ :mod:`sphinx.ext.viewcode` extension.
+
+* #979: Fix exclude handling in ``sphinx-apidoc``.
+
+Documentation
+-------------
+
+* #1325: Added a "Intersphinx" tutorial section. (:file:`doc/tutorial.rst`)
+
+
+Release 1.2 (released Dec 10, 2013)
+===================================
+
Features added
--------------
@@ -19,12 +166,27 @@ Bugs fixed
* Restore ``versionmodified`` CSS class for versionadded/changed and deprecated
directives.
+* PR#181: Fix `html_theme_path=['.']` is a trigger of rebuild all documents
+ always (This change keeps the current "theme changes cause a rebuild"
+ feature).
+
* #1296: Fix invalid charset in HTML help generated HTML files for default
locale.
* PR#190: Fix gettext does not extract figure caption and rubric title inside
other blocks. Thanks to Michael Schlenker.
+* PR#176: Make sure setup_command test can always import Sphinx. Thanks to
+ Dmitry Shachnev.
+
+* #1311: Fix test_linkcode.test_html fails with C locale and Python 3.
+
+* #1269: Fix ResourceWarnings with Python 3.2 or later.
+
+* #1138: Fix: When ``autodoc_docstring_signature = True`` and
+ ``autoclass_content = 'init'`` or ``'both'``, __init__ line should be
+ removed from class documentation.
+
Release 1.2 beta3 (released Oct 3, 2013)
========================================
@@ -228,6 +390,8 @@ Features added
reference documentation in doc directory provides a ``sphinx.pot`` file with
message strings from ``doc/_templates/*.html`` when using ``make gettext``.
+ - PR#61,#703: Add support for non-ASCII filename handling.
+
* Other builders:
- Added the Docutils-native XML and pseudo-XML builders. See
@@ -1004,4 +1168,4 @@ Previous versions
The changelog for versions before 1.0 can be found in the file ``CHANGES.old``
in the source distribution or `at BitBucket
-<http://bitbucket.org/birkenfeld/sphinx/raw/tip/CHANGES.old>`__.
+<https://bitbucket.org/birkenfeld/sphinx/raw/tip/CHANGES.old>`__.
diff --git a/EXAMPLES b/EXAMPLES
index 2c78b1d4..9ca4468a 100644
--- a/EXAMPLES
+++ b/EXAMPLES
@@ -4,7 +4,7 @@ Projects using Sphinx
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-users>`_.
+<https://groups.google.com/group/sphinx-users>`_.
I've grouped the list into sections to make it easier to find
interesting examples.
@@ -15,12 +15,12 @@ Documentation using the default theme
* APSW: http://apidoc.apsw.googlecode.com/hg/index.html
* ASE: https://wiki.fysik.dtu.dk/ase/
* boostmpi: http://documen.tician.de/boostmpi/
-* Calibre: http://calibre-ebook.com/user_manual/
+* Calibre: http://manual.calibre-ebook.com/
* CodePy: http://documen.tician.de/codepy/
* Cython: http://docs.cython.org/
* C\\C++ Python language binding project: http://language-binding.net/index.html
* Cormoran: http://cormoran.nhopkg.org/docs/
-* Director: http://packages.python.org/director/
+* Director: http://pythonhosted.org/director/
* Dirigible: http://www.projectdirigible.com/documentation/
* Elemental: http://elemental.googlecode.com/hg/doc/build/html/index.html
* F2py: http://f2py.sourceforge.net/docs/
diff --git a/MANIFEST.in b/MANIFEST.in
index 919b05a0..5db26b81 100644
--- a/MANIFEST.in
+++ b/MANIFEST.in
@@ -1,4 +1,4 @@
-include README
+include README.rst
include LICENSE
include AUTHORS
include CHANGES
@@ -20,7 +20,8 @@ recursive-include sphinx/ext/autosummary/templates *
recursive-include tests *
recursive-include utils *
recursive-include custom_fixers *
-include sphinx/pycode/Grammar.txt
+include sphinx/pycode/Grammar-py2.txt
+include sphinx/pycode/Grammar-py3.txt
recursive-include doc *
prune doc/_build
diff --git a/doc/_templates/index.html b/doc/_templates/index.html
index 0739191e..e6ef9178 100644
--- a/doc/_templates/index.html
+++ b/doc/_templates/index.html
@@ -21,7 +21,7 @@
</p>
<ul>
<li>{%trans%}<b>Output formats:</b> HTML (including Windows HTML Help), LaTeX (for
- printable PDF versions), Texinfo, manual pages, plain text{%endtrans%}</li>
+ printable PDF versions), ePub, Texinfo, manual pages, plain text{%endtrans%}</li>
<li>{%trans%}<b>Extensive cross-references:</b> semantic markup and automatic links
for functions, classes, citations, glossary terms and similar pieces of
information{%endtrans%}</li>
@@ -85,7 +85,16 @@
of this documentation, thanks to the Japanese Sphinx user group.{%endtrans%}</p>
<p>{%trans%}A Japanese book about Sphinx has been published by O'Reilly:
<a href="http://www.oreilly.co.jp/books/9784873116488/">Sphinxをはじめよう /
- Learning Sphinx</a>:{%endtrans%}</p>
- <p><img src="{{ pathto("_static/bookcover.png", 1) }}"/></p>
+ Learning Sphinx</a>.{%endtrans%}</p>
+ <!-- <p><img src="{{ pathto("_static/bookcover.png", 1) }}"/></p> -->
+
+
+ <h2>{%trans%}Hosting{%endtrans%}</h2>
+
+ <p>{%trans%}Need a place to host your Sphinx docs?
+ <a href="http://readthedocs.org">readthedocs.org</a> hosts a lot of Sphinx docs
+ already, and integrates well with projects' source control. It also features a
+ powerful built-in search that exceeds the possibilities of Sphinx' JavaScript-based
+ offline search.{%endtrans%}</p>
{% endblock %}
diff --git a/doc/builders.rst b/doc/builders.rst
index 1297a08e..00f4e223 100644
--- a/doc/builders.rst
+++ b/doc/builders.rst
@@ -64,13 +64,13 @@ The builder's "name" must be given to the **-b** command-line option of
Its name is ``qthelp``.
- .. _Qt help: http://doc.trolltech.com/4.6/qthelp-framework.html
+ .. _Qt help: http://qt-project.org/doc/qt-4.8/qthelp-framework.html
.. module:: sphinx.builders.devhelp
.. class:: DevhelpBuilder
This builder produces the same output as the standalone HTML builder, but
- also generates `GNOME Devhelp <http://live.gnome.org/devhelp>`__
+ also generates `GNOME Devhelp <https://wiki.gnome.org/Apps/Devhelp>`__
support file that allows the GNOME Devhelp reader to view them.
Its name is ``devhelp``.
@@ -110,8 +110,8 @@ The builder's "name" must be given to the **-b** command-line option of
Note that a direct PDF builder using ReportLab is available in `rst2pdf
<http://rst2pdf.googlecode.com>`_ version 0.12 or greater. You need to add
``'rst2pdf.pdfbuilder'`` to your :confval:`extensions` to enable it, its name is
-``pdf``. Refer to the `rst2pdf manual
-<http://lateral.netmanagers.com.ar/static/manual.pdf>`_ for details.
+``pdf``. Refer to the `rst2pdf manual <http://ralsina.me/static/manual.pdf>`_
+for details.
.. module:: sphinx.builders.text
.. class:: TextBuilder
@@ -179,7 +179,7 @@ Note that a direct PDF builder using ReportLab is available in `rst2pdf
globalcontext_filename = 'globalcontext.phpdump'
searchindex_filename = 'searchindex.phpdump'
- .. _PHP serialization: http://pypi.python.org/pypi/phpserialize
+ .. _PHP serialization: https://pypi.python.org/pypi/phpserialize
.. attribute:: implementation
diff --git a/doc/config.rst b/doc/config.rst
index 70ccd26e..e4d9feaf 100644
--- a/doc/config.rst
+++ b/doc/config.rst
@@ -40,10 +40,13 @@ Important points to note:
delete them from the namespace with ``del`` if appropriate. Modules are
removed automatically, so you don't need to ``del`` your imports after use.
+.. _conf-tags:
+
* There is a special object named ``tags`` available in the config file.
It can be used to query and change the tags (see :ref:`tags`). Use
``tags.has('tag')`` to query, ``tags.add('tag')`` and ``tags.remove('tag')``
- to change.
+ to change. Only tags set via the ``-t`` command-line option or via
+ ``tags.add('tag')`` can be queried using ``tags.has('tag')``.
General configuration
@@ -118,7 +121,7 @@ General configuration
in that case.
.. deprecated:: 1.0
- Use :confval:`exclude_patterns` instead.
+ Use :confval:`exclude_patterns` or :ref:`metadata` instead.
.. confval:: exclude_trees
@@ -236,7 +239,8 @@ General configuration
A list of ``(type, target)`` tuples (by default empty) that should be ignored
when generating warnings in "nitpicky mode". Note that ``type`` should
- include the domain name. An example entry would be ``('py:func', 'int')``.
+ include the domain name if present. Example entries would be ``('py:func',
+ 'int')`` or ``('envvar', 'LD_LIBRARY_PATH')``.
.. versionadded:: 1.1
@@ -472,8 +476,8 @@ that use Sphinx' HTMLWriter class.
The "title" for HTML documentation generated with Sphinx' own templates.
This is appended to the ``<title>`` tag of individual pages, and used in the
navigation bar as the "topmost" element. It defaults to :samp:`'{<project>}
- v{<revision>} documentation'`, where the placeholders are replaced by the
- config values of the same name.
+ v{<revision>} documentation'` (with the values coming from the config
+ values).
.. confval:: html_short_title
diff --git a/doc/develop.rst b/doc/develop.rst
index 95a615cb..faece78d 100644
--- a/doc/develop.rst
+++ b/doc/develop.rst
@@ -6,11 +6,11 @@ Sphinx development
Sphinx is a maintained by a group of volunteers. We value every contribution!
* The code can be found in a Mercurial repository, at
- http://bitbucket.org/birkenfeld/sphinx/.
+ https://bitbucket.org/birkenfeld/sphinx/.
* Issues and feature requests should be raised in the `tracker
- <http://bitbucket.org/birkenfeld/sphinx/issues/>`_.
+ <https://bitbucket.org/birkenfeld/sphinx/issues/>`_.
* The mailing list for development is at `Google Groups
- <http://groups.google.com/group/sphinx-dev/>`_.
+ <https://groups.google.com/group/sphinx-dev/>`_.
* There is also the #sphinx-doc IRC channel on `freenode
<http://freenode.net/>`_.
@@ -82,24 +82,24 @@ own extensions.
.. _gnuplot: http://www.gnuplot.info/
.. _paver: http://www.blueskyonmars.com/projects/paver/
.. _Sword: http://www.crosswire.org/sword/
-.. _Lilypond: http://lilypond.org/web/
+.. _Lilypond: http://lilypond.org/
.. _sdedit: http://sdedit.sourceforge.net/
.. _Trac: http://trac.edgewall.org
.. _TracLinks: http://trac.edgewall.org/wiki/TracLinks
.. _OmegaT: http://www.omegat.org/
.. _PlantUML: http://plantuml.sourceforge.net/
.. _PyEnchant: http://www.rfk.id.au/software/pyenchant/
-.. _sadisplay: http://bitbucket.org/estin/sadisplay/wiki/Home
-.. _blockdiag: http://blockdiag.com/
-.. _seqdiag: http://blockdiag.com/
-.. _actdiag: http://blockdiag.com/
-.. _nwdiag: http://blockdiag.com/
-.. _Google Chart: http://code.google.com/intl/ja/apis/chart/
-.. _Google Maps: http://maps.google.com/
+.. _sadisplay: https://bitbucket.org/estin/sadisplay/wiki/Home
+.. _blockdiag: http://blockdiag.com/en/
+.. _seqdiag: http://blockdiag.com/en/
+.. _actdiag: http://blockdiag.com/en/
+.. _nwdiag: http://blockdiag.com/en/
+.. _Google Chart: https://developers.google.com/chart/
+.. _Google Maps: https://maps.google.com/
.. _hyphenator: http://code.google.com/p/hyphenator/
-.. _exceltable: http://packages.python.org/sphinxcontrib-exceltable/
+.. _exceltable: http://pythonhosted.org/sphinxcontrib-exceltable/
.. _YouTube: http://www.youtube.com/
-.. _ClearQuest: http://www-01.ibm.com/software/awdtools/clearquest/
+.. _ClearQuest: http://www-03.ibm.com/software/products/en/clearquest
.. _Zope interfaces: http://docs.zope.org/zope.interface/README.html
.. _slideshare: http://www.slideshare.net/
.. _TikZ/PGF LaTeX package: http://sourceforge.net/projects/pgf/
diff --git a/doc/devguide.rst b/doc/devguide.rst
index 0e3563b8..b23acb1c 100644
--- a/doc/devguide.rst
+++ b/doc/devguide.rst
@@ -23,7 +23,7 @@ sphinx-dev <sphinx-dev@googlegroups.com>
#sphinx-doc on irc.freenode.net
IRC channel for development questions and user support.
-.. _`BitBucket`: http://bitbucket.org
+.. _`BitBucket`: https://bitbucket.org/
.. _`Mercurial`: http://mercurial.selenic.com/
@@ -43,7 +43,7 @@ Including or providing a link to the source files involved may help us fix the
issue. If possible, try to create a minimal project that produces the error
and post that instead.
-.. _`issue tracker`: http://bitbucket.org/birkenfeld/sphinx/issues
+.. _`issue tracker`: https://bitbucket.org/birkenfeld/sphinx/issues
Contributing to Sphinx
@@ -126,7 +126,7 @@ These are the basic steps needed to start developing on Sphinx.
would close issue #42.
- __ https://confluence.atlassian.com/display/BITBUCKET/Automatically+Resolving+Issues+when+Users+Push+Code
+ __ https://confluence.atlassian.com/display/BITBUCKET/Resolve+issues+automatically+when+users+push+code
#. Push changes to your forked repository on BitBucket. ::
@@ -190,7 +190,7 @@ identifier and put ``sphinx.po`` in there. Don't forget to update the possible
values for :confval:`language` in ``doc/config.rst``.
The Sphinx core messages can also be translated on `Transifex
-<http://transifex.com>`_. There exists a client tool named ``tx`` in the Python
+<https://www.transifex.com/>`_. There exists a client tool named ``tx`` in the Python
package "transifex_client", which can be used to pull translations in ``.po``
format from Transifex. To do this, go to ``sphinx/locale`` and then run
``tx pull -f -l LANG`` where LANG is an existing language identifier. It is
diff --git a/doc/domains.rst b/doc/domains.rst
index 56642887..6c3c4359 100644
--- a/doc/domains.rst
+++ b/doc/domains.rst
@@ -157,6 +157,23 @@ declarations:
The following directives are provided for module and class contents:
+.. rst:directive:: .. py:function:: name(parameters)
+
+ Describes a module-level function. The signature should include the
+ parameters as given in the Python function definition, see :ref:`signatures`.
+ For example::
+
+ .. py:function:: Timer.repeat(repeat=3, number=1000000)
+
+ For methods you should use :rst:dir:`py:method`.
+
+ The description normally includes information about the parameters required
+ and how they are used (especially whether mutable objects passed as
+ parameters are modified), side effects, and possible exceptions.
+
+ This information can (in any ``py`` directive) optionally be given in a
+ structured form, see :ref:`info-field-lists`.
+
.. rst:directive:: .. py:data:: name
Describes global data in a module, including both variables and values used
@@ -168,28 +185,11 @@ The following directives are provided for module and class contents:
Describes an exception class. The signature can, but need not include
parentheses with constructor arguments.
-.. rst:directive:: .. py:function:: name(signature)
-
- Describes a module-level function. The signature should include the
- parameters, enclosing optional parameters in brackets. Default values can be
- given if it enhances clarity; see :ref:`signatures`. For example::
-
- .. py:function:: Timer.repeat([repeat=3[, number=1000000]])
-
- Object methods are not documented using this directive. Bound object methods
- placed in the module namespace as part of the public interface of the module
- are documented using this, as they are equivalent to normal functions for
- most purposes.
-
- The description should include information about the parameters required and
- how they are used (especially whether mutable objects passed as parameters
- are modified), side effects, and possible exceptions. A small example may be
- provided.
+.. rst:directive:: .. py:class:: name
+ .. py:class:: name(parameters)
-.. rst:directive:: .. py:class:: name[(signature)]
-
- Describes a class. The signature can include parentheses with parameters
- which will be shown as the constructor arguments. See also
+ Describes a class. The signature can optionally include parentheses with
+ parameters which will be shown as the constructor arguments. See also
:ref:`signatures`.
Methods and attributes belonging to the class should be placed in this
@@ -197,6 +197,7 @@ The following directives are provided for module and class contents:
contain the class name so that cross-references still work. Example::
.. py:class:: Foo
+
.. py:method:: quux()
-- or --
@@ -213,30 +214,30 @@ The following directives are provided for module and class contents:
information about the type of the data to be expected and whether it may be
changed directly.
-.. rst:directive:: .. py:method:: name(signature)
+.. rst:directive:: .. py:method:: name(parameters)
Describes an object method. The parameters should not include the ``self``
parameter. The description should include similar information to that
- described for ``function``. See also :ref:`signatures`.
+ described for ``function``. See also :ref:`signatures` and
+ :ref:`info-field-lists`.
-.. rst:directive:: .. py:staticmethod:: name(signature)
+.. rst:directive:: .. py:staticmethod:: name(parameters)
Like :rst:dir:`py:method`, but indicates that the method is a static method.
.. versionadded:: 0.4
-.. rst:directive:: .. py:classmethod:: name(signature)
+.. rst:directive:: .. py:classmethod:: name(parameters)
Like :rst:dir:`py:method`, but indicates that the method is a class method.
.. versionadded:: 0.6
.. rst:directive:: .. py:decorator:: name
- .. py:decorator:: name(signature)
+ .. py:decorator:: name(parameters)
- Describes a decorator function. The signature should *not* represent the
- signature of the actual function, but the usage as a decorator. For example,
- given the functions
+ Describes a decorator function. The signature should represent the usage as
+ a decorator. For example, given the functions
.. code-block:: python
@@ -260,6 +261,8 @@ The following directives are provided for module and class contents:
Set name of the decorated function to *name*.
+ (as opposed to ``.. py:decorator:: removename(func)``.)
+
There is no ``py:deco`` role to link to a decorator that is marked up with
this directive; rather, use the :rst:role:`py:func` role.
@@ -277,23 +280,24 @@ Python Signatures
~~~~~~~~~~~~~~~~~
Signatures of functions, methods and class constructors can be given like they
-would be written in Python, with the exception that optional parameters can be
-indicated by brackets::
-
- .. py:function:: compile(source[, filename[, symbol]])
-
-It is customary to put the opening bracket before the comma. In addition to
-this "nested" bracket style, a "flat" style can also be used, due to the fact
-that most optional parameters can be given independently::
-
- .. py:function:: compile(source[, filename, symbol])
+would be written in Python.
Default values for optional arguments can be given (but if they contain commas,
they will confuse the signature parser). Python 3-style argument annotations
can also be given as well as return type annotations::
- .. py:function:: compile(source : string[, filename, symbol]) -> ast object
+ .. py:function:: compile(source : string, filename, symbol='file') -> ast object
+
+For functions with optional parameters that don't have default values (typically
+functions implemented in C extension modules without keyword argument support),
+you can use brackets to specify the optional parts:
+
+ .. py:function:: compile(source[, filename[, symbol]])
+
+It is customary to put the opening bracket before the comma.
+
+.. _info-field-lists:
Info field lists
~~~~~~~~~~~~~~~~
@@ -379,8 +383,8 @@ a matching identifier is found:
.. rst:role:: py:const
- Reference a "defined" constant. This may be a C-language ``#define`` or a
- Python variable that is not intended to be changed.
+ Reference a "defined" constant. This may be a Python variable that is not
+ intended to be changed.
.. rst:role:: py:class
@@ -468,8 +472,8 @@ The C domain (name **c**) is suited for documentation of C API.
Describes a "simple" C macro. Simple macros are macros which are used for
code expansion, but which do not take arguments so cannot be described as
- functions. This is not to be used for simple constant definitions. Examples
- of its use in the Python documentation include :c:macro:`PyObject_HEAD` and
+ functions. This is a simple C-language ``#define``. Examples of its use in
+ the Python documentation include :c:macro:`PyObject_HEAD` and
:c:macro:`Py_BEGIN_ALLOW_THREADS`.
.. rst:directive:: .. c:type:: name
@@ -709,24 +713,24 @@ The JavaScript domain (name **js**) provides the following directives:
.. js:function:: $.getJSON(href, callback[, errback])
:param string href: An URI to the location of the resource.
- :param callback: Get's called with the object.
+ :param callback: Gets called with the object.
:param errback:
- Get's called in case the request fails. And a lot of other
- text so we need multiple lines
+ Gets called in case the request fails. And a lot of other
+ text so we need multiple lines.
:throws SomeError: For whatever reason in that case.
- :returns: Something
+ :returns: Something.
This is rendered as:
.. js:function:: $.getJSON(href, callback[, errback])
:param string href: An URI to the location of the resource.
- :param callback: Get's called with the object.
+ :param callback: Gets called with the object.
:param errback:
- Get's called in case the request fails. And a lot of other
+ Gets called in case the request fails. And a lot of other
text so we need multiple lines.
:throws SomeError: For whatever reason in that case.
- :returns: Something
+ :returns: Something.
.. rst:directive:: .. js:class:: name
@@ -825,17 +829,17 @@ Operation_, and Scala_.
.. _sphinx-contrib: https://bitbucket.org/birkenfeld/sphinx-contrib/
-.. _Ada: http://pypi.python.org/pypi/sphinxcontrib-adadomain
-.. _CoffeeScript: http://pypi.python.org/pypi/sphinxcontrib-coffee
-.. _Common Lisp: http://pypi.python.org/pypi/sphinxcontrib-cldomain
-.. _dqn: http://pypi.python.org/pypi/sphinxcontrib-dqndomain
-.. _Erlang: http://pypi.python.org/pypi/sphinxcontrib-erlangdomain
-.. _Go: http://pypi.python.org/pypi/sphinxcontrib-golangdomain
-.. _HTTP: http://pypi.python.org/pypi/sphinxcontrib-httpdomain
-.. _Jinja: http://pypi.python.org/pypi/sphinxcontrib-jinjadomain
-.. _Lasso: http://pypi.python.org/pypi/sphinxcontrib-lassodomain
-.. _MATLAB: http://pypi.python.org/pypi/sphinxcontrib-matlabdomain
-.. _Operation: http://pypi.python.org/pypi/sphinxcontrib-operationdomain
-.. _PHP: http://pypi.python.org/pypi/sphinxcontrib-phpdomain
-.. _Ruby: http://bitbucket.org/birkenfeld/sphinx-contrib/src/default/rubydomain
-.. _Scala: http://pypi.python.org/pypi/sphinxcontrib-scaladomain
+.. _Ada: https://pypi.python.org/pypi/sphinxcontrib-adadomain
+.. _CoffeeScript: https://pypi.python.org/pypi/sphinxcontrib-coffee
+.. _Common Lisp: https://pypi.python.org/pypi/sphinxcontrib-cldomain
+.. _dqn: https://pypi.python.org/pypi/sphinxcontrib-dqndomain
+.. _Erlang: https://pypi.python.org/pypi/sphinxcontrib-erlangdomain
+.. _Go: https://pypi.python.org/pypi/sphinxcontrib-golangdomain
+.. _HTTP: https://pypi.python.org/pypi/sphinxcontrib-httpdomain
+.. _Jinja: https://pypi.python.org/pypi/sphinxcontrib-jinjadomain
+.. _Lasso: https://pypi.python.org/pypi/sphinxcontrib-lassodomain
+.. _MATLAB: https://pypi.python.org/pypi/sphinxcontrib-matlabdomain
+.. _Operation: https://pypi.python.org/pypi/sphinxcontrib-operationdomain
+.. _PHP: https://pypi.python.org/pypi/sphinxcontrib-phpdomain
+.. _Ruby: https://bitbucket.org/birkenfeld/sphinx-contrib/src/default/rubydomain
+.. _Scala: https://pypi.python.org/pypi/sphinxcontrib-scaladomain
diff --git a/doc/ext/appapi.rst b/doc/ext/appapi.rst
index a6393d40..156dede8 100644
--- a/doc/ext/appapi.rst
+++ b/doc/ext/appapi.rst
@@ -199,10 +199,13 @@ the following public API:
.. index:: pair: function; directive
The reference node will be of class ``literal`` (so it will be rendered in a
- proportional font, as appropriate for code) unless you give the *ref_nodeclass*
- argument, which must be a docutils node class (most useful are
- ``docutils.nodes.emphasis`` or ``docutils.nodes.strong`` -- you can also use
- ``docutils.nodes.generated`` if you want no further text decoration).
+ proportional font, as appropriate for code) unless you give the
+ *ref_nodeclass* argument, which must be a docutils node class. Most useful
+ are ``docutils.nodes.emphasis`` or ``docutils.nodes.strong`` -- you can also
+ use ``docutils.nodes.generated`` if you want no further text decoration. If
+ the text should be treated as literal (e.g. no smart quote replacement), but
+ not have typewriter styling, use ``sphinx.addnodes.literal_emphasis`` or
+ ``sphinx.addnodes.literal_strong``.
For the role content, you have the same syntactical possibilities as for
standard Sphinx roles (see :ref:`xref-syntax`).
diff --git a/doc/ext/autodoc.rst b/doc/ext/autodoc.rst
index c92fe0c4..94b05423 100644
--- a/doc/ext/autodoc.rst
+++ b/doc/ext/autodoc.rst
@@ -195,6 +195,12 @@ inserting them into the page source under a suitable :rst:dir:`py:module`,
.. versionadded:: 1.2
+ * Add a list of modules in the :confval:`autodoc_mock_imports` to prevent
+ import errors to halt the building process when some external dependencies
+ are not importable at build time.
+
+ .. versionadded:: 1.3
+
.. rst:directive:: autofunction
autodata
@@ -335,6 +341,14 @@ There are also new config values that you can set:
.. versionadded:: 1.1
+.. confval:: autodoc_mock_imports
+
+ This value contains a list of modules to be mocked up. This is useful when
+ some external dependencies are not met at build time and break the building
+ process.
+
+ .. versionadded:: 1.3
+
Docstring preprocessing
-----------------------
diff --git a/doc/ext/oldcmarkup.rst b/doc/ext/oldcmarkup.rst
deleted file mode 100644
index 0fdd9fec..00000000
--- a/doc/ext/oldcmarkup.rst
+++ /dev/null
@@ -1,35 +0,0 @@
-:mod:`sphinx.ext.oldcmarkup` -- Compatibility extension for old C markup
-========================================================================
-
-.. module:: sphinx.ext.oldcmarkup
- :synopsis: Allow further use of the pre-domain C markup
-.. moduleauthor:: Georg Brandl
-
-.. versionadded:: 1.0
-
-
-This extension is a transition helper for projects that used the old
-(pre-domain) C markup, i.e. the directives like ``cfunction`` and roles like
-``cfunc``. Since the introduction of domains, they must be called by their
-fully-qualified name (``c:function`` and ``c:func``, respectively) or, with the
-default domain set to ``c``, by their new name (``function`` and ``func``).
-(See :ref:`c-domain` for the details.)
-
-If you activate this extension, it will register the old names, and you can
-use them like before Sphinx 1.0. The directives are:
-
-- ``cfunction``
-- ``cmember``
-- ``cmacro``
-- ``ctype``
-- ``cvar``
-
-The roles are:
-
-- ``cdata``
-- ``cfunc``
-- ``cmacro``
-- ``ctype``
-
-However, it is advised to migrate to the new markup -- this extension is a
-compatibility convenience and will disappear in a future version of Sphinx.
diff --git a/doc/extensions.rst b/doc/extensions.rst
index b2ac3791..7597f281 100644
--- a/doc/extensions.rst
+++ b/doc/extensions.rst
@@ -53,7 +53,6 @@ These extensions are built in and can be activated by respective entries in the
ext/extlinks
ext/viewcode
ext/linkcode
- ext/oldcmarkup
Third-party extensions
@@ -68,10 +67,10 @@ maintains a list of those.
If you write an extension that you think others will find useful or you think
should be included as a part of Sphinx, please write to the project mailing
-list (`join here <http://groups.google.com/group/sphinx-dev>`_).
+list (`join here <https://groups.google.com/group/sphinx-dev>`_).
-.. _Wiki at BitBucket: https://www.bitbucket.org/birkenfeld/sphinx/wiki/Home
-.. _Sphinx Contrib: https://www.bitbucket.org/birkenfeld/sphinx-contrib
+.. _Wiki at BitBucket: https://bitbucket.org/birkenfeld/sphinx/wiki/Home
+.. _Sphinx Contrib: https://bitbucket.org/birkenfeld/sphinx-contrib
Where to put your own extensions?
diff --git a/doc/faq.rst b/doc/faq.rst
index ff74be1c..7aa35d1f 100644
--- a/doc/faq.rst
+++ b/doc/faq.rst
@@ -37,7 +37,7 @@ How do I...
come through cleanly.
... create HTML slides from Sphinx documents?
- See the "Hieroglyph" package at http://github.com/nyergler/hieroglyph.
+ See the "Hieroglyph" package at https://github.com/nyergler/hieroglyph.
For many more extensions and other contributed stuff, see the sphinx-contrib_
repository.
@@ -50,7 +50,7 @@ Using Sphinx with...
--------------------
Read the Docs
- http://readthedocs.org is a documentation hosting service based around Sphinx.
+ https://readthedocs.org is a documentation hosting service based around Sphinx.
They will host sphinx documentation, along with supporting a number of other
features including version support, PDF generation, and more. The `Getting
Started <http://read-the-docs.readthedocs.org/en/latest/getting_started.html>`_
@@ -62,7 +62,7 @@ Epydoc
Doxygen
Michael Jones is developing a reST/Sphinx bridge to doxygen called `breathe
- <http://github.com/michaeljones/breathe/tree/master>`_.
+ <https://github.com/michaeljones/breathe/tree/master>`_.
SCons
Glenn Hutchings has written a SCons build script to build Sphinx
@@ -70,9 +70,9 @@ SCons
PyPI
Jannis Leidel wrote a `setuptools command
- <http://pypi.python.org/pypi/Sphinx-PyPI-upload>`_ that automatically uploads
+ <https://pypi.python.org/pypi/Sphinx-PyPI-upload>`_ that automatically uploads
Sphinx documentation to the PyPI package documentation area at
- http://packages.python.org/.
+ http://pythonhosted.org/.
GitHub Pages
Directories starting with underscores are ignored by default which breaks
@@ -139,7 +139,7 @@ The following list gives some hints for the creation of epub files:
are often cut at the right margin. The default Courier font (or variant) is
quite wide and you can only display up to 60 characters on a line. If you
replace it with a narrower font, you can get more characters on a line. You
- may even use `FontForge <http://fontforge.sourceforge.net/>`_ and create
+ may even use `FontForge <http://fontforge.org/>`_ and create
narrow variants of some free font. In my case I get up to 70 characters on a
line.
@@ -168,8 +168,8 @@ The following list gives some hints for the creation of epub files:
.. _Epubcheck: http://code.google.com/p/epubcheck/
.. _Calibre: http://calibre-ebook.com/
-.. _FBreader: http://www.fbreader.org/
-.. _Bookworm: http://bookworm.oreilly.com/
+.. _FBreader: http://fbreader.org/
+.. _Bookworm: http://oreilly.com/bookworm/index.html
.. _texinfo-faq:
diff --git a/doc/install.rst b/doc/install.rst
index 9c258420..71e37e9c 100644
--- a/doc/install.rst
+++ b/doc/install.rst
@@ -4,10 +4,10 @@ Installing Sphinx
=================
Since Sphinx is written in the Python language, you need to install Python
-(the required version is at least 2.5) and Sphinx.
+(the required version is at least 2.6) and Sphinx.
Sphinx packages are available on the `Python Package Index
-<http://pypi.python.org/pypi/Sphinx>`_.
+<https://pypi.python.org/pypi/Sphinx>`_.
You can also download a snapshot from the Mercurial development repository:
@@ -79,8 +79,8 @@ sidebar and under "Quick Links", click "Windows Installer" to download.
.. note::
- Currently, Python offers two major versions, 2.x and 3.x. Sphinx 1.2 can run
- under Python 2.5 to 2.7 and 3.1 to 3.3, with the recommended version being
+ Currently, Python offers two major versions, 2.x and 3.x. Sphinx 1.3 can run
+ under Python 2.6, 2.7, 3.2, 3.3, with the recommended version being
2.7. This chapter assumes you have installed Python 2.7.
Follow the Windows installer for Python.
@@ -118,7 +118,7 @@ Install the easy_install command
Python has a very useful :command:`easy_install` command which can download and
install 3rd-party libraries with a single command. This is provided by the
-"setuptools" project: http://pypi.python.org/pypi/setuptools.
+"setuptools" project: https://pypi.python.org/pypi/setuptools.
To install setuptools, download
https://bitbucket.org/pypa/setuptools/raw/bootstrap/ez_setup.py and
diff --git a/doc/intl.rst b/doc/intl.rst
index 5f969d51..6f74deb0 100644
--- a/doc/intl.rst
+++ b/doc/intl.rst
@@ -71,7 +71,7 @@ Translating with sphinx-intl
----------------------------
Quick guide
-^^^^^^^^^^^^
+^^^^^^^^^^^
`sphinx-intl`_ is a useful tool to work with Sphinx translation flow.
This section describe a easy way to translate with sphinx-intl.
@@ -81,8 +81,8 @@ This section describe a easy way to translate with sphinx-intl.
#. Add configurations to your `conf.py`::
- locale_dirs = ['locale/'] #path is example but recommended.
- gettext_compact = False #optional.
+ locale_dirs = ['locale/'] # path is example but recommended.
+ gettext_compact = False # optional.
This case-study assumes that :confval:`locale_dirs` is set to 'locale/' and
:confval:`gettext_compact` is set to `False` (the Sphinx document is
@@ -108,19 +108,18 @@ This section describe a easy way to translate with sphinx-intl.
#. Build mo files and make translated document.
- You need :confval:`language` parameter in ``conf.py`` or you may also
+ You need a :confval:`language` parameter in ``conf.py`` or you may also
specify the parameter on the command line::
$ sphinx-intl build
$ make -e SPHINXOPTS="-D language='de'" html
-
-Congratulations!! You got the translated document in ``_build/html``
+Congratulations! You got the translated documentation in the ``_build/html``
directory.
Translating
-^^^^^^^^^^^^
+^^^^^^^^^^^
Translate po file under ``./locale/de/LC_MESSAGES`` directory.
The case of builders.po file for sphinx document:
@@ -146,16 +145,17 @@ syntax:
"FILL HERE BY TARGET LANGUAGE FILL HERE BY TARGET LANGUAGE FILL HERE "
"BY TARGET LANGUAGE :ref:`EXTENSIONS <extensions>` FILL HERE."
-Please be careful not to break reST notation.
+Please be careful not to break reST notation. Most po-editors will help you
+with that.
Update your po files by new pot files
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-If the document is updated, it is necessary to generate updated pot files
+If a document is updated, it is necessary to generate updated pot files
and to apply differences to translated po files.
In order to apply the updating difference of a pot file to po file,
-using :command:`sphinx-intl update` command.
+use the :command:`sphinx-intl update` command.
.. code-block:: bash
@@ -165,6 +165,10 @@ using :command:`sphinx-intl update` command.
Using Transifex service for team translation
--------------------------------------------
+Transifex_ is one of several services that allow collaborative translation via a
+web interface. It has a nifty Python-based command line client that makes it
+easy to fetch and push translations.
+
.. TODO: why use transifex?
@@ -181,9 +185,9 @@ Using Transifex service for team translation
#. Create your transifex_ account and create new project for your document
- Currently, transifex does not allow for a translation project to
- have more than one version of document, so you'd better include a
- version number in your project name.
+ Currently, transifex does not allow for a translation project to have more
+ than one version of the document, so you'd better include a version number in
+ your project name.
For example:
@@ -193,8 +197,8 @@ Using Transifex service for team translation
#. Create config files for tx command
- This process will create ``.tx/config`` in the current directory, as
- well as ``~/.transifexrc`` file that includes auth information.
+ This process will create ``.tx/config`` in the current directory, as well as
+ a ``~/.transifexrc`` file that includes auth information.
.. code-block:: bash
@@ -253,11 +257,11 @@ Using Transifex service for team translation
That's all!
-.. tip:: Translating on local and Transifex
+.. tip:: Translating locally and on Transifex
If you want to push all language's po files, you can be done by using
:command:`tx push -t` command.
- Watch out! this operation overwrites translations in transifex.
+ Watch out! This operation overwrites translations in transifex.
In other words, if you have updated each in the service and local po files,
it would take much time and effort to integrate them.
@@ -270,7 +274,7 @@ Contributing to Sphinx reference translation
The recommended way for new contributors to translate Sphinx reference
is to join the translation team on Transifex.
-There is `sphinx translation page`_ for Sphinx-1.2 document.
+There is `sphinx translation page`_ for Sphinx-1.2 documentation.
1. Login to transifex_ service.
2. Go to `sphinx translation page`_.
diff --git a/doc/intro.rst b/doc/intro.rst
index 4d052c81..dd541bf1 100644
--- a/doc/intro.rst
+++ b/doc/intro.rst
@@ -16,6 +16,10 @@ Though there is support for that kind of docs as well (which is intended to be
freely mixed with hand-written content), if you need pure API docs have a look
at `Epydoc <http://epydoc.sf.net/>`_, which also understands reST.
+For a great "introduction" to writing docs in general -- the whys and hows, see
+also `Write the docs <http://write-the-docs.readthedocs.org/>`_, written by Eric
+Holscher.
+
Conversion from other systems
-----------------------------
@@ -24,7 +28,7 @@ This section is intended to collect helpful hints for those wanting to migrate
to reStructuredText/Sphinx from other documentation systems.
* Gerard Flanagan has written a script to convert pure HTML to reST; it can be
- found at the `Python Package Index <http://pypi.python.org/pypi/html2rest>`_.
+ found at the `Python Package Index <https://pypi.python.org/pypi/html2rest>`_.
* For converting the old Python docs to Sphinx, a converter was written which
can be found at `the Python SVN repository
@@ -35,7 +39,7 @@ to reStructuredText/Sphinx from other documentation systems.
markup; it is at `Google Code <http://code.google.com/p/db2rst/>`_.
* Christophe de Vienne wrote a tool to convert from Open/LibreOffice documents
- to Sphinx: `odt2sphinx <http://pypi.python.org/pypi/odt2sphinx/>`_.
+ to Sphinx: `odt2sphinx <https://pypi.python.org/pypi/odt2sphinx/>`_.
* To convert different markups, `Pandoc <http://johnmacfarlane.net/pandoc/>`_ is
a very helpful tool.
@@ -50,7 +54,7 @@ See the :ref:`pertinent section in the FAQ list <usingwith>`.
Prerequisites
-------------
-Sphinx needs at least **Python 2.5** or **Python 3.1** to run, as well as the
+Sphinx needs at least **Python 2.6** or **Python 3.2** to run, as well as the
docutils_ and Jinja2_ libraries. Sphinx should work with docutils version 0.7
or some (not broken) SVN trunk snapshot. If you like to have source code
highlighting support, you must also install the Pygments_ library.
diff --git a/doc/invocation.rst b/doc/invocation.rst
index c6125ecc..f831dc0a 100644
--- a/doc/invocation.rst
+++ b/doc/invocation.rst
@@ -124,13 +124,22 @@ The :program:`sphinx-build` script has several options:
.. option:: -D setting=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``. For boolean
- values, use ``0`` or ``1`` as the value.
+ must be a number, string, list or dictionary value.
+
+ For lists, you can separate elements with a comma like this: ``-D
+ html_theme_path=path1,path2``.
+
+ For dictionary values, supply the setting name and key like this:
+ ``-D latex_elements.docclass=scrartcl``.
+
+ For boolean values, use ``0`` or ``1`` as the value.
.. versionchanged:: 0.6
The value can now be a dictionary value.
+ .. versionchanged:: 1.3
+ The value can now also be a list value.
+
.. option:: -A name=value
Make the *name* assigned to *value* in the HTML templates.
@@ -140,7 +149,8 @@ The :program:`sphinx-build` script has several options:
.. option:: -n
Run in nit-picky mode. Currently, this generates warnings for all missing
- references.
+ references. See the config value :confval:`nitpick_ignore` for a way to
+ exclude some references as "known missing".
.. option:: -N
@@ -269,7 +279,7 @@ The :program:`sphinx-apidoc` script has several options:
filesystem to discover packages and modules. You may need it if you want
to generate documentation from a source directory managed by
`collective.recipe.omelette
- <http://pypi.python.org/pypi/collective.recipe.omelette/>`_.
+ <https://pypi.python.org/pypi/collective.recipe.omelette/>`_.
By default, symbolic links are skipped.
.. versionadded:: 1.2
diff --git a/doc/man/sphinx-build.rst b/doc/man/sphinx-build.rst
index 0a5d4abb..aa1d71c6 100644
--- a/doc/man/sphinx-build.rst
+++ b/doc/man/sphinx-build.rst
@@ -32,6 +32,13 @@ List of available builders:
html
HTML file generation. This is the default builder.
+dirhtml
+ HTML file generation with every HTML file named "index.html" in a separate
+ directory.
+
+singlehtml
+ HTML file generation with all content in a single HTML file.
+
htmlhelp
Generates files for CHM (compiled help files) generation.
@@ -51,9 +58,15 @@ texinfo
Generates Texinfo output that can be processed by :program:`makeinfo` to
generate an Info document.
+epub
+ Generates an ePub e-book version of the HTML output.
+
text
Generates a plain-text version of the documentation.
+gettext
+ Generates Gettext message catalogs for content translation.
+
changes
Generates HTML files listing changed/added/deprecated items for
the current version of the documented project.
@@ -81,20 +94,24 @@ Options
output for new and changed files is generated.
-E Ignore cached files, forces to re-read all source files
from disk.
+-d <path> Path to cached files; defaults to <outdir>/.doctrees.
+-j <N> Build in parallel with N processes where possible.
-c <path> Locate the conf.py file in the specified path instead of
<sourcedir>.
-C Specify that no conf.py file at all is to be used.
Configuration can only be set with the -D option.
-D <setting=value> Override a setting from the configuration file.
--d <path> Path to cached files; defaults to <outdir>/.doctrees.
+-t <tag> Define *tag* for use in "only" blocks.
-A <name=value> Pass a value into the HTML templates (only for HTML builders).
-n Run in nit-picky mode, warn about all missing references.
+-v Increase verbosity (can be repeated).
-N Prevent colored output.
-q Quiet operation, just print warnings and errors on stderr.
-Q Very quiet operation, don't print anything except for errors.
-w <file> Write warnings and errors into the given file, in addition
to stderr.
-W Turn warnings into errors.
+-T Show full traceback on exception.
-P Run Pdb on exception.
diff --git a/doc/markup/code.rst b/doc/markup/code.rst
index c0e7e8eb..e9f8f1da 100644
--- a/doc/markup/code.rst
+++ b/doc/markup/code.rst
@@ -62,8 +62,8 @@ installed) and handled in a smart way:
* ``c``
* ... and any other lexer name that Pygments supports.
-* If highlighting with the selected language fails, the block is not highlighted
- in any way.
+* If highlighting with the selected language fails (i.e. Pygments emits an
+ "Error" token), the block is not highlighted in any way.
Line numbers
^^^^^^^^^^^^
@@ -86,6 +86,14 @@ on line numbers for the individual block::
Some more Ruby code.
+The first line number can be selected with the ``lineno-start`` option. If
+present, ``linenos`` is automatically activated as well.
+
+ .. code-block:: ruby
+ :lineno-start: 10
+
+ Some more Ruby code, with line numbering starting at 10.
+
Additionally, an ``emphasize-lines`` option can be given to have Pygments
emphasize particular lines::
@@ -101,6 +109,9 @@ emphasize particular lines::
.. versionchanged:: 1.1
``emphasize-lines`` has been added.
+.. versionchanged:: 1.3
+ ``lineno-start`` has been added.
+
Includes
^^^^^^^^
@@ -121,10 +132,11 @@ Includes
Tabs in the input are expanded if you give a ``tab-width`` option with the
desired tab width.
- The directive also supports the ``linenos`` flag option to switch on line
- numbers, the ``emphasize-lines`` option to emphasize particular lines, and
- a ``language`` option to select a language different from the current
- file's standard language. Example with options::
+ Like :rst:dir:`code-block`, the directive supports the ``linenos`` flag
+ option to switch on line numbers, the ``lineno-start`` option to select the
+ first line number, the ``emphasize-lines`` option to emphasize particular
+ lines, and a ``language`` option to select a language different from the
+ current file's standard language. Example with options::
.. literalinclude:: example.rb
:language: ruby
@@ -176,6 +188,25 @@ Includes
The ``prepend`` and ``append`` options, as well as ``tab-width``.
+Showing a file name
+^^^^^^^^^^^^^^^^^^^
+
+.. versionadded:: 1.3
+
+A ``filename`` option can be given to show that name before the code block. For
+example::
+
+ .. code-block:: python
+ :filename: this.py
+
+ print 'Explicit is better than implicit.'
+
+
+:rst:dir:`literalinclude` also supports the ``filename`` option, with the
+additional feature that if you leave the value empty, the shown filename will be
+exactly the one given as an argument.
+
+
.. rubric:: Footnotes
.. [1] There is a standard ``.. include`` directive, but it raises errors if the
diff --git a/doc/markup/misc.rst b/doc/markup/misc.rst
index 10ba491e..b2e9051f 100644
--- a/doc/markup/misc.rst
+++ b/doc/markup/misc.rst
@@ -176,8 +176,9 @@ Including content based on tags
.. only:: html and draft
Undefined tags are false, defined tags (via the ``-t`` command-line option or
- within :file:`conf.py`) are true. Boolean expressions, also using
- parentheses (like ``html and (latex or draft)``) are supported.
+ within :file:`conf.py`, see :ref:`here <conf-tags>`) are true. Boolean
+ expressions, also using parentheses (like ``html and (latex or draft)``) are
+ supported.
The *format* and the *name* of the current builder (``html``, ``latex`` or
``text``) are always set as a tag [#]_. To make the distinction between
@@ -185,6 +186,9 @@ Including content based on tags
``builder_``, e.g. the epub builder defines the tags ``html``, ``epub``,
``format_html`` and ``builder_epub``.
+ These standard tags are set *after* the configuration file is read, so they
+ are not available there.
+
.. versionadded:: 0.6
.. versionchanged:: 1.2
Added the name of the builder and the prefixes.
@@ -212,9 +216,9 @@ following directive exists:
``p{width}`` construct, or tabulary's automatic specifiers:
+-----+------------------------------------------+
- |``L``| ragged-left column with automatic width |
+ |``L``| flush left column with automatic width |
+-----+------------------------------------------+
- |``R``| ragged-right column with automatic width |
+ |``R``| flush right column with automatic width |
+-----+------------------------------------------+
|``C``| centered column with automatic width |
+-----+------------------------------------------+
diff --git a/doc/markup/toctree.rst b/doc/markup/toctree.rst
index c17fb9b0..fdecc37d 100644
--- a/doc/markup/toctree.rst
+++ b/doc/markup/toctree.rst
@@ -68,8 +68,8 @@ tables of contents. The ``toctree`` directive is the central element.
**Section numbering**
- If you want to have section numbers even in HTML output, give the toctree a
- ``numbered`` option. For example::
+ If you want to have section numbers even in HTML output, give the
+ **toplevel** toctree a ``numbered`` option. For example::
.. toctree::
:numbered:
@@ -141,9 +141,9 @@ tables of contents. The ``toctree`` directive is the central element.
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
finds a file that is not included, because that means that this file will not
- be reachable through standard navigation. Use :confval:`unused_docs` to
- explicitly exclude documents from building, and :confval:`exclude_trees` to
- exclude whole directories.
+ be reachable through standard navigation. Use :ref:`metadata` to remove the
+ warning, and :confval:`exclude_patterns` to explicitly exclude documents or
+ directories from building.
The "master document" (selected by :confval:`master_doc`) is the "root" of
the TOC tree hierarchy. It can be used as the documentation's main page, or
diff --git a/doc/rest.rst b/doc/rest.rst
index ccfdf11d..b35ebc91 100644
--- a/doc/rest.rst
+++ b/doc/rest.rst
@@ -373,6 +373,8 @@ For instance, if the file name ``gnu.*`` was given and two files :file:`gnu.pdf`
and :file:`gnu.png` existed in the source tree, the LaTeX builder would choose
the former, while the HTML builder would prefer the latter.
+Note that image file names should not contain spaces.
+
.. versionchanged:: 0.4
Added the support for file names ending in an asterisk.
diff --git a/doc/templating.rst b/doc/templating.rst
index b9dfc683..b9561b69 100644
--- a/doc/templating.rst
+++ b/doc/templating.rst
@@ -251,7 +251,8 @@ in the future.
.. data:: docstitle
- The title of the documentation (the value of :confval:`html_title`).
+ The title of the documentation (the value of :confval:`html_title`), except
+ when the "single-file" builder is used, when it is set to ``None``.
.. data:: embedded
diff --git a/doc/tutorial.rst b/doc/tutorial.rst
index 9fea11db..8e949d4c 100644
--- a/doc/tutorial.rst
+++ b/doc/tutorial.rst
@@ -248,11 +248,40 @@ Therefore, you must add the appropriate path to :py:data:`sys.path` in your
|more| See :mod:`sphinx.ext.autodoc` for the complete description of the
features of autodoc.
+Intersphinx
+-----------
+
+Many Sphinx documents including the `Python documentation`_ are published on the
+internet. When you want to make links to such documents from your
+documentation, you can do it with :mod:`sphinx.ext.intersphinx`.
+
+.. _Python documentation: http://docs.python.org/3
+
+In order to use intersphinx, you need to activate it in :file:`conf.py` by
+putting the string ``'sphinx.ext.intersphinx'`` into the :confval:`extensions`
+list and set up the :confval:`intersphinx_mapping` config value.
+
+For example, to link to ``io.open()`` in the Python library manual, you need to
+setup your :confval:`intersphinx_mapping` like::
+
+ intersphinx_mapping = {'python': ('http://docs.python.org/3', None)}
+
+And now, you can write a cross-reference like ``:py:func:`io.open```. Any
+cross-reference that has no matching target in the current documentation set,
+will be looked up in the documentation sets configured in
+:confval:`intersphinx_mapping` (this needs access to the URL in order to
+download the list of valid targets). Intersphinx also works for some other
+:ref:`domains' <domains>` roles including ``:ref:``, however it doesn't work for
+``:doc:`` as that is non-domain role.
+
+|more| See :mod:`sphinx.ext.intersphinx` for the complete description of the
+features of intersphinx.
+
More topics to be covered
-------------------------
-- Other extensions (math, intersphinx, viewcode, doctest)
+- Other extensions (math, viewcode, doctest)
- Static files
- Selecting a theme
- Templating
diff --git a/setup.py b/setup.py
index 553cf12d..53a4c04b 100644
--- a/setup.py
+++ b/setup.py
@@ -44,20 +44,20 @@ A development egg can be found `here
<http://bitbucket.org/birkenfeld/sphinx/get/tip.gz#egg=Sphinx-dev>`_.
'''
+if sys.version_info < (2, 6) or (3, 0) <= sys.version_info < (3, 2):
+ print('ERROR: Sphinx requires at least Python 2.6 or 3.2 to run.')
+ sys.exit(1)
+
requires = ['Pygments>=1.2', 'docutils>=0.7']
if sys.version_info[:3] >= (3, 3, 0):
requires[1] = 'docutils>=0.10'
-if sys.version_info < (2, 6) or (3, 0) <= sys.version_info < (3, 3):
+if (3, 0) <= sys.version_info < (3, 3):
requires.append('Jinja2>=2.3,<2.7')
-else:
+else: # 2.6, 2.7, 3.3 or later
requires.append('Jinja2>=2.3')
-if sys.version_info < (2, 5):
- print('ERROR: Sphinx requires at least Python 2.5 to run.')
- sys.exit(1)
-
# tell distribute to use 2to3 with our own fixers
extra = {}
if sys.version_info >= (3, 0):
diff --git a/sphinx/__init__.py b/sphinx/__init__.py
index 0f45ecb0..2551526f 100644
--- a/sphinx/__init__.py
+++ b/sphinx/__init__.py
@@ -15,11 +15,12 @@
import sys
from os import path
-__version__ = '1.2b3'
-__released__ = '1.2b3' # used when Sphinx builds its own docs
+__version__ = '1.3a0'
+__released__ = '1.3a0' # used when Sphinx builds its own docs
# version info for better programmatic use
# possible values for 3rd element: 'alpha', 'beta', 'rc', 'final'
-version_info = (1, 2, 0, 'beta', 3)
+# 'final' has 0 as the last element
+version_info = (1, 3, 0, 'alpha', 0)
package_dir = path.abspath(path.dirname(__file__))
@@ -41,8 +42,9 @@ if '+' in __version__ or 'pre' in __version__:
def main(argv=sys.argv):
"""Sphinx build "main" command-line entry."""
- if sys.version_info[:3] < (2, 5, 0):
- sys.stderr.write('Error: Sphinx requires at least Python 2.5 to run.\n')
+ if (sys.version_info[:3] < (2, 6, 0) or
+ (3, 0, 0) <= sys.version_info[:3] < (3, 2, 0)):
+ sys.stderr.write('Error: Sphinx requires at least Python 2.6 to run.\n')
return 1
try:
from sphinx import cmdline
diff --git a/sphinx/addnodes.py b/sphinx/addnodes.py
index d8dca2ce..e3f6d7d6 100644
--- a/sphinx/addnodes.py
+++ b/sphinx/addnodes.py
@@ -168,6 +168,11 @@ class literal_emphasis(nodes.emphasis):
applied (e.g. smartypants for HTML output).
"""
+class literal_strong(nodes.strong):
+ """Node that behaves like `strong`, but further text processors are not
+ applied (e.g. smartypants for HTML output).
+ """
+
class abbreviation(nodes.Inline, nodes.TextElement):
"""Node for abbreviations with explanations."""
diff --git a/sphinx/apidoc.py b/sphinx/apidoc.py
index c3054662..4430cdd0 100644
--- a/sphinx/apidoc.py
+++ b/sphinx/apidoc.py
@@ -65,7 +65,7 @@ def write_file(name, text, opts):
def format_heading(level, text):
"""Create a heading of <level> [1, 2 or 3 supported]."""
- underlining = ['=', '-', '~', ][level-1] * len(text)
+ underlining = ['=', '-', '~', ][level - 1] * len(text)
return '%s\n%s\n\n' % (text, underlining)
@@ -173,9 +173,6 @@ def recurse_tree(rootpath, excludes, opts):
Look for every file in the directory tree and create the corresponding
ReST files.
"""
- # use absolute path for root, as relative paths like '../../foo' cause
- # 'if "/." in root ...' to filter out *all* modules otherwise
- rootpath = path.normpath(path.abspath(rootpath))
# check if the base directory is a package and get its name
if INITPY in os.listdir(rootpath):
root_package = rootpath.split(path.sep)[-1]
@@ -186,12 +183,10 @@ def recurse_tree(rootpath, excludes, opts):
toplevels = []
followlinks = getattr(opts, 'followlinks', False)
for root, subs, files in os.walk(rootpath, followlinks=followlinks):
- if is_excluded(root, excludes):
- del subs[:]
- continue
- # document only Python module files
+ # document only Python module files (that aren't excluded)
py_files = sorted(f for f in files
- if path.splitext(f)[1] in PY_SUFFIXES)
+ if path.splitext(f)[1] in PY_SUFFIXES and
+ not is_excluded(path.join(root, f), excludes))
is_pkg = INITPY in py_files
if is_pkg:
py_files.remove(INITPY)
@@ -200,8 +195,10 @@ def recurse_tree(rootpath, excludes, opts):
# only accept non-package at toplevel
del subs[:]
continue
- # remove hidden ('.') and private ('_') directories
- subs[:] = sorted(sub for sub in subs if sub[0] not in ['.', '_'])
+ # remove hidden ('.') and private ('_') directories, as well as
+ # excluded dirs
+ subs[:] = sorted(sub for sub in subs if sub[0] not in ['.', '_']
+ and not is_excluded(path.join(root, sub), excludes))
if is_pkg:
# we are in a package with something to document
@@ -225,47 +222,35 @@ def recurse_tree(rootpath, excludes, opts):
def normalize_excludes(rootpath, excludes):
- """
- Normalize the excluded directory list:
- * must be either an absolute path or start with rootpath,
- * otherwise it is joined with rootpath
- * with trailing slash
- """
- f_excludes = []
- for exclude in excludes:
- if not path.isabs(exclude) and not exclude.startswith(rootpath):
- exclude = path.join(rootpath, exclude)
- f_excludes.append(path.normpath(exclude) + path.sep)
- return f_excludes
+ """Normalize the excluded directory list."""
+ return [path.normpath(path.abspath(exclude)) for exclude in excludes]
def is_excluded(root, excludes):
- """
- Check if the directory is in the exclude list.
+ """Check if the directory is in the exclude list.
Note: by having trailing slashes, we avoid common prefix issues, like
e.g. an exlude "foo" also accidentally excluding "foobar".
"""
- sep = path.sep
- if not root.endswith(sep):
- root += sep
+ root = path.normpath(root)
for exclude in excludes:
- if root.startswith(exclude):
+ if root == exclude:
return True
return False
def main(argv=sys.argv):
- """
- Parse and check the command line arguments.
- """
+ """Parse and check the command line arguments."""
parser = optparse.OptionParser(
usage="""\
-usage: %prog [options] -o <output_path> <module_path> [exclude_paths, ...]
+usage: %prog [options] -o <output_path> <module_path> [exclude_path, ...]
Look recursively in <module_path> for Python modules and packages and create
one reST file with automodule directives per package in the <output_path>.
+The <exclude_path>s can be files and/or directories that will be excluded
+from generation.
+
Note: By default this script will not overwrite already created files.""")
parser.add_option('-o', '--output-dir', action='store', dest='destdir',
@@ -327,6 +312,7 @@ Note: By default this script will not overwrite already created files.""")
if not path.isdir(opts.destdir):
if not opts.dryrun:
os.makedirs(opts.destdir)
+ rootpath = path.normpath(path.abspath(rootpath))
excludes = normalize_excludes(rootpath, excludes)
modules = recurse_tree(rootpath, excludes, opts)
if opts.full:
diff --git a/sphinx/application.py b/sphinx/application.py
index ceb7c32c..6b86b181 100644
--- a/sphinx/application.py
+++ b/sphinx/application.py
@@ -15,6 +15,7 @@ import os
import sys
import types
import posixpath
+import traceback
from os import path
from cStringIO import StringIO
@@ -112,8 +113,6 @@ class Sphinx(object):
if self.confdir is None:
self.confdir = self.srcdir
- # backwards compatibility: activate old C markup
- self.setup_extension('sphinx.ext.oldcmarkup')
# load all user-given extension modules
for extension in self.config.extensions:
self.setup_extension(extension)
@@ -122,7 +121,7 @@ class Sphinx(object):
self.config.setup(self)
# now that we know all config values, collect them from conf.py
- self.config.init_values()
+ self.config.init_values(self.warn)
# check the Sphinx version if requested
if self.config.needs_sphinx and \
@@ -282,6 +281,7 @@ class Sphinx(object):
try:
mod = __import__(extension, None, None, ['setup'])
except ImportError, err:
+ self.verbose('Original exception:\n' + traceback.format_exc())
raise ExtensionError('Could not import extension %s' % extension,
err)
if not hasattr(mod, 'setup'):
diff --git a/sphinx/builders/epub.py b/sphinx/builders/epub.py
index 1dfcc704..35061b79 100644
--- a/sphinx/builders/epub.py
+++ b/sphinx/builders/epub.py
@@ -12,7 +12,6 @@
import os
import re
-import sys
import time
import codecs
import zipfile
@@ -750,12 +749,5 @@ class EpubBuilder(StandaloneHTMLBuilder):
zipfile.ZIP_STORED)
for file in projectfiles:
fp = path.join(outdir, file)
- if sys.version_info < (2, 6):
- # When zipile.ZipFile.write call with unicode filename, ZipFile
- # encode filename to 'utf-8' (only after Python-2.6).
- if isinstance(file, unicode):
- # OEBPS Container Format (OCF) 2.0.1 specification require
- # "File Names MUST be UTF-8 encoded".
- file = file.encode('utf-8')
epub.write(fp, file, zipfile.ZIP_DEFLATED)
epub.close()
diff --git a/sphinx/builders/gettext.py b/sphinx/builders/gettext.py
index 50d5163b..f648c311 100644
--- a/sphinx/builders/gettext.py
+++ b/sphinx/builders/gettext.py
@@ -9,6 +9,8 @@
:license: BSD, see LICENSE for details.
"""
+from __future__ import with_statement
+
from os import path, walk
from codecs import open
from time import time
@@ -160,7 +162,8 @@ class MessageCatalogBuilder(I18nBuilder):
for template in self.status_iterator(files,
'reading templates... ', purple, len(files)):
- context = open(template, 'r', encoding='utf-8').read()
+ with open(template, 'r', encoding='utf-8') as f:
+ context = f.read()
for line, meth, msg in extract_translations(context):
origin = MsgOrigin(template, line)
self.catalogs['sphinx'].add(msg, origin)
diff --git a/sphinx/builders/html.py b/sphinx/builders/html.py
index e00b91c3..b6ebf926 100644
--- a/sphinx/builders/html.py
+++ b/sphinx/builders/html.py
@@ -16,11 +16,7 @@ import codecs
import posixpath
import cPickle as pickle
from os import path
-try:
- from hashlib import md5
-except ImportError:
- # 2.4 compatibility
- from md5 import md5
+from hashlib import md5
from docutils import nodes
from docutils.io import DocTreeInput, StringOutput
@@ -35,7 +31,7 @@ from sphinx.util.osutil import SEP, os_path, relative_uri, ensuredir, \
movefile, ustrftime, copyfile
from sphinx.util.nodes import inline_all_toctrees
from sphinx.util.matching import patmatch, compile_matchers
-from sphinx.util.pycompat import any, b
+from sphinx.util.pycompat import b
from sphinx.errors import SphinxError
from sphinx.locale import _
from sphinx.search import js_index
@@ -597,7 +593,9 @@ class StandaloneHTMLBuilder(Builder):
if self.config.html_logo:
logobase = path.basename(self.config.html_logo)
logotarget = path.join(self.outdir, '_static', logobase)
- if not path.isfile(logotarget):
+ if not path.isfile(logobase):
+ self.warn('logo file %r does not exist' % logobase)
+ elif not path.isfile(logotarget):
copyfile(path.join(self.confdir, self.config.html_logo),
logotarget)
if self.config.html_favicon:
@@ -618,6 +616,7 @@ class StandaloneHTMLBuilder(Builder):
self.warn('html_extra_path entry %r does not exist' % entry)
continue
copy_static_entry(entry, self.outdir, self)
+ self.info('done')
def write_buildinfo(self):
# write build info file
@@ -1095,8 +1094,4 @@ class JSONHTMLBuilder(SerializingHTMLBuilder):
searchindex_filename = 'searchindex.json'
def init(self):
- if jsonimpl.json is None:
- raise SphinxError(
- 'The module simplejson (or json in Python >= 2.6) '
- 'is not available. The JSONHTMLBuilder builder will not work.')
SerializingHTMLBuilder.init(self)
diff --git a/sphinx/builders/linkcheck.py b/sphinx/builders/linkcheck.py
index c567401c..171e68d5 100644
--- a/sphinx/builders/linkcheck.py
+++ b/sphinx/builders/linkcheck.py
@@ -10,22 +10,34 @@
"""
import re
-import sys
import Queue
import socket
import threading
from os import path
-from urllib2 import build_opener, unquote, Request
+from urllib2 import build_opener, unquote, Request, \
+ HTTPError, HTTPRedirectHandler
from HTMLParser import HTMLParser, HTMLParseError
from docutils import nodes
from sphinx.builders import Builder
-from sphinx.util.console import purple, red, darkgreen, darkgray
+from sphinx.util.console import purple, red, darkgreen, darkgray, \
+ darkred, turquoise
+
+
+class RedirectHandler(HTTPRedirectHandler):
+ """A RedirectHandler that records the redirect code we got."""
+
+ def redirect_request(self, req, fp, code, msg, headers, newurl):
+ new_req = HTTPRedirectHandler.redirect_request(self, req, fp, code,
+ msg, headers, newurl)
+ req.redirect_code = code
+ return new_req
# create an opener that will simulate a browser user-agent
-opener = build_opener()
-opener.addheaders = [('User-agent', 'Mozilla/5.0')]
+opener = build_opener(RedirectHandler)
+opener.addheaders = [('User-agent', 'Mozilla/5.0 (X11; Linux x86_64; rv:25.0) '
+ 'Gecko/20100101 Firefox/25.0')]
class HeadRequest(Request):
@@ -97,25 +109,25 @@ class CheckExternalLinksBuilder(Builder):
def check_thread(self):
kwargs = {}
- if sys.version_info > (2, 5) and self.app.config.linkcheck_timeout:
+ if self.app.config.linkcheck_timeout:
kwargs['timeout'] = self.app.config.linkcheck_timeout
def check():
# check for various conditions without bothering the network
if len(uri) == 0 or uri[0] == '#' or \
uri[0:7] == 'mailto:' or uri[0:4] == 'ftp:':
- return 'unchecked', ''
+ return 'unchecked', '', 0
elif not (uri[0:5] == 'http:' or uri[0:6] == 'https:'):
- return 'local', ''
+ return 'local', '', 0
elif uri in self.good:
- return 'working', ''
+ return 'working', '', 0
elif uri in self.broken:
- return 'broken', self.broken[uri]
+ return 'broken', self.broken[uri], 0
elif uri in self.redirected:
- return 'redirected', self.redirected[uri]
+ return 'redirected', self.redirected[uri][0], self.redirected[uri][1]
for rex in self.to_ignore:
if rex.match(uri):
- return 'ignored', ''
+ return 'ignored', '', 0
if '#' in uri:
req_url, hash = uri.split('#', 1)
@@ -127,61 +139,82 @@ class CheckExternalLinksBuilder(Builder):
try:
if hash and self.app.config.linkcheck_anchors:
# Read the whole document and see if #hash exists
- f = opener.open(Request(req_url), **kwargs)
+ req = Request(req_url)
+ f = opener.open(req, **kwargs)
found = check_anchor(f, unquote(hash))
f.close()
if not found:
raise Exception("Anchor '%s' not found" % hash)
else:
- f = opener.open(HeadRequest(req_url), **kwargs)
- f.close()
+ try:
+ # try a HEAD request, which should be easier on
+ # the server and the network
+ req = HeadRequest(req_url)
+ f = opener.open(req, **kwargs)
+ f.close()
+ except HTTPError, err:
+ if err.code != 405:
+ raise
+ # retry with GET if that fails, some servers
+ # don't like HEAD requests and reply with 405
+ req = Request(req_url)
+ f = opener.open(req, **kwargs)
+ f.close()
except Exception, err:
self.broken[uri] = str(err)
- return 'broken', str(err)
+ return 'broken', str(err), 0
if f.url.rstrip('/') == req_url.rstrip('/'):
self.good.add(uri)
- return 'working', 'new'
+ return 'working', 'new', 0
else:
new_url = f.url
if hash:
new_url += '#' + hash
-
- self.redirected[uri] = new_url
- return 'redirected', new_url
+ code = getattr(req, 'redirect_code', 0)
+ self.redirected[uri] = (new_url, code)
+ return 'redirected', new_url, code
while True:
uri, docname, lineno = self.wqueue.get()
if uri is None:
break
- status, info = check()
- self.rqueue.put((uri, docname, lineno, status, info))
+ status, info, code = check()
+ self.rqueue.put((uri, docname, lineno, status, info, code))
def process_result(self, result):
- uri, docname, lineno, status, info = result
+ uri, docname, lineno, status, info, code = result
if status == 'unchecked':
return
if status == 'working' and info != 'new':
return
if lineno:
- self.info('(line %3d) ' % lineno, nonl=1)
+ self.info('(line %4d) ' % lineno, nonl=1)
if status == 'ignored':
- self.info(uri + ' - ' + darkgray('ignored'))
+ self.info(darkgray('-ignored- ') + uri)
elif status == 'local':
- self.info(uri + ' - ' + darkgray('local'))
+ self.info(darkgray('-local- ') + uri)
self.write_entry('local', docname, lineno, uri)
elif status == 'working':
- self.info(uri + ' - ' + darkgreen('working'))
+ self.info(darkgreen('ok ') + uri)
elif status == 'broken':
- self.info(uri + ' - ' + red('broken: ') + info)
+ self.info(red('broken ') + uri + red(' - ' + info))
self.write_entry('broken', docname, lineno, uri + ': ' + info)
if self.app.quiet:
self.warn('broken link: %s' % uri,
'%s:%s' % (self.env.doc2path(docname), lineno))
elif status == 'redirected':
- self.info(uri + ' - ' + purple('redirected') + ' to ' + info)
- self.write_entry('redirected', docname, lineno, uri + ' to ' + info)
+ text, color = {
+ 301: ('permanently', darkred),
+ 302: ('with Found', purple),
+ 303: ('with See Other', purple),
+ 307: ('temporarily', turquoise),
+ 0: ('with unknown code', purple),
+ }[code]
+ self.write_entry('redirected ' + text, docname, lineno,
+ uri + ' to ' + info)
+ self.info(color('redirect ') + uri + color(' - ' + text + ' to ' + info))
def get_target_uri(self, docname, typ=None):
return ''
diff --git a/sphinx/builders/text.py b/sphinx/builders/text.py
index 4b73167b..f09ad654 100644
--- a/sphinx/builders/text.py
+++ b/sphinx/builders/text.py
@@ -54,6 +54,7 @@ class TextBuilder(Builder):
self.writer = TextWriter(self)
def write_doc(self, docname, doctree):
+ self.current_docname = docname
destination = StringOutput(encoding='utf-8')
self.writer.write(doctree, destination)
outfilename = path.join(self.outdir, os_path(docname) + self.out_suffix)
diff --git a/sphinx/cmdline.py b/sphinx/cmdline.py
index e5ad3ab5..2d7146c3 100644
--- a/sphinx/cmdline.py
+++ b/sphinx/cmdline.py
@@ -173,14 +173,11 @@ def main(argv):
print >>sys.stderr, ('Error: -D option argument must be '
'in the form name=value.')
return 1
- try:
- val = int(val)
- except ValueError:
- if likely_encoding and isinstance(val, bytes):
- try:
- val = val.decode(likely_encoding)
- except UnicodeError:
- pass
+ if likely_encoding and isinstance(val, bytes):
+ try:
+ val = val.decode(likely_encoding)
+ except UnicodeError:
+ pass
confoverrides[key] = val
elif opt == '-A':
try:
diff --git a/sphinx/config.py b/sphinx/config.py
index 4cca4b35..df74e914 100644
--- a/sphinx/config.py
+++ b/sphinx/config.py
@@ -72,7 +72,7 @@ class Config(object):
primary_domain = ('py', 'env'),
needs_sphinx = (None, None),
nitpicky = (False, 'env'),
- nitpick_ignore = ([], 'env'),
+ nitpick_ignore = ([], 'html'),
# HTML options
html_theme = ('default', 'html'),
@@ -214,8 +214,11 @@ class Config(object):
self.overrides = overrides
self.values = Config.config_values.copy()
config = {}
- if "extensions" in overrides:
- config["extensions"] = overrides["extensions"]
+ if 'extensions' in overrides:
+ if isinstance(overrides['extensions'], (str, unicode)):
+ config['extensions'] = overrides.pop('extensions').split(',')
+ else:
+ config['extensions'] = overrides.pop('extensions')
if dirname is not None:
config_file = path.join(dirname, filename)
config['__file__'] = config_file
@@ -248,12 +251,36 @@ class Config(object):
'Please use Unicode strings, e.g. %r.' % (name, u'Content')
)
- def init_values(self):
+ def init_values(self, warn):
config = self._raw_config
for valname, value in self.overrides.iteritems():
if '.' in valname:
realvalname, key = valname.split('.', 1)
config.setdefault(realvalname, {})[key] = value
+ continue
+ elif valname not in self.values:
+ warn('unknown config value %r in override, ignoring' % valname)
+ continue
+ defvalue = self.values[valname][0]
+ if isinstance(value, (str, unicode)):
+ if isinstance(defvalue, dict):
+ warn('cannot override dictionary config setting %r, '
+ 'ignoring (use %r to set individual elements)' %
+ (valname, valname + '.key=value'))
+ continue
+ elif isinstance(defvalue, list):
+ config[valname] = value.split(',')
+ elif isinstance(defvalue, (int, long)):
+ try:
+ config[valname] = int(value)
+ except ValueError:
+ warn('invalid number %r for config value %r, ignoring'
+ % (value, valname))
+ elif defvalue is not None and not isinstance(defvalue, (str, unicode)):
+ warn('cannot override config setting %r with unsupported type, '
+ 'ignoring' % valname)
+ else:
+ config[valname] = value
else:
config[valname] = value
for name in config:
diff --git a/sphinx/directives/__init__.py b/sphinx/directives/__init__.py
index 388522dc..3133b7e3 100644
--- a/sphinx/directives/__init__.py
+++ b/sphinx/directives/__init__.py
@@ -12,7 +12,6 @@
import re
from docutils.parsers.rst import Directive, directives
-from docutils.parsers.rst.directives import images
from sphinx import addnodes
from sphinx.util.docfields import DocFieldTransformer
@@ -22,15 +21,6 @@ from sphinx.directives.code import *
from sphinx.directives.other import *
-# allow units for the figure's "figwidth"
-try:
- images.Figure.option_spec['figwidth'] = \
- directives.length_or_percentage_or_unitless
-except AttributeError:
- images.figure.options['figwidth'] = \
- directives.length_or_percentage_or_unitless
-
-
# RE to strip backslash escapes
nl_escape_re = re.compile(r'\\\n')
strip_backslash_re = re.compile(r'\\(.)')
@@ -149,11 +139,12 @@ class ObjectDescription(Directive):
signode.clear()
signode += addnodes.desc_name(sig, sig)
continue # we don't want an index entry here
- if not noindex and name not in self.names:
- # only add target and index entry if this is the first
- # description of the object with this name in this desc block
+ if name not in self.names:
self.names.append(name)
- self.add_target_and_index(name, sig, signode)
+ if not noindex:
+ # only add target and index entry if this is the first
+ # description of the object with this name in this desc block
+ self.add_target_and_index(name, sig, signode)
contentnode = addnodes.desc_content()
node.append(contentnode)
diff --git a/sphinx/directives/code.py b/sphinx/directives/code.py
index 4d43e5ff..6900ea6b 100644
--- a/sphinx/directives/code.py
+++ b/sphinx/directives/code.py
@@ -56,7 +56,9 @@ class CodeBlock(Directive):
final_argument_whitespace = False
option_spec = {
'linenos': directives.flag,
+ 'lineno-start': int,
'emphasize-lines': directives.unchanged_required,
+ 'filename': directives.unchanged_required,
}
def run(self):
@@ -75,9 +77,16 @@ class CodeBlock(Directive):
literal = nodes.literal_block(code, code)
literal['language'] = self.arguments[0]
- literal['linenos'] = 'linenos' in self.options
+ filename = self.options.get('filename')
+ if filename:
+ literal['filename'] = filename
+ literal['linenos'] = 'linenos' in self.options or \
+ 'lineno-start' in self.options
+ extra_args = literal['highlight_args'] = {}
if hl_lines is not None:
- literal['highlight_args'] = {'hl_lines': hl_lines}
+ extra_args['hl_lines'] = hl_lines
+ if 'lineno-start' in self.options:
+ extra_args['linenostart'] = self.options['lineno-start']
set_source_info(self, literal)
return [literal]
@@ -95,6 +104,7 @@ class LiteralInclude(Directive):
final_argument_whitespace = True
option_spec = {
'linenos': directives.flag,
+ 'lineno-start': int,
'tab-width': int,
'language': directives.unchanged_required,
'encoding': directives.encoding,
@@ -105,6 +115,7 @@ class LiteralInclude(Directive):
'prepend': directives.unchanged_required,
'append': directives.unchanged_required,
'emphasize-lines': directives.unchanged_required,
+ 'filename': directives.unchanged,
}
def run(self):
@@ -204,10 +215,18 @@ class LiteralInclude(Directive):
set_source_info(self, retnode)
if self.options.get('language', ''):
retnode['language'] = self.options['language']
- if 'linenos' in self.options:
- retnode['linenos'] = True
+ retnode['linenos'] = 'linenos' in self.options or \
+ 'lineno-start' in self.options
+ filename = self.options.get('filename')
+ if filename is not None:
+ if not filename:
+ filename = self.arguments[0]
+ retnode['filename'] = filename
+ extra_args = retnode['highlight_args'] = {}
if hl_lines is not None:
- retnode['highlight_args'] = {'hl_lines': hl_lines}
+ extra_args['hl_lines'] = hl_lines
+ if 'lineno-start' in self.options:
+ extra_args['linenostart'] = self.options['lineno-start']
env.note_dependency(rel_filename)
return [retnode]
diff --git a/sphinx/domains/c.py b/sphinx/domains/c.py
index f9f2e664..26e3c984 100644
--- a/sphinx/domains/c.py
+++ b/sphinx/domains/c.py
@@ -59,7 +59,12 @@ class CObject(ObjectDescription):
# These C types aren't described anywhere, so don't try to create
# a cross-reference to them
- stopwords = set(('const', 'void', 'char', 'int', 'long', 'FILE', 'struct'))
+ stopwords = set((
+ 'const', 'void', 'char', 'wchar_t', 'int', 'short',
+ 'long', 'float', 'double', 'unsigned', 'signed', 'FILE',
+ 'clock_t', 'time_t', 'ptrdiff_t', 'size_t', 'ssize_t',
+ 'struct', '_Bool',
+ ))
def _parse_type(self, node, ctype):
# add cross-ref nodes for all words
@@ -151,10 +156,12 @@ class CObject(ObjectDescription):
return ''
def add_target_and_index(self, name, sig, signode):
- # note target
- if name not in self.state.document.ids:
- signode['names'].append(name)
- signode['ids'].append(name)
+ # for C API items we add a prefix since names are usually not qualified
+ # by a module name and so easily clash with e.g. section titles
+ targetname = 'c.' + name
+ if targetname not in self.state.document.ids:
+ signode['names'].append(targetname)
+ signode['ids'].append(targetname)
signode['first'] = (not self.names)
self.state.document.note_explicit_target(signode)
inv = self.env.domaindata['c']['objects']
@@ -167,7 +174,8 @@ class CObject(ObjectDescription):
indextext = self.get_index_text(name)
if indextext:
- self.indexnode['entries'].append(('single', indextext, name, ''))
+ self.indexnode['entries'].append(('single', indextext,
+ targetname, ''))
def before_content(self):
self.typename_set = False
@@ -237,9 +245,9 @@ class CDomain(Domain):
if target not in self.data['objects']:
return None
obj = self.data['objects'][target]
- return make_refnode(builder, fromdocname, obj[0], target,
+ return make_refnode(builder, fromdocname, obj[0], 'c.' + target,
contnode, target)
def get_objects(self):
for refname, (docname, type) in self.data['objects'].iteritems():
- yield (refname, refname, type, docname, refname, 1)
+ yield (refname, refname, type, docname, 'c.' + refname, 1)
diff --git a/sphinx/domains/python.py b/sphinx/domains/python.py
index 0c08b60b..6714e838 100644
--- a/sphinx/domains/python.py
+++ b/sphinx/domains/python.py
@@ -81,6 +81,23 @@ def _pseudo_parse_arglist(signode, arglist):
signode += paramlist
+# This override allows our inline type specifiers to behave like :class: link
+# when it comes to handling "." and "~" prefixes.
+class PyTypedField(TypedField):
+ def make_xref(self, rolename, domain, target, innernode=nodes.emphasis):
+ result = super(PyTypedField, self).make_xref(rolename, domain, target,
+ innernode)
+ if target.startswith('.'):
+ result['reftarget'] = target[1:]
+ result['refspecific'] = True
+ result[0][0] = nodes.Text(target[1:])
+ if target.startswith('~'):
+ result['reftarget'] = target[1:]
+ title = target.split('.')[-1]
+ result[0][0] = nodes.Text(title)
+ return result
+
+
class PyObject(ObjectDescription):
"""
Description of a general Python object.
@@ -92,7 +109,7 @@ class PyObject(ObjectDescription):
}
doc_field_types = [
- TypedField('parameter', label=l_('Parameters'),
+ PyTypedField('parameter', label=l_('Parameters'),
names=('param', 'parameter', 'arg', 'argument',
'keyword', 'kwarg', 'kwparam'),
typerolename='obj', typenames=('paramtype', 'type'),
@@ -559,8 +576,8 @@ class PythonDomain(Domain):
object_types = {
'function': ObjType(l_('function'), 'func', 'obj'),
'data': ObjType(l_('data'), 'data', 'obj'),
- 'class': ObjType(l_('class'), 'class', 'obj'),
- 'exception': ObjType(l_('exception'), 'exc', 'obj'),
+ 'class': ObjType(l_('class'), 'class', 'exc', 'obj'),
+ 'exception': ObjType(l_('exception'), 'exc', 'class', 'obj'),
'method': ObjType(l_('method'), 'meth', 'obj'),
'classmethod': ObjType(l_('class method'), 'meth', 'obj'),
'staticmethod': ObjType(l_('static method'), 'meth', 'obj'),
diff --git a/sphinx/domains/std.py b/sphinx/domains/std.py
index ae67bf0e..895e35e5 100644
--- a/sphinx/domains/std.py
+++ b/sphinx/domains/std.py
@@ -27,8 +27,7 @@ from sphinx.util.compat import Directive
# RE for option descriptions
-option_desc_re = re.compile(
- r'((?:/|-|--)[-_a-zA-Z0-9]+)(\s*.*?)(?=,\s+(?:/|-|--)|$)')
+option_desc_re = re.compile(r'((?:/|-|--)[-_a-zA-Z0-9]+)(\s*.*)')
class GenericObject(ObjectDescription):
@@ -130,14 +129,23 @@ class Target(Directive):
class Cmdoption(ObjectDescription):
"""
- Description of a command-line option (.. cmdoption).
+ Description of a command-line option (.. option).
"""
def handle_signature(self, sig, signode):
"""Transform an option description into RST nodes."""
count = 0
firstname = ''
- for m in option_desc_re.finditer(sig):
+ for potential_option in sig.split(', '):
+ potential_option = potential_option.strip()
+ m = option_desc_re.match(potential_option)
+ if not m:
+ self.env.warn(
+ self.env.docname,
+ 'Malformed option description %r, should '
+ 'look like "-opt args", "--opt args" or '
+ '"/opt args"' % potential_option, self.lineno)
+ continue
optname, args = m.groups()
if count:
signode += addnodes.desc_addname(', ', ', ')
@@ -190,17 +198,26 @@ class Program(Directive):
class OptionXRefRole(XRefRole):
innernodeclass = addnodes.literal_emphasis
+ def _split(self, text, refnode, env):
+ try:
+ program, target = re.split(' (?=-|--|/)', text, 1)
+ except ValueError:
+ env.warn_node('Malformed :option: %r, does not contain option '
+ 'marker - or -- or /' % text, refnode)
+ return None, text
+ else:
+ program = ws_re.sub('-', program)
+ return program, target
+
def process_link(self, env, refnode, has_explicit_title, title, target):
program = env.temp_data.get('std:program')
if not has_explicit_title:
if ' ' in title and not (title.startswith('/') or
title.startswith('-')):
- program, target = re.split(' (?=-|--|/)', title, 1)
- program = ws_re.sub('-', program)
+ program, target = self._split(title, refnode, env)
target = target.strip()
elif ' ' in target:
- program, target = re.split(' (?=-|--|/)', target, 1)
- program = ws_re.sub('-', program)
+ program, target = self._split(target, refnode, env)
refnode['refprogram'] = program
return title, target
@@ -603,6 +620,11 @@ class StandardDomain(Domain):
self.object_types[type].attrs['searchprio'])
for name, info in self.data['labels'].iteritems():
yield (name, info[2], 'label', info[0], info[1], -1)
+ # add anonymous-only labels as well
+ non_anon_labels = set(self.data['labels'])
+ for name, info in self.data['anonlabels'].iteritems():
+ if name not in non_anon_labels:
+ yield (name, name, 'label', info[0], info[1], -1)
def get_type_name(self, type, primary=False):
# never prepend "Default"
diff --git a/sphinx/environment.py b/sphinx/environment.py
index 3c9c830c..a319ef3c 100644
--- a/sphinx/environment.py
+++ b/sphinx/environment.py
@@ -177,9 +177,6 @@ class BuildEnvironment:
# this is to invalidate old pickles
self.version = ENV_VERSION
- # make this a set for faster testing
- self._nitpick_ignore = set(self.config.nitpick_ignore)
-
# All "docnames" here are /-separated and relative and exclude
# the source suffix.
@@ -440,6 +437,9 @@ class BuildEnvironment:
self.find_files(config)
self.config = config
+ # this cache also needs to be updated every time
+ self._nitpick_ignore = set(self.config.nitpick_ignore)
+
added, changed, removed = self.get_outdated_files(config_changed)
# allow user intervention as well
@@ -1385,6 +1385,9 @@ class BuildEnvironment:
dtype = domain and '%s:%s' % (domain.name, typ) or typ
if (dtype, target) in self._nitpick_ignore:
warn = False
+ # for "std" types also try without domain name
+ if domain.name == 'std' and (typ, target) in self._nitpick_ignore:
+ warn = False
if not warn:
return
if domain and typ in domain.dangling_warnings:
@@ -1489,6 +1492,10 @@ class BuildEnvironment:
new = {}
def add_entry(word, subword, link=True, dic=new):
+ # Force the word to be unicode if it's a ASCII bytestring.
+ # This will solve problems with unicode normalization later.
+ # For instance the RFC role will add bytestrings at the moment
+ word = unicode(word)
entry = dic.get(word)
if not entry:
dic[word] = entry = [[], {}]
diff --git a/sphinx/ext/autodoc.py b/sphinx/ext/autodoc.py
index 348c072c..86837ff8 100644
--- a/sphinx/ext/autodoc.py
+++ b/sphinx/ext/autodoc.py
@@ -28,8 +28,8 @@ from sphinx.application import ExtensionError
from sphinx.util.nodes import nested_parse_with_titles
from sphinx.util.compat import Directive
from sphinx.util.inspect import getargspec, isdescriptor, safe_getmembers, \
- safe_getattr, safe_repr
-from sphinx.util.pycompat import base_exception, class_types
+ safe_getattr, safe_repr, is_builtin_class_method
+from sphinx.util.pycompat import class_types
from sphinx.util.docstrings import prepare_docstring
@@ -70,6 +70,35 @@ class Options(dict):
return None
+class _MockModule(object):
+ """Used by autodoc_mock_imports."""
+ def __init__(self, *args, **kwargs):
+ pass
+
+ def __call__(self, *args, **kwargs):
+ return _MockModule()
+
+ @classmethod
+ def __getattr__(cls, name):
+ if name in ('__file__', '__path__'):
+ return '/dev/null'
+ elif name[0] == name[0].upper():
+ # Not very good, we assume Uppercase names are classes...
+ mocktype = type(name, (), {})
+ mocktype.__module__ = __name__
+ return mocktype
+ else:
+ return _MockModule()
+
+def mock_import(modname):
+ if '.' in modname:
+ pkg, _n, mods = modname.rpartition('.')
+ mock_import(pkg)
+ mod = _MockModule()
+ sys.modules[modname] = mod
+ return mod
+
+
ALL = object()
INSTANCEATTR = object()
@@ -332,6 +361,9 @@ class Documenter(object):
self.modname, '.'.join(self.objpath))
try:
dbg('[autodoc] import %s', self.modname)
+ for modname in self.env.config.autodoc_mock_imports:
+ dbg('[autodoc] adding a mock module %s!', self.modname)
+ mock_import(modname)
__import__(self.modname)
parent = None
obj = self.module = sys.modules[self.modname]
@@ -450,9 +482,10 @@ class Documenter(object):
# into lines
if isinstance(docstring, unicode):
return [prepare_docstring(docstring, ignore)]
- elif docstring:
+ elif isinstance(docstring, str): # this will not trigger on Py3
return [prepare_docstring(force_decode(docstring, encoding),
ignore)]
+ # ... else it is something strange, let's ignore it
return []
def process_doc(self, docstrings):
@@ -957,6 +990,10 @@ class FunctionDocumenter(DocstringSignatureMixin, ModuleLevelDocumenter):
try:
argspec = getargspec(self.object)
except TypeError:
+ if (is_builtin_class_method(self.object, '__new__') and
+ is_builtin_class_method(self.object, '__init__')):
+ raise TypeError('%r is a builtin class' % self.object)
+
# if a class should be documented as function (yay duck
# typing) we try to use the constructor signature as function
# signature without the first argument.
@@ -1009,8 +1046,9 @@ class ClassDocumenter(ModuleLevelDocumenter):
initmeth = self.get_attr(self.object, '__init__', None)
# classes without __init__ method, default __init__ or
# __init__ written in C?
- if initmeth is None or initmeth is object.__init__ or not \
- (inspect.ismethod(initmeth) or inspect.isfunction(initmeth)):
+ if initmeth is None or \
+ is_builtin_class_method(self.object, '__init__') or \
+ not(inspect.ismethod(initmeth) or inspect.isfunction(initmeth)):
return None
try:
argspec = getargspec(initmeth)
@@ -1047,7 +1085,7 @@ class ClassDocumenter(ModuleLevelDocumenter):
# add inheritance info, if wanted
if not self.doc_as_attr and self.options.show_inheritance:
self.add_line(u'', '<autodoc>')
- if len(self.object.__bases__):
+ if hasattr(self.object, '__bases__') and len(self.object.__bases__):
bases = [b.__module__ == '__builtin__' and
u':class:`%s`' % b.__name__ or
u':class:`%s.%s`' % (b.__module__, b.__name__)
@@ -1066,10 +1104,21 @@ class ClassDocumenter(ModuleLevelDocumenter):
# for classes, what the "docstring" is can be controlled via a
# config value; the default is only the class docstring
if content in ('both', 'init'):
- initdocstring = self.get_attr(
- self.get_attr(self.object, '__init__', None), '__doc__')
+ # get __init__ method document from __init__.__doc__
+ if self.env.config.autodoc_docstring_signature:
+ # only act if the feature is enabled
+ init_doc = MethodDocumenter(self.directive, '__init__')
+ init_doc.object = self.get_attr(self.object, '__init__', None)
+ init_doc.objpath = ['__init__']
+ init_doc._find_signature() # this effects to get_doc() result
+ initdocstring = '\n'.join(
+ ['\n'.join(l) for l in init_doc.get_doc(encoding)])
+ else:
+ initdocstring = self.get_attr(
+ self.get_attr(self.object, '__init__', None), '__doc__')
# for new-style classes, no __init__ means default __init__
- if initdocstring == object.__init__.__doc__:
+ if (initdocstring == object.__init__.__doc__ or # for pypy
+ initdocstring.strip() == object.__init__.__doc__): #for !pypy
initdocstring = None
if initdocstring:
if content == 'init':
@@ -1113,7 +1162,7 @@ class ExceptionDocumenter(ClassDocumenter):
@classmethod
def can_document_member(cls, member, membername, isattr, parent):
return isinstance(member, class_types) and \
- issubclass(member, base_exception)
+ issubclass(member, BaseException)
class DataDocumenter(ModuleLevelDocumenter):
@@ -1228,7 +1277,8 @@ class AttributeDocumenter(ClassLevelDocumenter):
def can_document_member(cls, member, membername, isattr, parent):
isdatadesc = isdescriptor(member) and not \
isinstance(member, cls.method_types) and not \
- type(member).__name__ in ("type", "method_descriptor")
+ type(member).__name__ in ("type", "method_descriptor",
+ "instancemethod")
return isdatadesc or (not isinstance(parent, ModuleDocumenter)
and not inspect.isroutine(member)
and not isinstance(member, class_types))
@@ -1368,8 +1418,15 @@ class AutoDirective(Directive):
not negated:
self.options[flag] = None
# process the options with the selected documenter's option_spec
- self.genopt = Options(assemble_option_dict(
- self.options.items(), doc_class.option_spec))
+ try:
+ self.genopt = Options(assemble_option_dict(
+ self.options.items(), doc_class.option_spec))
+ except (KeyError, ValueError, TypeError), err:
+ # an option is either unknown or has a wrong type
+ msg = self.reporter.error('An option to %s is either unknown or '
+ 'has an invalid value: %s' % (self.name, err),
+ line=self.lineno)
+ return [msg]
# generate the output
documenter = doc_class(self, self.arguments[0])
documenter.generate(more_content=self.content)
@@ -1428,6 +1485,7 @@ def setup(app):
app.add_config_value('autodoc_member_order', 'alphabetic', True)
app.add_config_value('autodoc_default_flags', [], True)
app.add_config_value('autodoc_docstring_signature', True, True)
+ app.add_config_value('autodoc_mock_imports', [], True)
app.add_event('autodoc-process-docstring')
app.add_event('autodoc-process-signature')
app.add_event('autodoc-skip-member')
diff --git a/sphinx/ext/autosummary/__init__.py b/sphinx/ext/autosummary/__init__.py
index f5c5a884..af0fa65c 100644
--- a/sphinx/ext/autosummary/__init__.py
+++ b/sphinx/ext/autosummary/__init__.py
@@ -199,15 +199,12 @@ class Autosummary(Directive):
nodes = self.get_table(items)
if 'toctree' in self.options:
- suffix = env.config.source_suffix
dirname = posixpath.dirname(env.docname)
tree_prefix = self.options['toctree'].strip()
docnames = []
for name, sig, summary, real_name in items:
docname = posixpath.join(tree_prefix, real_name)
- if docname.endswith(suffix):
- docname = docname[:-len(suffix)]
docname = posixpath.normpath(posixpath.join(dirname, docname))
if docname not in env.found_docs:
self.warn('toctree references unknown document %r'
@@ -278,7 +275,7 @@ class Autosummary(Directive):
while doc and not doc[0].strip():
doc.pop(0)
- m = re.search(r"^([A-Z][^A-Z]*?\.\s)", " ".join(doc).strip())
+ m = re.search(r"^([A-Z].*?\.)(?:\s|$)", " ".join(doc).strip())
if m:
summary = m.group(1).strip()
elif doc:
diff --git a/sphinx/ext/autosummary/generate.py b/sphinx/ext/autosummary/generate.py
index 0640a332..f45aa085 100644
--- a/sphinx/ext/autosummary/generate.py
+++ b/sphinx/ext/autosummary/generate.py
@@ -33,6 +33,21 @@ from sphinx.jinja2glue import BuiltinTemplateLoader
from sphinx.util.osutil import ensuredir
from sphinx.util.inspect import safe_getattr
+# Add documenters to AutoDirective registry
+from sphinx.ext.autodoc import add_documenter, \
+ ModuleDocumenter, ClassDocumenter, ExceptionDocumenter, DataDocumenter, \
+ FunctionDocumenter, MethodDocumenter, AttributeDocumenter, \
+ InstanceAttributeDocumenter
+add_documenter(ModuleDocumenter)
+add_documenter(ClassDocumenter)
+add_documenter(ExceptionDocumenter)
+add_documenter(DataDocumenter)
+add_documenter(FunctionDocumenter)
+add_documenter(MethodDocumenter)
+add_documenter(AttributeDocumenter)
+add_documenter(InstanceAttributeDocumenter)
+
+
def main(argv=sys.argv):
usage = """%prog [OPTIONS] SOURCEFILE ..."""
p = optparse.OptionParser(usage.strip())
@@ -101,7 +116,7 @@ def generate_autosummary_docs(sources, output_dir=None, suffix='.rst',
new_files = []
# write
- for name, path, template_name in sorted(items):
+ for name, path, template_name in sorted(items, key=str):
if path is None:
# The corresponding autosummary:: directive did not have
# a :toctree: option
diff --git a/sphinx/ext/mathbase.py b/sphinx/ext/mathbase.py
index 3955e4bc..0c5eaf8b 100644
--- a/sphinx/ext/mathbase.py
+++ b/sphinx/ext/mathbase.py
@@ -30,11 +30,15 @@ def wrap_displaymath(math, label):
parts = math.split('\n\n')
ret = []
for i, part in enumerate(parts):
+ if not part.strip():
+ continue
if label is not None and i == 0:
ret.append('\\begin{split}%s\\end{split}' % part +
(label and '\\label{'+label+'}' or ''))
else:
ret.append('\\begin{split}%s\\end{split}\\notag' % part)
+ if not ret:
+ return ''
return '\\begin{gather}\n' + '\\\\'.join(ret) + '\n\\end{gather}'
@@ -84,7 +88,7 @@ class MathDirective(Directive):
def latex_visit_math(self, node):
- self.body.append('$' + node['latex'] + '$')
+ self.body.append('\\(' + node['latex'] + '\\)')
raise nodes.SkipNode
def latex_visit_displaymath(self, node):
diff --git a/sphinx/ext/oldcmarkup.py b/sphinx/ext/oldcmarkup.py
deleted file mode 100644
index aa10246b..00000000
--- a/sphinx/ext/oldcmarkup.py
+++ /dev/null
@@ -1,67 +0,0 @@
-# -*- coding: utf-8 -*-
-"""
- sphinx.ext.oldcmarkup
- ~~~~~~~~~~~~~~~~~~~~~
-
- Extension for compatibility with old C markup (directives and roles).
-
- :copyright: Copyright 2007-2013 by the Sphinx team, see AUTHORS.
- :license: BSD, see LICENSE for details.
-"""
-
-from docutils.parsers.rst import directives
-
-from sphinx.util.compat import Directive
-
-_warned_oldcmarkup = False
-WARNING_MSG = 'using old C markup; please migrate to new-style markup ' \
- '(e.g. c:function instead of cfunction), see ' \
- 'http://sphinx-doc.org/domains.html'
-
-
-class OldCDirective(Directive):
- has_content = True
- required_arguments = 1
- optional_arguments = 0
- final_argument_whitespace = True
- option_spec = {
- 'noindex': directives.flag,
- 'module': directives.unchanged,
- }
-
- def run(self):
- env = self.state.document.settings.env
- if not env.app._oldcmarkup_warned:
- self.state_machine.reporter.warning(WARNING_MSG, line=self.lineno)
- env.app._oldcmarkup_warned = True
- newname = 'c:' + self.name[1:]
- newdir = env.lookup_domain_element('directive', newname)[0]
- return newdir(newname, self.arguments, self.options,
- self.content, self.lineno, self.content_offset,
- self.block_text, self.state, self.state_machine).run()
-
-
-def old_crole(typ, rawtext, text, lineno, inliner, options={}, content=[]):
- env = inliner.document.settings.env
- if not typ:
- typ = env.config.default_role
- if not env.app._oldcmarkup_warned:
- inliner.reporter.warning(WARNING_MSG, line=lineno)
- env.app._oldcmarkup_warned = True
- newtyp = 'c:' + typ[1:]
- newrole = env.lookup_domain_element('role', newtyp)[0]
- return newrole(newtyp, rawtext, text, lineno, inliner, options, content)
-
-
-def setup(app):
- app._oldcmarkup_warned = False
- app.add_directive('cfunction', OldCDirective)
- app.add_directive('cmember', OldCDirective)
- app.add_directive('cmacro', OldCDirective)
- app.add_directive('ctype', OldCDirective)
- app.add_directive('cvar', OldCDirective)
- app.add_role('cdata', old_crole)
- app.add_role('cfunc', old_crole)
- app.add_role('cmacro', old_crole)
- app.add_role('ctype', old_crole)
- app.add_role('cmember', old_crole)
diff --git a/sphinx/ext/pngmath.py b/sphinx/ext/pngmath.py
index 3938dab1..e23bbd06 100644
--- a/sphinx/ext/pngmath.py
+++ b/sphinx/ext/pngmath.py
@@ -26,7 +26,7 @@ from docutils import nodes
from sphinx.errors import SphinxError
from sphinx.util.png import read_png_depth, write_png_depth
from sphinx.util.osutil import ensuredir, ENOENT
-from sphinx.util.pycompat import b
+from sphinx.util.pycompat import b, sys_encoding
from sphinx.ext.mathbase import setup_math as mathbase_setup, wrap_displaymath
class MathExtError(SphinxError):
@@ -34,9 +34,9 @@ class MathExtError(SphinxError):
def __init__(self, msg, stderr=None, stdout=None):
if stderr:
- msg += '\n[stderr]\n' + stderr
+ msg += '\n[stderr]\n' + stderr.decode(sys_encoding, 'replace')
if stdout:
- msg += '\n[stdout]\n' + stdout
+ msg += '\n[stdout]\n' + stdout.decode(sys_encoding, 'replace')
SphinxError.__init__(self, msg)
@@ -82,8 +82,10 @@ def render_math(self, math):
may not fail since that indicates a problem in the math source.
"""
use_preview = self.builder.config.pngmath_use_preview
+ latex = DOC_HEAD + self.builder.config.pngmath_latex_preamble
+ latex += (use_preview and DOC_BODY_PREVIEW or DOC_BODY) % math
- shasum = "%s.png" % sha(math.encode('utf-8')).hexdigest()
+ shasum = "%s.png" % sha(latex.encode('utf-8')).hexdigest()
relfn = posixpath.join(self.builder.imgpath, 'math', shasum)
outfn = path.join(self.builder.outdir, '_images', 'math', shasum)
if path.isfile(outfn):
@@ -95,9 +97,6 @@ def render_math(self, math):
hasattr(self.builder, '_mathpng_warned_dvipng'):
return None, None
- latex = DOC_HEAD + self.builder.config.pngmath_latex_preamble
- latex += (use_preview and DOC_BODY_PREVIEW or DOC_BODY) % math
-
# use only one tempdir per build -- the use of a directory is cleaner
# than using temporary files, since we can clean up everything at once
# just removing the whole directory (see cleanup_tempdir)
@@ -192,11 +191,11 @@ def html_visit_math(self, node):
try:
fname, depth = render_math(self, '$'+node['latex']+'$')
except MathExtError, exc:
- msg = unicode(str(exc), 'utf-8', 'replace')
+ msg = unicode(exc)
sm = nodes.system_message(msg, type='WARNING', level=2,
backrefs=[], source=node['latex'])
sm.walkabout(self)
- self.builder.warn('display latex %r: ' % node['latex'] + str(exc))
+ self.builder.warn('display latex %r: ' % node['latex'] + msg)
raise nodes.SkipNode
if fname is None:
# something failed -- use text-only as a bad substitute
diff --git a/sphinx/ext/todo.py b/sphinx/ext/todo.py
index de5d2b9f..253ae07d 100644
--- a/sphinx/ext/todo.py
+++ b/sphinx/ext/todo.py
@@ -171,4 +171,3 @@ def setup(app):
app.connect('doctree-read', process_todos)
app.connect('doctree-resolved', process_todo_nodes)
app.connect('env-purge-doc', purge_todos)
-
diff --git a/sphinx/ext/viewcode.py b/sphinx/ext/viewcode.py
index 962b543b..36fb47d2 100644
--- a/sphinx/ext/viewcode.py
+++ b/sphinx/ext/viewcode.py
@@ -24,17 +24,17 @@ def doctree_read(app, doctree):
def has_tag(modname, fullname, docname):
entry = env._viewcode_modules.get(modname, None)
- if entry is None:
- try:
- analyzer = ModuleAnalyzer.for_module(modname)
- except Exception:
- env._viewcode_modules[modname] = False
- return
+ try:
+ analyzer = ModuleAnalyzer.for_module(modname)
+ except Exception:
+ env._viewcode_modules[modname] = False
+ return
+ if not isinstance(analyzer.code, unicode):
+ code = analyzer.code.decode(analyzer.encoding)
+ else:
+ code = analyzer.code
+ if entry is None or entry[0] != code:
analyzer.find_tags()
- if not isinstance(analyzer.code, unicode):
- code = analyzer.code.decode(analyzer.encoding)
- else:
- code = analyzer.code
entry = code, analyzer.tags, {}
env._viewcode_modules[modname] = entry
elif entry is False:
@@ -142,7 +142,7 @@ def collect_pages(app):
if not modnames:
return
- app.builder.info(' _modules/index')
+ app.builder.info(' _modules/index', nonl=True)
html = ['\n']
# the stack logic is needed for using nested lists for submodules
stack = ['']
diff --git a/sphinx/highlighting.py b/sphinx/highlighting.py
index df422321..c30c9ef3 100644
--- a/sphinx/highlighting.py
+++ b/sphinx/highlighting.py
@@ -63,12 +63,6 @@ _LATEX_STYLES = r'''
\newcommand\PYGZcb{\char`\}}
'''
-parsing_exceptions = (SyntaxError, UnicodeEncodeError)
-if sys.version_info < (2, 5):
- # Python <= 2.4 raises MemoryError when parsing an
- # invalid encoding cookie
- parsing_exceptions += MemoryError,
-
class PygmentsBridge(object):
# Set these attributes if you want to have different Pygments formatters
@@ -131,10 +125,6 @@ class PygmentsBridge(object):
# lines beginning with "..." are probably placeholders for suite
src = re.sub(r"(?m)^(\s*)" + mark + "(.)", r"\1"+ mark + r"# \2", src)
- # if we're using 2.5, use the with statement
- if sys.version_info >= (2, 5):
- src = 'from __future__ import with_statement\n' + src
-
if sys.version_info < (3, 0) and isinstance(src, unicode):
# Non-ASCII chars will only occur in string literals
# and comments. If we wanted to give them to the parser
@@ -143,18 +133,12 @@ class PygmentsBridge(object):
# just replace all non-ASCII characters.
src = src.encode('ascii', 'replace')
- if (3, 0) <= sys.version_info < (3, 2):
- # Python 3.1 can't process '\r' as linesep.
- # `parser.suite("print('hello')\r\n")` cause error.
- if '\r\n' in src:
- src = src.replace('\r\n', '\n')
-
if parser is None:
return True
try:
parser.suite(src)
- except parsing_exceptions:
+ except (SyntaxError, UnicodeEncodeError):
return False
else:
return True
@@ -175,7 +159,7 @@ class PygmentsBridge(object):
if self.try_parse(source):
lexer = lexers['python']
else:
- return self.unhighlighted(source)
+ lexer = lexers['none']
else:
lexer = lexers['python']
elif lang in ('python3', 'py3') and source.startswith('>>>'):
@@ -185,7 +169,7 @@ class PygmentsBridge(object):
try:
lexer = guess_lexer(source)
except Exception:
- return self.unhighlighted(source)
+ lexer = lexers['none']
else:
if lang in lexers:
lexer = lexers[lang]
@@ -195,7 +179,7 @@ class PygmentsBridge(object):
except ClassNotFound:
if warn:
warn('Pygments lexer name %r is not known' % lang)
- return self.unhighlighted(source)
+ lexer = lexers['none']
else:
raise
else:
@@ -207,19 +191,19 @@ class PygmentsBridge(object):
source = doctest.doctestopt_re.sub('', source)
# highlight via Pygments
+ formatter = self.get_formatter(**kwargs)
try:
- formatter = self.get_formatter(**kwargs)
hlsource = highlight(source, lexer, formatter)
- if self.dest == 'html':
- return hlsource
- else:
- if not isinstance(hlsource, unicode): # Py2 / Pygments < 1.6
- hlsource = hlsource.decode()
- return hlsource.translate(tex_hl_escape_map_new)
except ErrorToken:
# this is most probably not the selected language,
# so let it pass unhighlighted
- return self.unhighlighted(source)
+ hlsource = highlight(source, lexers['none'], formatter)
+ if self.dest == 'html':
+ return hlsource
+ else:
+ if not isinstance(hlsource, unicode): # Py2 / Pygments < 1.6
+ hlsource = hlsource.decode()
+ return hlsource.translate(tex_hl_escape_map_new)
def get_stylesheet(self):
if not pygments:
diff --git a/sphinx/jinja2glue.py b/sphinx/jinja2glue.py
index 20d92a32..a298d2ea 100644
--- a/sphinx/jinja2glue.py
+++ b/sphinx/jinja2glue.py
@@ -91,25 +91,29 @@ class BuiltinTemplateLoader(TemplateBridge, BaseLoader):
# create a chain of paths to search
if theme:
# the theme's own dir and its bases' dirs
- chain = theme.get_dirchain()
+ pathchain = theme.get_dirchain()
# then the theme parent paths
- chain.extend(theme.themepath)
+ loaderchain = pathchain + theme.themepath
elif dirs:
- chain = list(dirs)
+ pathchain = list(dirs)
+ loaderchain = list(dirs)
else:
- chain = []
+ pathchain = []
+ loaderchain = []
# prepend explicit template paths
self.templatepathlen = len(builder.config.templates_path)
if builder.config.templates_path:
- chain[0:0] = [path.join(builder.confdir, tp)
- for tp in builder.config.templates_path]
+ cfg_templates_path = [path.join(builder.confdir, tp)
+ for tp in builder.config.templates_path]
+ pathchain[0:0] = cfg_templates_path
+ loaderchain[0:0] = cfg_templates_path
# store it for use in newest_template_mtime
- self.pathchain = chain
+ self.pathchain = pathchain
# make the paths into loaders
- self.loaders = map(SphinxFileSystemLoader, chain)
+ self.loaders = map(SphinxFileSystemLoader, loaderchain)
use_i18n = builder.app.translator is not None
extensions = use_i18n and ['jinja2.ext.i18n'] or []
diff --git a/sphinx/locale/__init__.py b/sphinx/locale/__init__.py
index 96da67d6..06a11a6e 100644
--- a/sphinx/locale/__init__.py
+++ b/sphinx/locale/__init__.py
@@ -215,7 +215,7 @@ def init(locale_dirs, language, catalog='sphinx'):
except Exception:
# Language couldn't be found in the specified path
pass
- # guarantee translations[catalog] exists
+ # guarantee translators[catalog] exists
if translator is None:
translator = gettext.NullTranslations()
has_translation = False
diff --git a/sphinx/locale/cs/LC_MESSAGES/sphinx.mo b/sphinx/locale/cs/LC_MESSAGES/sphinx.mo
index 972f39de..79f22853 100644
--- a/sphinx/locale/cs/LC_MESSAGES/sphinx.mo
+++ b/sphinx/locale/cs/LC_MESSAGES/sphinx.mo
Binary files differ
diff --git a/sphinx/locale/cs/LC_MESSAGES/sphinx.po b/sphinx/locale/cs/LC_MESSAGES/sphinx.po
index 2a4722dc..76b26189 100644
--- a/sphinx/locale/cs/LC_MESSAGES/sphinx.po
+++ b/sphinx/locale/cs/LC_MESSAGES/sphinx.po
@@ -9,8 +9,8 @@ msgstr ""
"Project-Id-Version: Sphinx\n"
"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
"POT-Creation-Date: 2013-04-02 10:33+0200\n"
-"PO-Revision-Date: 2013-04-02 15:12+0000\n"
-"Last-Translator: birkenfeld <g.brandl@gmx.net>\n"
+"PO-Revision-Date: 2013-12-26 13:32+0000\n"
+"Last-Translator: pm13 <petr.marhoun@gmail.com>\n"
"Language-Team: Czech (http://www.transifex.com/projects/p/sphinx-1/language/cs/)\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
@@ -22,21 +22,21 @@ msgstr ""
#: sphinx/config.py:81
#, python-format
msgid "%s %s documentation"
-msgstr ""
+msgstr "Dokumentace pro %s %s"
#: sphinx/environment.py:1510
#, python-format
msgid "see %s"
-msgstr ""
+msgstr "viz %s"
#: sphinx/environment.py:1513
#, python-format
msgid "see also %s"
-msgstr ""
+msgstr "viz také %s"
#: sphinx/environment.py:1570
msgid "Symbols"
-msgstr ""
+msgstr "Symboly"
#: sphinx/roles.py:175
#, python-format
@@ -55,7 +55,7 @@ msgstr "Vestavěné funkce"
#: sphinx/builders/changes.py:75
msgid "Module level"
-msgstr "Úroveň modulů"
+msgstr "Úroveň modulu"
#: sphinx/builders/html.py:290
#, python-format
@@ -64,11 +64,11 @@ msgstr "%d.%m.%Y"
#: sphinx/builders/html.py:309 sphinx/themes/basic/defindex.html:30
msgid "General Index"
-msgstr "Rejstřík indexů"
+msgstr "Obecný rejstřík"
#: sphinx/builders/html.py:309
msgid "index"
-msgstr "index"
+msgstr "rejstřík"
#: sphinx/builders/html.py:369
msgid "next"
@@ -80,7 +80,7 @@ msgstr "předchozí"
#: sphinx/builders/latex.py:141 sphinx/builders/texinfo.py:196
msgid " (in "
-msgstr "(v"
+msgstr " (v "
#: sphinx/directives/other.py:138
msgid "Section author: "
@@ -92,7 +92,7 @@ msgstr "Autor modulu: "
#: sphinx/directives/other.py:142
msgid "Code author: "
-msgstr ""
+msgstr "Autor kódu:"
#: sphinx/directives/other.py:144
msgid "Author: "
@@ -101,7 +101,7 @@ msgstr "Autor: "
#: sphinx/domains/__init__.py:244
#, python-format
msgid "%s %s"
-msgstr ""
+msgstr "%s %s"
#: sphinx/domains/c.py:51 sphinx/domains/cpp.py:939
#: sphinx/domains/python.py:95
@@ -126,7 +126,7 @@ msgstr "%s (C funkce)"
#: sphinx/domains/c.py:143
#, python-format
msgid "%s (C member)"
-msgstr "%s (člen C)"
+msgstr "%s (C člen)"
#: sphinx/domains/c.py:145
#, python-format
@@ -154,7 +154,7 @@ msgstr "člen"
#: sphinx/domains/c.py:205
msgid "macro"
-msgstr ""
+msgstr "makro"
#: sphinx/domains/c.py:206 sphinx/domains/cpp.py:1209
msgid "type"
@@ -162,11 +162,11 @@ msgstr "typ"
#: sphinx/domains/c.py:207
msgid "variable"
-msgstr ""
+msgstr "proměnná"
#: sphinx/domains/cpp.py:942 sphinx/domains/javascript.py:125
msgid "Throws"
-msgstr ""
+msgstr "Vyvolá"
#: sphinx/domains/cpp.py:1038
#, python-format
@@ -181,7 +181,7 @@ msgstr "%s (C++ typ)"
#: sphinx/domains/cpp.py:1081
#, python-format
msgid "%s (C++ member)"
-msgstr "%s (člen C++)"
+msgstr "%s (C++ člen)"
#: sphinx/domains/cpp.py:1137
#, python-format
@@ -211,20 +211,20 @@ msgstr "%s() (třída)"
#: sphinx/domains/javascript.py:111
#, python-format
msgid "%s (global variable or constant)"
-msgstr ""
+msgstr "%s (globální proměnná nebo konstanta)"
#: sphinx/domains/javascript.py:113 sphinx/domains/python.py:355
#, python-format
msgid "%s (%s attribute)"
-msgstr "%s() (atribut %s)"
+msgstr "%s (atribut %s)"
#: sphinx/domains/javascript.py:122
msgid "Arguments"
-msgstr ""
+msgstr "Argumenty"
#: sphinx/domains/javascript.py:166 sphinx/domains/python.py:561
msgid "data"
-msgstr ""
+msgstr "data"
#: sphinx/domains/javascript.py:167 sphinx/domains/python.py:567
msgid "attribute"
@@ -232,7 +232,7 @@ msgstr "atribut"
#: sphinx/domains/python.py:100
msgid "Variables"
-msgstr ""
+msgstr "Proměnné"
#: sphinx/domains/python.py:104
msgid "Raises"
@@ -247,22 +247,22 @@ msgstr "%s() (v modulu %s)"
#: sphinx/domains/python.py:257
#, python-format
msgid "%s (built-in variable)"
-msgstr "%s() (vestavěná proměnná)"
+msgstr "%s (vestavěná proměnná)"
#: sphinx/domains/python.py:258 sphinx/domains/python.py:349
#, python-format
msgid "%s (in module %s)"
-msgstr "%s() (v modulu %s)"
+msgstr "%s (v modulu %s)"
#: sphinx/domains/python.py:274
#, python-format
msgid "%s (built-in class)"
-msgstr "%s () (vestavěná proměnná)"
+msgstr "%s (vestavěná třída)"
#: sphinx/domains/python.py:275
#, python-format
msgid "%s (class in %s)"
-msgstr "%s() (třída v %s)"
+msgstr "%s (třída v %s)"
#: sphinx/domains/python.py:315
#, python-format
@@ -282,26 +282,26 @@ msgstr "%s() (statická metoda %s)"
#: sphinx/domains/python.py:340
#, python-format
msgid "%s() (%s.%s class method)"
-msgstr ""
+msgstr "%s() (třídní metoda %s.%s)"
#: sphinx/domains/python.py:343
#, python-format
msgid "%s() (%s class method)"
-msgstr ""
+msgstr "%s() (třídní metoda %s)"
#: sphinx/domains/python.py:353
#, python-format
msgid "%s (%s.%s attribute)"
-msgstr "%s() (atribut %s.%s)"
+msgstr "%s (atribut %s.%s)"
#: sphinx/domains/python.py:434
#, python-format
msgid "%s (module)"
-msgstr "%s (module)"
+msgstr "%s (modul)"
#: sphinx/domains/python.py:491
msgid "Python Module Index"
-msgstr ""
+msgstr "Rejstřík modulů Pythonu"
#: sphinx/domains/python.py:492
msgid "modules"
@@ -317,11 +317,11 @@ msgstr "výjimka"
#: sphinx/domains/python.py:564
msgid "method"
-msgstr ""
+msgstr "metoda"
#: sphinx/domains/python.py:565
msgid "class method"
-msgstr ""
+msgstr "třídní metoda"
#: sphinx/domains/python.py:566
msgid "static method"
@@ -338,50 +338,50 @@ msgstr " (zastaralé)"
#: sphinx/domains/rst.py:53
#, python-format
msgid "%s (directive)"
-msgstr ""
+msgstr "%s (direktiva)"
#: sphinx/domains/rst.py:55
#, python-format
msgid "%s (role)"
-msgstr ""
+msgstr "%s (role)"
#: sphinx/domains/rst.py:104
msgid "directive"
-msgstr ""
+msgstr "direktiva"
#: sphinx/domains/rst.py:105
msgid "role"
-msgstr ""
+msgstr "role"
#: sphinx/domains/std.py:70 sphinx/domains/std.py:86
#, python-format
msgid "environment variable; %s"
-msgstr "promměná prostředí, %s"
+msgstr "proměnná prostředí; %s"
#: sphinx/domains/std.py:162
#, python-format
msgid "%scommand line option; %s"
-msgstr "%s parametry příkazového řádku; %s"
+msgstr "%svolba příkazového řádku; %s"
#: sphinx/domains/std.py:414
msgid "glossary term"
-msgstr ""
+msgstr "termín v glosáři"
#: sphinx/domains/std.py:415
msgid "grammar token"
-msgstr ""
+msgstr "token gramatiky"
#: sphinx/domains/std.py:416
msgid "reference label"
-msgstr ""
+msgstr "referenční návěstí"
#: sphinx/domains/std.py:418
msgid "environment variable"
-msgstr "promměná prostředí"
+msgstr "proměnná prostředí"
#: sphinx/domains/std.py:419
msgid "program option"
-msgstr ""
+msgstr "volba programu"
#: sphinx/domains/std.py:449 sphinx/themes/basic/genindex-single.html:32
#: sphinx/themes/basic/genindex-single.html:57
@@ -391,11 +391,11 @@ msgstr ""
#: sphinx/themes/basic/genindex.html:68 sphinx/themes/basic/layout.html:134
#: sphinx/writers/latex.py:191 sphinx/writers/texinfo.py:475
msgid "Index"
-msgstr "Index"
+msgstr "Rejstřík"
#: sphinx/domains/std.py:450
msgid "Module Index"
-msgstr "Rejstřík modulů "
+msgstr "Rejstřík modulů"
#: sphinx/domains/std.py:451 sphinx/themes/basic/defindex.html:25
msgid "Search Page"
@@ -404,42 +404,42 @@ msgstr "Vyhledávací stránka"
#: sphinx/ext/autodoc.py:1042
#, python-format
msgid " Bases: %s"
-msgstr ""
+msgstr " Nadtřídy: %s"
#: sphinx/ext/autodoc.py:1078
#, python-format
msgid "alias of :class:`%s`"
-msgstr ""
+msgstr "alias třídy :class:`%s`"
#: sphinx/ext/graphviz.py:294 sphinx/ext/graphviz.py:302
#, python-format
msgid "[graph: %s]"
-msgstr ""
+msgstr "[graf: %s]"
#: sphinx/ext/graphviz.py:296 sphinx/ext/graphviz.py:304
msgid "[graph]"
-msgstr ""
+msgstr "[graf]"
#: sphinx/ext/intersphinx.py:234
#, python-format
msgid "(in %s v%s)"
-msgstr ""
+msgstr "(v %s v%s)"
#: sphinx/ext/linkcode.py:66 sphinx/ext/viewcode.py:70
msgid "[source]"
-msgstr ""
+msgstr "[zdroj]"
#: sphinx/ext/refcounting.py:83
msgid "Return value: Always NULL."
-msgstr ""
+msgstr "Navrácená hodnota: Vždy NULL."
#: sphinx/ext/refcounting.py:85
msgid "Return value: New reference."
-msgstr ""
+msgstr "Navrácená hodnota: Nová reference."
#: sphinx/ext/refcounting.py:87
msgid "Return value: Borrowed reference."
-msgstr ""
+msgstr "Navrácená hodnota: Vypůjčená reference."
#: sphinx/ext/todo.py:42
msgid "Todo"
@@ -448,32 +448,32 @@ msgstr "Todo"
#: sphinx/ext/todo.py:110
#, python-format
msgid "(The <<original entry>> is located in %s, line %d.)"
-msgstr ""
+msgstr "(<<original entry>> se nachází v %s, řádka %d.)"
#: sphinx/ext/todo.py:119
msgid "original entry"
-msgstr ""
+msgstr "původní záznam"
#: sphinx/ext/viewcode.py:117
msgid "[docs]"
-msgstr ""
+msgstr "[dokumentace]"
#: sphinx/ext/viewcode.py:131
msgid "Module code"
-msgstr ""
+msgstr "Kód modulu"
#: sphinx/ext/viewcode.py:137
#, python-format
msgid "<h1>Source code for %s</h1>"
-msgstr ""
+msgstr "<h1>Zdrojový kód pro %s</h1>"
#: sphinx/ext/viewcode.py:164
msgid "Overview: module code"
-msgstr ""
+msgstr "Přehled: kód modulu"
#: sphinx/ext/viewcode.py:165
msgid "<h1>All modules for which code is available</h1>"
-msgstr ""
+msgstr "<h1>Všechny moduly s dostupným kódem</h1>"
#: sphinx/locale/__init__.py:155
msgid "Attention"
@@ -559,15 +559,15 @@ msgstr "Obsah"
#: sphinx/themes/basic/search.html:11 sphinx/themes/basic/search.html:23
#: sphinx/themes/basic/searchresults.html:10
msgid "Search"
-msgstr "Hledání"
+msgstr "Vyhledávání"
#: sphinx/themes/agogo/layout.html:53 sphinx/themes/basic/searchbox.html:15
msgid "Go"
-msgstr "hledej"
+msgstr "OK"
#: sphinx/themes/agogo/layout.html:58 sphinx/themes/basic/searchbox.html:20
msgid "Enter search terms or a module, class or function name."
-msgstr ""
+msgstr "Zadejte hledané termíny nebo jméno modulu, třídy či funkce."
#: sphinx/themes/agogo/layout.html:79 sphinx/themes/basic/sourcelink.html:14
msgid "Show Source"
@@ -579,15 +579,15 @@ msgstr "Přehled"
#: sphinx/themes/basic/defindex.html:15
msgid "Welcome! This is"
-msgstr ""
+msgstr "Vítejte! Toto je"
#: sphinx/themes/basic/defindex.html:16
msgid "the documentation for"
-msgstr ""
+msgstr "dokumentace pro"
#: sphinx/themes/basic/defindex.html:17
msgid "last updated"
-msgstr ""
+msgstr "naposledy aktualizováno"
#: sphinx/themes/basic/defindex.html:20
msgid "Indices and tables:"
@@ -603,7 +603,7 @@ msgstr "seznam všech sekcí a podsekcí"
#: sphinx/themes/basic/defindex.html:26
msgid "search this documentation"
-msgstr "prohledej tuto dokumentaci"
+msgstr "prohledat tuto dokumentaci"
#: sphinx/themes/basic/defindex.html:28
msgid "Global Module Index"
@@ -620,18 +620,18 @@ msgstr "všechny funkce, třídy, termíny"
#: sphinx/themes/basic/genindex-single.html:35
#, python-format
msgid "Index &ndash; %(key)s"
-msgstr "Index &ndash; %(key)s"
+msgstr "Rejstřík &ndash; %(key)s"
#: sphinx/themes/basic/genindex-single.html:63
#: sphinx/themes/basic/genindex-split.html:24
#: sphinx/themes/basic/genindex-split.html:38
#: sphinx/themes/basic/genindex.html:74
msgid "Full index on one page"
-msgstr "Plný index na jedné stránce"
+msgstr "Celý rejstřík na jedné stránce"
#: sphinx/themes/basic/genindex-split.html:16
msgid "Index pages by letter"
-msgstr "Index podle písmene"
+msgstr "Rejstřík podle písmene"
#: sphinx/themes/basic/genindex-split.html:25
msgid "can be huge"
@@ -644,7 +644,7 @@ msgstr "Navigace"
#: sphinx/themes/basic/layout.html:122
#, python-format
msgid "Search within %(docstitle)s"
-msgstr "Hledání uvnitř %(docstitle)s"
+msgstr "Prohledat %(docstitle)s"
#: sphinx/themes/basic/layout.html:131
msgid "About these documents"
@@ -701,7 +701,7 @@ msgstr "další kapitola"
msgid ""
"Please activate JavaScript to enable the search\n"
" functionality."
-msgstr ""
+msgstr "Pro podporu vyhledávání aktivujte JavaScript."
#: sphinx/themes/basic/search.html:32
msgid ""
@@ -709,18 +709,18 @@ msgid ""
" 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 a klikněte na \"hledej\". \nVyhledávání hledá automaticky všechna slova. Nebudou tedy nalezeny stránky, obsahující méně slov."
+msgstr "Toto je vyhledávací stránka. Zadejte klíčová slova a klikněte na \"hledat\". \nVyhledávání automaticky hledá všechna slova, nebudou tedy nalezeny stránky obsahující jen některé z nich."
#: sphinx/themes/basic/search.html:39
#: sphinx/themes/basic/searchresults.html:17
msgid "search"
-msgstr "hledej"
+msgstr "hledat"
#: sphinx/themes/basic/search.html:43
#: sphinx/themes/basic/searchresults.html:21
#: sphinx/themes/basic/static/searchtools.js_t:281
msgid "Search Results"
-msgstr "Výsledky hledání"
+msgstr "Výsledky vyhledávání"
#: sphinx/themes/basic/search.html:45
#: sphinx/themes/basic/searchresults.html:23
@@ -728,7 +728,7 @@ msgstr "Výsledky hledání"
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 ""
+msgstr "Vyhledávání nenalezlo žádný odpovídající dokument. Ujistěte se, že jste všechna slova zapsal/a správně a že jste vybral/a dostatek kategorií."
#: sphinx/themes/basic/searchbox.html:12
msgid "Quick search"
@@ -781,33 +781,33 @@ msgstr "Skrýt výsledky vyhledávání"
#: sphinx/themes/basic/static/searchtools.js_t:119
msgid "Searching"
-msgstr ""
+msgstr "Probíhá vyhledání"
#: sphinx/themes/basic/static/searchtools.js_t:124
msgid "Preparing search..."
-msgstr ""
+msgstr "Vyhledávání se připravuje..."
#: sphinx/themes/basic/static/searchtools.js_t:285
#, python-format
msgid "Search finished, found %s page(s) matching the search query."
-msgstr ""
+msgstr "Vyhledávání dokončeno, stránky odpovídající hledanému výrazu: %s."
#: sphinx/themes/basic/static/searchtools.js_t:337
msgid ", in "
-msgstr ""
+msgstr ", v "
#: sphinx/themes/default/static/sidebar.js_t:83
msgid "Expand sidebar"
-msgstr ""
+msgstr "Rozbalit boční lištu"
#: sphinx/themes/default/static/sidebar.js_t:96
#: sphinx/themes/default/static/sidebar.js_t:124
msgid "Collapse sidebar"
-msgstr ""
+msgstr "Sbalit boční lištu"
#: sphinx/themes/haiku/layout.html:26
msgid "Contents"
-msgstr ""
+msgstr "Obsah"
#: sphinx/writers/latex.py:189
msgid "Release"
@@ -816,20 +816,20 @@ msgstr "Vydání"
#: sphinx/writers/latex.py:620 sphinx/writers/manpage.py:181
#: sphinx/writers/texinfo.py:612
msgid "Footnotes"
-msgstr ""
+msgstr "Poznámky pod čarou"
#: sphinx/writers/latex.py:704
msgid "continued from previous page"
-msgstr ""
+msgstr "pokračujte na předchozí stránce"
#: sphinx/writers/latex.py:710
msgid "Continued on next page"
-msgstr ""
+msgstr "Pokračujte na další stránce"
#: sphinx/writers/manpage.py:226 sphinx/writers/text.py:541
#, python-format
msgid "[image: %s]"
-msgstr ""
+msgstr "[obrázek: %s]"
#: sphinx/writers/manpage.py:227 sphinx/writers/text.py:542
msgid "[image]"
diff --git a/sphinx/locale/ja/LC_MESSAGES/sphinx.mo b/sphinx/locale/ja/LC_MESSAGES/sphinx.mo
index 67e2656f..82b838b0 100644
--- a/sphinx/locale/ja/LC_MESSAGES/sphinx.mo
+++ b/sphinx/locale/ja/LC_MESSAGES/sphinx.mo
Binary files differ
diff --git a/sphinx/locale/ja/LC_MESSAGES/sphinx.po b/sphinx/locale/ja/LC_MESSAGES/sphinx.po
index a6fbb348..7906d68b 100644
--- a/sphinx/locale/ja/LC_MESSAGES/sphinx.po
+++ b/sphinx/locale/ja/LC_MESSAGES/sphinx.po
@@ -3,7 +3,7 @@
# This file is distributed under the same license as the Sphinx project.
#
# Translators:
-# しろう, 2013
+# shirou - しろう, 2013
# Akitoshi Ohta <fire.kuma8@gmail.com>, 2011
# Kouhei Sutou <kou@clear-code.com>, 2011
# Takayuki Shimizukawa <shimizukawa@gmail.com>, 2013
@@ -13,7 +13,7 @@ msgstr ""
"Project-Id-Version: Sphinx\n"
"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
"POT-Creation-Date: 2013-04-02 10:33+0200\n"
-"PO-Revision-Date: 2013-08-05 23:51+0000\n"
+"PO-Revision-Date: 2013-11-20 09:59+0000\n"
"Last-Translator: Takayuki Shimizukawa <shimizukawa@gmail.com>\n"
"Language-Team: Japanese (http://www.transifex.com/projects/p/sphinx-1/language/ja/)\n"
"MIME-Version: 1.0\n"
diff --git a/sphinx/pycode/Grammar.txt b/sphinx/pycode/Grammar-py2.txt
index fcab0b69..98bd1f22 100644
--- a/sphinx/pycode/Grammar.txt
+++ b/sphinx/pycode/Grammar-py2.txt
@@ -1,18 +1,11 @@
-# Grammar for Python. This grammar supports Python 2.x and 3.x.
+# Grammar for Python 2.x
-# 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@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"
+# IMPORTANT: when copying over a new Grammar file, make sure file_input
+# is the first nonterminal in the file!
# 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;
+# file_input is a module or sequence of commands read from an input file;
# 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
@@ -22,28 +15,20 @@ 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)* [',']
+funcdef: 'def' NAME parameters ':' suite
+parameters: '(' [varargslist] ')'
+varargslist: ((fpdef ['=' test] ',')*
+ ('*' NAME [',' '**' NAME] | '**' NAME) |
+ fpdef ['=' test] (',' fpdef ['=' test])* [','])
+fpdef: NAME | '(' fplist ')'
+fplist: fpdef (',' fpdef)* [',']
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_star_expr (augassign (yield_expr|testlist) |
- ('=' (yield_expr|testlist_star_expr))*)
-testlist_star_expr: (test|star_expr) (',' (test|star_expr))* [',']
+expr_stmt: testlist (augassign (yield_expr|testlist) |
+ ('=' (yield_expr|testlist))*)
augassign: ('+=' | '-=' | '*=' | '/=' | '%=' | '&=' | '|=' | '^=' |
'<<=' | '>>=' | '**=' | '//=')
# For normal assignments, additional restrictions enforced by the interpreter
@@ -56,7 +41,7 @@ break_stmt: 'break'
continue_stmt: 'continue'
return_stmt: 'return' [testlist]
yield_stmt: yield_expr
-raise_stmt: 'raise' [test ['from' test | ',' test [',' test]]]
+raise_stmt: 'raise' [test [',' test [',' test]]]
import_stmt: import_name | import_from
import_name: 'import' dotted_as_names
import_from: ('from' ('.'* dotted_name | '.'+)
@@ -66,7 +51,7 @@ 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)*
+global_stmt: 'global' NAME (',' NAME)*
exec_stmt: 'exec' expr ['in' test [',' test]]
assert_stmt: 'assert' test [',' test]
@@ -82,7 +67,7 @@ try_stmt: ('try' ':' suite
with_stmt: 'with' with_item (',' with_item)* ':' suite
with_item: test ['as' expr]
# NB compile.c makes sure that the default except clause is last
-except_clause: 'except' [test [(',' | 'as') test]]
+except_clause: 'except' [test [('as' | ',') test]]
suite: simple_stmt | NEWLINE INDENT stmt+ DEDENT
# Backward compatibility cruft to support:
@@ -100,7 +85,6 @@ 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'
-star_expr: '*' expr
expr: xor_expr ('|' xor_expr)*
xor_expr: and_expr ('^' and_expr)*
and_expr: shift_expr ('&' shift_expr)*
@@ -109,32 +93,38 @@ arith_expr: term (('+'|'-') term)*
term: factor (('*'|'/'|'%'|'//') factor)*
factor: ('+'|'-'|'~') factor | power
power: atom trailer* ['**' factor]
-atom: ('(' [yield_expr|testlist_gexp] ')' |
+atom: ('(' [yield_expr|testlist_comp] ')' |
'[' [listmaker] ']' |
- '{' [dictsetmaker] '}' |
+ '{' [dictorsetmaker] '}' |
'`' testlist1 '`' |
- NAME | NUMBER | STRING+ | '.' '.' '.')
-listmaker: (test|star_expr) ( comp_for | (',' (test|star_expr))* [','] )
-testlist_gexp: (test|star_expr) ( comp_for | (',' (test|star_expr))* [','] )
+ NAME | NUMBER | STRING+)
+listmaker: test ( list_for | (',' test)* [','] )
+testlist_comp: test ( comp_for | (',' test)* [','] )
lambdef: 'lambda' [varargslist] ':' test
trailer: '(' [arglist] ')' | '[' subscriptlist ']' | '.' NAME
subscriptlist: subscript (',' subscript)* [',']
-subscript: test | [test] ':' [test] [sliceop]
+subscript: '.' '.' '.' | test | [test] ':' [test] [sliceop]
sliceop: ':' [test]
-exprlist: (expr|star_expr) (',' (expr|star_expr))* [',']
+exprlist: expr (',' expr)* [',']
testlist: test (',' test)* [',']
-dictsetmaker: ( (test ':' test (comp_for | (',' test ':' test)* [','])) |
- (test (comp_for | (',' test)* [','])) )
+dictorsetmaker: ( (test ':' test (comp_for | (',' test ':' test)* [','])) |
+ (test (comp_for | (',' test)* [','])) )
-classdef: 'class' NAME ['(' [arglist] ')'] ':' suite
+classdef: 'class' NAME ['(' [testlist] ')'] ':' suite
arglist: (argument ',')* (argument [',']
- |'*' test (',' argument)* [',' '**' test]
+ |'*' test (',' argument)* [',' '**' test]
|'**' test)
-argument: test [comp_for] | test '=' test # Really [keyword '='] test
+# The reason that keywords are test nodes instead of NAME is that using NAME
+# results in an ambiguity. ast.c makes sure it's a NAME.
+argument: test [comp_for] | test '=' test
+
+list_iter: list_for | list_if
+list_for: 'for' exprlist 'in' testlist_safe [list_iter]
+list_if: 'if' old_test [list_iter]
comp_iter: comp_for | comp_if
-comp_for: 'for' exprlist 'in' testlist_safe [comp_iter]
+comp_for: 'for' exprlist 'in' or_test [comp_iter]
comp_if: 'if' old_test [comp_iter]
testlist1: test (',' test)*
diff --git a/sphinx/pycode/Grammar-py3.txt b/sphinx/pycode/Grammar-py3.txt
new file mode 100644
index 00000000..083b5f91
--- /dev/null
+++ b/sphinx/pycode/Grammar-py3.txt
@@ -0,0 +1,126 @@
+# Grammar for Python 3.x (with at least x <= 4)
+
+# IMPORTANT: when copying over a new Grammar file, make sure file_input
+# is the first nonterminal in the file!
+
+# Start symbols for the grammar:
+# single_input is a single interactive statement;
+# file_input is a module or sequence of commands read from an input file;
+# eval_input is the input for the eval() 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] (',' tfpdef ['=' test])* [','
+ ['*' [tfpdef] (',' tfpdef ['=' test])* [',' '**' tfpdef] | '**' tfpdef]]
+ | '*' [tfpdef] (',' tfpdef ['=' test])* [',' '**' tfpdef] | '**' tfpdef)
+tfpdef: NAME [':' test]
+varargslist: (vfpdef ['=' test] (',' vfpdef ['=' test])* [','
+ ['*' [vfpdef] (',' vfpdef ['=' test])* [',' '**' vfpdef] | '**' vfpdef]]
+ | '*' [vfpdef] (',' vfpdef ['=' test])* [',' '**' vfpdef] | '**' vfpdef)
+vfpdef: NAME
+
+stmt: simple_stmt | compound_stmt
+simple_stmt: small_stmt (';' small_stmt)* [';'] NEWLINE
+small_stmt: (expr_stmt | del_stmt | pass_stmt | flow_stmt |
+ import_stmt | global_stmt | nonlocal_stmt | assert_stmt)
+expr_stmt: testlist_star_expr (augassign (yield_expr|testlist) |
+ ('=' (yield_expr|testlist_star_expr))*)
+testlist_star_expr: (test|star_expr) (',' (test|star_expr))* [',']
+augassign: ('+=' | '-=' | '*=' | '/=' | '%=' | '&=' | '|=' | '^=' |
+ '<<=' | '>>=' | '**=' | '//=')
+# For normal assignments, additional restrictions enforced by the interpreter
+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]]
+import_stmt: import_name | import_from
+import_name: 'import' dotted_as_names
+# note below: the ('.' | '...') is necessary because '...' is tokenized as ELLIPSIS
+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' NAME (',' NAME)*
+nonlocal_stmt: 'nonlocal' NAME (',' NAME)*
+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' with_item (',' with_item)* ':' suite
+with_item: test ['as' expr]
+# NB compile.c makes sure that the default except clause is last
+except_clause: 'except' [test ['as' NAME]]
+suite: simple_stmt | NEWLINE INDENT stmt+ DEDENT
+
+test: or_test ['if' or_test 'else' test] | lambdef
+test_nocond: or_test | lambdef_nocond
+lambdef: 'lambda' [varargslist] ':' test
+lambdef_nocond: 'lambda' [varargslist] ':' test_nocond
+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)*
+# <> isn't actually a valid comparison operator in Python. It's here for the
+# sake of a __future__ import described in PEP 401
+comp_op: '<'|'>'|'=='|'>='|'<='|'<>'|'!='|'in'|'not' 'in'|'is'|'is' 'not'
+star_expr: '*' expr
+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_comp] ')' |
+ '[' [testlist_comp] ']' |
+ '{' [dictorsetmaker] '}' |
+ NAME | NUMBER | STRING+ | '...' | 'None' | 'True' | 'False')
+testlist_comp: (test|star_expr) ( comp_for | (',' (test|star_expr))* [','] )
+trailer: '(' [arglist] ')' | '[' subscriptlist ']' | '.' NAME
+subscriptlist: subscript (',' subscript)* [',']
+subscript: test | [test] ':' [test] [sliceop]
+sliceop: ':' [test]
+exprlist: (expr|star_expr) (',' (expr|star_expr))* [',']
+testlist: test (',' test)* [',']
+dictorsetmaker: ( (test ':' test (comp_for | (',' test ':' test)* [','])) |
+ (test (comp_for | (',' test)* [','])) )
+
+classdef: 'class' NAME ['(' [arglist] ')'] ':' suite
+
+arglist: (argument ',')* (argument [',']
+ |'*' test (',' argument)* [',' '**' test]
+ |'**' test)
+# The reason that keywords are test nodes instead of NAME is that using NAME
+# results in an ambiguity. ast.c makes sure it's a NAME.
+argument: test [comp_for] | test '=' test # Really [keyword '='] test
+comp_iter: comp_for | comp_if
+comp_for: 'for' exprlist 'in' or_test [comp_iter]
+comp_if: 'if' test_nocond [comp_iter]
+
+# not used in grammar, but may appear in "node" passed from Parser to Compiler
+encoding_decl: NAME
+
+yield_expr: 'yield' [yield_arg]
+yield_arg: 'from' test | testlist
diff --git a/sphinx/pycode/__init__.py b/sphinx/pycode/__init__.py
index 64999df8..54e79da6 100644
--- a/sphinx/pycode/__init__.py
+++ b/sphinx/pycode/__init__.py
@@ -9,6 +9,7 @@
:license: BSD, see LICENSE for details.
"""
+import sys
from os import path
from sphinx import package_dir
@@ -16,12 +17,13 @@ from sphinx.errors import PycodeError
from sphinx.pycode import nodes
from sphinx.pycode.pgen2 import driver, token, tokenize, parse, literals
from sphinx.util import get_module_source, detect_encoding
-from sphinx.util.pycompat import next, StringIO, BytesIO, TextIOWrapper
+from sphinx.util.pycompat import StringIO, BytesIO, TextIOWrapper
from sphinx.util.docstrings import prepare_docstring, prepare_commentdoc
# load the Python grammar
-_grammarfile = path.join(package_dir, 'pycode', 'Grammar.txt')
+_grammarfile = path.join(package_dir, 'pycode',
+ 'Grammar-py%d.txt' % sys.version_info[0])
pygrammar = driver.load_grammar(_grammarfile)
pydriver = driver.Driver(pygrammar, convert=nodes.convert)
diff --git a/sphinx/pycode/pgen2/driver.py b/sphinx/pycode/pgen2/driver.py
index 5e6cf9a5..422671db 100644
--- a/sphinx/pycode/pgen2/driver.py
+++ b/sphinx/pycode/pgen2/driver.py
@@ -18,7 +18,8 @@ __all__ = ["Driver", "load_grammar"]
# Python imports
import os
import logging
-import sys
+
+import sphinx
# Pgen imports
from sphinx.pycode.pgen2 import grammar, parse, token, tokenize, pgen
@@ -120,7 +121,9 @@ def load_grammar(gt="Grammar.txt", gp=None,
head, tail = os.path.splitext(gt)
if tail == ".txt":
tail = ""
- gp = head + tail + ".".join(map(str, sys.version_info[:2])) + ".pickle"
+ # embed Sphinx major version for the case we ever change the grammar...
+ gp = head + tail + "-sphinx" + \
+ ".".join(map(str, sphinx.version_info[:2])) + ".pickle"
if force or not _newer(gp, gt):
logger.info("Generating grammar tables from %s", gt)
g = pgen.generate_grammar(gt)
diff --git a/sphinx/pycode/pgen2/grammar.py b/sphinx/pycode/pgen2/grammar.py
index 5a433578..01d84346 100644
--- a/sphinx/pycode/pgen2/grammar.py
+++ b/sphinx/pycode/pgen2/grammar.py
@@ -162,6 +162,7 @@ opmap_raw = """
// DOUBLESLASH
//= DOUBLESLASHEQUAL
-> RARROW
+... ELLIPSIS
"""
opmap = {}
diff --git a/sphinx/pycode/pgen2/parse.c b/sphinx/pycode/pgen2/parse.c
index e09f5058..96fa6c8b 100644
--- a/sphinx/pycode/pgen2/parse.c
+++ b/sphinx/pycode/pgen2/parse.c
@@ -353,95 +353,6 @@ static void __Pyx_RaiseArgtupleInvalid(const char* func_name, int exact,
static int __Pyx_ParseOptionalKeywords(PyObject *kwds, PyObject **argnames[], PyObject *kwds2, PyObject *values[], Py_ssize_t num_pos_args, const char* function_name); /*proto*/
-#if PY_VERSION_HEX < 0x02050000
-#ifndef PyAnySet_CheckExact
-
-#define PyAnySet_CheckExact(ob) \
- ((ob)->ob_type == &PySet_Type || \
- (ob)->ob_type == &PyFrozenSet_Type)
-
-#define PySet_New(iterable) \
- PyObject_CallFunctionObjArgs((PyObject *)&PySet_Type, (iterable), NULL)
-
-#define Pyx_PyFrozenSet_New(iterable) \
- PyObject_CallFunctionObjArgs((PyObject *)&PyFrozenSet_Type, (iterable), NULL)
-
-#define PySet_Size(anyset) \
- PyObject_Size((anyset))
-
-#define PySet_Contains(anyset, key) \
- PySequence_Contains((anyset), (key))
-
-#define PySet_Pop(set) \
- PyObject_CallMethod(set, (char *)"pop", NULL)
-
-static INLINE int PySet_Clear(PyObject *set) {
- PyObject *ret = PyObject_CallMethod(set, (char *)"clear", NULL);
- if (!ret) return -1;
- Py_DECREF(ret); return 0;
-}
-
-static INLINE int PySet_Discard(PyObject *set, PyObject *key) {
- PyObject *ret = PyObject_CallMethod(set, (char *)"discard", (char *)"O", key);
- if (!ret) return -1;
- Py_DECREF(ret); return 0;
-}
-
-static INLINE int PySet_Add(PyObject *set, PyObject *key) {
- PyObject *ret = PyObject_CallMethod(set, (char *)"add", (char *)"O", key);
- if (!ret) return -1;
- Py_DECREF(ret); return 0;
-}
-
-#endif /* PyAnySet_CheckExact (<= Py2.4) */
-
-#if PY_VERSION_HEX < 0x02040000
-#ifndef Py_SETOBJECT_H
-#define Py_SETOBJECT_H
-
-static PyTypeObject *__Pyx_PySet_Type = NULL;
-static PyTypeObject *__Pyx_PyFrozenSet_Type = NULL;
-
-#define PySet_Type (*__Pyx_PySet_Type)
-#define PyFrozenSet_Type (*__Pyx_PyFrozenSet_Type)
-
-#define PyAnySet_Check(ob) \
- (PyAnySet_CheckExact(ob) || \
- PyType_IsSubtype((ob)->ob_type, &PySet_Type) || \
- PyType_IsSubtype((ob)->ob_type, &PyFrozenSet_Type))
-
-#define PyFrozenSet_CheckExact(ob) ((ob)->ob_type == &PyFrozenSet_Type)
-
-static int __Pyx_Py23SetsImport(void) {
- PyObject *sets=0, *Set=0, *ImmutableSet=0;
-
- sets = PyImport_ImportModule((char *)"sets");
- if (!sets) goto bad;
- Set = PyObject_GetAttrString(sets, (char *)"Set");
- if (!Set) goto bad;
- ImmutableSet = PyObject_GetAttrString(sets, (char *)"ImmutableSet");
- if (!ImmutableSet) goto bad;
- Py_DECREF(sets);
-
- __Pyx_PySet_Type = (PyTypeObject*) Set;
- __Pyx_PyFrozenSet_Type = (PyTypeObject*) ImmutableSet;
-
- return 0;
-
- bad:
- Py_XDECREF(sets);
- Py_XDECREF(Set);
- Py_XDECREF(ImmutableSet);
- return -1;
-}
-
-#else
-static int __Pyx_Py23SetsImport(void) { return 0; }
-#endif /* !Py_SETOBJECT_H */
-#endif /* < Py2.4 */
-#endif /* < Py2.5 */
-
-
static INLINE PyObject *__Pyx_GetItemInt_Generic(PyObject *o, PyObject* j) {
PyObject *r;
if (!j) return NULL;
diff --git a/sphinx/pycode/pgen2/token.py b/sphinx/pycode/pgen2/token.py
index 61468b31..56a40ce7 100755
--- a/sphinx/pycode/pgen2/token.py
+++ b/sphinx/pycode/pgen2/token.py
@@ -62,7 +62,8 @@ COMMENT = 52
NL = 53
RARROW = 54
ERRORTOKEN = 55
-N_TOKENS = 56
+ELLIPSIS = 56
+N_TOKENS = 57
NT_OFFSET = 256
#--end constants--
diff --git a/sphinx/quickstart.py b/sphinx/quickstart.py
index a4dca333..3e32f35b 100644
--- a/sphinx/quickstart.py
+++ b/sphinx/quickstart.py
@@ -11,6 +11,7 @@
import sys, os, time, re
from os import path
+from io import open
TERM_ENCODING = getattr(sys.stdin, 'encoding', None)
@@ -21,7 +22,6 @@ from sphinx.util.osutil import make_filename
from sphinx.util.console import purple, bold, red, turquoise, \
nocolor, color_terminal
from sphinx.util import texescape
-from sphinx.util.pycompat import open
# function to get input from terminal -- overridden by the test suite
try:
@@ -99,7 +99,10 @@ release = '%(release_str)s'
# The language for content autogenerated by Sphinx. Refer to documentation
# for a list of supported languages.
-#language = None
+#
+# This is also used if you do content translation via gettext catalogs.
+# Usually you set "language" from the command line for these cases.
+language = %(language)r
# There are two options for replacing |today|: either, you set today to some
# non-false value, then it is used:
@@ -320,7 +323,7 @@ epub_copyright = u'%(copyright_str)s'
#epub_theme = 'epub'
# The language of the text. It defaults to the language option
-# or en if the language is not set.
+# or 'en' if the language is not set.
#epub_language = ''
# The scheme of the identifier. Typical schemes are ISBN or URL.
@@ -348,7 +351,7 @@ epub_copyright = u'%(copyright_str)s'
#epub_post_files = []
# A list of files that should not be packed into the epub file.
-#epub_exclude_files = []
+epub_exclude_files = ['search.html']
# The depth of the table of contents in toc.ncx.
#epub_tocdepth = 3
@@ -948,6 +951,7 @@ def ask_user(d):
* author: author names
* version: version of project
* release: release of project
+ * language: document language
* suffix: source file suffix
* master: master document name
* epub: use epub (bool)
@@ -986,7 +990,7 @@ Enter the root path for documentation.'''
You have two options for placing the build directory for Sphinx output.
Either, you use a directory "_build" within the root path, or you separate
"source" and "build" directories within the root path.'''
- do_prompt(d, 'sep', 'Separate source and build directories (y/N)', 'n',
+ do_prompt(d, 'sep', 'Separate source and build directories (y/n)', 'n',
boolean)
if 'dot' not in d:
@@ -1014,6 +1018,18 @@ just set both to the same value.'''
if 'release' not in d:
do_prompt(d, 'release', 'Project release', d['version'])
+ if 'language' not in d:
+ print '''
+If the documents are to be written in a language other than English,
+you can select a language here by its language code. Sphinx will then
+translate text that it generates into that language.
+
+For a list of supported codes, see
+http://sphinx-doc.org/config.html#confval-language.'''
+ do_prompt(d, 'language', 'Project language', 'en')
+ if d['language'] == 'en':
+ d['language'] = None
+
if 'suffix' not in d:
print '''
The file name suffix for source files. Commonly, this is either ".txt"
@@ -1042,50 +1058,50 @@ document is a custom template, you can also set this to another filename.'''
if 'epub' not in d:
print '''
Sphinx can also add configuration for epub output:'''
- do_prompt(d, 'epub', 'Do you want to use the epub builder (y/N)',
+ do_prompt(d, 'epub', 'Do you want to use the epub builder (y/n)',
'n', boolean)
if 'ext_autodoc' not in d:
print '''
Please indicate if you want to use one of the following Sphinx extensions:'''
do_prompt(d, 'ext_autodoc', 'autodoc: automatically insert docstrings '
- 'from modules (y/N)', 'n', boolean)
+ 'from modules (y/n)', 'n', boolean)
if 'ext_doctest' not in d:
do_prompt(d, 'ext_doctest', 'doctest: automatically test code snippets '
- 'in doctest blocks (y/N)', 'n', boolean)
+ 'in doctest blocks (y/n)', 'n', boolean)
if 'ext_intersphinx' not in d:
do_prompt(d, 'ext_intersphinx', 'intersphinx: link between Sphinx '
- 'documentation of different projects (y/N)', 'n', boolean)
+ 'documentation of different projects (y/n)', 'n', boolean)
if 'ext_todo' not in d:
do_prompt(d, 'ext_todo', 'todo: write "todo" entries '
- 'that can be shown or hidden on build (y/N)', 'n', boolean)
+ 'that can be shown or hidden on build (y/n)', 'n', boolean)
if 'ext_coverage' not in d:
do_prompt(d, 'ext_coverage', 'coverage: checks for documentation '
- 'coverage (y/N)', 'n', boolean)
+ 'coverage (y/n)', 'n', boolean)
if 'ext_pngmath' not in d:
do_prompt(d, 'ext_pngmath', 'pngmath: include math, rendered '
- 'as PNG images (y/N)', 'n', boolean)
+ 'as PNG images (y/n)', 'n', boolean)
if 'ext_mathjax' not in d:
do_prompt(d, 'ext_mathjax', 'mathjax: include math, rendered in the '
- 'browser by MathJax (y/N)', 'n', boolean)
+ 'browser by MathJax (y/n)', 'n', boolean)
if d['ext_pngmath'] and d['ext_mathjax']:
print '''Note: pngmath and mathjax cannot be enabled at the same time.
pngmath has been deselected.'''
if 'ext_ifconfig' not in d:
do_prompt(d, 'ext_ifconfig', 'ifconfig: conditional inclusion of '
- 'content based on config values (y/N)', 'n', boolean)
+ 'content based on config values (y/n)', 'n', boolean)
if 'ext_viewcode' not in d:
do_prompt(d, 'ext_viewcode', 'viewcode: include links to the source '
- 'code of documented Python objects (y/N)', 'n', boolean)
+ 'code of documented Python objects (y/n)', 'n', boolean)
if 'makefile' not in d:
print '''
A Makefile and a Windows command file can be generated for you so that you
only have to run e.g. `make html' instead of invoking sphinx-build
directly.'''
- do_prompt(d, 'makefile', 'Create Makefile? (Y/n)', 'y', boolean)
+ do_prompt(d, 'makefile', 'Create Makefile? (y/n)', 'y', boolean)
if 'batchfile' not in d:
- do_prompt(d, 'batchfile', 'Create Windows command file? (Y/n)',
+ do_prompt(d, 'batchfile', 'Create Windows command file? (y/n)',
'y', boolean)
print
diff --git a/sphinx/roles.py b/sphinx/roles.py
index 6703b6b8..3b858588 100644
--- a/sphinx/roles.py
+++ b/sphinx/roles.py
@@ -22,15 +22,15 @@ from sphinx.util.nodes import split_explicit_title, process_index_entry, \
generic_docroles = {
- 'command' : nodes.strong,
+ 'command' : addnodes.literal_strong,
'dfn' : nodes.emphasis,
'kbd' : nodes.literal,
'mailheader' : addnodes.literal_emphasis,
- 'makevar' : nodes.strong,
+ 'makevar' : addnodes.literal_strong,
'manpage' : addnodes.literal_emphasis,
'mimetype' : addnodes.literal_emphasis,
'newsgroup' : addnodes.literal_emphasis,
- 'program' : nodes.strong, # XXX should be an x-ref
+ 'program' : addnodes.literal_strong, # XXX should be an x-ref
'regexp' : nodes.literal,
}
diff --git a/sphinx/search/__init__.py b/sphinx/search/__init__.py
index 5f64495b..87377c31 100644
--- a/sphinx/search/__init__.py
+++ b/sphinx/search/__init__.py
@@ -10,10 +10,9 @@
"""
from __future__ import with_statement
import re
-import itertools
import cPickle as pickle
-from docutils.nodes import comment, title, Text, NodeVisitor, SkipNode
+from docutils.nodes import raw, comment, title, Text, NodeVisitor, SkipNode
from sphinx.util import jsdump, rpartition
@@ -146,7 +145,16 @@ class WordCollector(NodeVisitor):
def dispatch_visit(self, node):
if node.__class__ is comment:
raise SkipNode
- elif node.__class__ is Text:
+ if node.__class__ is raw:
+ # Some people might put content in raw HTML that should be searched,
+ # so we just amateurishly strip HTML tags and index the remaining
+ # content
+ nodetext = re.sub(r'(?is)<style.*?</style>', '', node.astext())
+ nodetext = re.sub(r'(?is)<script.*?</script>', '', nodetext)
+ nodetext = re.sub(r'<[^<]+?>', '', nodetext)
+ self.found_words.extend(self.lang.split(nodetext))
+ raise SkipNode
+ if node.__class__ is Text:
self.found_words.extend(self.lang.split(node.astext()))
elif node.__class__ is title:
self.found_title_words.extend(self.lang.split(node.astext()))
@@ -306,8 +314,7 @@ class IndexBuilder(object):
return self._stem_cache[word]
_filter = self.lang.word_filter
- for word in itertools.chain(visitor.found_title_words,
- self.lang.split(title)):
+ for word in visitor.found_title_words:
word = stem(word)
if _filter(word):
self._title_mapping.setdefault(word, set()).add(filename)
diff --git a/sphinx/search/ja.py b/sphinx/search/ja.py
index f0deb154..099f4717 100644
--- a/sphinx/search/ja.py
+++ b/sphinx/search/ja.py
@@ -236,7 +236,7 @@ class TinySegmenter(object):
score += self.ts_(self.TQ4__, p3 + c2 + c3 + c4)
p = u'O'
if score > 0:
- result.append(word)
+ result.append(word.strip())
word = u''
p = u'B'
p1 = p2
@@ -244,7 +244,7 @@ class TinySegmenter(object):
p3 = p
word += seg[i]
- result.append(word)
+ result.append(word.strip())
return result
diff --git a/sphinx/texinputs/Makefile b/sphinx/texinputs/Makefile
index 6b87ad88..5e6030c0 100644
--- a/sphinx/texinputs/Makefile
+++ b/sphinx/texinputs/Makefile
@@ -9,6 +9,10 @@ ARCHIVEPRREFIX =
# Additional LaTeX options
LATEXOPTS =
+LATEX = latex
+PDFLATEX = pdflatex
+MAKEINDEX = makeindex
+
all: $(ALLPDF)
all-pdf: $(ALLPDF)
all-dvi: $(ALLDVI)
@@ -43,20 +47,20 @@ bz2: tar
# The number of LaTeX runs is quite conservative, but I don't expect it
# to get run often, so the little extra time won't hurt.
%.dvi: %.tex
- latex $(LATEXOPTS) '$<'
- latex $(LATEXOPTS) '$<'
- latex $(LATEXOPTS) '$<'
- -makeindex -s python.ist '$(basename $<).idx'
- latex $(LATEXOPTS) '$<'
- latex $(LATEXOPTS) '$<'
+ $(LATEX) $(LATEXOPTS) '$<'
+ $(LATEX) $(LATEXOPTS) '$<'
+ $(LATEX) $(LATEXOPTS) '$<'
+ -$(MAKEINDEX) -s python.ist '$(basename $<).idx'
+ $(LATEX) $(LATEXOPTS) '$<'
+ $(LATEX) $(LATEXOPTS) '$<'
%.pdf: %.tex
- pdflatex $(LATEXOPTS) '$<'
- pdflatex $(LATEXOPTS) '$<'
- pdflatex $(LATEXOPTS) '$<'
- -makeindex -s python.ist '$(basename $<).idx'
- pdflatex $(LATEXOPTS) '$<'
- pdflatex $(LATEXOPTS) '$<'
+ $(PDFLATEX) $(LATEXOPTS) '$<'
+ $(PDFLATEX) $(LATEXOPTS) '$<'
+ $(PDFLATEX) $(LATEXOPTS) '$<'
+ -$(MAKEINDEX) -s python.ist '$(basename $<).idx'
+ $(PDFLATEX) $(LATEXOPTS) '$<'
+ $(PDFLATEX) $(LATEXOPTS) '$<'
clean:
rm -f *.dvi *.log *.ind *.aux *.toc *.syn *.idx *.out *.ilg *.pla
diff --git a/sphinx/texinputs/sphinx.sty b/sphinx/texinputs/sphinx.sty
index 9b083cc6..554845f8 100644
--- a/sphinx/texinputs/sphinx.sty
+++ b/sphinx/texinputs/sphinx.sty
@@ -30,6 +30,8 @@
\RequirePackage{wrapfig}
% Separate paragraphs by space by default.
\RequirePackage{parskip}
+% For parsed-literal blocks.
+\RequirePackage{alltt}
% Redefine these colors to your liking in the preamble.
\definecolor{TitleColor}{rgb}{0.126,0.263,0.361}
@@ -238,9 +240,11 @@
\def\productioncont##1{\\& &\code{##1}}
\parindent=2em
\indent
- \begin{tabular}{lcl}
+ \setlength{\LTpre}{0pt}
+ \setlength{\LTpost}{0pt}
+ \begin{longtable}[l]{lcl}
}{%
- \end{tabular}
+ \end{longtable}
}
% Notices / Admonitions
@@ -508,13 +512,11 @@
}
\fi
-% do not use \@chappos in Appendix in pTeX
+% disable \@chappos in Appendix in pTeX
\ifx\kanjiskip\undefined\else
- \renewcommand{\appendix}{\par
- \setcounter{chapter}{0}
- \setcounter{section}{0}
- \gdef\@chapapp{\appendixname}
- \gdef\@chappos{}
- \gdef\thechapter{\@Alph\c@chapter}
+ \let\py@OldAppendix=\appendix
+ \renewcommand{\appendix}{
+ \py@OldAppendix
+ \gdef\@chappos{}
}
\fi
diff --git a/sphinx/texinputs/sphinxmanual.cls b/sphinx/texinputs/sphinxmanual.cls
index 26df488e..a6b9b392 100644
--- a/sphinx/texinputs/sphinxmanual.cls
+++ b/sphinx/texinputs/sphinxmanual.cls
@@ -97,6 +97,7 @@
%
\let\py@OldTableofcontents=\tableofcontents
\renewcommand{\tableofcontents}{%
+ \pagenumbering{roman}%
\setcounter{page}{1}%
\pagebreak%
\pagestyle{plain}%
@@ -114,7 +115,7 @@
\pagenumbering{arabic}%
\@ifundefined{fancyhf}{}{\pagestyle{normal}}%
}
-\pagenumbering{roman}
+\pagenumbering{alph}
% This is needed to get the width of the section # area wide enough in the
% library reference. Doing it here keeps it the same for all the manuals.
diff --git a/sphinx/texinputs/tabulary.sty b/sphinx/texinputs/tabulary.sty
index ba83c0af..7ea572c1 100644
--- a/sphinx/texinputs/tabulary.sty
+++ b/sphinx/texinputs/tabulary.sty
@@ -8,13 +8,13 @@
%% DRAFT VERSION
%%
%% File `tabulary.dtx'.
-%% Copyright (C) 1995 1996 2003 David Carlisle
+%% Copyright (C) 1995 1996 2003 2008 David Carlisle
%% This file may be distributed under the terms of the LPPL.
%% See 00readme.txt for details.
%%
\NeedsTeXFormat{LaTeX2e}
\ProvidesPackage{tabulary}
- [2007/10/02 v0.9 tabulary package (DPC)]
+ [2008/12/01 v0.9 tabulary package (DPC)]
\RequirePackage{array}
\catcode`\Z=14
\DeclareOption{debugshow}{\catcode`\Z=9\relax}
@@ -109,8 +109,6 @@ Z \string\tymax: \the\tymax^^J}%
\global\advance\TY@linewidth-#1\relax}
\def\endtabulary{%
\gdef\@halignto{}%
- \let\TY@footnote\footnote%
- \def\footnote{}% prevent footnotes from doing anything
\expandafter\TY@tab\the\toks@
\crcr\omit
{\xdef\TY@save@row{}%
@@ -174,7 +172,6 @@ Z \message{> tymin}%
\TY@checkmin
\TY@count\z@
\let\TY@box\TY@box@v
- \let\footnote\TY@footnote % restore footnotes
{\expandafter\TY@final\the\toks@\endTY@final}%
\count@\z@
\@tempswatrue
@@ -195,7 +192,7 @@ Z \message{> tymin}%
\let\TY@checkmin\relax
\ifdim\TY@tablewidth>\z@
\Gscale@div\TY@ratio\TY@linewidth\TY@tablewidth
- \ifdim\TY@tablewidth <\linewidth
+ \ifdim\TY@tablewidth <\TY@linewidth
\def\TY@ratio{1}%
\fi
\else
diff --git a/sphinx/themes/agogo/layout.html b/sphinx/themes/agogo/layout.html
index fde19dbc..f2ddb217 100644
--- a/sphinx/themes/agogo/layout.html
+++ b/sphinx/themes/agogo/layout.html
@@ -11,7 +11,7 @@
{%- extends "basic/layout.html" %}
{% block header %}
- <div class="header-wrapper">
+ <div class="header-wrapper" role="banner">
<div class="header">
{%- if logo %}
<p class="logo"><a href="{{ pathto(master_doc) }}">
@@ -22,7 +22,7 @@
<div class="headertitle"><a
href="{{ pathto(master_doc) }}">{{ shorttitle|e }}</a></div>
{%- endblock %}
- <div class="rel">
+ <div class="rel" role="navigation" aria-label="related navigation">
{%- for rellink in rellinks|reverse %}
<a href="{{ pathto(rellink[0]) }}" title="{{ rellink[1]|striptags|e }}"
{{ accesskey(rellink[2]) }}>{{ rellink[3] }}</a>
@@ -47,16 +47,18 @@
{{ toctree() }}
{%- endblock %}
{%- block sidebarsearch %}
- <h3 style="margin-top: 1.5em;">{{ _('Search') }}</h3>
- <form class="search" action="{{ pathto('search') }}" method="get">
- <input type="text" name="q" />
- <input type="submit" value="{{ _('Go') }}" />
- <input type="hidden" name="check_keywords" value="yes" />
- <input type="hidden" name="area" value="default" />
- </form>
- <p class="searchtip" style="font-size: 90%">
- {{ _('Enter search terms or a module, class or function name.') }}
- </p>
+ <div role="search">
+ <h3 style="margin-top: 1.5em;">{{ _('Search') }}</h3>
+ <form class="search" action="{{ pathto('search') }}" method="get">
+ <input type="text" name="q" />
+ <input type="submit" value="{{ _('Go') }}" />
+ <input type="hidden" name="check_keywords" value="yes" />
+ <input type="hidden" name="area" value="default" />
+ </form>
+ <p class="searchtip" style="font-size: 90%">
+ {{ _('Enter search terms or a module, class or function name.') }}
+ </p>
+ </div>
{%- endblock %}
</div>
<div class="clearer"></div>
@@ -68,16 +70,20 @@
<div class="footer-wrapper">
<div class="footer">
<div class="left">
- {%- for rellink in rellinks|reverse %}
- <a href="{{ pathto(rellink[0]) }}" title="{{ rellink[1]|striptags|e }}"
- {{ accesskey(rellink[2]) }}>{{ rellink[3] }}</a>
- {%- if not loop.last %}{{ reldelim2 }}{% endif %}
- {%- endfor %}
- {%- if show_source and has_source and sourcename %}
- <br/>
- <a href="{{ pathto('_sources/' + sourcename, true)|e }}"
- rel="nofollow">{{ _('Show Source') }}</a>
- {%- endif %}
+ <div role="navigation" aria-label="related navigaton">
+ {%- for rellink in rellinks|reverse %}
+ <a href="{{ pathto(rellink[0]) }}" title="{{ rellink[1]|striptags|e }}"
+ {{ accesskey(rellink[2]) }}>{{ rellink[3] }}</a>
+ {%- if not loop.last %}{{ reldelim2 }}{% endif %}
+ {%- endfor %}
+ </div>
+ <div role="note" aria-label="source link">
+ {%- if show_source and has_source and sourcename %}
+ <br/>
+ <a href="{{ pathto('_sources/' + sourcename, true)|e }}"
+ rel="nofollow">{{ _('Show Source') }}</a>
+ {%- endif %}
+ </div>
</div>
<div class="right">
diff --git a/sphinx/themes/agogo/static/agogo.css_t b/sphinx/themes/agogo/static/agogo.css_t
index 3fb81178..4c7eb378 100644
--- a/sphinx/themes/agogo/static/agogo.css_t
+++ b/sphinx/themes/agogo/static/agogo.css_t
@@ -462,3 +462,10 @@ div.viewcode-block:target {
border-top: 1px solid #ac9;
border-bottom: 1px solid #ac9;
}
+
+div.code-block-filename {
+ background-color: #ddd;
+ color: #333;
+ padding: 2px 5px;
+ font-size: small;
+}
diff --git a/sphinx/themes/basic/layout.html b/sphinx/themes/basic/layout.html
index 9e4e39a1..68a070b3 100644
--- a/sphinx/themes/basic/layout.html
+++ b/sphinx/themes/basic/layout.html
@@ -25,7 +25,7 @@
{%- endif %}
{%- macro relbar() %}
- <div class="related">
+ <div class="related" role="navigation" aria-label="related navigation">
<h3>{{ _('Navigation') }}</h3>
<ul>
{%- for rellink in rellinks %}
@@ -47,7 +47,7 @@
{%- macro sidebar() %}
{%- if render_sidebar %}
- <div class="sphinxsidebar">
+ <div class="sphinxsidebar" role="navigation" aria-label="main navigation">
<div class="sphinxsidebarwrapper">
{%- block sidebarlogo %}
{%- if logo %}
@@ -152,7 +152,7 @@
{%- endblock %}
{%- block extrahead %} {% endblock %}
</head>
- <body>
+ <body role="document">
{%- block header %}{% endblock %}
{%- block relbar1 %}{{ relbar() }}{% endblock %}
@@ -166,7 +166,7 @@
{%- if render_sidebar %}
<div class="bodywrapper">
{%- endif %}
- <div class="body">
+ <div class="body" role="main">
{% block body %} {% endblock %}
</div>
{%- if render_sidebar %}
@@ -183,7 +183,7 @@
{%- block relbar2 %}{{ relbar() }}{% endblock %}
{%- block footer %}
- <div class="footer">
+ <div class="footer" role="contentinfo">
{%- if show_copyright %}
{%- if hasdoc('copyright') %}
{% trans path=pathto('copyright'), copyright=copyright|e %}&copy; <a href="{{ path }}">Copyright</a> {{ copyright }}.{% endtrans %}
diff --git a/sphinx/themes/basic/searchbox.html b/sphinx/themes/basic/searchbox.html
index 609aac83..0a573c32 100644
--- a/sphinx/themes/basic/searchbox.html
+++ b/sphinx/themes/basic/searchbox.html
@@ -8,7 +8,7 @@
:license: BSD, see LICENSE for details.
#}
{%- if pagename != "search" %}
-<div id="searchbox" style="display: none">
+<div id="searchbox" style="display: none" role="search">
<h3>{{ _('Quick search') }}</h3>
<form class="search" action="{{ pathto('search') }}" method="get">
<input type="text" name="q" />
diff --git a/sphinx/themes/basic/sourcelink.html b/sphinx/themes/basic/sourcelink.html
index 08232efc..fbbae064 100644
--- a/sphinx/themes/basic/sourcelink.html
+++ b/sphinx/themes/basic/sourcelink.html
@@ -8,9 +8,11 @@
:license: BSD, see LICENSE for details.
#}
{%- if show_source and has_source and sourcename %}
- <h3>{{ _('This Page') }}</h3>
- <ul class="this-page-menu">
- <li><a href="{{ pathto('_sources/' + sourcename, true)|e }}"
- rel="nofollow">{{ _('Show Source') }}</a></li>
- </ul>
+ <div role="note" aria-label="source link">
+ <h3>{{ _('This Page') }}</h3>
+ <ul class="this-page-menu">
+ <li><a href="{{ pathto('_sources/' + sourcename, true)|e }}"
+ rel="nofollow">{{ _('Show Source') }}</a></li>
+ </ul>
+ </div>
{%- endif %}
diff --git a/sphinx/themes/basic/static/basic.css_t b/sphinx/themes/basic/static/basic.css_t
index 83af2303..a3255ebd 100644
--- a/sphinx/themes/basic/static/basic.css_t
+++ b/sphinx/themes/basic/static/basic.css_t
@@ -89,6 +89,7 @@ div.sphinxsidebar #searchbox input[type="submit"] {
img {
border: 0;
+ max-width: 100%;
}
/* -- search page ----------------------------------------------------------- */
@@ -470,6 +471,20 @@ table.highlighttable td {
padding: 0 0.5em 0 0.5em;
}
+div.code-block-filename {
+ padding: 2px 5px;
+ font-size: small;
+}
+
+div.code-block-filename tt {
+ background-color: transparent;
+}
+
+div.code-block-filename + pre,
+div.code-block-filename + div.highlight > pre {
+ margin-top: 0;
+}
+
tt.descname {
background-color: transparent;
font-weight: bold;
diff --git a/sphinx/themes/basic/static/doctools.js b/sphinx/themes/basic/static/doctools.js
index 8614442e..2036e5f5 100644
--- a/sphinx/themes/basic/static/doctools.js
+++ b/sphinx/themes/basic/static/doctools.js
@@ -168,6 +168,9 @@ var Documentation = {
var terms = (params.highlight) ? params.highlight[0].split(/\s+/) : [];
if (terms.length) {
var body = $('div.body');
+ if (!body.length) {
+ body = $('body');
+ }
window.setTimeout(function() {
$.each(terms, function() {
body.highlightText(this.toLowerCase(), 'highlighted');
diff --git a/sphinx/themes/basic/static/searchtools.js_t b/sphinx/themes/basic/static/searchtools.js_t
index 50b970ff..523ecaaa 100644
--- a/sphinx/themes/basic/static/searchtools.js_t
+++ b/sphinx/themes/basic/static/searchtools.js_t
@@ -150,13 +150,13 @@ var Search = {
objectterms.push(tmp[i].toLowerCase());
}
- if ($u.indexOf(stopwords, tmp[i]) != -1 || tmp[i].match(/^\d+$/) ||
+ if ($u.indexOf(stopwords, tmp[i].toLowerCase()) != -1 || tmp[i].match(/^\d+$/) ||
tmp[i] === "") {
// skip this "word"
continue;
}
// stem the word
- var word = stemmer.stemWord(tmp[i]).toLowerCase();
+ var word = stemmer.stemWord(tmp[i].toLowerCase());
var toAppend;
// select the correct list
if (word[0] == '-') {
diff --git a/sphinx/themes/default/static/default.css_t b/sphinx/themes/default/static/default.css_t
index 5db77108..cdc1b782 100644
--- a/sphinx/themes/default/static/default.css_t
+++ b/sphinx/themes/default/static/default.css_t
@@ -308,3 +308,8 @@ div.viewcode-block:target {
border-top: 1px solid #ac9;
border-bottom: 1px solid #ac9;
}
+
+div.code-block-filename {
+ color: #efefef;
+ background-color: #1c4e63;
+}
diff --git a/sphinx/themes/epub/static/epub.css b/sphinx/themes/epub/static/epub.css
index 5e5f07c1..3f4664f6 100644
--- a/sphinx/themes/epub/static/epub.css
+++ b/sphinx/themes/epub/static/epub.css
@@ -92,6 +92,7 @@ div.sphinxsidebar input {
img {
border: 0;
+ max-width: 100%;
}
/* -- search page ----------------------------------------------------------- */
diff --git a/sphinx/themes/haiku/layout.html b/sphinx/themes/haiku/layout.html
index 337d0ca2..a98d89c6 100644
--- a/sphinx/themes/haiku/layout.html
+++ b/sphinx/themes/haiku/layout.html
@@ -8,8 +8,6 @@
:license: BSD, see LICENSE for details.
#}
{%- extends "basic/layout.html" %}
-{% set script_files = script_files + ['_static/theme_extras.js'] %}
-{% set css_files = css_files + ['_static/print.css'] %}
{# do not display relbars #}
{% block relbar1 %}{% endblock %}
@@ -34,7 +32,7 @@
{% endmacro %}
{% block content %}
- <div class="header">
+ <div class="header" role="banner">
{%- block haikuheader %}
{%- if theme_full_logo != "false" %}
<a href="{{ pathto('index') }}">
@@ -50,7 +48,7 @@
{%- endif %}
{%- endblock %}
</div>
- <div class="topnav">
+ <div class="topnav" role="navigation" aria-label="top navigation">
{{ nav() }}
</div>
<div class="content">
@@ -62,7 +60,7 @@
{%- endif %}#}
{% block body %}{% endblock %}
</div>
- <div class="bottomnav">
+ <div class="bottomnav" role="navigation" aria-label="bottom navigation">
{{ nav() }}
</div>
{% endblock %}
diff --git a/sphinx/themes/nature/static/nature.css_t b/sphinx/themes/nature/static/nature.css_t
index 3c492034..e4f4d2ed 100644
--- a/sphinx/themes/nature/static/nature.css_t
+++ b/sphinx/themes/nature/static/nature.css_t
@@ -243,3 +243,9 @@ div.viewcode-block:target {
border-top: 1px solid #ac9;
border-bottom: 1px solid #ac9;
}
+
+div.code-block-filename {
+ background-color: #ddd;
+ color: #222;
+ border: 1px solid #C6C9CB;
+}
diff --git a/sphinx/themes/pyramid/layout.html b/sphinx/themes/pyramid/layout.html
index 8780ceae..318a3662 100644
--- a/sphinx/themes/pyramid/layout.html
+++ b/sphinx/themes/pyramid/layout.html
@@ -10,7 +10,7 @@
{% block header %}
{%- if logo %}
-<div class="header">
+<div class="header" role="banner">
<div class="logo">
<a href="{{ pathto(master_doc) }}">
<img class="logo" src="{{ pathto('_static/' + logo, 1) }}" alt="Logo"/>
diff --git a/sphinx/themes/pyramid/static/pyramid.css_t b/sphinx/themes/pyramid/static/pyramid.css_t
index c4e94908..c724a493 100644
--- a/sphinx/themes/pyramid/static/pyramid.css_t
+++ b/sphinx/themes/pyramid/static/pyramid.css_t
@@ -340,3 +340,8 @@ tt.xref {
font-weight: normal;
font-style: normal;
}
+
+div.code-block-filename {
+ background-color: #ddd;
+ color: #222;
+}
diff --git a/sphinx/themes/scrolls/layout.html b/sphinx/themes/scrolls/layout.html
index 48e5e4e4..0961808e 100644
--- a/sphinx/themes/scrolls/layout.html
+++ b/sphinx/themes/scrolls/layout.html
@@ -20,7 +20,7 @@
<h1 class="heading"><a href="{{ pathto('index') }}"
title="back to the documentation overview"><span>{{ title|striptags|e }}</span></a></h1>
</div>
- <div class="relnav">
+ <div class="relnav" role="navigation" aria-label="related navigation">
{%- if prev %}
<a href="{{ prev.link|e }}">&laquo; {{ prev.title }}</a> |
{%- endif %}
@@ -31,7 +31,7 @@
</div>
<div id="contentwrapper">
{%- if display_toc %}
- <div id="toc">
+ <div id="toc" role="navigation" aria-label="table of contents navigation">
<h3>{{ _('Table Of Contents') }}</h3>
{{ toc }}
</div>
diff --git a/sphinx/themes/scrolls/static/print.css b/sphinx/themes/scrolls/static/print.css
index fb633d87..715d90ab 100644
--- a/sphinx/themes/scrolls/static/print.css
+++ b/sphinx/themes/scrolls/static/print.css
@@ -1,5 +1,7 @@
-div.header, div.relnav, #toc { display: none; }
-#contentwrapper { padding: 0; margin: 0; border: none; }
-body { color: black; background-color: white; }
-div.footer { border-top: 1px solid #888; color: #888; margin-top: 1cm; }
-div.footer a { text-decoration: none; }
+@media print {
+ div.header, div.relnav, #toc { display: none; }
+ #contentwrapper { padding: 0; margin: 0; border: none; }
+ body { color: black; background-color: white; }
+ div.footer { border-top: 1px solid #888; color: #888; margin-top: 1cm; }
+ div.footer a { text-decoration: none; }
+}
diff --git a/sphinx/themes/sphinxdoc/static/sphinxdoc.css_t b/sphinx/themes/sphinxdoc/static/sphinxdoc.css_t
index af498257..1d7c5796 100644
--- a/sphinx/themes/sphinxdoc/static/sphinxdoc.css_t
+++ b/sphinx/themes/sphinxdoc/static/sphinxdoc.css_t
@@ -337,3 +337,9 @@ div.viewcode-block:target {
border-top: 1px solid #ac9;
border-bottom: 1px solid #ac9;
}
+
+div.code-block-filename {
+ background-color: #ddd;
+ color: #222;
+ border: 1px solid #ccc;
+}
diff --git a/sphinx/themes/traditional/static/traditional.css_t b/sphinx/themes/traditional/static/traditional.css_t
index fff411ef..cbea798c 100644
--- a/sphinx/themes/traditional/static/traditional.css_t
+++ b/sphinx/themes/traditional/static/traditional.css_t
@@ -698,3 +698,7 @@ div.viewcode-block:target {
margin: -1px -10px;
padding: 0 10px;
}
+
+div.code-block-filename {
+ background-color: #cceeff;
+}
diff --git a/sphinx/transforms.py b/sphinx/transforms.py
index 338d4739..35e9d297 100644
--- a/sphinx/transforms.py
+++ b/sphinx/transforms.py
@@ -23,7 +23,6 @@ from sphinx.util import split_index_msg
from sphinx.util.nodes import traverse_translatable_index, extract_messages
from sphinx.util.osutil import ustrftime, find_catalog
from sphinx.util.compat import docutils_version
-from sphinx.util.pycompat import all
from sphinx.domains.std import (
make_term_from_paragraph_node,
make_termnodes_from_paragraph_node,
diff --git a/sphinx/util/docfields.py b/sphinx/util/docfields.py
index 6fd8ba95..150bf3a1 100644
--- a/sphinx/util/docfields.py
+++ b/sphinx/util/docfields.py
@@ -99,7 +99,8 @@ class GroupedField(Field):
return Field.make_field(self, types, domain, items[0])
for fieldarg, content in items:
par = nodes.paragraph()
- par += self.make_xref(self.rolename, domain, fieldarg, nodes.strong)
+ par += self.make_xref(self.rolename, domain, fieldarg,
+ addnodes.literal_strong)
par += nodes.Text(' -- ')
par += content
listnode += nodes.list_item('', par)
@@ -137,7 +138,8 @@ class TypedField(GroupedField):
def make_field(self, types, domain, items):
def handle_item(fieldarg, content):
par = nodes.paragraph()
- par += self.make_xref(self.rolename, domain, fieldarg, nodes.strong)
+ par += self.make_xref(self.rolename, domain, fieldarg,
+ addnodes.literal_strong)
if fieldarg in types:
par += nodes.Text(' (')
# NOTE: using .pop() here to prevent a single type node to be
diff --git a/sphinx/util/inspect.py b/sphinx/util/inspect.py
index 4c337ef9..c7556d05 100644
--- a/sphinx/util/inspect.py
+++ b/sphinx/util/inspect.py
@@ -55,7 +55,7 @@ if sys.version_info >= (3, 0):
raise TypeError('%r is not a Python function' % func)
return inspect.getfullargspec(func)
-elif sys.version_info >= (2, 5):
+else: # 2.6, 2.7
from functools import partial
def getargspec(func):
"""Like inspect.getargspec but supports functools.partial as well."""
@@ -86,12 +86,7 @@ elif sys.version_info >= (2, 5):
del func_defaults[i]
except IndexError:
pass
- if sys.version_info >= (2, 6):
- return inspect.ArgSpec(args, varargs, varkw, func_defaults)
- else:
- return (args, varargs, varkw, func_defaults)
-else:
- getargspec = inspect.getargspec
+ return inspect.ArgSpec(args, varargs, varkw, func_defaults)
def isdescriptor(x):
@@ -137,3 +132,20 @@ def safe_repr(object):
if isinstance(s, bytes):
return force_decode(s, None).replace('\n', ' ')
return s.replace('\n', ' ')
+
+
+def is_builtin_class_method(obj, attr_name):
+ """If attr_name is implemented at builtin class, return True.
+
+ >>> is_builtin_class_method(int, '__init__')
+ True
+
+ Why this function needed? CPython implements int.__init__ by Descriptor
+ but PyPy implements it by pure Python code.
+ """
+ classes = [c for c in inspect.getmro(obj) if attr_name in c.__dict__]
+ cls = classes[0] if classes else object
+
+ if not hasattr(__builtins__, cls.__name__):
+ return False
+ return getattr(__builtins__, cls.__name__) is cls
diff --git a/sphinx/util/jsonimpl.py b/sphinx/util/jsonimpl.py
index aa0ea825..de846b24 100644
--- a/sphinx/util/jsonimpl.py
+++ b/sphinx/util/jsonimpl.py
@@ -10,27 +10,15 @@
"""
import UserString
+import json
-try:
- import json
- # json-py's json module has no JSONEncoder; this will raise AttributeError
- # if json-py is imported instead of the built-in json module
- JSONEncoder = json.JSONEncoder
-except (ImportError, AttributeError):
- try:
- import simplejson as json
- JSONEncoder = json.JSONEncoder
- except ImportError:
- json = None
- JSONEncoder = object
-
-
-class SphinxJSONEncoder(JSONEncoder):
+
+class SphinxJSONEncoder(json.JSONEncoder):
"""JSONEncoder subclass that forces translation proxies."""
def default(self, obj):
if isinstance(obj, UserString.UserString):
return unicode(obj)
- return JSONEncoder.default(self, obj)
+ return json.JSONEncoder.default(self, obj)
def dump(obj, fp, *args, **kwds):
diff --git a/sphinx/util/osutil.py b/sphinx/util/osutil.py
index 87717771..a5c461a6 100644
--- a/sphinx/util/osutil.py
+++ b/sphinx/util/osutil.py
@@ -69,6 +69,9 @@ def ensuredir(path):
raise
+# This function is same as os.walk of Python2.6, 2.7, 3.2, 3.3 except a
+# customization that check UnicodeError.
+# The customization obstacle to replace the function with the os.walk.
def walk(top, topdown=True, followlinks=False):
"""Backport of os.walk from 2.6, where the *followlinks* argument was
added.
@@ -155,9 +158,8 @@ else:
def safe_relpath(path, start=None):
- from sphinx.util.pycompat import relpath
try:
- return relpath(path, start)
+ return os.path.relpath(path, start)
except ValueError:
return path
@@ -171,14 +173,13 @@ def find_catalog(docname, compaction):
def find_catalog_files(docname, srcdir, locale_dirs, lang, compaction):
- from sphinx.util.pycompat import relpath
if not(lang and locale_dirs):
return []
domain = find_catalog(docname, compaction)
files = [gettext.find(domain, path.join(srcdir, dir_), [lang])
for dir_ in locale_dirs]
- files = [relpath(f, srcdir) for f in files if f]
+ files = [path.relpath(f, srcdir) for f in files if f]
return files
diff --git a/sphinx/util/pycompat.py b/sphinx/util/pycompat.py
index 3d252c91..9941dc0c 100644
--- a/sphinx/util/pycompat.py
+++ b/sphinx/util/pycompat.py
@@ -11,7 +11,6 @@
import sys
import codecs
-import encodings
# ------------------------------------------------------------------------------
# Python 2/3 compatibility
@@ -30,6 +29,9 @@ if sys.version_info >= (3, 0):
# safely encode a string for printing to the terminal
def terminal_safe(s):
return s.encode('ascii', 'backslashreplace').decode('ascii')
+ # some kind of default system encoding; should be used with a lenient
+ # error handler
+ sys_encoding = sys.getdefaultencoding()
# support for running 2to3 over config files
def convert_with_2to3(filepath):
from lib2to3.refactor import RefactoringTool, get_fixers_from_package
@@ -45,6 +47,7 @@ if sys.version_info >= (3, 0):
# try to match ParseError details with SyntaxError details
raise SyntaxError(err.msg, (filepath, lineno, offset, err.value))
return unicode(tree)
+ from itertools import zip_longest # Python 3 name
else:
# Python 2
@@ -62,6 +65,12 @@ else:
# safely encode a string for printing to the terminal
def terminal_safe(s):
return s.encode('ascii', 'backslashreplace')
+ # some kind of default system encoding; should be used with a lenient
+ # error handler
+ import locale
+ sys_encoding = locale.getpreferredencoding()
+ # use Python 3 name
+ from itertools import izip_longest as zip_longest
def execfile_(filepath, _globals):
@@ -74,8 +83,8 @@ def execfile_(filepath, _globals):
finally:
f.close()
- # py25,py26,py31 accept only LF eol instead of CRLF
- if sys.version_info[:2] in ((2, 5), (2, 6), (3, 1)):
+ # py26 accept only LF eol instead of CRLF
+ if sys.version_info[:2] == (2, 6):
source = source.replace(b('\r\n'), b('\n'))
# compile to a code object, handle syntax errors
@@ -93,178 +102,7 @@ def execfile_(filepath, _globals):
exec code in _globals
-try:
- from html import escape as htmlescape
-except ImportError:
+if sys.version_info >= (3, 2):
+ from html import escape as htmlescape # >= Python 3.2
+else: # 2.6, 2.7, 3.1
from cgi import escape as htmlescape
-
-# ------------------------------------------------------------------------------
-# Missing builtins and itertools in Python < 2.6
-
-if sys.version_info >= (2, 6):
- # Python >= 2.6
- next = next
-
- from itertools import product
- try:
- from itertools import zip_longest # Python 3 name
- except ImportError:
- from itertools import izip_longest as zip_longest
-
- import os
- relpath = os.path.relpath
- del os
-
- import io
- open = io.open
-
-else:
- # Python < 2.6
- from itertools import izip, repeat, chain
-
- # this is on Python 2, where the method is called "next" (it is refactored
- # to __next__ by 2to3, but in that case never executed)
- def next(iterator):
- return iterator.next()
-
- # These replacement functions have been taken from the Python 2.6
- # itertools documentation.
- def product(*args, **kwargs):
- pools = map(tuple, args) * kwargs.get('repeat', 1)
- result = [[]]
- for pool in pools:
- result = [x + [y] for x in result for y in pool]
- for prod in result:
- yield tuple(prod)
-
- def zip_longest(*args, **kwds):
- # zip_longest('ABCD', 'xy', fillvalue='-') --> Ax By C- D-
- fillvalue = kwds.get('fillvalue')
- def sentinel(counter = ([fillvalue]*(len(args)-1)).pop):
- yield counter() # yields the fillvalue, or raises IndexError
- fillers = repeat(fillvalue)
- iters = [chain(it, sentinel(), fillers) for it in args]
- try:
- for tup in izip(*iters):
- yield tup
- except IndexError:
- pass
-
- from os.path import curdir
- def relpath(path, start=curdir):
- """Return a relative version of a path"""
- from os.path import sep, abspath, commonprefix, join, pardir
-
- if not path:
- raise ValueError("no path specified")
-
- start_list = abspath(start).split(sep)
- path_list = abspath(path).split(sep)
-
- # Work out how much of the filepath is shared by start and path.
- i = len(commonprefix([start_list, path_list]))
-
- rel_list = [pardir] * (len(start_list)-i) + path_list[i:]
- if not rel_list:
- return start
- return join(*rel_list)
- del curdir
-
- from types import MethodType
- def open(filename, mode='r', *args, **kw):
- newline = kw.pop('newline', None)
- mode = mode.replace('t', '')
- f = codecs.open(filename, mode, *args, **kw)
- if newline is not None:
- f._write = f.write
- def write(self, text):
- text = text.replace(u'\r\n', u'\n').replace(u'\n', newline)
- self._write(text)
- f.write = MethodType(write, f)
- return f
-
-
-# ------------------------------------------------------------------------------
-# Missing builtins and codecs in Python < 2.5
-
-if sys.version_info >= (2, 5):
- # Python >= 2.5
- base_exception = BaseException
- any = any
- all = all
-
-else:
- # Python 2.4
- base_exception = Exception
-
- def all(gen):
- for i in gen:
- if not i:
- return False
- return True
-
- def any(gen):
- for i in gen:
- if i:
- return True
- return False
-
- # Python 2.4 doesn't know the utf-8-sig encoding, so deliver it here
-
- def my_search_function(encoding):
- norm_encoding = encodings.normalize_encoding(encoding)
- if norm_encoding != 'utf_8_sig':
- return None
- return (encode, decode, StreamReader, StreamWriter)
-
- codecs.register(my_search_function)
-
- # begin code copied from utf_8_sig.py in Python 2.6
-
- def encode(input, errors='strict'):
- return (codecs.BOM_UTF8 +
- codecs.utf_8_encode(input, errors)[0], len(input))
-
- def decode(input, errors='strict'):
- prefix = 0
- if input[:3] == codecs.BOM_UTF8:
- input = input[3:]
- prefix = 3
- (output, consumed) = codecs.utf_8_decode(input, errors, True)
- return (output, consumed+prefix)
-
- class StreamWriter(codecs.StreamWriter):
- def reset(self):
- codecs.StreamWriter.reset(self)
- try:
- del self.encode
- except AttributeError:
- pass
-
- def encode(self, input, errors='strict'):
- self.encode = codecs.utf_8_encode
- return encode(input, errors)
-
- class StreamReader(codecs.StreamReader):
- def reset(self):
- codecs.StreamReader.reset(self)
- try:
- del self.decode
- except AttributeError:
- pass
-
- def decode(self, input, errors='strict'):
- if len(input) < 3:
- if codecs.BOM_UTF8.startswith(input):
- # not enough data to decide if this is a BOM
- # => try again on the next call
- return (u"", 0)
- elif input[:3] == codecs.BOM_UTF8:
- self.decode = codecs.utf_8_decode
- (output, consumed) = codecs.utf_8_decode(input[3:],errors)
- return (output, consumed+3)
- # (else) no BOM present
- self.decode = codecs.utf_8_decode
- return codecs.utf_8_decode(input, errors)
-
- # end code copied from utf_8_sig.py
diff --git a/sphinx/versioning.py b/sphinx/versioning.py
index a16751bb..ccab41d4 100644
--- a/sphinx/versioning.py
+++ b/sphinx/versioning.py
@@ -11,8 +11,9 @@
"""
from uuid import uuid4
from operator import itemgetter
+from itertools import product
-from sphinx.util.pycompat import product, zip_longest, all
+from sphinx.util.pycompat import zip_longest
# anything below that ratio is considered equal/changed
diff --git a/sphinx/writers/html.py b/sphinx/writers/html.py
index 1abe7b3a..61b905f6 100644
--- a/sphinx/writers/html.py
+++ b/sphinx/writers/html.py
@@ -131,24 +131,40 @@ class HTMLTranslator(BaseTranslator):
def visit_desc_parameterlist(self, node):
self.body.append('<big>(</big>')
self.first_param = 1
+ self.optional_param_level = 0
+ # How many required parameters are left.
+ self.required_params_left = sum([isinstance(c, addnodes.desc_parameter)
+ for c in node.children])
self.param_separator = node.child_text_separator
def depart_desc_parameterlist(self, node):
self.body.append('<big>)</big>')
+ # If required parameters are still to come, then put the comma after
+ # the parameter. Otherwise, put the comma before. This ensures that
+ # signatures like the following render correctly (see issue #1001):
+ #
+ # foo([a, ]b, c[, d])
+ #
def visit_desc_parameter(self, node):
- if not self.first_param:
- self.body.append(self.param_separator)
- else:
+ if self.first_param:
self.first_param = 0
+ elif not self.required_params_left:
+ self.body.append(self.param_separator)
+ if self.optional_param_level == 0:
+ self.required_params_left -= 1
if not node.hasattr('noemph'):
self.body.append('<em>')
def depart_desc_parameter(self, node):
if not node.hasattr('noemph'):
self.body.append('</em>')
+ if self.required_params_left:
+ self.body.append(self.param_separator)
def visit_desc_optional(self, node):
+ self.optional_param_level += 1
self.body.append('<span class="optional">[</span>')
def depart_desc_optional(self, node):
+ self.optional_param_level -= 1
self.body.append('<span class="optional">]</span>')
def visit_desc_annotation(self, node):
@@ -251,6 +267,9 @@ class HTMLTranslator(BaseTranslator):
**highlight_args)
starttag = self.starttag(node, 'div', suffix='',
CLASS='highlight-%s' % lang)
+ if node.has_key('filename'):
+ starttag += '<div class="code-block-filename"><tt>%s</tt></div>' % (
+ node['filename'],)
self.body.append(starttag + highlighted + '</div>\n')
raise nodes.SkipNode
@@ -492,6 +511,11 @@ class HTMLTranslator(BaseTranslator):
def depart_literal_emphasis(self, node):
return self.depart_emphasis(node)
+ def visit_literal_strong(self, node):
+ return self.visit_strong(node)
+ def depart_literal_strong(self, node):
+ return self.depart_strong(node)
+
def visit_abbreviation(self, node):
attrs = {}
if node.hasattr('explanation'):
@@ -551,6 +575,13 @@ class HTMLTranslator(BaseTranslator):
node['classes'].append('field-odd')
self.body.append(self.starttag(node, 'tr', '', CLASS='field'))
+ def visit_math(self, node, math_env=''):
+ self.builder.warn('using "math" markup without a Sphinx math extension '
+ 'active, please use one of the math extensions '
+ 'described at http://sphinx-doc.org/ext/math.html',
+ (self.builder.current_docname, node.line))
+ raise nodes.SkipNode
+
def unknown_visit(self, node):
raise NotImplementedError('Unknown node: ' + node.__class__.__name__)
@@ -595,6 +626,14 @@ class SmartyPantsHTMLTranslator(HTMLTranslator):
self.depart_emphasis(node)
self.no_smarty -= 1
+ def visit_literal_strong(self, node):
+ self.no_smarty += 1
+ self.visit_strong(node)
+
+ def depart_literal_strong(self, node):
+ self.depart_strong(node)
+ self.no_smarty -= 1
+
def visit_desc_signature(self, node):
self.no_smarty += 1
HTMLTranslator.visit_desc_signature(self, node)
diff --git a/sphinx/writers/latex.py b/sphinx/writers/latex.py
index 80080752..61aa5828 100644
--- a/sphinx/writers/latex.py
+++ b/sphinx/writers/latex.py
@@ -25,7 +25,6 @@ from sphinx.errors import SphinxError
from sphinx.locale import admonitionlabels, _
from sphinx.util import split_into
from sphinx.util.osutil import ustrftime
-from sphinx.util.pycompat import any
from sphinx.util.texescape import tex_escape_map, tex_replace_map
from sphinx.util.smartypants import educate_quotes_latex
@@ -264,7 +263,6 @@ class LaTeXTranslator(nodes.NodeVisitor):
self.next_figure_ids = set()
self.next_table_ids = set()
# flags
- self.verbatim = None
self.in_title = 0
self.in_production_list = 0
self.in_footnote = 0
@@ -1248,6 +1246,13 @@ class LaTeXTranslator(nodes.NodeVisitor):
def depart_strong(self, node):
self.body.append('}')
+ def visit_literal_strong(self, node):
+ self.body.append(r'\textbf{\texttt{')
+ self.no_contractions += 1
+ def depart_literal_strong(self, node):
+ self.body.append('}}')
+ self.no_contractions -= 1
+
def visit_abbreviation(self, node):
abbr = node.astext()
self.body.append(r'\textsc{')
@@ -1318,36 +1323,45 @@ class LaTeXTranslator(nodes.NodeVisitor):
raise UnsupportedError('%s:%s: literal blocks in footnotes are '
'not supported by LaTeX' %
(self.curfilestack[-1], node.line))
- self.verbatim = ''
+ if node.rawsource != node.astext():
+ # most probably a parsed-literal block -- don't highlight
+ self.body.append('\\begin{alltt}\n')
+ else:
+ code = node.astext().rstrip('\n')
+ lang = self.hlsettingstack[-1][0]
+ linenos = code.count('\n') >= self.hlsettingstack[-1][1] - 1
+ highlight_args = node.get('highlight_args', {})
+ if 'language' in node:
+ # code-block directives
+ lang = node['language']
+ highlight_args['force'] = True
+ if 'linenos' in node:
+ linenos = node['linenos']
+ filename = node.get('filename')
+ if filename:
+ self.body.append('\n{\\colorbox[rgb]{0.9,0.9,0.9}'
+ '{\\makebox[\\textwidth][l]'
+ '{\\small\\texttt{%s}}}}\n' % (filename,))
+ def warner(msg):
+ self.builder.warn(msg, (self.curfilestack[-1], node.line))
+ hlcode = self.highlighter.highlight_block(code, lang, warn=warner,
+ linenos=linenos, **highlight_args)
+ # 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_problematic = True
+ 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 ''))
+ raise nodes.SkipNode
def depart_literal_block(self, node):
- code = self.verbatim.rstrip('\n')
- lang = self.hlsettingstack[-1][0]
- linenos = code.count('\n') >= self.hlsettingstack[-1][1] - 1
- highlight_args = node.get('highlight_args', {})
- if 'language' in node:
- # code-block directives
- lang = node['language']
- highlight_args['force'] = True
- if 'linenos' in node:
- linenos = node['linenos']
- def warner(msg):
- self.builder.warn(msg, (self.curfilestack[-1], node.line))
- hlcode = self.highlighter.highlight_block(code, lang, warn=warner,
- linenos=linenos, **highlight_args)
- # 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_problematic = True
- 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
+ self.body.append('\n\\end{alltt}\n')
visit_doctest_block = visit_literal_block
depart_doctest_block = depart_literal_block
@@ -1510,13 +1524,10 @@ class LaTeXTranslator(nodes.NodeVisitor):
return self.encode(text).replace('\\textasciitilde{}', '~')
def visit_Text(self, node):
- if self.verbatim is not None:
- self.verbatim += node.astext()
- else:
- text = self.encode(node.astext())
- if not self.no_contractions:
- text = educate_quotes_latex(text)
- self.body.append(text)
+ text = self.encode(node.astext())
+ if not self.no_contractions:
+ text = educate_quotes_latex(text)
+ self.body.append(text)
def depart_Text(self, node):
pass
@@ -1532,5 +1543,14 @@ class LaTeXTranslator(nodes.NodeVisitor):
def depart_system_message(self, node):
self.body.append('\n')
+ def visit_math(self, node):
+ self.builder.warn('using "math" markup without a Sphinx math extension '
+ 'active, please use one of the math extensions '
+ 'described at http://sphinx-doc.org/ext/math.html',
+ (self.curfilestack[-1], node.line))
+ raise nodes.SkipNode
+
+ visit_math_block = visit_math
+
def unknown_visit(self, node):
raise NotImplementedError('Unknown node: ' + node.__class__.__name__)
diff --git a/sphinx/writers/manpage.py b/sphinx/writers/manpage.py
index f652e918..0aa0058c 100644
--- a/sphinx/writers/manpage.py
+++ b/sphinx/writers/manpage.py
@@ -304,6 +304,11 @@ class ManualPageTranslator(BaseTranslator):
def depart_literal_emphasis(self, node):
return self.depart_emphasis(node)
+ def visit_literal_strong(self, node):
+ return self.visit_strong(node)
+ def depart_literal_strong(self, node):
+ return self.depart_strong(node)
+
def visit_abbreviation(self, node):
pass
def depart_abbreviation(self, node):
@@ -342,5 +347,13 @@ class ManualPageTranslator(BaseTranslator):
def depart_inline(self, node):
pass
+ def visit_math(self, node):
+ self.builder.warn('using "math" markup without a Sphinx math extension '
+ 'active, please use one of the math extensions '
+ 'described at http://sphinx-doc.org/ext/math.html')
+ raise nodes.SkipNode
+
+ visit_math_block = visit_math
+
def unknown_visit(self, node):
raise NotImplementedError('Unknown node: ' + node.__class__.__name__)
diff --git a/sphinx/writers/texinfo.py b/sphinx/writers/texinfo.py
index 66a0e039..a930a525 100644
--- a/sphinx/writers/texinfo.py
+++ b/sphinx/writers/texinfo.py
@@ -1207,6 +1207,11 @@ class TexinfoTranslator(nodes.NodeVisitor):
def depart_literal_emphasis(self, node):
self.body.append('}')
+ def visit_literal_strong(self, node):
+ self.body.append('@code{')
+ def depart_literal_strong(self, node):
+ self.body.append('}')
+
def visit_index(self, node):
# terminate the line but don't prevent paragraph breaks
if isinstance(node.parent, nodes.paragraph):
@@ -1393,3 +1398,11 @@ class TexinfoTranslator(nodes.NodeVisitor):
pass
def depart_pending_xref(self, node):
pass
+
+ def visit_math(self, node):
+ self.builder.warn('using "math" markup without a Sphinx math extension '
+ 'active, please use one of the math extensions '
+ 'described at http://sphinx-doc.org/ext/math.html')
+ raise nodes.SkipNode
+
+ visit_math_block = visit_math
diff --git a/sphinx/writers/text.py b/sphinx/writers/text.py
index 3bf7588a..a174bc26 100644
--- a/sphinx/writers/text.py
+++ b/sphinx/writers/text.py
@@ -152,6 +152,7 @@ class TextTranslator(nodes.NodeVisitor):
def __init__(self, document, builder):
nodes.NodeVisitor.__init__(self, document)
+ self.builder = builder
newlines = builder.config.text_newlines
if newlines == 'windows':
@@ -761,6 +762,11 @@ class TextTranslator(nodes.NodeVisitor):
def depart_strong(self, node):
self.add_text('**')
+ def visit_literal_strong(self, node):
+ self.add_text('**')
+ def depart_literal_strong(self, node):
+ self.add_text('**')
+
def visit_abbreviation(self, node):
self.add_text('')
def depart_abbreviation(self, node):
@@ -838,5 +844,14 @@ class TextTranslator(nodes.NodeVisitor):
self.body.append(node.astext())
raise nodes.SkipNode
+ def visit_math(self, node):
+ self.builder.warn('using "math" markup without a Sphinx math extension '
+ 'active, please use one of the math extensions '
+ 'described at http://sphinx-doc.org/ext/math.html',
+ (self.builder.current_docname, node.line))
+ raise nodes.SkipNode
+
+ visit_math_block = visit_math
+
def unknown_visit(self, node):
raise NotImplementedError('Unknown node: ' + node.__class__.__name__)
diff --git a/tests/root/autodoc.txt b/tests/root/autodoc.txt
index d4b3404c..aa0dffba 100644
--- a/tests/root/autodoc.txt
+++ b/tests/root/autodoc.txt
@@ -45,3 +45,5 @@ Just testing a few autodoc possibilities...
:members: ca1, ia1
Specific members (2 total)
+
+.. automodule:: autodoc_missing_imports
diff --git a/tests/root/autodoc_missing_imports.py b/tests/root/autodoc_missing_imports.py
new file mode 100644
index 00000000..7a717345
--- /dev/null
+++ b/tests/root/autodoc_missing_imports.py
@@ -0,0 +1,9 @@
+
+import missing_module
+from missing_module import missing_name
+import missing_package1.missing_module1
+from missing_package2 import missing_module2
+from missing_package3.missing_module3 import missing_name
+
+class TestAutodoc(object):
+ """TestAutodoc docstring."""
diff --git a/tests/root/conf.py b/tests/root/conf.py
index 8025ba33..cf88c2bb 100644
--- a/tests/root/conf.py
+++ b/tests/root/conf.py
@@ -8,7 +8,7 @@ sys.path.append(os.path.abspath('..'))
extensions = ['sphinx.ext.autodoc', 'sphinx.ext.jsmath', 'sphinx.ext.todo',
'sphinx.ext.coverage', 'sphinx.ext.autosummary',
'sphinx.ext.doctest', 'sphinx.ext.extlinks',
- 'sphinx.ext.viewcode', 'sphinx.ext.oldcmarkup', 'ext']
+ 'sphinx.ext.viewcode', 'ext']
jsmath_path = 'dummy.js'
@@ -71,6 +71,13 @@ autosummary_generate = ['autosummary']
extlinks = {'issue': ('http://bugs.python.org/issue%s', 'issue '),
'pyurl': ('http://python.org/%s', None)}
+autodoc_mock_imports = [
+ 'missing_module',
+ 'missing_package1.missing_module1',
+ 'missing_package2.missing_module2',
+ 'missing_package3.missing_module3',
+]
+
# modify tags from conf.py
tags.add('confpytag')
diff --git a/tests/root/includes.txt b/tests/root/includes.txt
index 904f0677..08917811 100644
--- a/tests/root/includes.txt
+++ b/tests/root/includes.txt
@@ -40,6 +40,7 @@ Literalinclude options
.. cssclass:: inc-lines
.. literalinclude:: literal.inc
:lines: 6-7,9
+ :lineno-start: 6
.. cssclass:: inc-startend
.. literalinclude:: literal.inc
diff --git a/tests/root/markup.txt b/tests/root/markup.txt
index 1fb20cf0..34e8fdb8 100644
--- a/tests/root/markup.txt
+++ b/tests/root/markup.txt
@@ -79,6 +79,10 @@ Body directives
b
+.. parsed-literal::
+
+ with some *markup* inside
+
.. _admonition-section:
@@ -139,6 +143,7 @@ Adding \n to test unescaping.
* :doc:`subdir/includes`
* ``:download:`` is tested in includes.txt
* :option:`Python -c option <python -c>`
+* This used to crash: :option:`Python c option`
Test :abbr:`abbr (abbreviation)` and another :abbr:`abbr (abbreviation)`.
diff --git a/tests/root/objects.txt b/tests/root/objects.txt
index 57e82212..73661d22 100644
--- a/tests/root/objects.txt
+++ b/tests/root/objects.txt
@@ -101,6 +101,7 @@ Referring to :func:`nothing <>`.
:type hour: DuplicateType
:param hour: Duplicate param. Should not lead to crashes.
:type hour: DuplicateType
+ :param .Cls extcls: A class from another module.
C items
@@ -117,14 +118,6 @@ C items
.. c:var:: sphinx_global
-Old C items (from oldcmarkup ext)
----------------------------------
-
-.. cfunction:: Sphinx_Func()
-
-Refer to :cfunc:`Sphinx_Func`.
-
-
Javascript items
================
diff --git a/tests/roots/test-templating/_templates/autosummary/class.rst b/tests/roots/test-templating/_templates/autosummary/class.rst
new file mode 100644
index 00000000..7f153617
--- /dev/null
+++ b/tests/roots/test-templating/_templates/autosummary/class.rst
@@ -0,0 +1,8 @@
+{% extends "!autosummary/class.rst" %}
+
+{% block methods %}
+
+ .. note:: autosummary/class.rst method block overloading
+
+ {{ super() }}
+{% endblock %}
diff --git a/tests/roots/test-templating/_templates/layout.html b/tests/roots/test-templating/_templates/layout.html
new file mode 100644
index 00000000..f836c773
--- /dev/null
+++ b/tests/roots/test-templating/_templates/layout.html
@@ -0,0 +1,6 @@
+{% extends "!layout.html" %}
+
+{% block extrahead %}
+<!-- layout overloading -->
+{{ super() }}
+{% endblock %}
diff --git a/tests/roots/test-templating/autosummary_templating.txt b/tests/roots/test-templating/autosummary_templating.txt
new file mode 100644
index 00000000..05643a02
--- /dev/null
+++ b/tests/roots/test-templating/autosummary_templating.txt
@@ -0,0 +1,13 @@
+Autosummary templating test
+===========================
+
+.. autosummary::
+ :toctree: generated
+
+ sphinx.application.Sphinx
+
+.. currentmodule:: sphinx.application
+
+.. autoclass:: TemplateBridge
+
+ .. automethod:: render
diff --git a/tests/roots/test-templating/conf.py b/tests/roots/test-templating/conf.py
new file mode 100644
index 00000000..225da82e
--- /dev/null
+++ b/tests/roots/test-templating/conf.py
@@ -0,0 +1,11 @@
+# -*- coding: utf-8 -*-
+
+project = 'Sphinx templating <Tests>'
+source_suffix = '.txt'
+keep_warnings = True
+templates_path = ['_templates']
+release = version = '2013.120'
+
+extensions = ['sphinx.ext.autosummary']
+autosummary_generate = ['autosummary_templating']
+
diff --git a/tests/roots/test-templating/contents.txt b/tests/roots/test-templating/contents.txt
new file mode 100644
index 00000000..04a40e21
--- /dev/null
+++ b/tests/roots/test-templating/contents.txt
@@ -0,0 +1,7 @@
+Welcome to Sphinx Tests's documentation!
+========================================
+
+.. toctree::
+
+ autosummary_templating
+
diff --git a/tests/test_autodoc.py b/tests/test_autodoc.py
index 1931c0d0..82eb0f71 100644
--- a/tests/test_autodoc.py
+++ b/tests/test_autodoc.py
@@ -301,6 +301,53 @@ def test_get_doc():
assert getdocl('class', D) == ['Class docstring', '', 'Init docstring',
'', 'Other', ' lines']
+ #__init__ have signature at first line of docstring
+ class E:
+ """Class docstring"""
+ def __init__(self, *args, **kw):
+ """
+ __init__(a1, a2, kw1=True, kw2=False)
+
+ Init docstring
+ """
+
+ # signature line in the docstring will be kept when
+ # autodoc_docstring_signature == False
+ directive.env.config.autodoc_docstring_signature = False
+ directive.env.config.autoclass_content = 'class'
+ assert getdocl('class', E) == ['Class docstring']
+ directive.env.config.autoclass_content = 'init'
+ assert getdocl('class', E) == ['__init__(a1, a2, kw1=True, kw2=False)',
+ '', 'Init docstring']
+ directive.env.config.autoclass_content = 'both'
+ assert getdocl('class', E) == ['Class docstring', '',
+ '__init__(a1, a2, kw1=True, kw2=False)',
+ '', 'Init docstring']
+
+ # signature line in the docstring will be removed when
+ # autodoc_docstring_signature == True
+ directive.env.config.autodoc_docstring_signature = True #default
+ directive.env.config.autoclass_content = 'class'
+ assert getdocl('class', E) == ['Class docstring']
+ directive.env.config.autoclass_content = 'init'
+ assert getdocl('class', E) == ['Init docstring']
+ directive.env.config.autoclass_content = 'both'
+ assert getdocl('class', E) == ['Class docstring', '', 'Init docstring']
+
+ # class does not have __init__ method
+ class F(object):
+ """Class docstring"""
+
+ # docstring in the __init__ method of base class will be discard
+ for f in (False, True):
+ directive.env.config.autodoc_docstring_signature = f
+ directive.env.config.autoclass_content = 'class'
+ assert getdocl('class', F) == ['Class docstring']
+ directive.env.config.autoclass_content = 'init'
+ assert getdocl('class', F) == ['Class docstring']
+ directive.env.config.autoclass_content = 'both'
+ assert getdocl('class', F) == ['Class docstring']
+
@with_setup(setup_test)
def test_docstring_processing():
@@ -704,12 +751,8 @@ def _funky_classmethod(name, b, c, d, docstring=None):
some arguments."""
def template(cls, a, b, c, d=4, e=5, f=6):
return a, b, c, d, e, f
- if sys.version_info >= (2, 5):
- from functools import partial
- function = partial(template, b=b, c=c, d=d)
- else:
- def function(cls, a, e=5, f=6):
- return template(a, b, c, d, e, f)
+ from functools import partial
+ function = partial(template, b=b, c=c, d=d)
function.__name__ = name
function.__doc__ = docstring
return classmethod(function)
@@ -741,10 +784,9 @@ class Class(Base):
#: should be documented -- süß
attr = 'bar'
+ @property
def prop(self):
"""Property."""
- # stay 2.4 compatible (docstring!)
- prop = property(prop, doc="Property.")
docattr = 'baz'
"""should likewise be documented -- süß"""
diff --git a/tests/test_build_html.py b/tests/test_build_html.py
index aef73305..603ad546 100644
--- a/tests/test_build_html.py
+++ b/tests/test_build_html.py
@@ -42,9 +42,8 @@ http://www.python.org/logo.png
reading included file u'.*?wrongenc.inc' seems to be wrong, try giving an \
:encoding: option\\n?
%(root)s/includes.txt:4: WARNING: download file not readable: .*?nonexisting.png
-%(root)s/objects.txt:\\d*: WARNING: using old C markup; please migrate to \
-new-style markup \(e.g. c:function instead of cfunction\), see \
-http://sphinx-doc.org/domains.html
+%(root)s/markup.txt:\\d+: WARNING: Malformed :option: u'Python c option', does \
+not contain option marker - or -- or /
"""
HTML_WARNINGS = ENV_WARNINGS + """\
@@ -184,13 +183,11 @@ HTML_XPATH = {
(".//a[@href='#userdesc-myobj'][@class='reference internal']", ''),
# C references
(".//span[@class='pre']", 'CFunction()'),
- (".//a[@href='#Sphinx_DoSomething']", ''),
- (".//a[@href='#SphinxStruct.member']", ''),
- (".//a[@href='#SPHINX_USE_PYTHON']", ''),
- (".//a[@href='#SphinxType']", ''),
- (".//a[@href='#sphinx_global']", ''),
- # reference from old C markup extension
- (".//a[@href='#Sphinx_Func']", ''),
+ (".//a[@href='#c.Sphinx_DoSomething']", ''),
+ (".//a[@href='#c.SphinxStruct.member']", ''),
+ (".//a[@href='#c.SPHINX_USE_PYTHON']", ''),
+ (".//a[@href='#c.SphinxType']", ''),
+ (".//a[@href='#c.sphinx_global']", ''),
# test global TOC created by toctree()
(".//ul[@class='current']/li[@class='toctree-l1 current']/a[@href='']",
'Testing object descriptions'),
@@ -365,7 +362,7 @@ def test_html(app):
confoverrides={'html_sidebars': {'*': ['globaltoc.html']}},
)
def test_html_with_globaltoc_and_hidden_toctree(app):
- # issue #1157: combination of 'globaltoc.html' and hidden toctree cause
+ # issue #1157: combination of 'globaltoc.html' and hidden toctree cause
# exception.
(app.srcdir / 'contents.rst').write_text(
'\n.. toctree::'
diff --git a/tests/test_config.py b/tests/test_config.py
index 4d3d51b0..ea6f3ba4 100644
--- a/tests/test_config.py
+++ b/tests/test_config.py
@@ -19,7 +19,8 @@ from sphinx.util.pycompat import b
@with_app(confoverrides={'master_doc': 'master', 'nonexisting_value': 'True',
- 'latex_elements.docclass': 'scrartcl'})
+ 'latex_elements.docclass': 'scrartcl',
+ 'modindex_common_prefix': 'path1,path2'})
def test_core_config(app):
cfg = app.config
@@ -31,6 +32,7 @@ def test_core_config(app):
# overrides
assert cfg.master_doc == 'master'
assert cfg.latex_elements['docclass'] == 'scrartcl'
+ assert cfg.modindex_common_prefix == ['path1', 'path2']
# simple default values
assert 'locale_dirs' not in cfg.__dict__
@@ -92,7 +94,7 @@ def test_errors_warnings(dir):
write_file(dir / 'conf.py', u'# -*- coding: utf-8\n\n'
u'project = u"Jägermeister"\n', 'utf-8')
cfg = Config(dir, 'conf.py', {}, None)
- cfg.init_values()
+ cfg.init_values(lambda warning: 1/0)
assert cfg.project == u'Jägermeister'
# test the warning for bytestrings with non-ascii content
@@ -122,5 +124,5 @@ def test_config_eol(tmpdir):
for eol in ('\n', '\r\n'):
configfile.write_bytes(b('project = "spam"' + eol))
cfg = Config(tmpdir, 'conf.py', {}, None)
- cfg.init_values()
+ cfg.init_values(lambda warning: 1/0)
assert cfg.project == u'spam'
diff --git a/tests/test_intersphinx.py b/tests/test_intersphinx.py
index a8679e7e..8ce02cc1 100644
--- a/tests/test_intersphinx.py
+++ b/tests/test_intersphinx.py
@@ -81,7 +81,7 @@ def test_read_inventory_v2():
'/util/glossary.html#term-a-term'
-@with_app(confoverrides={'extensions': 'sphinx.ext.intersphinx'})
+@with_app()
@with_tempdir
def test_missing_reference(tempdir, app):
inv_file = tempdir / 'inventory'
@@ -157,7 +157,7 @@ def test_missing_reference(tempdir, app):
assert contnode[0].astext() == 'py3k:unknown'
-@with_app(confoverrides={'extensions': 'sphinx.ext.intersphinx'})
+@with_app()
@with_tempdir
def test_load_mappings_warnings(tempdir, app):
"""
diff --git a/tests/test_intl.py b/tests/test_intl.py
index c9822089..0119d677 100644
--- a/tests/test_intl.py
+++ b/tests/test_intl.py
@@ -16,8 +16,6 @@ from StringIO import StringIO
from subprocess import Popen, PIPE
from xml.etree import ElementTree
-from sphinx.util.pycompat import relpath
-
from util import test_roots, path, with_app, SkipTest
@@ -49,7 +47,7 @@ def setup_module():
for f in [f for f in files if f.endswith('.po')]:
po = dirpath / f
mo = root / 'xx' / 'LC_MESSAGES' / (
- relpath(po[:-3], root) + '.mo')
+ os.path.relpath(po[:-3], root) + '.mo')
if not mo.parent.exists():
mo.parent.makedirs()
try:
@@ -75,7 +73,7 @@ def teardown_module():
def elem_gettexts(elem):
def itertext(self):
# this function copied from Python-2.7 'ElementTree.itertext'.
- # for compatibility to Python-2.5, 2.6, 3.1
+ # for compatibility to Python-2.6
tag = self.tag
if not isinstance(tag, basestring) and tag is not None:
return
diff --git a/tests/test_linkcode.py b/tests/test_linkcode.py
index 507cd9ce..190c3bf2 100644
--- a/tests/test_linkcode.py
+++ b/tests/test_linkcode.py
@@ -12,15 +12,12 @@
import os
from util import with_app
+
@with_app(srcdir='(temp)', buildername='html', tags=['test_linkcode'])
def test_html(app):
app.builder.build_all()
- fp = open(os.path.join(app.outdir, 'objects.html'), 'r')
- try:
- stuff = fp.read()
- finally:
- fp.close()
+ stuff = (app.outdir / 'objects.html').text(encoding='utf-8')
assert 'http://foobar/source/foolib.py' in stuff
assert 'http://foobar/js/' in stuff
diff --git a/tests/test_markup.py b/tests/test_markup.py
index 311222ba..f182830a 100644
--- a/tests/test_markup.py
+++ b/tests/test_markup.py
@@ -132,7 +132,7 @@ def test_latex_escaping():
# in verbatim code fragments
yield (verify, u'::\n\n @Γ\\∞${}', None,
u'\\begin{Verbatim}[commandchars=\\\\\\{\\}]\n'
- u'@\\(\\Gamma\\)\\PYGZbs{}\\(\\infty\\)\\$\\PYGZob{}\\PYGZcb{}\n'
+ u'@\\(\\Gamma\\)\\PYGZbs{}\\(\\infty\\)\\PYGZdl{}\\PYGZob{}\\PYGZcb{}\n'
u'\\end{Verbatim}')
# in URIs
yield (verify_re, u'`test <http://example.com/~me/>`_', None,
diff --git a/tests/test_metadata.py b/tests/test_metadata.py
index db955390..92dbe1c9 100644
--- a/tests/test_metadata.py
+++ b/tests/test_metadata.py
@@ -14,7 +14,7 @@
from util import TestApp
-from nose.tools import assert_equals
+from nose.tools import assert_equal
app = env = None
@@ -64,6 +64,6 @@ def test_docinfo():
}
# I like this way of comparing dicts - easier to see the error.
for key in exampledocinfo:
- yield assert_equals, exampledocinfo.get(key), expecteddocinfo.get(key)
+ yield assert_equal, exampledocinfo.get(key), expecteddocinfo.get(key)
# but then we still have to check for missing keys
- yield assert_equals, set(expecteddocinfo.keys()), set(exampledocinfo.keys())
+ yield assert_equal, set(expecteddocinfo.keys()), set(exampledocinfo.keys())
diff --git a/tests/test_quickstart.py b/tests/test_quickstart.py
index 9daa7401..7323f48e 100644
--- a/tests/test_quickstart.py
+++ b/tests/test_quickstart.py
@@ -170,6 +170,7 @@ def test_quickstart_all_answers(tempdir):
'Author name': u'Wolfgang Schäuble & G\'Beckstein'.encode('utf-8'),
'Project version': '2.0',
'Project release': '2.0.1',
+ 'Project language': 'de',
'Source file suffix': '.txt',
'Name of your master document': 'contents',
'autodoc': 'y',
diff --git a/tests/test_setup_command.py b/tests/test_setup_command.py
index af4b75c0..f32d6abc 100644
--- a/tests/test_setup_command.py
+++ b/tests/test_setup_command.py
@@ -14,6 +14,7 @@ import sys
import subprocess
from functools import wraps
import tempfile
+import sphinx
from util import with_tempdir, test_roots, SkipTest
from path import path
@@ -35,16 +36,20 @@ def with_setup_command(root, *args, **kwds):
root.copytree(pkgrootdir)
cwd = os.getcwd()
os.chdir(pkgrootdir)
+ pythonpath = os.path.dirname(os.path.dirname(sphinx.__file__))
+ if os.getenv('PYTHONPATH'):
+ pythonpath = os.getenv('PYTHONPATH') + os.pathsep + pythonpath
command = [sys.executable, 'setup.py', 'build_sphinx']
command.extend(args)
try:
proc = subprocess.Popen(
command,
+ env=dict(os.environ, PYTHONPATH=pythonpath),
stdout=subprocess.PIPE,
stderr=subprocess.PIPE)
func(pkgrootdir, proc, *args, **kwds)
finally:
- tempdir.rmtree()
+ tempdir.rmtree(ignore_errors=True)
os.chdir(cwd)
return deco
return generator
diff --git a/tests/test_templating.py b/tests/test_templating.py
new file mode 100644
index 00000000..025d6fd0
--- /dev/null
+++ b/tests/test_templating.py
@@ -0,0 +1,36 @@
+# -*- coding: utf-8 -*-
+"""
+ test_templating
+ ~~~~~~~~~~~~~~~~
+
+ Test templating.
+
+ :copyright: Copyright 2007-2013 by the Sphinx team, see AUTHORS.
+ :license: BSD, see LICENSE for details.
+"""
+
+from util import test_roots, with_app
+
+
+def teardown_module():
+ (test_roots / 'test-templating' / '_build').rmtree(True),
+
+
+@with_app(buildername='html', srcdir=(test_roots / 'test-templating'))
+def test_layout_overloading(app):
+ app.builder.build_all()
+
+ result = (app.outdir / 'contents.html').text(encoding='utf-8')
+
+ assert '<!-- layout overloading -->' in result
+
+
+@with_app(buildername='html', srcdir=(test_roots / 'test-templating'))
+def test_autosummary_class_template_overloading(app):
+ app.builder.build_all()
+
+ result = (app.outdir / 'generated' / 'sphinx.application.Sphinx.html').text(
+ encoding='utf-8')
+
+ assert 'autosummary/class.rst method block overloading' in result
+
diff --git a/tests/test_versioning.py b/tests/test_versioning.py
index 6469a33c..5cff92ff 100644
--- a/tests/test_versioning.py
+++ b/tests/test_versioning.py
@@ -15,7 +15,6 @@ from docutils.parsers.rst.directives.html import MetaBody
from sphinx import addnodes
from sphinx.versioning import add_uids, merge_doctrees, get_ratio
-from sphinx.util.pycompat import all
from util import test_root, TestApp
diff --git a/tests/test_websupport.py b/tests/test_websupport.py
index 611a131a..d950a36c 100644
--- a/tests/test_websupport.py
+++ b/tests/test_websupport.py
@@ -11,12 +11,7 @@
import os
from StringIO import StringIO
-
-try:
- from functools import wraps
-except ImportError:
- # functools is new in 2.5
- wraps = lambda f: (lambda w: w)
+from functools import wraps
from sphinx.websupport import WebSupport
from sphinx.websupport.errors import DocumentNotFoundError, \
diff --git a/tests/util.py b/tests/util.py
index 4ba89030..a2f345bf 100644
--- a/tests/util.py
+++ b/tests/util.py
@@ -13,12 +13,7 @@ import tempfile
import shutil
import re
from codecs import open
-
-try:
- from functools import wraps
-except ImportError:
- # functools is new in 2.4
- wraps = lambda f: (lambda w: w)
+from functools import wraps
from sphinx import application
from sphinx.theming import Theme
diff --git a/tox.ini b/tox.ini
index f1675e90..006819ef 100644
--- a/tox.ini
+++ b/tox.ini
@@ -1,5 +1,5 @@
[tox]
-envlist=py25,py26,py27,py31,py32,py33,pypy,du11,du10,du09,du08,du07
+envlist=py26,py27,py32,py33,pypy,du11,du10,du09,du08,du07
[testenv]
deps=
@@ -12,14 +12,6 @@ commands=
{envpython} tests/run.py {posargs}
sphinx-build -W -b html -d {envtmpdir}/doctrees doc {envtmpdir}/html
-[testenv:py25]
-deps=
- simplejson==2.5.0
- {[testenv]deps}
-setenv=
- PIP_INSECURE = 1
- {[testenv]setenv}
-
[testenv:py33]
deps=
docutils>=0.10.0
diff --git a/utils/release-checklist b/utils/release-checklist
new file mode 100644
index 00000000..ab234f3e
--- /dev/null
+++ b/utils/release-checklist
@@ -0,0 +1,21 @@
+Release checklist
+=================
+
+* Check hg status
+* Make check
+* Update version info in sphinx/__init__.py
+* Update release date in CHANGES
+* hg commit
+* make clean
+* python setup.py release bdist_wheel sdist upload
+* For all other versions: pythonX.Y setup.py release bdist_wheel upload
+ (remove build/ before each one)
+* Check PyPI release page for obvious errors
+* hg tag
+* Merge default into stable if final major release
+* Update homepage (release info), regenerate docs (+printable!)
+* Add new version/milestone to tracker categories
+* Write announcement and send to mailing list/python-announce
+* Update version info, add new CHANGES entry for next version
+* hg commit
+* hg push