diff --git a/.travis.yml b/.travis.yml
index c468867ae..45bf4bb40 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -17,12 +17,19 @@ env:
matrix:
- DOCUTILS=0.11
- DOCUTILS=0.12
+addons:
+ apt:
+ packages:
+ - graphviz
+ - texlive-latex-recommended
+ - texlive-latex-extra
+ - texlive-fonts-recommended
+ - texlive-fonts-extra
install:
- pip install -U pip
- pip install docutils==$DOCUTILS
- pip install -r test-reqs.txt
before_script: flake8
script:
-
- - if [[ $TRAVIS_PYTHON_VERSION == '3.5' ]]; then make test-async; fi
+ - if [[ $TRAVIS_PYTHON_VERSION == '3.5' ]]; then make style-check test-async; fi
- if [[ $TRAVIS_PYTHON_VERSION != '3.5' ]]; then make test; fi
diff --git a/CHANGES b/CHANGES
index 2e925c761..c71261032 100644
--- a/CHANGES
+++ b/CHANGES
@@ -4,8 +4,28 @@ Release 1.5 (in development)
Incompatible changes
--------------------
-* LaTeX package fancybox is not longer a dependency of sphinx.sty
+* latex, package fancybox is not longer a dependency of sphinx.sty
* Use ``'locales'`` as a default value of `locale_dirs`
+* latex, package ifthen is not any longer a dependency of sphinx.sty
+* latex, style file does not modify fancyvrb's Verbatim (also available as
+ OriginalVerbatim) but uses sphinxVerbatim for name of custom wrapper.
+* latex, package newfloat is no longer a dependency of sphinx.sty (ref #2660;
+ it was shipped with Sphinx since 1.3.4).
+* latex, literal blocks in tables do not use OriginalVerbatim but
+ sphinxVerbatimintable which handles captions and wraps lines(ref #2704).
+* latex, replace ``pt`` by TeX equivalent ``bp`` if found in ``width`` or
+ ``height`` attribute of an image.
+* latex, if ``width`` or ``height`` attribute of an image is given with no unit,
+ use ``px`` rather than ignore it.
+* latex: Separate stylesheets of pygments to independent .sty file
+* #2454: The filename of sourcelink is now changed. The value of
+ `html_sourcelink_suffix` will be appended to the original filename (like
+ ``index.rst.txt``).
+* ``sphinx.util.copy_static_entry()`` is now deprecated.
+ Use ``sphinx.util.fileutil.copy_asset()`` instead.
+* ``sphinx.util.osutil.filecopy()`` skips copying if the file has not been changed
+ (ref: #2510, #2753)
+
Features added
--------------
@@ -17,20 +37,141 @@ Features added
* #2463, #2516: Add keywords of "meta" directive to search index
* ``:maxdepth:`` option of toctree affects ``secnumdepth`` (ref: #2547)
* #2575: Now ``sphinx.ext.graphviz`` allows ``:align:`` option
+* Show warnings if unknown key is specified to `latex_elements`
+* Show warnings if no domains match with `primary_domain` (ref: #2001)
+* C++, show warnings when the kind of role is misleading for the kind
+ of target it refers to (e.g., using the `class` role for a function).
+* latex, writer abstracts more of text styling into customizable macros, e.g.
+ the ``visit_emphasis`` will output ``\sphinxstyleemphasis`` rather than
+ ``\emph`` (which may be in use elsewhere or in an added LaTeX package). See
+ list at end of ``sphinx.sty`` (ref: #2686)
+* latex, public names for environments and parameters used by note, warning,
+ and other admonition types, allowing full customizability from the
+ ``'preamble'`` key or an input file (ref: feature request #2674, #2685)
+* latex, better computes column widths of some tables (as a result, there will
+ be slight changes as tables now correctly fill the line width; ref: #2708)
+* latex, sphinxVerbatim environment is more easily customizable (ref: #2704).
+ In addition to already existing VerbatimColor and VerbatimBorderColor:
+
+ - two lengths ``\sphinxverbatimsep`` and ``\sphinxverbatimborder``,
+ - booleans ``\ifsphinxverbatimwithframe`` and ``\ifsphinxverbatimwrapslines``.
+* latex, captions for literal blocks inside tables are handled, and long code
+ lines wrapped to fit table cell (ref: #2704)
+* #2597: Show warning messages as darkred
+* latex, allow image dimensions using px unit (default is 96px=1in)
+* Show warnings if invalid dimension units found
+* #2650: Add ``--pdb`` option to setup.py command
+* latex, make the use of ``\small`` for code listings customizable (ref #2721)
+* #2663: Add ``--warning-is-error`` option to setup.py command
+* Show warnings if deprecated latex options are used
+* Add sphinx.config.ENUM to check the config values is in candidates
+* math: Add hyperlink marker to each equations in HTML output
+
Bugs fixed
----------
+* #2707: (latex) the column width is badly computed for tabular
+
Documentation
-------------
-Release 1.4.3 (in development)
+Release 1.4.5 (in development)
==============================
+Incompatible changes
+--------------------
+
+* latex, inclusion of non-inline images from image directive resulted in
+ non-coherent whitespaces depending on original image width; new behaviour
+ by necessity differs from earlier one in some cases. (ref: #2672)
+* latex, use of ``\includegraphics`` to refer to Sphinx custom variant is
+ deprecated; in future it will revert to original LaTeX macro, custom one
+ already has alternative name ``\sphinxincludegraphics``.
+
+Features added
+--------------
+
+* new config option ``latex_keep_old_macro_names``, defaults to True. If False,
+ lets macros (for text styling) be defined only with ``\sphinx``-prefixed names.
+* latex writer allows user customization of "shadowed" boxes (topics), via
+ three length variables.
+* woff-format web font files now supported by the epub builder.
+
Bugs fixed
----------
+* #2676: (latex) Error with verbatim text in captions since Sphinx 1.4.4
+* #2629: memoir class crashes LaTeX. Fixed ``by latex_keep_old_macro_names=False`` (ref 2675)
+* #2684: `sphinx.ext.intersphinx` crashes with six-1.4.1
+* #2679: ``float`` package needed for ``'figure_align': 'H'`` latex option
+* #2671: image directive may lead to inconsistent spacing in pdf
+* #2705: ``toctree`` generates empty bullet_list if ``:titlesonly:`` specified
+* #2479: `sphinx.ext.viewcode` uses python2 highlighter by default
+* #2700: HtmlHelp builder has hard coded index.html
+* latex, since 1.4.4 inline literal text is followed by spurious space
+* #2722: C++, fix id generation for var/member declarations to include namespaces.
+* latex, images (from image directive) in lists or quoted blocks did not obey
+ indentation (fixed together with #2671)
+* #2733: since Sphinx-1.4.4 ``make latexpdf`` generates lots of hyperref warnings
+* #2731: `sphinx.ext.autodoc` does not access propertymethods which raises any
+ exceptions
+* #2666: C++, properly look up nested names involving constructors.
+* #2579: Could not refer a label including both spaces and colons via
+ `sphinx.ext.intersphinx`
+* #2718: Sphinx crashes if the document file is not readable
+* #2699: hyperlinks in help HTMLs are broken if `html_file_suffix` is set
+* #2723: extra spaces in latex pdf output from multirow cell
+* #2735: latexpdf ``Underfull \hbox (badness 10000)`` warnings from title page
+* #2667: latex crashes if resized images appeared in section title
+
+
+Release 1.4.4 (released Jun 12, 2016)
+=====================================
+
+Bugs fixed
+----------
+
+* #2630: Latex sphinx.sty Notice Enviroment formatting problem
+* #2632: Warning directives fail in quote environment latex build
+* #2633: Sphinx crashes with old styled indices
+* Fix a ``\begin{\minipage}`` typo in sphinx.sty from 1.4.2 (ref: 68becb1)
+* #2622: Latex produces empty pages after title and table of contents
+* #2640: 1.4.2 LaTeX crashes if code-block inside warning directive
+* Let LaTeX use straight quotes also in inline code (ref #2627)
+* #2351: latex crashes if enumerated lists are placed on footnotes
+* #2646: latex crashes if math contains twice empty lines
+* #2480: `sphinx.ext.autodoc`: memory addresses were shown
+* latex: allow code-blocks appearing inside lists and quotes at maximal nesting
+ depth (ref #777, #2624, #2651)
+* #2635: Latex code directives produce inconsistent frames based on viewing
+ resolution
+* #2639: Sphinx now bundles iftex.sty
+* Failed to build PDF with framed.sty 0.95
+* Sphinx now bundles needspace.sty
+
+
+Release 1.4.3 (released Jun 5, 2016)
+====================================
+
+Bugs fixed
+----------
+
+* #2530: got "Counter too large" error on building PDF if large numbered
+ footnotes existed in admonitions
+* ``width`` option of figure directive does not work if ``align`` option specified at same time (ref: #2595)
+* #2590: The ``inputenc`` package breaks compiling under lualatex and xelatex
+* #2540: date on latex front page use different font
+* Suppress "document isn't included in any toctree" warning if the document is included (ref: #2603)
+* #2614: Some tables in PDF output will end up shifted if user sets non zero
+ \parindent in preamble
+* #2602: URL redirection breaks the hyperlinks generated by `sphinx.ext.intersphinx`
+* #2613: Show warnings if merged extensions are loaded
+* #2619: make sure amstext LaTeX package always loaded (ref: d657225, 488ee52,
+ 9d82cad and #2615)
+* #2593: latex crashes if any figures in the table
+
Release 1.4.2 (released May 29, 2016)
=====================================
@@ -69,7 +210,8 @@ Bugs fixed
* #2397: Setup shorthandoff for turkish documents
* #2447: VerbatimBorderColor wrongly used also for captions of PDF
* #2456: C++, fix crash related to document merging (e.g., singlehtml and Latex builders).
-* #2446: latex(pdf) sets local tables of contents (or more generally topic nodes) in unbreakable boxes, causes overflow at bottom
+* #2446: latex(pdf) sets local tables of contents (or more generally topic
+ nodes) in unbreakable boxes, causes overflow at bottom
* #2476: Omit MathJax markers if :nowrap: is given
* #2465: latex builder fails in case no caption option is provided to toctree directive
* Sphinx crashes if self referenced toctree found
@@ -278,7 +420,8 @@ Bugs fixed
is highlighted as Python 3 (which is mostly a superset of Python 2) if possible.
To get the old behavior back, add ``highlight_language = "python"`` to conf.py.
* #2329: Refresh environment forcely if source directory has changed.
-* #2331: Fix code-blocks are filled by block in dvi; remove ``xcdraw`` option from xcolor package
+* #2331: Fix code-blocks are filled by block in dvi; remove ``xcdraw`` option from
+ xcolor package
* Fix the confval type checker emits warnings if unicode is given to confvals which expects string value
* #2360: Fix numref in LaTeX output is broken
* #2361: Fix additional paragraphs inside the "compound" directive are indented
diff --git a/Makefile b/Makefile
index 02854840e..3b9581033 100644
--- a/Makefile
+++ b/Makefile
@@ -33,12 +33,15 @@ all: clean-pyc clean-backupfiles style-check test
style-check:
@$(PYTHON) utils/check_sources.py $(DONT_CHECK) .
-clean: clean-pyc clean-patchfiles clean-backupfiles clean-generated
+clean: clean-pyc clean-pycache clean-patchfiles clean-backupfiles clean-generated clean-testfiles
clean-pyc:
find . -name '*.pyc' -exec rm -f {} +
find . -name '*.pyo' -exec rm -f {} +
+clean-pycache:
+ find . -name __pycache__ -exec rm -rf {} +
+
clean-patchfiles:
find . -name '*.orig' -exec rm -f {} +
find . -name '*.rej' -exec rm -f {} +
@@ -50,6 +53,10 @@ clean-backupfiles:
clean-generated:
rm -f utils/*3.py*
+clean-testfiles:
+ rm -rf tests/build
+ rm -rf .tox/
+
pylint:
@pylint --rcfile utils/pylintrc sphinx
diff --git a/README.rst b/README.rst
index 391d0bd1a..384e2cc6a 100644
--- a/README.rst
+++ b/README.rst
@@ -33,6 +33,12 @@ Install from cloned source as editable::
pip install -e .
+Release signatures
+==================
+
+Releases are signed with `498D6B9E `_
+
+
Reading the docs
================
diff --git a/doc/_static/bookcover.png b/doc/_static/bookcover.png
index 5b521b67b..0a8167fcc 100644
Binary files a/doc/_static/bookcover.png and b/doc/_static/bookcover.png differ
diff --git a/doc/_static/pocoo.png b/doc/_static/pocoo.png
index 67663b976..1648bb8d7 100644
Binary files a/doc/_static/pocoo.png and b/doc/_static/pocoo.png differ
diff --git a/doc/_static/sphinx.png b/doc/_static/sphinx.png
index 4bd9c7536..0a103cd3e 100644
Binary files a/doc/_static/sphinx.png and b/doc/_static/sphinx.png differ
diff --git a/doc/_themes/sphinx13/static/bodybg.png b/doc/_themes/sphinx13/static/bodybg.png
index ebe92f669..6f667b99e 100644
Binary files a/doc/_themes/sphinx13/static/bodybg.png and b/doc/_themes/sphinx13/static/bodybg.png differ
diff --git a/doc/_themes/sphinx13/static/footerbg.png b/doc/_themes/sphinx13/static/footerbg.png
index df783e2c7..d1bcb009b 100644
Binary files a/doc/_themes/sphinx13/static/footerbg.png and b/doc/_themes/sphinx13/static/footerbg.png differ
diff --git a/doc/_themes/sphinx13/static/headerbg.png b/doc/_themes/sphinx13/static/headerbg.png
index 22830f99e..522504964 100644
Binary files a/doc/_themes/sphinx13/static/headerbg.png and b/doc/_themes/sphinx13/static/headerbg.png differ
diff --git a/doc/_themes/sphinx13/static/listitem.png b/doc/_themes/sphinx13/static/listitem.png
index e45715f91..f7f814d00 100644
Binary files a/doc/_themes/sphinx13/static/listitem.png and b/doc/_themes/sphinx13/static/listitem.png differ
diff --git a/doc/_themes/sphinx13/static/relbg.png b/doc/_themes/sphinx13/static/relbg.png
index 2006af7d2..68a9b77eb 100644
Binary files a/doc/_themes/sphinx13/static/relbg.png and b/doc/_themes/sphinx13/static/relbg.png differ
diff --git a/doc/_themes/sphinx13/static/sphinxheader.png b/doc/_themes/sphinx13/static/sphinxheader.png
index 12988c3d1..845da4ab9 100644
Binary files a/doc/_themes/sphinx13/static/sphinxheader.png and b/doc/_themes/sphinx13/static/sphinxheader.png differ
diff --git a/doc/config.rst b/doc/config.rst
index f0a290a23..a71555974 100644
--- a/doc/config.rst
+++ b/doc/config.rst
@@ -56,7 +56,7 @@ General configuration
.. confval:: extensions
- A list of strings that are module names of Sphinx extensions. These can be
+ A list of strings that are module names of :ref:`extensions`. These can be
extensions coming with Sphinx (named ``sphinx.ext.*``) or custom ones.
Note that you can extend :data:`sys.path` within the conf file if your
@@ -870,6 +870,13 @@ that use Sphinx's HTMLWriter class.
.. versionadded:: 0.6
+.. confval:: html_sourcelink_suffix
+
+ Suffix to be appended to source links (see :confval:`html_show_sourcelink`),
+ unless they have this suffix already. Default is ``'.txt'``.
+
+ .. versionadded:: 1.5
+
.. confval:: html_use_opensearch
If nonempty, an `OpenSearch `_ description file will be
@@ -1460,7 +1467,7 @@ the `Dublin Core metadata `_.
Options for LaTeX output
------------------------
-These options influence LaTeX output.
+These options influence LaTeX output. See further :doc:`latex`.
.. confval:: latex_documents
@@ -1568,6 +1575,21 @@ These options influence LaTeX output.
value selected the ``'inline'`` display. For backwards compatibility,
``True`` is still accepted.
+.. confval:: latex_keep_old_macro_names
+
+ If ``True`` (default) the ``\strong``, ``\code``, ``\bfcode``, ``\email``,
+ ``\tablecontinued``, ``\titleref``, ``\menuselection``, ``\accelerator``,
+ ``\crossref``, ``\termref``, and ``\optional`` text styling macros are
+ pre-defined by Sphinx and may be user-customized by some
+ ``\renewcommand``'s inserted either via ``'preamble'`` key or :dudir:`raw
+ ` directive. If ``False``, only ``\sphinxstrong``,
+ etc... macros are defined (and may be redefined by user). Setting to
+ ``False`` may help solve macro name conflicts caused by user-added latex
+ packages.
+
+ .. versionadded:: 1.4.5
+
+
.. confval:: latex_elements
.. versionadded:: 0.5
@@ -1586,6 +1608,15 @@ These options influence LaTeX output.
``'pointsize'``
Point size option of the document class (``'10pt'``, ``'11pt'`` or
``'12pt'``), default ``'10pt'``.
+ ``'pxunit'``
+ the value of the ``px`` when used in image attributes ``width`` and
+ ``height``. The default value is ``'49336sp'`` which achieves
+ ``96px=1in`` (``1in = 72.27*65536 = 4736286.72sp``, and all dimensions
+ in TeX are internally integer multiples of ``sp``). To obtain for
+ example ``100px=1in``, one can use ``'0.01in'`` but it is more precise
+ to use ``'47363sp'``. To obtain ``72px=1in``, use ``'1bp'``.
+
+ .. versionadded:: 1.5
``'babel'``
"babel" package inclusion, default ``'\\usepackage{babel}'``.
``'fontpkg'``
@@ -1608,7 +1639,7 @@ These options influence LaTeX output.
.. versionadded:: 1.4
``'preamble'``
- Additional preamble content, default empty.
+ Additional preamble content, default empty. See :doc:`latex`.
``'figure_align'``
Latex figure float alignment, default 'htbp' (here, top, bottom, page).
Whenever an image doesn't fit into the current page, it will be
@@ -1627,7 +1658,7 @@ These options influence LaTeX output.
``'\\usepackage[utf8]{inputenc}'`` when using pdflatex.
Otherwise unset.
- .. versionchanged:: 1.5
+ .. versionchanged:: 1.4.3
Previously ``'\\usepackage[utf8]{inputenc}'`` was used for all
compilers.
``'cmappkg'``
diff --git a/doc/contents.rst b/doc/contents.rst
index a51910b81..79a10493d 100644
--- a/doc/contents.rst
+++ b/doc/contents.rst
@@ -1,3 +1,4 @@
+
.. _contents:
Sphinx documentation contents
@@ -17,6 +18,7 @@ Sphinx documentation contents
intl
theming
templating
+ latex
extensions
extdev/index
websupport
diff --git a/doc/ext/doctest.rst b/doc/ext/doctest.rst
index 3d4f66a9a..818b86007 100644
--- a/doc/ext/doctest.rst
+++ b/doc/ext/doctest.rst
@@ -182,7 +182,7 @@ The doctest extension uses the following configuration values:
.. confval:: doctest_default_flags
By default, these options are enabled:
-
+
- ``ELLIPSIS``, allowing you to put ellipses in the expected output that
match anything in the actual output;
- ``IGNORE_EXCEPTION_DETAIL``, causing everything following the leftmost
diff --git a/doc/ext/example_google.py b/doc/ext/example_google.py
index 81a312cfd..c3ba273b8 100644
--- a/doc/ext/example_google.py
+++ b/doc/ext/example_google.py
@@ -43,6 +43,39 @@ on the first line, separated by a colon.
"""
+def function_with_types_in_docstring(param1, param2):
+ """Example function with types documented in the docstring.
+
+ `PEP 484`_ type annotations are supported. If attribute, parameter, and
+ return types are annotated according to `PEP 484`_, they do not need to be
+ included in the docstring:
+
+ Args:
+ param1 (int): The first parameter.
+ param2 (str): The second parameter.
+
+ Returns:
+ bool: The return value. True for success, False otherwise.
+
+ .. _PEP 484:
+ https://www.python.org/dev/peps/pep-0484/
+
+ """
+
+
+def function_with_pep484_type_annotations(param1: int, param2: str) -> bool:
+ """Example function with PEP 484 type annotations.
+
+ Args:
+ param1: The first parameter.
+ param2: The second parameter.
+
+ Returns:
+ The return value. True for success, False otherwise.
+
+ """
+
+
def module_level_function(param1, param2=None, *args, **kwargs):
"""This is an example of a module level function.
@@ -50,9 +83,6 @@ def module_level_function(param1, param2=None, *args, **kwargs):
of each parameter is required. The type and description of each parameter
is optional, but should be included if not obvious.
- Parameter types -- if given -- should be specified according to
- `PEP 484`_, though `PEP 484`_ conformance isn't required or enforced.
-
If \*args or \*\*kwargs are accepted,
they should be listed as ``*args`` and ``**kwargs``.
@@ -67,7 +97,7 @@ def module_level_function(param1, param2=None, *args, **kwargs):
Args:
param1 (int): The first parameter.
- param2 (Optional[str]): The second parameter. Defaults to None.
+ param2 (:obj:`str`, optional): The second parameter. Defaults to None.
Second line of description should be indented.
*args: Variable length argument list.
**kwargs: Arbitrary keyword arguments.
@@ -94,10 +124,6 @@ def module_level_function(param1, param2=None, *args, **kwargs):
that are relevant to the interface.
ValueError: If `param2` is equal to `param1`.
-
- .. _PEP 484:
- https://www.python.org/dev/peps/pep-0484/
-
"""
if param1 == param2:
raise ValueError('param1 may not be equal to param2')
@@ -139,7 +165,7 @@ class ExampleError(Exception):
Args:
msg (str): Human readable string describing the exception.
- code (Optional[int]): Error code.
+ code (:obj:`int`, optional): Error code.
Attributes:
msg (str): Human readable string describing the exception.
@@ -163,16 +189,9 @@ class ExampleClass(object):
Properties created with the ``@property`` decorator should be documented
in the property's getter method.
- Attribute and property types -- if given -- should be specified according
- to `PEP 484`_, though `PEP 484`_ conformance isn't required or enforced.
-
Attributes:
attr1 (str): Description of `attr1`.
- attr2 (Optional[int]): Description of `attr2`.
-
-
- .. _PEP 484:
- https://www.python.org/dev/peps/pep-0484/
+ attr2 (:obj:`int`, optional): Description of `attr2`.
"""
@@ -190,20 +209,20 @@ class ExampleClass(object):
Args:
param1 (str): Description of `param1`.
- param2 (Optional[int]): Description of `param2`. Multiple
+ param2 (:obj:`int`, optional): Description of `param2`. Multiple
lines are supported.
- param3 (List[str]): Description of `param3`.
+ param3 (:obj:`list` of :obj:`str`): Description of `param3`.
"""
self.attr1 = param1
self.attr2 = param2
self.attr3 = param3 #: Doc comment *inline* with attribute
- #: List[str]: Doc comment *before* attribute, with type specified
+ #: list of str: Doc comment *before* attribute, with type specified
self.attr4 = ['attr4']
self.attr5 = None
- """Optional[str]: Docstring *after* attribute, with type specified."""
+ """str: Docstring *after* attribute, with type specified."""
@property
def readonly_property(self):
@@ -212,8 +231,8 @@ class ExampleClass(object):
@property
def readwrite_property(self):
- """List[str]: Properties with both a getter and setter should only
- be documented in their getter method.
+ """:obj:`list` of :obj:`str`: Properties with both a getter and setter
+ should only be documented in their getter method.
If the setter method contains notable behavior, it should be
mentioned here.
diff --git a/doc/ext/example_numpy.py b/doc/ext/example_numpy.py
index bb91cac82..0e71008e1 100644
--- a/doc/ext/example_numpy.py
+++ b/doc/ext/example_numpy.py
@@ -37,6 +37,7 @@ module_level_variable1 : int
one convention to document module level variables and be consistent
with it.
+
.. _NumPy Documentation HOWTO:
https://github.com/numpy/numpy/blob/master/doc/HOWTO_DOCUMENT.rst.txt
@@ -52,6 +53,52 @@ on the first line, separated by a colon.
"""
+def function_with_types_in_docstring(param1, param2):
+ """Example function with types documented in the docstring.
+
+ `PEP 484`_ type annotations are supported. If attribute, parameter, and
+ return types are annotated according to `PEP 484`_, they do not need to be
+ included in the docstring:
+
+ Parameters
+ ----------
+ param1 : int
+ The first parameter.
+ param2 : str
+ The second parameter.
+
+ Returns
+ -------
+ bool
+ True if successful, False otherwise.
+
+ .. _PEP 484:
+ https://www.python.org/dev/peps/pep-0484/
+
+ """
+
+
+def function_with_pep484_type_annotations(param1: int, param2: str) -> bool:
+ """Example function with PEP 484 type annotations.
+
+ The return type must be duplicated in the docstring to comply
+ with the NumPy docstring style.
+
+ Parameters
+ ----------
+ param1
+ The first parameter.
+ param2
+ The second parameter.
+
+ Returns
+ -------
+ bool
+ True if successful, False otherwise.
+
+ """
+
+
def module_level_function(param1, param2=None, *args, **kwargs):
"""This is an example of a module level function.
@@ -59,9 +106,6 @@ def module_level_function(param1, param2=None, *args, **kwargs):
The name of each parameter is required. The type and description of each
parameter is optional, but should be included if not obvious.
- Parameter types -- if given -- should be specified according to
- `PEP 484`_, though `PEP 484`_ conformance isn't required or enforced.
-
If \*args or \*\*kwargs are accepted,
they should be listed as ``*args`` and ``**kwargs``.
@@ -81,7 +125,7 @@ def module_level_function(param1, param2=None, *args, **kwargs):
----------
param1 : int
The first parameter.
- param2 : Optional[str]
+ param2 : :obj:`str`, optional
The second parameter.
*args
Variable length argument list.
@@ -113,10 +157,6 @@ def module_level_function(param1, param2=None, *args, **kwargs):
ValueError
If `param2` is equal to `param1`.
-
- .. _PEP 484:
- https://www.python.org/dev/peps/pep-0484/
-
"""
if param1 == param2:
raise ValueError('param1 may not be equal to param2')
@@ -166,7 +206,7 @@ class ExampleError(Exception):
----------
msg : str
Human readable string describing the exception.
- code : Optional[int]
+ code : :obj:`int`, optional
Numeric error code.
Attributes
@@ -194,20 +234,13 @@ class ExampleClass(object):
Properties created with the ``@property`` decorator should be documented
in the property's getter method.
- Attribute and property types -- if given -- should be specified according
- to `PEP 484`_, though `PEP 484`_ conformance isn't required or enforced.
-
Attributes
----------
attr1 : str
Description of `attr1`.
- attr2 : Optional[int]
+ attr2 : :obj:`int`, optional
Description of `attr2`.
-
- .. _PEP 484:
- https://www.python.org/dev/peps/pep-0484/
-
"""
def __init__(self, param1, param2, param3):
@@ -227,10 +260,10 @@ class ExampleClass(object):
----------
param1 : str
Description of `param1`.
- param2 : List[str]
+ param2 : :obj:`list` of :obj:`str`
Description of `param2`. Multiple
lines are supported.
- param3 : Optional[int]
+ param3 : :obj:`int`, optional
Description of `param3`.
"""
@@ -238,11 +271,11 @@ class ExampleClass(object):
self.attr2 = param2
self.attr3 = param3 #: Doc comment *inline* with attribute
- #: List[str]: Doc comment *before* attribute, with type specified
+ #: list of str: Doc comment *before* attribute, with type specified
self.attr4 = ["attr4"]
self.attr5 = None
- """Optional[str]: Docstring *after* attribute, with type specified."""
+ """str: Docstring *after* attribute, with type specified."""
@property
def readonly_property(self):
@@ -251,8 +284,8 @@ class ExampleClass(object):
@property
def readwrite_property(self):
- """List[str]: Properties with both a getter and setter should only
- be documented in their getter method.
+ """:obj:`list` of :obj:`str`: Properties with both a getter and setter
+ should only be documented in their getter method.
If the setter method contains notable behavior, it should be
mentioned here.
diff --git a/doc/ext/inheritance.rst b/doc/ext/inheritance.rst
index dd8d5aa99..bd287aa49 100644
--- a/doc/ext/inheritance.rst
+++ b/doc/ext/inheritance.rst
@@ -40,7 +40,7 @@ It adds this directive:
included.
.. versionchanged:: 1.5
- Added ``caption`` option
+ Added ``caption`` option
New config values are:
diff --git a/doc/ext/napoleon.rst b/doc/ext/napoleon.rst
index 2f2fb4376..ea3e4042f 100644
--- a/doc/ext/napoleon.rst
+++ b/doc/ext/napoleon.rst
@@ -186,11 +186,60 @@ not be mixed. Choose one style for your project and be consistent with it.
* :ref:`example_google`
* :ref:`example_numpy`
- For Python type annotations, see `PEP 484`_.
+
+Type Annotations
+----------------
+
+`PEP 484`_ introduced a standard way to express types in Python code.
+This is an alternative to expressing types directly in docstrings.
+One benefit of expressing types according to `PEP 484`_ is that
+type checkers and IDEs can take advantage of them for static code
+analysis.
+
+Google style with Python 3 type annotations::
+
+ def func(arg1: int, arg2: str) -> bool:
+ """Summary line.
+
+ Extended description of function.
+
+ Args:
+ arg1: Description of arg1
+ arg2: Description of arg2
+
+ Returns:
+ Description of return value
+
+ """
+ return True
+
+Google style with types in docstrings::
+
+ def func(arg1, arg2):
+ """Summary line.
+
+ Extended description of function.
+
+ Args:
+ arg1 (int): Description of arg1
+ arg2 (str): Description of arg2
+
+ Returns:
+ bool: Description of return value
+
+ """
+ return True
+
+.. Note::
+ `Python 2/3 compatible annotations`_ aren't currently
+ supported by Sphinx and won't show up in the docs.
.. _PEP 484:
https://www.python.org/dev/peps/pep-0484/
+.. _Python 2/3 compatible annotations:
+ https://www.python.org/dev/peps/pep-0484/#suggested-syntax-for-python-2-7-and-straddling-code
+
Configuration
=============
@@ -208,6 +257,7 @@ enabled in `conf.py`::
# Napoleon settings
napoleon_google_docstring = True
napoleon_numpy_docstring = True
+ napoleon_include_init_with_doc = False
napoleon_include_private_with_doc = False
napoleon_include_special_with_doc = True
napoleon_use_admonition_for_examples = False
@@ -234,6 +284,23 @@ enabled in `conf.py`::
True to parse `NumPy style`_ docstrings. False to disable support
for NumPy style docstrings. *Defaults to True.*
+.. confval:: napoleon_include_init_with_doc
+
+ True to list ``__init___`` docstrings separately from the class
+ docstring. False to fall back to Sphinx's default behavior, which
+ considers the ``__init___`` docstring as part of the class
+ documentation. *Defaults to False.*
+
+ **If True**::
+
+ def __init__(self):
+ \"\"\"
+ This will be included in the docs because it has a docstring
+ \"\"\"
+
+ def __init__(self):
+ # This will NOT be included in the docs
+
.. confval:: napoleon_include_private_with_doc
True to include private members (like ``_membername``) with docstrings
diff --git a/doc/install.rst b/doc/install.rst
index 0ecd73609..a2aeaf9cb 100644
--- a/doc/install.rst
+++ b/doc/install.rst
@@ -135,7 +135,7 @@ install.
.. note::
``pip`` has been contained in the Python official installation after version
- of Python-3.4.0 or Python-2.7.9.
+ of Python-3.4.0 or Python-2.7.9.
Installing Sphinx with pip
diff --git a/doc/installpython.jpg b/doc/installpython.jpg
index b0e458e40..fff4630ae 100644
Binary files a/doc/installpython.jpg and b/doc/installpython.jpg differ
diff --git a/doc/latex.rst b/doc/latex.rst
new file mode 100644
index 000000000..826a715c6
--- /dev/null
+++ b/doc/latex.rst
@@ -0,0 +1,151 @@
+.. highlightlang:: python
+
+.. _latex:
+
+LaTeX customization
+===================
+
+.. module:: latex
+ :synopsis: LaTeX specifics.
+
+The *latex* target does not (yet) benefit from pre-prepared themes like the
+*html* target does (see :doc:`theming`).
+
+There are two principal means of setting up customization:
+
+#. usage of the :ref:`latex-options` as described in :doc:`config`, particularly the
+ various keys of :confval:`latex_elements`, to modify the loaded packages,
+ for example::
+
+ 'fontpkg': '\\usepackage{times}', # can load other font
+ 'fncychap': '\\usepackage[Bjarne]{fncychap}', # can use other option
+
+ .. tip::
+
+ It is not mandatory to load *fncychap*. Naturally, without it and in
+ absence of further customizations, the chapter headings will revert to
+ LaTeX's default for the *report* class.
+
+#. usage of LaTeX ``\renewcommand``, ``\renewenvironment``, ``\setlength``,
+ ``\definecolor`` to modify the defaults from package file :file:`sphinx.sty`
+ and class files :file:`sphinxhowto.cls` and :file:`sphinxmanual.cls`. If such
+ definitions are few, they can be located inside the ``'preamble'`` key of
+ :confval:`latex_elements`. In case of many it may prove more convenient to
+ assemble them into a specialized file :file:`customizedmacros.tex` and use::
+
+ 'preamble': '\\makeatletter\\input{customizedmacros.tex}\\makeatother',
+
+ More advanced LaTeX users will set up a style file
+ :file:`customizedmacros.sty`, which can then be loaded via::
+
+ 'preamble': '\\usepackage{customizedmacros}',
+
+ The :ref:`build configuration file ` file will then have its variable
+ :confval:`latex_additional_files` appropriately configured, for example::
+
+ latex_additional_files = ["customizedmacros.sty"]
+
+ Such *LaTeX Sphinx theme* files could possibly be contributed in the
+ future by advanced users for wider use.
+
+Let us illustrate here what can be modified by the second method.
+
+- text styling commands (they have one argument): ``\sphinx`` with
+ ```` being one of ``strong``, ``bfcode``, ``email``, ``tablecontinued``,
+ ``titleref``, ``menuselection``, ``accelerator``, ``crossref``, ``termref``,
+ ``optional``. By default and for backwards compatibility the ``\sphinx``
+ expands to ``\`` hence the user can choose to customize rather the latter
+ (the non-prefixed macros will be left undefined if option
+ :confval:`latex_keep_old_macro_names` is set to ``False`` in :file:`conf.py`.)
+
+ .. versionchanged:: 1.4.5
+ use of ``\sphinx`` prefixed macro names to limit possibilities of conflict
+ with user added packages. The LaTeX writer uses always the prefixed names.
+- more text styling commands: ``\sphinxstyle`` with ```` one of
+ ``indexentry``, ``indexextra``, ``indexpageref``, ``topictitle``,
+ ``sidebartitle``, ``othertitle``, ``sidebarsubtitle``, ``thead``,
+ ``emphasis``, ``literalemphasis``, ``strong``, ``literalstrong``,
+ ``abbreviation``, ``literalintitle``.
+
+ .. versionadded:: 1.5
+ earlier, the LaTeX writer used hard-coded ``\texttt``, ``\emph``, etc...
+- parameters for paragraph level environments: with ```` one of
+ :dudir:`warning`, :dudir:`caution`, :dudir:`attention`,
+ :dudir:`danger`, :dudir:`error`, the colours
+ *sphinxbordercolor* and *sphinxbgcolor* can be
+ re-defined using ``\definecolor`` command. The
+ ``\sphinxborder`` is a command (not a LaTeX length) which
+ specifies the thickness of the frame (default ``1pt``) and can be
+ ``\renewcommand`` 'd. The same applies with ```` one of
+ :dudir:`note`, :dudir:`hint`, :dudir:`important`, :dudir:`tip`, but
+ the background colour is not implemented by the default environments
+ and the top and bottom rule thickness default is ``0.5pt``.
+
+ .. versionchanged:: 1.5
+ customizability of the parameters for each type of admonition.
+- paragraph level environments: for each admonition as in the previous item, the
+ used environment is named ``sphinx``. They may be ``\renewenvironment``
+ 'd individually, and must then be defined with one argument (it is the heading
+ of the notice, for example ``Warning:`` for :dudir:`warning` directive, if
+ English is the document language). Their default definitions use either the
+ *sphinxheavybox* (for the first listed directives) or the *sphinxlightbox*
+ environments, configured to use the parameters (colours, border thickness)
+ specific to each type, as mentioned in the previous item.
+
+ .. versionchanged:: 1.5
+ use of public environment names, separate customizability of the parameters.
+- the :dudir:`contents` directive (with ``:local:`` option) and the
+ :dudir:`topic` directive are implemented by environment ``sphinxShadowBox``.
+ Its default definition obeys three LaTeX lengths (not commands) as parameters:
+ ``\sphinxshadowsep`` (distance from contents), ``\sphinxshadowsize`` (width of
+ lateral shadow), ``\sphinxshadowrule`` (thickness of the frame).
+
+ .. versionchanged:: 1.5
+ use of public names for the three lengths. The environment itself was
+ redefined to allow page breaks at release 1.4.2.
+- the literal blocks (:rst:dir:`code-block` directives, etc ...), are
+ implemented using ``sphinxVerbatim`` environment which is a wrapper of
+ ``Verbatim`` environment from package ``fancyvrb.sty``. It adds the handling
+ of the top caption and the wrapping of long lines, and a frame which allows
+ pagebreaks. The LaTeX lengths (not commands) ``\sphinxverbatimsep`` and
+ ``\sphinxverbatimborder`` customize the framing. Inside tables the used
+ environment is ``sphinxVerbatimintable`` (it does not draw a frame, but
+ allows a caption).
+
+ .. versionchanged:: 1.5
+ ``Verbatim`` keeps exact same meaning as in ``fancyvrb.sty`` (meaning
+ which is the one of ``OriginalVerbatim`` too), and custom one is called
+ ``sphinxVerbatim``. Also, earlier version of Sphinx used
+ ``OriginalVerbatim`` inside tables (captions were lost, long code lines
+ were not wrapped), they now use ``sphinxVerbatimintable``.
+ .. versionadded:: 1.5
+ the two customizable lengths, the ``sphinxVerbatimintable``.
+- by default the Sphinx style file ``sphinx.sty`` includes the command
+ ``\fvset{fontsize=\small}`` as part of its configuration of
+ ``fancyvrb.sty``. The user may override this for example via
+ ``\fvset{fontsize=auto}`` which will use for listings the ambient
+ font size. Refer to ``fancyvrb.sty``'s documentation for further keys.
+
+ .. versionadded:: 1.5
+ formerly, the use of ``\small`` for code listings was not customizable.
+- miscellaneous colours: *TitleColor*, *InnerLinkColor*, *OuterLinkColor*,
+ *VerbatimColor* (this is a background colour), *VerbatimBorderColor*.
+- the ``\sphinxAtStartFootnote`` is inserted between footnote numbers and their
+ texts, by default it does ``\mbox{ }``.
+- use ``\sphinxSetHeaderFamily`` to set the font used by headings
+ (default is ``\sffamily\bfseries``).
+
+ .. versionadded:: 1.5
+- the section, subsection, ... headings are set using *titlesec*'s
+ ``\titleformat`` command.
+- for the ``'manual'`` class, the chapter headings can be customized using
+ *fncychap*'s commands ``\ChNameVar``, ``\ChNumVar``, ``\ChTitleVar``. Or, if
+ the loading of this package has been removed from ``'fncychap'`` key, one can
+ use the *titlesec* ``\titleformat`` command.
+
+.. note::
+
+ It is impossible to revert or prevent the loading of a package that results
+ from a ``\usepackage`` executed from inside the :file:`sphinx.sty` style
+ file. Sphinx aims at loading as few packages as are really needed for its
+ default design.
diff --git a/doc/more.png b/doc/more.png
index a27a0fcba..97553a8b7 100644
Binary files a/doc/more.png and b/doc/more.png differ
diff --git a/doc/pythonorg.png b/doc/pythonorg.png
index 32f0787d1..cf9ccbbdb 100644
Binary files a/doc/pythonorg.png and b/doc/pythonorg.png differ
diff --git a/doc/rest.rst b/doc/rest.rst
index 293b2ea02..7b2b92ddc 100644
--- a/doc/rest.rst
+++ b/doc/rest.rst
@@ -363,8 +363,9 @@ directory on building (e.g. the ``_static`` directory for HTML output.)
Interpretation of image size options (``width`` and ``height``) is as follows:
if the size has no unit or the unit is pixels, the given size will only be
-respected for output channels that support pixels (i.e. not in LaTeX output).
-Other units (like ``pt`` for points) will be used for HTML and LaTeX output.
+respected for output channels that support pixels. Other units (like ``pt``
+for points) will be used for HTML and LaTeX output (the latter replaces ``pt``
+by ``bp`` as this is the TeX unit such that ``72bp=1in``).
Sphinx extends the standard docutils behavior by allowing an asterisk for the
extension::
@@ -386,6 +387,9 @@ Note that image file names should not contain spaces.
.. versionchanged:: 0.6
Image paths can now be absolute.
+.. versionchanged:: 1.5
+ latex target supports pixels (default is ``96px=1in``).
+
Footnotes
---------
diff --git a/doc/themes/agogo.png b/doc/themes/agogo.png
index 453a1f7dc..5a09cb96c 100644
Binary files a/doc/themes/agogo.png and b/doc/themes/agogo.png differ
diff --git a/doc/themes/alabaster.png b/doc/themes/alabaster.png
index 6e02c35ca..4a49c1ad0 100644
Binary files a/doc/themes/alabaster.png and b/doc/themes/alabaster.png differ
diff --git a/doc/themes/bizstyle.png b/doc/themes/bizstyle.png
index 4deae9a79..e19fb6b34 100644
Binary files a/doc/themes/bizstyle.png and b/doc/themes/bizstyle.png differ
diff --git a/doc/themes/classic.png b/doc/themes/classic.png
index 6989ebe9b..3b3c9cbd8 100644
Binary files a/doc/themes/classic.png and b/doc/themes/classic.png differ
diff --git a/doc/themes/fullsize/agogo.png b/doc/themes/fullsize/agogo.png
index bfdba3a17..106a16cea 100644
Binary files a/doc/themes/fullsize/agogo.png and b/doc/themes/fullsize/agogo.png differ
diff --git a/doc/themes/fullsize/alabaster.png b/doc/themes/fullsize/alabaster.png
index 3e026c999..5eca20912 100644
Binary files a/doc/themes/fullsize/alabaster.png and b/doc/themes/fullsize/alabaster.png differ
diff --git a/doc/themes/fullsize/bizstyle.png b/doc/themes/fullsize/bizstyle.png
index d917e2ff2..586064765 100644
Binary files a/doc/themes/fullsize/bizstyle.png and b/doc/themes/fullsize/bizstyle.png differ
diff --git a/doc/themes/fullsize/classic.png b/doc/themes/fullsize/classic.png
index 9c00f6899..269dab22f 100644
Binary files a/doc/themes/fullsize/classic.png and b/doc/themes/fullsize/classic.png differ
diff --git a/doc/themes/fullsize/haiku.png b/doc/themes/fullsize/haiku.png
index 8d807f4e1..707d2bfec 100644
Binary files a/doc/themes/fullsize/haiku.png and b/doc/themes/fullsize/haiku.png differ
diff --git a/doc/themes/fullsize/nature.png b/doc/themes/fullsize/nature.png
index 02d8743b3..00730c0a5 100644
Binary files a/doc/themes/fullsize/nature.png and b/doc/themes/fullsize/nature.png differ
diff --git a/doc/themes/fullsize/pyramid.png b/doc/themes/fullsize/pyramid.png
index 961cb896c..3b9d04d13 100644
Binary files a/doc/themes/fullsize/pyramid.png and b/doc/themes/fullsize/pyramid.png differ
diff --git a/doc/themes/fullsize/scrolls.png b/doc/themes/fullsize/scrolls.png
index 4e5c45f21..8a1c1faf5 100644
Binary files a/doc/themes/fullsize/scrolls.png and b/doc/themes/fullsize/scrolls.png differ
diff --git a/doc/themes/fullsize/sphinx_rtd_theme.png b/doc/themes/fullsize/sphinx_rtd_theme.png
index 4a3d74c88..95cff4ccd 100644
Binary files a/doc/themes/fullsize/sphinx_rtd_theme.png and b/doc/themes/fullsize/sphinx_rtd_theme.png differ
diff --git a/doc/themes/fullsize/sphinxdoc.png b/doc/themes/fullsize/sphinxdoc.png
index b74633452..eb498e3e8 100644
Binary files a/doc/themes/fullsize/sphinxdoc.png and b/doc/themes/fullsize/sphinxdoc.png differ
diff --git a/doc/themes/fullsize/traditional.png b/doc/themes/fullsize/traditional.png
index da69efe12..07ad00875 100644
Binary files a/doc/themes/fullsize/traditional.png and b/doc/themes/fullsize/traditional.png differ
diff --git a/doc/themes/haiku.png b/doc/themes/haiku.png
index 78a2570c4..4530debb9 100644
Binary files a/doc/themes/haiku.png and b/doc/themes/haiku.png differ
diff --git a/doc/themes/nature.png b/doc/themes/nature.png
index cbe773d5c..ad39b32b7 100644
Binary files a/doc/themes/nature.png and b/doc/themes/nature.png differ
diff --git a/doc/themes/pyramid.png b/doc/themes/pyramid.png
index eb13cd5f2..72749dd6b 100644
Binary files a/doc/themes/pyramid.png and b/doc/themes/pyramid.png differ
diff --git a/doc/themes/scrolls.png b/doc/themes/scrolls.png
index 30ccc8d49..1a117379f 100644
Binary files a/doc/themes/scrolls.png and b/doc/themes/scrolls.png differ
diff --git a/doc/themes/sphinx_rtd_theme.png b/doc/themes/sphinx_rtd_theme.png
index e13f52b04..7c3b7ae05 100644
Binary files a/doc/themes/sphinx_rtd_theme.png and b/doc/themes/sphinx_rtd_theme.png differ
diff --git a/doc/themes/sphinxdoc.png b/doc/themes/sphinxdoc.png
index 31512d8d8..587363e61 100644
Binary files a/doc/themes/sphinxdoc.png and b/doc/themes/sphinxdoc.png differ
diff --git a/doc/themes/traditional.png b/doc/themes/traditional.png
index 5ff44f869..9820fd0ea 100644
Binary files a/doc/themes/traditional.png and b/doc/themes/traditional.png differ
diff --git a/doc/theming.rst b/doc/theming.rst
index df0755f1f..ee45df52d 100644
--- a/doc/theming.rst
+++ b/doc/theming.rst
@@ -81,6 +81,8 @@ that has to return the directory with themes in it::
Builtin themes
--------------
+.. cssclass:: longtable
+
+--------------------+--------------------+
| **Theme overview** | |
+--------------------+--------------------+
diff --git a/doc/translation.png b/doc/translation.png
index 347e287f6..11f3d02cd 100644
Binary files a/doc/translation.png and b/doc/translation.png differ
diff --git a/doc/tutorial.rst b/doc/tutorial.rst
index 385746f72..bced21ade 100644
--- a/doc/tutorial.rst
+++ b/doc/tutorial.rst
@@ -300,12 +300,17 @@ features of intersphinx.
More topics to be covered
-------------------------
-- Other extensions (math, viewcode, doctest)
+- :doc:`Other extensions `:
+
+ * :doc:`ext/math`,
+ * :doc:`ext/viewcode`,
+ * :doc:`ext/doctest`,
+ * ...
- Static files
-- Selecting a theme
-- Templating
+- :doc:`Selecting a theme `
+- :ref:`Templating `
- Using extensions
-- Writing extensions
+- :ref:`Writing extensions `
.. rubric:: Footnotes
diff --git a/setup.cfg b/setup.cfg
index 2d2f3b535..be78d68d3 100644
--- a/setup.cfg
+++ b/setup.cfg
@@ -25,5 +25,5 @@ universal = 1
[flake8]
max-line-length=95
-ignore=E113,E116,E221,E226,E241,E251
-exclude=ez_setup.py,utils/*,tests/*,build/*,sphinx/search/*,sphinx/pycode/pgen2/*
+ignore=E113,E116,E221,E226,E241,E251,E901
+exclude=tests/*,build/*,sphinx/search/*,sphinx/pycode/pgen2/*
diff --git a/setup.py b/setup.py
index 3d792b2dc..c1aa346ba 100644
--- a/setup.py
+++ b/setup.py
@@ -64,6 +64,7 @@ extras_require = {
'nose',
'mock', # it would be better for 'test:python_version in "2.6,2.7"'
'simplejson', # better: 'test:platform_python_implementation=="PyPy"'
+ 'html5lib',
],
}
@@ -137,11 +138,8 @@ else:
domain + '.js'))
for js_file, (locale, po_file) in zip(js_files, po_files):
- infile = open(po_file, 'r')
- try:
+ with open(po_file, 'r') as infile:
catalog = read_po(infile, locale)
- finally:
- infile.close()
if catalog.fuzzy and not self.use_fuzzy:
continue
@@ -158,8 +156,7 @@ else:
msgid = msgid[0]
jscatalog[msgid] = message.string
- outfile = open(js_file, 'wb')
- try:
+ with open(js_file, 'wb') as outfile:
outfile.write('Documentation.addTranslations(')
dump(dict(
messages=jscatalog,
@@ -167,8 +164,6 @@ else:
locale=str(catalog.locale)
), outfile, sort_keys=True)
outfile.write(');')
- finally:
- outfile.close()
cmdclass['compile_catalog'] = compile_catalog_plusjs
diff --git a/sphinx/application.py b/sphinx/application.py
index e82719d77..8a23cddd7 100644
--- a/sphinx/application.py
+++ b/sphinx/application.py
@@ -32,9 +32,8 @@ from sphinx.roles import XRefRole
from sphinx.config import Config
from sphinx.errors import SphinxError, SphinxWarning, ExtensionError, \
VersionRequirementError, ConfigError
-from sphinx.domains import ObjType, BUILTIN_DOMAINS
+from sphinx.domains import ObjType
from sphinx.domains.std import GenericObject, Target, StandardDomain
-from sphinx.builders import BUILTIN_BUILDERS
from sphinx.environment import BuildEnvironment
from sphinx.io import SphinxStandaloneReader
from sphinx.util import pycompat # noqa: imported for side-effects
@@ -42,7 +41,7 @@ from sphinx.util import import_object
from sphinx.util.tags import Tags
from sphinx.util.osutil import ENOENT
from sphinx.util.logging import is_suppressed_warning
-from sphinx.util.console import bold, lightgray, darkgray, darkgreen, \
+from sphinx.util.console import bold, lightgray, darkgray, darkred, darkgreen, \
term_width_line
from sphinx.util.i18n import find_catalog_source_files
@@ -65,10 +64,39 @@ events = {
'html-page-context': 'pagename, context, doctree or None',
'build-finished': 'exception',
}
+builtin_extensions = (
+ 'sphinx.builders.applehelp',
+ 'sphinx.builders.changes',
+ 'sphinx.builders.epub',
+ 'sphinx.builders.epub3',
+ 'sphinx.builders.devhelp',
+ 'sphinx.builders.dummy',
+ 'sphinx.builders.gettext',
+ 'sphinx.builders.html',
+ 'sphinx.builders.htmlhelp',
+ 'sphinx.builders.latex',
+ 'sphinx.builders.linkcheck',
+ 'sphinx.builders.manpage',
+ 'sphinx.builders.qthelp',
+ 'sphinx.builders.texinfo',
+ 'sphinx.builders.text',
+ 'sphinx.builders.websupport',
+ 'sphinx.builders.xml',
+ 'sphinx.domains.c',
+ 'sphinx.domains.cpp',
+ 'sphinx.domains.javascript',
+ 'sphinx.domains.python',
+ 'sphinx.domains.rst',
+ 'sphinx.domains.std',
+)
CONFIG_FILENAME = 'conf.py'
ENV_PICKLE_FILENAME = 'environment.pickle'
+# list of deprecated extensions. Keys are extension name.
+# Values are Sphinx version that merge the extension.
+EXTENSION_BLACKLIST = {"sphinxjp.themecore": "1.2"}
+
class Sphinx(object):
@@ -83,9 +111,9 @@ class Sphinx(object):
self._additional_source_parsers = {}
self._listeners = {}
self._setting_up_extension = ['?']
- self.domains = BUILTIN_DOMAINS.copy()
+ self.domains = {}
self.buildername = buildername
- self.builderclasses = BUILTIN_BUILDERS.copy()
+ self.builderclasses = {}
self.builder = None
self.env = None
self.enumerable_nodes = {}
@@ -148,6 +176,10 @@ class Sphinx(object):
if self.confdir is None:
self.confdir = self.srcdir
+ # load all built-in extension modules
+ for extension in builtin_extensions:
+ self.setup_extension(extension)
+
# extension loading support for alabaster theme
# self.config.html_theme is not set from conf.py at here
# for now, sphinx always load a 'alabaster' extension.
@@ -188,6 +220,10 @@ class Sphinx(object):
'version %s and therefore cannot be built with the '
'loaded version (%s).' % (extname, needs_ver, has_ver))
+ # check primary_domain if requested
+ if self.config.primary_domain and self.config.primary_domain not in self.domains:
+ self.warn('primary_domain %r not found, ignored.' % self.config.primary_domain)
+
# set up translation infrastructure
self._init_i18n()
# check all configuration values for permissible types
@@ -235,8 +271,8 @@ class Sphinx(object):
def _init_env(self, freshenv):
if freshenv:
- self.env = BuildEnvironment(self.srcdir, self.doctreedir,
- self.config)
+ self.env = BuildEnvironment(self.srcdir, self.doctreedir, self.config)
+ self.env.set_warnfunc(self.warn)
self.env.find_files(self.config)
for domain in self.domains.keys():
self.env.domains[domain] = self.domains[domain](self.env)
@@ -245,6 +281,7 @@ class Sphinx(object):
self.info(bold('loading pickled environment... '), nonl=True)
self.env = BuildEnvironment.frompickle(
self.srcdir, self.config, path.join(self.doctreedir, ENV_PICKLE_FILENAME))
+ self.env.set_warnfunc(self.warn)
self.env.domains = {}
for domain in self.domains.keys():
# this can raise if the data version doesn't fit
@@ -257,8 +294,6 @@ class Sphinx(object):
self.info('failed: %s' % err)
return self._init_env(freshenv=True)
- self.env.set_warnfunc(self.warn)
-
def _init_builder(self, buildername):
if buildername is None:
print('No builder selected, using default: html', file=self._status)
@@ -267,11 +302,6 @@ class Sphinx(object):
raise SphinxError('Builder name %s not registered' % buildername)
builderclass = self.builderclasses[buildername]
- if isinstance(builderclass, tuple):
- # builtin builder
- mod, cls = builderclass
- builderclass = getattr(
- __import__('sphinx.builders.' + mod, None, None, [cls]), cls)
self.builder = builderclass(self)
self.emit('builder-inited')
@@ -326,7 +356,8 @@ class Sphinx(object):
wfile.flush()
self.messagelog.append(message)
- def warn(self, message, location=None, prefix='WARNING: ', type=None, subtype=None):
+ def warn(self, message, location=None, prefix='WARNING: ',
+ type=None, subtype=None, colorfunc=darkred):
"""Emit a warning.
If *location* is given, it should either be a tuple of (docname, lineno)
@@ -356,7 +387,7 @@ class Sphinx(object):
if self.warningiserror:
raise SphinxWarning(warntext)
self._warncount += 1
- self._log(warntext, self._warning, True)
+ self._log(colorfunc(warntext), self._warning, True)
def info(self, message='', nonl=False):
"""Emit an informational message.
@@ -460,6 +491,11 @@ class Sphinx(object):
self.debug('[app] setting up extension: %r', extension)
if extension in self._extensions:
return
+ if extension in EXTENSION_BLACKLIST:
+ self.warn('the extension %r was already merged with Sphinx since version %s; '
+ 'this extension is ignored.' % (
+ extension, EXTENSION_BLACKLIST[extension]))
+ return
self._setting_up_extension.append(extension)
try:
mod = __import__(extension, None, None, ['setup'])
@@ -557,13 +593,9 @@ class Sphinx(object):
raise ExtensionError('Builder class %s has no "name" attribute'
% builder)
if builder.name in self.builderclasses:
- if isinstance(self.builderclasses[builder.name], tuple):
- raise ExtensionError('Builder %r is a builtin builder' %
- builder.name)
- else:
- raise ExtensionError(
- 'Builder %r already exists (in module %s)' % (
- builder.name, self.builderclasses[builder.name].__module__))
+ raise ExtensionError(
+ 'Builder %r already exists (in module %s)' % (
+ builder.name, self.builderclasses[builder.name].__module__))
self.builderclasses[builder.name] = builder
def add_config_value(self, name, default, rebuild, types=()):
diff --git a/sphinx/builders/__init__.py b/sphinx/builders/__init__.py
index 8863050ba..fe0c9c665 100644
--- a/sphinx/builders/__init__.py
+++ b/sphinx/builders/__init__.py
@@ -451,29 +451,3 @@ class Builder(object):
except AttributeError:
optname = '%s_%s' % (default, option)
return getattr(self.config, optname)
-
-BUILTIN_BUILDERS = {
- 'dummy': ('dummy', 'DummyBuilder'),
- 'html': ('html', 'StandaloneHTMLBuilder'),
- 'dirhtml': ('html', 'DirectoryHTMLBuilder'),
- 'singlehtml': ('html', 'SingleFileHTMLBuilder'),
- 'pickle': ('html', 'PickleHTMLBuilder'),
- 'json': ('html', 'JSONHTMLBuilder'),
- 'web': ('html', 'PickleHTMLBuilder'),
- 'htmlhelp': ('htmlhelp', 'HTMLHelpBuilder'),
- 'devhelp': ('devhelp', 'DevhelpBuilder'),
- 'qthelp': ('qthelp', 'QtHelpBuilder'),
- 'applehelp': ('applehelp', 'AppleHelpBuilder'),
- 'epub': ('epub', 'EpubBuilder'),
- 'epub3': ('epub3', 'Epub3Builder'),
- 'latex': ('latex', 'LaTeXBuilder'),
- 'text': ('text', 'TextBuilder'),
- 'man': ('manpage', 'ManualPageBuilder'),
- 'texinfo': ('texinfo', 'TexinfoBuilder'),
- 'changes': ('changes', 'ChangesBuilder'),
- 'linkcheck': ('linkcheck', 'CheckExternalLinksBuilder'),
- 'websupport': ('websupport', 'WebSupportBuilder'),
- 'gettext': ('gettext', 'MessageCatalogBuilder'),
- 'xml': ('xml', 'XMLBuilder'),
- 'pseudoxml': ('xml', 'PseudoXMLBuilder'),
-}
diff --git a/sphinx/builders/applehelp.py b/sphinx/builders/applehelp.py
index d3ad861dc..e8a476f60 100644
--- a/sphinx/builders/applehelp.py
+++ b/sphinx/builders/applehelp.py
@@ -13,14 +13,16 @@ from __future__ import print_function
import codecs
import pipes
-from os import path
+from os import path, environ
+import shlex
from sphinx.builders.html import StandaloneHTMLBuilder
-from sphinx.util import copy_static_entry
-from sphinx.util.osutil import copyfile, ensuredir
+from sphinx.config import string_classes
+from sphinx.util.osutil import copyfile, ensuredir, make_filename
from sphinx.util.console import bold
+from sphinx.util.fileutil import copy_asset
from sphinx.util.pycompat import htmlescape
-from sphinx.util.matching import compile_matchers
+from sphinx.util.matching import Matcher
from sphinx.errors import SphinxError
import plistlib
@@ -84,6 +86,7 @@ class AppleHelpBuilder(StandaloneHTMLBuilder):
super(AppleHelpBuilder, self).init()
# the output files for HTML help must be .html only
self.out_suffix = '.html'
+ self.link_suffix = '.html'
if self.config.applehelp_bundle_id is None:
raise SphinxError('You must set applehelp_bundle_id before '
@@ -104,17 +107,15 @@ class AppleHelpBuilder(StandaloneHTMLBuilder):
self.finish_tasks.add_task(self.build_helpbook)
def copy_localized_files(self):
- source_dir = path.join(self.confdir,
- self.config.applehelp_locale + '.lproj')
+ source_dir = path.join(self.confdir, self.config.applehelp_locale + '.lproj')
target_dir = self.outdir
if path.isdir(source_dir):
self.info(bold('copying localized files... '), nonl=True)
- ctx = self.globalcontext.copy()
- matchers = compile_matchers(self.config.exclude_patterns)
- copy_static_entry(source_dir, target_dir, self, ctx,
- exclude_matchers=matchers)
+ excluded = Matcher(self.config.exclude_patterns + ['**/.*'])
+ copy_asset(source_dir, target_dir, excluded,
+ context=self.globalcontext, renderer=self.templates)
self.info('done')
@@ -254,3 +255,35 @@ class AppleHelpBuilder(StandaloneHTMLBuilder):
raise AppleHelpCodeSigningFailed(output)
else:
self.info('done')
+
+
+def setup(app):
+ app.setup_extension('sphinx.builders.html')
+ app.add_builder(AppleHelpBuilder)
+
+ app.add_config_value('applehelp_bundle_name',
+ lambda self: make_filename(self.project), 'applehelp')
+ app.add_config_value('applehelp_bundle_id', None, 'applehelp', string_classes)
+ app.add_config_value('applehelp_dev_region', 'en-us', 'applehelp')
+ app.add_config_value('applehelp_bundle_version', '1', 'applehelp')
+ app.add_config_value('applehelp_icon', None, 'applehelp', string_classes)
+ app.add_config_value('applehelp_kb_product',
+ lambda self: '%s-%s' % (make_filename(self.project), self.release),
+ 'applehelp')
+ app.add_config_value('applehelp_kb_url', None, 'applehelp', string_classes)
+ app.add_config_value('applehelp_remote_url', None, 'applehelp', string_classes)
+ app.add_config_value('applehelp_index_anchors', False, 'applehelp', string_classes)
+ app.add_config_value('applehelp_min_term_length', None, 'applehelp', string_classes)
+ app.add_config_value('applehelp_stopwords',
+ lambda self: self.language or 'en', 'applehelp')
+ app.add_config_value('applehelp_locale', lambda self: self.language or 'en', 'applehelp')
+ app.add_config_value('applehelp_title', lambda self: self.project + ' Help', 'applehelp')
+ app.add_config_value('applehelp_codesign_identity',
+ lambda self: environ.get('CODE_SIGN_IDENTITY', None),
+ 'applehelp'),
+ app.add_config_value('applehelp_codesign_flags',
+ lambda self: shlex.split(environ.get('OTHER_CODE_SIGN_FLAGS', '')),
+ 'applehelp'),
+ app.add_config_value('applehelp_indexer_path', '/usr/bin/hiutil', 'applehelp')
+ app.add_config_value('applehelp_codesign_path', '/usr/bin/codesign', 'applehelp')
+ app.add_config_value('applehelp_disable_external_tools', False, None)
diff --git a/sphinx/builders/changes.py b/sphinx/builders/changes.py
index ed9edc403..1bccb67d9 100644
--- a/sphinx/builders/changes.py
+++ b/sphinx/builders/changes.py
@@ -15,12 +15,12 @@ from os import path
from six import iteritems
from sphinx import package_dir
-from sphinx.util import copy_static_entry
from sphinx.locale import _
from sphinx.theming import Theme
from sphinx.builders import Builder
from sphinx.util.osutil import ensuredir, os_path
from sphinx.util.console import bold
+from sphinx.util.fileutil import copy_asset_file
from sphinx.util.pycompat import htmlescape
@@ -138,12 +138,10 @@ class ChangesBuilder(Builder):
f.write(self.templates.render('changes/rstsource.html', ctx))
themectx = dict(('theme_' + key, val) for (key, val) in
iteritems(self.theme.get_options({})))
- copy_static_entry(path.join(package_dir, 'themes', 'default',
- 'static', 'default.css_t'),
- self.outdir, self, themectx)
- copy_static_entry(path.join(package_dir, 'themes', 'basic',
- 'static', 'basic.css'),
- self.outdir, self)
+ copy_asset_file(path.join(package_dir, 'themes', 'default', 'static', 'default.css_t'),
+ self.outdir, context=themectx, renderer=self.templates)
+ copy_asset_file(path.join(package_dir, 'themes', 'basic', 'static', 'basic.css'),
+ self.outdir)
def hl(self, text, version):
text = htmlescape(text)
@@ -154,3 +152,7 @@ class ChangesBuilder(Builder):
def finish(self):
pass
+
+
+def setup(app):
+ app.add_builder(ChangesBuilder)
diff --git a/sphinx/builders/devhelp.py b/sphinx/builders/devhelp.py
index eb3e997d8..0f88e9f38 100644
--- a/sphinx/builders/devhelp.py
+++ b/sphinx/builders/devhelp.py
@@ -18,6 +18,7 @@ from os import path
from docutils import nodes
from sphinx import addnodes
+from sphinx.util.osutil import make_filename
from sphinx.builders.html import StandaloneHTMLBuilder
try:
@@ -59,6 +60,7 @@ class DevhelpBuilder(StandaloneHTMLBuilder):
def init(self):
StandaloneHTMLBuilder.init(self)
self.out_suffix = '.html'
+ self.link_suffix = '.html'
def handle_finish(self):
self.build_devhelp(self.outdir, self.config.devhelp_basename)
@@ -129,3 +131,10 @@ class DevhelpBuilder(StandaloneHTMLBuilder):
# Dump the XML file
with comp_open(path.join(outdir, outname + '.devhelp'), 'w') as f:
tree.write(f, 'utf-8')
+
+
+def setup(app):
+ app.setup_extension('sphinx.builders.html')
+ app.add_builder(DevhelpBuilder)
+
+ app.add_config_value('devhelp_basename', lambda self: make_filename(self.project), None)
diff --git a/sphinx/builders/dummy.py b/sphinx/builders/dummy.py
index 75b834c2b..b119d9687 100644
--- a/sphinx/builders/dummy.py
+++ b/sphinx/builders/dummy.py
@@ -34,3 +34,7 @@ class DummyBuilder(Builder):
def finish(self):
pass
+
+
+def setup(app):
+ app.add_builder(DummyBuilder)
diff --git a/sphinx/builders/epub.py b/sphinx/builders/epub.py
index 349574ae0..e46d2cba0 100644
--- a/sphinx/builders/epub.py
+++ b/sphinx/builders/epub.py
@@ -29,7 +29,7 @@ from docutils import nodes
from sphinx import addnodes
from sphinx.builders.html import StandaloneHTMLBuilder
from sphinx.util.i18n import format_date
-from sphinx.util.osutil import ensuredir, copyfile, EEXIST
+from sphinx.util.osutil import ensuredir, copyfile, make_filename, EEXIST
from sphinx.util.smartypants import sphinx_smarty_pants as ssp
from sphinx.util.console import brown
@@ -152,6 +152,7 @@ MEDIA_TYPES = {
'.jpeg': 'image/jpeg',
'.otf': 'application/x-font-otf',
'.ttf': 'application/x-font-ttf',
+ '.woff': 'application/font-woff',
}
VECTOR_GRAPHICS_EXTENSIONS = ('.svg',)
@@ -760,3 +761,33 @@ class EpubBuilder(StandaloneHTMLBuilder):
fp = path.join(outdir, file)
epub.write(fp, file, zipfile.ZIP_DEFLATED)
epub.close()
+
+
+def setup(app):
+ app.setup_extension('sphinx.builders.html')
+ app.add_builder(EpubBuilder)
+
+ # config values
+ app.add_config_value('epub_basename', lambda self: make_filename(self.project), None)
+ app.add_config_value('epub_theme', 'epub', 'html')
+ app.add_config_value('epub_theme_options', {}, 'html')
+ app.add_config_value('epub_title', lambda self: self.html_title, 'html')
+ app.add_config_value('epub_author', 'unknown', 'html')
+ app.add_config_value('epub_language', lambda self: self.language or 'en', 'html')
+ app.add_config_value('epub_publisher', 'unknown', 'html')
+ app.add_config_value('epub_copyright', lambda self: self.copyright, 'html')
+ app.add_config_value('epub_identifier', 'unknown', 'html')
+ app.add_config_value('epub_scheme', 'unknown', 'html')
+ app.add_config_value('epub_uid', 'unknown', 'env')
+ app.add_config_value('epub_cover', (), 'env')
+ app.add_config_value('epub_guide', (), 'env')
+ app.add_config_value('epub_pre_files', [], 'env')
+ app.add_config_value('epub_post_files', [], 'env')
+ app.add_config_value('epub_exclude_files', [], 'env')
+ app.add_config_value('epub_tocdepth', 3, 'env')
+ app.add_config_value('epub_tocdup', True, 'env')
+ app.add_config_value('epub_tocscope', 'default', 'env')
+ app.add_config_value('epub_fix_images', False, 'env')
+ app.add_config_value('epub_max_image_width', 0, 'env')
+ app.add_config_value('epub_show_urls', 'inline', 'html')
+ app.add_config_value('epub_use_index', lambda self: self.html_use_index, 'html')
diff --git a/sphinx/builders/epub3.py b/sphinx/builders/epub3.py
index b243486f6..57ed1abbe 100644
--- a/sphinx/builders/epub3.py
+++ b/sphinx/builders/epub3.py
@@ -13,6 +13,7 @@
import codecs
from os import path
+from sphinx.config import string_classes
from sphinx.builders.epub import EpubBuilder
@@ -209,3 +210,12 @@ class Epub3Builder(EpubBuilder):
# Add nav.xhtml to epub file
self.files.append(outname)
+
+
+def setup(app):
+ app.setup_extension('sphinx.builders.epub')
+ app.add_builder(Epub3Builder)
+
+ app.add_config_value('epub3_description', '', 'epub3', string_classes)
+ app.add_config_value('epub3_contributor', 'unknown', 'epub3', string_classes)
+ app.add_config_value('epub3_page_progression_direction', 'ltr', 'epub3', string_classes)
diff --git a/sphinx/builders/gettext.py b/sphinx/builders/gettext.py
index c8f4dab4f..aa9400575 100644
--- a/sphinx/builders/gettext.py
+++ b/sphinx/builders/gettext.py
@@ -135,7 +135,7 @@ tzdelta = datetime.fromtimestamp(timestamp) - \
source_date_epoch = getenv('SOURCE_DATE_EPOCH')
if source_date_epoch is not None:
timestamp = float(source_date_epoch)
- tzdelta = 0
+ tzdelta = timedelta(0)
class LocalTimeZone(tzinfo):
@@ -233,3 +233,13 @@ class MessageCatalogBuilder(I18nBuilder):
replace('"', r'\"'). \
replace('\n', '\\n"\n"')
pofile.write('msgid "%s"\nmsgstr ""\n\n' % message)
+
+
+def setup(app):
+ app.add_builder(MessageCatalogBuilder)
+
+ app.add_config_value('gettext_compact', True, 'gettext')
+ app.add_config_value('gettext_location', True, 'gettext')
+ app.add_config_value('gettext_uuid', False, 'gettext')
+ app.add_config_value('gettext_auto_build', True, 'env')
+ app.add_config_value('gettext_additional_targets', [], 'env')
diff --git a/sphinx/builders/html.py b/sphinx/builders/html.py
index 63ccdd66c..462f5f00a 100644
--- a/sphinx/builders/html.py
+++ b/sphinx/builders/html.py
@@ -27,13 +27,15 @@ from docutils.frontend import OptionParser
from docutils.readers.doctree import Reader as DoctreeReader
from sphinx import package_dir, __display_version__
-from sphinx.util import jsonimpl, copy_static_entry, copy_extra_entry
+from sphinx.util import jsonimpl
from sphinx.util.i18n import format_date
from sphinx.util.osutil import SEP, os_path, relative_uri, ensuredir, \
movefile, copyfile
from sphinx.util.nodes import inline_all_toctrees
-from sphinx.util.matching import patmatch, compile_matchers
-from sphinx.locale import _
+from sphinx.util.fileutil import copy_asset
+from sphinx.util.matching import patmatch, Matcher, DOTFILES
+from sphinx.config import string_classes
+from sphinx.locale import _, l_
from sphinx.search import js_index
from sphinx.theming import Theme
from sphinx.builders import Builder
@@ -339,6 +341,7 @@ class StandaloneHTMLBuilder(Builder):
show_sphinx = self.config.html_show_sphinx,
has_source = self.config.html_copy_source,
show_source = self.config.html_show_sourcelink,
+ sourcelink_suffix = self.config.html_sourcelink_suffix,
file_suffix = self.out_suffix,
script_files = self.script_files,
language = self.config.language,
@@ -402,15 +405,21 @@ class StandaloneHTMLBuilder(Builder):
# title rendered as HTML
title = self.env.longtitles.get(docname)
title = title and self.render_partial(title)['title'] or ''
+
+ # Suffix for the document
+ source_suffix = path.splitext(self.env.doc2path(docname))[1]
+
# the name for the copied source
- sourcename = self.config.html_copy_source and docname + '.txt' or ''
+ if self.config.html_copy_source:
+ sourcename = docname + source_suffix
+ if source_suffix != self.config.html_sourcelink_suffix:
+ sourcename += self.config.html_sourcelink_suffix
+ else:
+ sourcename = ''
# metadata for the document
meta = self.env.metadata.get(docname)
- # Suffix for the document
- source_suffix = '.' + self.env.doc2path(docname).split('.')[-1]
-
# local TOC and global TOC tree
self_toc = self.env.get_toc_for(docname, self)
toc = self.render_partial(self_toc)['fragment']
@@ -581,9 +590,8 @@ class StandaloneHTMLBuilder(Builder):
self.info(bold('copying static files... '), nonl=True)
ensuredir(path.join(self.outdir, '_static'))
# first, create pygments style file
- f = open(path.join(self.outdir, '_static', 'pygments.css'), 'w')
- f.write(self.highlighter.get_stylesheet())
- f.close()
+ with open(path.join(self.outdir, '_static', 'pygments.css'), 'w') as f:
+ f.write(self.highlighter.get_stylesheet())
# then, copy translations JavaScript file
if self.config.language is not None:
jsfile = self._get_translations_js()
@@ -605,21 +613,19 @@ class StandaloneHTMLBuilder(Builder):
# then, copy over theme-supplied static files
if self.theme:
- themeentries = [path.join(themepath, 'static')
- for themepath in self.theme.get_dirchain()[::-1]]
- for entry in themeentries:
- copy_static_entry(entry, path.join(self.outdir, '_static'),
- self, ctx)
+ for theme_path in self.theme.get_dirchain()[::-1]:
+ entry = path.join(theme_path, 'static')
+ copy_asset(entry, path.join(self.outdir, '_static'), excluded=DOTFILES,
+ context=ctx, renderer=self.templates)
# then, copy over all user-supplied static files
- staticentries = [path.join(self.confdir, spath)
- for spath in self.config.html_static_path]
- matchers = compile_matchers(self.config.exclude_patterns)
- for entry in staticentries:
+ excluded = Matcher(self.config.exclude_patterns + ["**/.*"])
+ for static_path in self.config.html_static_path:
+ entry = path.join(self.confdir, static_path)
if not path.exists(entry):
self.warn('html_static_path entry %r does not exist' % entry)
continue
- copy_static_entry(entry, path.join(self.outdir, '_static'), self,
- ctx, exclude_matchers=matchers)
+ copy_asset(entry, path.join(self.outdir, '_static'), excluded,
+ context=ctx, renderer=self.templates)
# copy logo and favicon files if not already in static path
if self.config.html_logo:
logobase = path.basename(self.config.html_logo)
@@ -642,14 +648,15 @@ class StandaloneHTMLBuilder(Builder):
def copy_extra_files(self):
# copy html_extra_path files
self.info(bold('copying extra files... '), nonl=True)
- extraentries = [path.join(self.confdir, epath)
- for epath in self.config.html_extra_path]
- matchers = compile_matchers(self.config.exclude_patterns)
- for entry in extraentries:
+ excluded = Matcher(self.config.exclude_patterns)
+
+ for extra_path in self.config.html_extra_path:
+ entry = path.join(self.confdir, extra_path)
if not path.exists(entry):
self.warn('html_extra_path entry %r does not exist' % entry)
continue
- copy_extra_entry(entry, self.outdir, matchers)
+
+ copy_asset(entry, self.outdir, excluded)
self.info('done')
def write_buildinfo(self):
@@ -712,7 +719,12 @@ class StandaloneHTMLBuilder(Builder):
def index_page(self, pagename, doctree, title):
# only index pages with title
if self.indexer is not None and title:
- self.indexer.feed(pagename, title, doctree)
+ filename = self.env.doc2path(pagename, base=None)
+ try:
+ self.indexer.feed(pagename, filename, title, doctree)
+ except TypeError:
+ # fallback for old search-adapters
+ self.indexer.feed(pagename, title, doctree)
def _get_local_toctree(self, docname, collapse=True, **kwds):
if 'includehidden' not in kwds:
@@ -1056,6 +1068,7 @@ class SerializingHTMLBuilder(StandaloneHTMLBuilder):
self.theme = None # no theme necessary
self.templates = None # no template bridge necessary
self.init_translator_class()
+ self.init_templates()
self.init_highlighter()
def get_target_uri(self, docname, typ=None):
@@ -1148,3 +1161,52 @@ class JSONHTMLBuilder(SerializingHTMLBuilder):
def init(self):
SerializingHTMLBuilder.init(self)
+
+
+def setup(app):
+ # builders
+ app.add_builder(StandaloneHTMLBuilder)
+ app.add_builder(DirectoryHTMLBuilder)
+ app.add_builder(SingleFileHTMLBuilder)
+ app.add_builder(PickleHTMLBuilder)
+ app.add_builder(JSONHTMLBuilder)
+
+ # config values
+ app.add_config_value('html_theme', 'alabaster', 'html')
+ app.add_config_value('html_theme_path', [], 'html')
+ app.add_config_value('html_theme_options', {}, 'html')
+ app.add_config_value('html_title',
+ lambda self: l_('%s %s documentation') % (self.project, self.release),
+ 'html', string_classes)
+ app.add_config_value('html_short_title', lambda self: self.html_title, 'html')
+ app.add_config_value('html_style', None, 'html', string_classes)
+ app.add_config_value('html_logo', None, 'html', string_classes)
+ app.add_config_value('html_favicon', None, 'html', string_classes)
+ app.add_config_value('html_static_path', [], 'html')
+ app.add_config_value('html_extra_path', [], 'html')
+ app.add_config_value('html_last_updated_fmt', None, 'html', string_classes)
+ app.add_config_value('html_use_smartypants', True, 'html')
+ app.add_config_value('html_translator_class', None, 'html', string_classes)
+ app.add_config_value('html_sidebars', {}, 'html')
+ app.add_config_value('html_additional_pages', {}, 'html')
+ app.add_config_value('html_use_modindex', True, 'html') # deprecated
+ app.add_config_value('html_domain_indices', True, 'html', [list])
+ app.add_config_value('html_add_permalinks', u'\u00B6', 'html')
+ app.add_config_value('html_use_index', True, 'html')
+ app.add_config_value('html_split_index', False, 'html')
+ app.add_config_value('html_copy_source', True, 'html')
+ app.add_config_value('html_show_sourcelink', True, 'html')
+ app.add_config_value('html_sourcelink_suffix', '.txt', 'html')
+ app.add_config_value('html_use_opensearch', '', 'html')
+ app.add_config_value('html_file_suffix', None, 'html', string_classes)
+ app.add_config_value('html_link_suffix', None, 'html', string_classes)
+ app.add_config_value('html_show_copyright', True, 'html')
+ app.add_config_value('html_show_sphinx', True, 'html')
+ app.add_config_value('html_context', {}, 'html')
+ app.add_config_value('html_output_encoding', 'utf-8', 'html')
+ app.add_config_value('html_compact_lists', True, 'html')
+ app.add_config_value('html_secnumber_suffix', '. ', 'html')
+ app.add_config_value('html_search_language', None, 'html', string_classes)
+ app.add_config_value('html_search_options', {}, 'html')
+ app.add_config_value('html_search_scorer', '', None)
+ app.add_config_value('html_scaled_image_link', True, 'html')
diff --git a/sphinx/builders/htmlhelp.py b/sphinx/builders/htmlhelp.py
index b1a5d7dda..cdb51b2c6 100644
--- a/sphinx/builders/htmlhelp.py
+++ b/sphinx/builders/htmlhelp.py
@@ -18,6 +18,7 @@ from os import path
from docutils import nodes
from sphinx import addnodes
+from sphinx.util.osutil import make_filename
from sphinx.builders.html import StandaloneHTMLBuilder
from sphinx.util.pycompat import htmlescape
@@ -63,7 +64,7 @@ Binary Index=No
Compiled file=%(outname)s.chm
Contents file=%(outname)s.hhc
Default Window=%(outname)s
-Default topic=index.html
+Default topic=%(master_doc)s
Display compile progress=No
Full text search stop list file=%(outname)s.stp
Full-text search=Yes
@@ -73,7 +74,7 @@ Title=%(title)s
[WINDOWS]
%(outname)s="%(title)s","%(outname)s.hhc","%(outname)s.hhk",\
-"index.html","index.html",,,,,0x63520,220,0x10384e,[0,0,1024,768],,,,,,,0
+"%(master_doc)s","%(master_doc)s",,,,,0x63520,220,0x10384e,[0,0,1024,768],,,,,,,0
[FILES]
'''
@@ -183,6 +184,7 @@ class HTMLHelpBuilder(StandaloneHTMLBuilder):
StandaloneHTMLBuilder.init(self)
# the output files for HTML help must be .html only
self.out_suffix = '.html'
+ self.link_suffix = '.html'
# determine the correct locale setting
locale = chm_locales.get(self.config.language)
if locale is not None:
@@ -204,11 +206,14 @@ class HTMLHelpBuilder(StandaloneHTMLBuilder):
self.info('writing project file...')
with self.open_file(outdir, outname+'.hhp') as f:
- f.write(project_template % {'outname': outname,
- 'title': self.config.html_title,
- 'version': self.config.version,
- 'project': self.config.project,
- 'lcid': self.lcid})
+ f.write(project_template % {
+ 'outname': outname,
+ 'title': self.config.html_title,
+ 'version': self.config.version,
+ 'project': self.config.project,
+ 'lcid': self.lcid,
+ 'master_doc': self.config.master_doc + self.out_suffix
+ })
if not outdir.endswith(os.sep):
outdir += os.sep
olen = len(outdir)
@@ -225,7 +230,7 @@ class HTMLHelpBuilder(StandaloneHTMLBuilder):
f.write(contents_header)
# special books
f.write(' ' + object_sitemap % (self.config.html_short_title,
- 'index.html'))
+ self.config.master_doc + self.out_suffix))
for indexname, indexcls, content, collapse in self.domain_indices:
f.write(' ' + object_sitemap % (indexcls.localname,
'%s.html' % indexname))
@@ -292,3 +297,10 @@ class HTMLHelpBuilder(StandaloneHTMLBuilder):
for title, (refs, subitems, key_) in group:
write_index(title, refs, subitems)
f.write('\n')
+
+
+def setup(app):
+ app.setup_extension('sphinx.builders.html')
+ app.add_builder(HTMLHelpBuilder)
+
+ app.add_config_value('htmlhelp_basename', lambda self: make_filename(self.project), None)
diff --git a/sphinx/builders/latex.py b/sphinx/builders/latex.py
index ac26e33c9..f82e7ade0 100644
--- a/sphinx/builders/latex.py
+++ b/sphinx/builders/latex.py
@@ -11,7 +11,6 @@
import os
from os import path
-import warnings
from six import iteritems
from docutils import nodes
@@ -19,14 +18,15 @@ from docutils.io import FileOutput
from docutils.utils import new_document
from docutils.frontend import OptionParser
-from sphinx import package_dir, addnodes
+from sphinx import package_dir, addnodes, highlighting
from sphinx.util import texescape
+from sphinx.config import string_classes
from sphinx.errors import SphinxError
from sphinx.locale import _
from sphinx.builders import Builder
from sphinx.environment import NoUri
from sphinx.util.nodes import inline_all_toctrees
-from sphinx.util.osutil import SEP, copyfile
+from sphinx.util.osutil import SEP, copyfile, make_filename
from sphinx.util.console import bold, darkgreen
from sphinx.writers.latex import LaTeXWriter
@@ -44,21 +44,6 @@ class LaTeXBuilder(Builder):
self.docnames = []
self.document_data = []
texescape.init()
- self.check_options()
-
- def check_options(self):
- if self.config.latex_toplevel_sectioning not in (None, 'part', 'chapter', 'section'):
- self.warn('invalid latex_toplevel_sectioning, ignored: %s' %
- self.config.latex_top_sectionlevel)
- self.config.latex_top_sectionlevel = None
-
- if self.config.latex_use_parts:
- warnings.warn('latex_use_parts will be removed at Sphinx-1.5. '
- 'Use latex_toplevel_sectioning instead.',
- DeprecationWarning)
-
- if self.config.latex_toplevel_sectioning:
- self.warn('latex_use_parts conflicts with latex_toplevel_sectioning, ignored.')
def get_outdated_docs(self):
return 'all documents' # for now
@@ -92,6 +77,16 @@ class LaTeXBuilder(Builder):
docname = docname[:-5]
self.titles.append((docname, entry[2]))
+ def write_stylesheet(self):
+ highlighter = highlighting.PygmentsBridge(
+ 'latex', self.config.pygments_style, self.config.trim_doctest_flags)
+ stylesheet = path.join(self.outdir, 'sphinxhighlight.sty')
+ with open(stylesheet, 'w') as f:
+ f.write('\\NeedsTeXFormat{LaTeX2e}[1995/12/01]\n')
+ f.write('\\ProvidesPackage{sphinxhighlight}'
+ '[2016/05/29 stylesheet for highlighting with pygments]\n\n')
+ f.write(highlighter.get_stylesheet())
+
def write(self, *ignored):
docwriter = LaTeXWriter(self)
docsettings = OptionParser(
@@ -100,6 +95,7 @@ class LaTeXBuilder(Builder):
read_config_files=True).get_default_values()
self.init_document_data()
+ self.write_stylesheet()
for entry in self.document_data:
docname, targetname, title, author, docclass = entry[:5]
@@ -222,3 +218,72 @@ class LaTeXBuilder(Builder):
elif not path.isfile(logotarget):
copyfile(path.join(self.confdir, self.config.latex_logo), logotarget)
self.info('done')
+
+
+def validate_config_values(app):
+ if app.config.latex_toplevel_sectioning not in (None, 'part', 'chapter', 'section'):
+ app.warn('invalid latex_toplevel_sectioning, ignored: %s' %
+ app.config.latex_toplevel_sectioning)
+ app.config.latex_toplevel_sectioning = None
+
+ if app.config.latex_use_parts:
+ if app.config.latex_toplevel_sectioning:
+ app.warn('latex_use_parts conflicts with latex_toplevel_sectioning, ignored.')
+ else:
+ app.warn('latex_use_parts is deprecated. Use latex_toplevel_sectioning instead.')
+ app.config.latex_toplevel_sectioning = 'parts'
+
+ if app.config.latex_use_modindex is not True: # changed by user
+ app.warn('latex_use_modeindex is deprecated. Use latex_domain_indices instead.')
+
+ if app.config.latex_preamble:
+ if app.config.latex_elements.get('preamble'):
+ app.warn("latex_preamble conflicts with latex_elements['preamble'], ignored.")
+ else:
+ app.warn("latex_preamble is deprecated. Use latex_elements['preamble'] instead.")
+ app.config.latex_elements['preamble'] = app.config.latex_preamble
+
+ if app.config.latex_paper_size != 'letter':
+ if app.config.latex_elements.get('papersize'):
+ app.warn("latex_paper_size conflicts with latex_elements['papersize'], ignored.")
+ else:
+ app.warn("latex_paper_size is deprecated. "
+ "Use latex_elements['papersize'] instead.")
+ if app.config.latex_paper_size:
+ app.config.latex_elements['papersize'] = app.config.latex_paper_size + 'paper'
+
+ if app.config.latex_font_size != '10pt':
+ if app.config.latex_elements.get('pointsize'):
+ app.warn("latex_font_size conflicts with latex_elements['pointsize'], ignored.")
+ else:
+ app.warn("latex_font_size is deprecated. Use latex_elements['pointsize'] instead.")
+ app.config.latex_elements['pointsize'] = app.config.latex_font_size
+
+
+def setup(app):
+ app.add_builder(LaTeXBuilder)
+ app.connect('builder-inited', validate_config_values)
+
+ app.add_config_value('latex_documents',
+ lambda self: [(self.master_doc, make_filename(self.project) + '.tex',
+ self.project, '', 'manual')],
+ None)
+ app.add_config_value('latex_logo', None, None, string_classes)
+ app.add_config_value('latex_appendices', [], None)
+ app.add_config_value('latex_keep_old_macro_names', True, None)
+ # now deprecated - use latex_toplevel_sectioning
+ app.add_config_value('latex_use_parts', False, None)
+ app.add_config_value('latex_toplevel_sectioning', None, None, [str])
+ app.add_config_value('latex_use_modindex', True, None) # deprecated
+ app.add_config_value('latex_domain_indices', True, None, [list])
+ app.add_config_value('latex_show_urls', 'no', None)
+ app.add_config_value('latex_show_pagerefs', False, None)
+ # paper_size and font_size are still separate values
+ # so that you can give them easily on the command line
+ app.add_config_value('latex_paper_size', 'letter', None)
+ app.add_config_value('latex_font_size', '10pt', None)
+ app.add_config_value('latex_elements', {}, None)
+ app.add_config_value('latex_additional_files', [], None)
+ app.add_config_value('latex_docclass', {}, None)
+ # now deprecated - use latex_elements
+ app.add_config_value('latex_preamble', '', None)
diff --git a/sphinx/builders/linkcheck.py b/sphinx/builders/linkcheck.py
index 7c30597a8..4764f6947 100644
--- a/sphinx/builders/linkcheck.py
+++ b/sphinx/builders/linkcheck.py
@@ -300,3 +300,13 @@ class CheckExternalLinksBuilder(Builder):
def finish(self):
for worker in self.workers:
self.wqueue.put((None, None, None), False)
+
+
+def setup(app):
+ app.add_builder(CheckExternalLinksBuilder)
+
+ app.add_config_value('linkcheck_ignore', [], None)
+ app.add_config_value('linkcheck_retries', 1, None)
+ app.add_config_value('linkcheck_timeout', None, None, [int])
+ app.add_config_value('linkcheck_workers', 5, None)
+ app.add_config_value('linkcheck_anchors', True, None)
diff --git a/sphinx/builders/manpage.py b/sphinx/builders/manpage.py
index a2e75f9f7..248ed40b2 100644
--- a/sphinx/builders/manpage.py
+++ b/sphinx/builders/manpage.py
@@ -19,6 +19,7 @@ from sphinx import addnodes
from sphinx.builders import Builder
from sphinx.environment import NoUri
from sphinx.util.nodes import inline_all_toctrees
+from sphinx.util.osutil import make_filename
from sphinx.util.console import bold, darkgreen
from sphinx.writers.manpage import ManualPageWriter
@@ -88,3 +89,13 @@ class ManualPageBuilder(Builder):
def finish(self):
pass
+
+
+def setup(app):
+ app.add_builder(ManualPageBuilder)
+
+ app.add_config_value('man_pages',
+ lambda self: [(self.master_doc, make_filename(self.project).lower(),
+ '%s %s' % (self.project, self.release), [], 1)],
+ None)
+ app.add_config_value('man_show_urls', False, None)
diff --git a/sphinx/builders/qthelp.py b/sphinx/builders/qthelp.py
index 4139c92c6..d55ea3cc7 100644
--- a/sphinx/builders/qthelp.py
+++ b/sphinx/builders/qthelp.py
@@ -21,6 +21,7 @@ from docutils import nodes
from sphinx import addnodes
from sphinx.builders.html import StandaloneHTMLBuilder
from sphinx.util import force_decode
+from sphinx.util.osutil import make_filename
from sphinx.util.pycompat import htmlescape
@@ -111,6 +112,7 @@ class QtHelpBuilder(StandaloneHTMLBuilder):
StandaloneHTMLBuilder.init(self)
# the output files for HTML help must be .html only
self.out_suffix = '.html'
+ self.link_suffix = '.html'
# self.config.html_style = 'traditional.css'
def handle_finish(self):
@@ -290,3 +292,10 @@ class QtHelpBuilder(StandaloneHTMLBuilder):
keywords.extend(self.build_keywords(subitem[0], subitem[1], []))
return keywords
+
+
+def setup(app):
+ app.setup_extension('sphinx.builders.html')
+ app.add_builder(QtHelpBuilder)
+
+ app.add_config_value('qthelp_basename', lambda self: make_filename(self.project), None)
diff --git a/sphinx/builders/texinfo.py b/sphinx/builders/texinfo.py
index 8c4bd2419..f070840b6 100644
--- a/sphinx/builders/texinfo.py
+++ b/sphinx/builders/texinfo.py
@@ -22,7 +22,7 @@ from sphinx.locale import _
from sphinx.builders import Builder
from sphinx.environment import NoUri
from sphinx.util.nodes import inline_all_toctrees
-from sphinx.util.osutil import SEP, copyfile
+from sphinx.util.osutil import SEP, copyfile, make_filename
from sphinx.util.console import bold, darkgreen
from sphinx.writers.texinfo import TexinfoWriter
@@ -225,3 +225,20 @@ class TexinfoBuilder(Builder):
except (IOError, OSError) as err:
self.warn("error writing file %s: %s" % (fn, err))
self.info(' done')
+
+
+def setup(app):
+ app.add_builder(TexinfoBuilder)
+
+ app.add_config_value('texinfo_documents',
+ lambda self: [(self.master_doc, make_filename(self.project).lower(),
+ self.project, '', make_filename(self.project),
+ 'The %s reference manual.' %
+ make_filename(self.project),
+ 'Python')],
+ None)
+ app.add_config_value('texinfo_appendices', [], None)
+ app.add_config_value('texinfo_elements', {}, None)
+ app.add_config_value('texinfo_domain_indices', True, None, [list])
+ app.add_config_value('texinfo_show_urls', 'footnote', None)
+ app.add_config_value('texinfo_no_detailmenu', False, None)
diff --git a/sphinx/builders/text.py b/sphinx/builders/text.py
index 202ec20db..2daf8b043 100644
--- a/sphinx/builders/text.py
+++ b/sphinx/builders/text.py
@@ -67,3 +67,10 @@ class TextBuilder(Builder):
def finish(self):
pass
+
+
+def setup(app):
+ app.add_builder(TextBuilder)
+
+ app.add_config_value('text_sectionchars', '*=-~"+`', 'env')
+ app.add_config_value('text_newlines', 'unix', 'env')
diff --git a/sphinx/builders/websupport.py b/sphinx/builders/websupport.py
index 843b0899e..d8ff5ad8d 100644
--- a/sphinx/builders/websupport.py
+++ b/sphinx/builders/websupport.py
@@ -165,3 +165,7 @@ class WebSupportBuilder(PickleHTMLBuilder):
def dump_search_index(self):
self.indexer.finish_indexing()
+
+
+def setup(app):
+ app.add_builder(WebSupportBuilder)
diff --git a/sphinx/builders/xml.py b/sphinx/builders/xml.py
index 589e8a63a..e0e33312c 100644
--- a/sphinx/builders/xml.py
+++ b/sphinx/builders/xml.py
@@ -95,3 +95,10 @@ class PseudoXMLBuilder(XMLBuilder):
out_suffix = '.pseudoxml'
_writer_class = PseudoXMLWriter
+
+
+def setup(app):
+ app.add_builder(XMLBuilder)
+ app.add_builder(PseudoXMLBuilder)
+
+ app.add_config_value('xml_pretty', True, 'env')
diff --git a/sphinx/config.py b/sphinx/config.py
index ef57334fe..13921aac8 100644
--- a/sphinx/config.py
+++ b/sphinx/config.py
@@ -10,14 +10,13 @@
"""
import re
-from os import path, environ, getenv
-import shlex
+from os import path, getenv
from six import PY2, PY3, iteritems, string_types, binary_type, text_type, integer_types
from sphinx.errors import ConfigError
from sphinx.locale import l_
-from sphinx.util.osutil import make_filename, cd
+from sphinx.util.osutil import cd
from sphinx.util.pycompat import execfile_, NoneType
from sphinx.util.i18n import format_date
@@ -29,10 +28,25 @@ if PY3:
CONFIG_SYNTAX_ERROR += "\nDid you change the syntax from 2.x to 3.x?"
CONFIG_EXIT_ERROR = "The configuration file (or one of the modules it imports) " \
"called sys.exit()"
+CONFIG_ENUM_WARNING = "The config value `{name}` has to be a one of {candidates}, " \
+ "but `{current}` is given."
CONFIG_TYPE_WARNING = "The config value `{name}' has type `{current.__name__}', " \
"defaults to `{default.__name__}.'"
+class ENUM:
+ """represents the config value should be a one of candidates.
+
+ Example:
+ app.add_config_value('latex_show_urls', 'no', ENUM('no', 'footnote', 'inline'))
+ """
+ def __init__(self, *candidates):
+ self.candidates = candidates
+
+ def match(self, value):
+ return value in self.candidates
+
+
string_classes = [text_type]
if PY2:
string_classes.append(binary_type) # => [str, unicode]
@@ -94,181 +108,6 @@ class Config(object):
'table': l_('Table %s'),
'code-block': l_('Listing %s')},
'env'),
-
- # HTML options
- html_theme = ('alabaster', 'html'),
- html_theme_path = ([], 'html'),
- html_theme_options = ({}, 'html'),
- html_title = (lambda self: l_('%s %s documentation') %
- (self.project, self.release),
- 'html', string_classes),
- html_short_title = (lambda self: self.html_title, 'html'),
- html_style = (None, 'html', string_classes),
- html_logo = (None, 'html', string_classes),
- html_favicon = (None, 'html', string_classes),
- html_static_path = ([], 'html'),
- html_extra_path = ([], 'html'),
- # the real default is locale-dependent
- html_last_updated_fmt = (None, 'html', string_classes),
- html_use_smartypants = (True, 'html'),
- html_translator_class = (None, 'html', string_classes),
- html_sidebars = ({}, 'html'),
- html_additional_pages = ({}, 'html'),
- html_use_modindex = (True, 'html'), # deprecated
- html_domain_indices = (True, 'html', [list]),
- html_add_permalinks = (u'\u00B6', 'html'),
- html_use_index = (True, 'html'),
- html_split_index = (False, 'html'),
- html_copy_source = (True, 'html'),
- html_show_sourcelink = (True, 'html'),
- html_use_opensearch = ('', 'html'),
- html_file_suffix = (None, 'html', string_classes),
- html_link_suffix = (None, 'html', string_classes),
- html_show_copyright = (True, 'html'),
- html_show_sphinx = (True, 'html'),
- html_context = ({}, 'html'),
- html_output_encoding = ('utf-8', 'html'),
- html_compact_lists = (True, 'html'),
- html_secnumber_suffix = ('. ', 'html'),
- html_search_language = (None, 'html', string_classes),
- html_search_options = ({}, 'html'),
- html_search_scorer = ('', None),
- html_scaled_image_link = (True, 'html'),
-
- # HTML help only options
- htmlhelp_basename = (lambda self: make_filename(self.project), None),
-
- # Qt help only options
- qthelp_basename = (lambda self: make_filename(self.project), None),
-
- # Devhelp only options
- devhelp_basename = (lambda self: make_filename(self.project), None),
-
- # Apple help options
- applehelp_bundle_name = (lambda self: make_filename(self.project),
- 'applehelp'),
- applehelp_bundle_id = (None, 'applehelp', string_classes),
- applehelp_dev_region = ('en-us', 'applehelp'),
- applehelp_bundle_version = ('1', 'applehelp'),
- applehelp_icon = (None, 'applehelp', string_classes),
- applehelp_kb_product = (lambda self: '%s-%s' %
- (make_filename(self.project), self.release),
- 'applehelp'),
- applehelp_kb_url = (None, 'applehelp', string_classes),
- applehelp_remote_url = (None, 'applehelp', string_classes),
- applehelp_index_anchors = (False, 'applehelp', string_classes),
- applehelp_min_term_length = (None, 'applehelp', string_classes),
- applehelp_stopwords = (lambda self: self.language or 'en', 'applehelp'),
- applehelp_locale = (lambda self: self.language or 'en', 'applehelp'),
- applehelp_title = (lambda self: self.project + ' Help', 'applehelp'),
- applehelp_codesign_identity = (lambda self:
- environ.get('CODE_SIGN_IDENTITY', None),
- 'applehelp'),
- applehelp_codesign_flags = (lambda self:
- shlex.split(
- environ.get('OTHER_CODE_SIGN_FLAGS',
- '')),
- 'applehelp'),
- applehelp_indexer_path = ('/usr/bin/hiutil', 'applehelp'),
- applehelp_codesign_path = ('/usr/bin/codesign', 'applehelp'),
- applehelp_disable_external_tools = (False, None),
-
- # Epub options
- epub_basename = (lambda self: make_filename(self.project), None),
- epub_theme = ('epub', 'html'),
- epub_theme_options = ({}, 'html'),
- epub_title = (lambda self: self.html_title, 'html'),
- epub3_description = ('', 'epub3', string_classes),
- epub_author = ('unknown', 'html'),
- epub3_contributor = ('unknown', 'epub3', string_classes),
- epub_language = (lambda self: self.language or 'en', 'html'),
- epub_publisher = ('unknown', 'html'),
- epub_copyright = (lambda self: self.copyright, 'html'),
- epub_identifier = ('unknown', 'html'),
- epub_scheme = ('unknown', 'html'),
- epub_uid = ('unknown', 'env'),
- epub_cover = ((), 'env'),
- epub_guide = ((), 'env'),
- epub_pre_files = ([], 'env'),
- epub_post_files = ([], 'env'),
- epub_exclude_files = ([], 'env'),
- epub_tocdepth = (3, 'env'),
- epub_tocdup = (True, 'env'),
- epub_tocscope = ('default', 'env'),
- epub_fix_images = (False, 'env'),
- epub_max_image_width = (0, 'env'),
- epub_show_urls = ('inline', 'html'),
- epub_use_index = (lambda self: self.html_use_index, 'html'),
- epub3_page_progression_direction = ('ltr', 'epub3', string_classes),
-
- # LaTeX options
- latex_documents = (lambda self: [(self.master_doc,
- make_filename(self.project) + '.tex',
- self.project,
- '', 'manual')],
- None),
- latex_logo = (None, None, string_classes),
- latex_appendices = ([], None),
- # now deprecated - use latex_toplevel_sectioning
- latex_use_parts = (False, None),
- latex_toplevel_sectioning = (None, None, [str]),
- latex_use_modindex = (True, None), # deprecated
- latex_domain_indices = (True, None, [list]),
- latex_show_urls = ('no', None),
- latex_show_pagerefs = (False, None),
- # paper_size and font_size are still separate values
- # so that you can give them easily on the command line
- latex_paper_size = ('letter', None),
- latex_font_size = ('10pt', None),
- latex_elements = ({}, None),
- latex_additional_files = ([], None),
- latex_docclass = ({}, None),
- # now deprecated - use latex_elements
- latex_preamble = ('', None),
-
- # text options
- text_sectionchars = ('*=-~"+`', 'env'),
- text_newlines = ('unix', 'env'),
-
- # manpage options
- man_pages = (lambda self: [(self.master_doc,
- make_filename(self.project).lower(),
- '%s %s' % (self.project, self.release),
- [], 1)],
- None),
- man_show_urls = (False, None),
-
- # Texinfo options
- texinfo_documents = (lambda self: [(self.master_doc,
- make_filename(self.project).lower(),
- self.project, '',
- make_filename(self.project),
- 'The %s reference manual.' %
- make_filename(self.project),
- 'Python')],
- None),
- texinfo_appendices = ([], None),
- texinfo_elements = ({}, None),
- texinfo_domain_indices = (True, None, [list]),
- texinfo_show_urls = ('footnote', None),
- texinfo_no_detailmenu = (False, None),
-
- # linkcheck options
- linkcheck_ignore = ([], None),
- linkcheck_retries = (1, None),
- linkcheck_timeout = (None, None, [int]),
- linkcheck_workers = (5, None),
- linkcheck_anchors = (True, None),
-
- # gettext options
- gettext_compact = (True, 'gettext'),
- gettext_location = (True, 'gettext'),
- gettext_uuid = (False, 'gettext'),
- gettext_auto_build = (True, 'env'),
- gettext_additional_targets = ([], 'env'),
-
- # XML options
- xml_pretty = (True, 'env'),
)
def __init__(self, dirname, filename, overrides, tags):
@@ -326,19 +165,24 @@ class Config(object):
if default is None and not permitted:
continue # neither inferrable nor expliclitly permitted types
current = self[name]
- if type(current) is type(default):
- continue
- if type(current) in permitted:
- continue
+ if isinstance(permitted, ENUM):
+ if not permitted.match(current):
+ warn(CONFIG_ENUM_WARNING.format(
+ name=name, current=current, candidates=permitted.candidates))
+ else:
+ if type(current) is type(default):
+ continue
+ if type(current) in permitted:
+ continue
- common_bases = (set(type(current).__bases__ + (type(current),)) &
- set(type(default).__bases__))
- common_bases.discard(object)
- if common_bases:
- continue # at least we share a non-trivial base class
+ common_bases = (set(type(current).__bases__ + (type(current),)) &
+ set(type(default).__bases__))
+ common_bases.discard(object)
+ if common_bases:
+ continue # at least we share a non-trivial base class
- warn(CONFIG_TYPE_WARNING.format(
- name=name, current=type(current), default=type(default)))
+ warn(CONFIG_TYPE_WARNING.format(
+ name=name, current=type(current), default=type(default)))
def check_unicode(self, warn):
# check all string values for non-ASCII characters in bytestrings,
diff --git a/sphinx/directives/other.py b/sphinx/directives/other.py
index 51294570c..bab2f9f54 100644
--- a/sphinx/directives/other.py
+++ b/sphinx/directives/other.py
@@ -405,6 +405,7 @@ class Include(BaseInclude):
return BaseInclude.run(self)
rel_filename, filename = env.relfn2path(self.arguments[0])
self.arguments[0] = filename
+ env.note_included(filename)
return BaseInclude.run(self)
diff --git a/sphinx/domains/__init__.py b/sphinx/domains/__init__.py
index e4d397efe..c67abc207 100644
--- a/sphinx/domains/__init__.py
+++ b/sphinx/domains/__init__.py
@@ -273,20 +273,3 @@ class Domain(object):
if primary:
return type.lname
return _('%s %s') % (self.label, type.lname)
-
-
-from sphinx.domains.c import CDomain # noqa
-from sphinx.domains.cpp import CPPDomain # noqa
-from sphinx.domains.std import StandardDomain # noqa
-from sphinx.domains.python import PythonDomain # noqa
-from sphinx.domains.javascript import JavaScriptDomain # noqa
-from sphinx.domains.rst import ReSTDomain # noqa
-
-BUILTIN_DOMAINS = {
- 'std': StandardDomain,
- 'py': PythonDomain,
- 'c': CDomain,
- 'cpp': CPPDomain,
- 'js': JavaScriptDomain,
- 'rst': ReSTDomain,
-}
diff --git a/sphinx/domains/c.py b/sphinx/domains/c.py
index c7fd0681e..43e869dbc 100644
--- a/sphinx/domains/c.py
+++ b/sphinx/domains/c.py
@@ -279,6 +279,9 @@ class CDomain(Domain):
typ, target, node, contnode):
# strip pointer asterisk
target = target.rstrip(' *')
+ # becase TypedField can generate xrefs
+ if target in CObject.stopwords:
+ return contnode
if target not in self.data['objects']:
return None
obj = self.data['objects'][target]
@@ -299,3 +302,7 @@ class CDomain(Domain):
def get_objects(self):
for refname, (docname, type) in list(self.data['objects'].items()):
yield (refname, refname, type, docname, 'c.' + refname, 1)
+
+
+def setup(app):
+ app.add_domain(CDomain)
diff --git a/sphinx/domains/cpp.py b/sphinx/domains/cpp.py
index 7d41d6570..9a3d10a3f 100644
--- a/sphinx/domains/cpp.py
+++ b/sphinx/domains/cpp.py
@@ -1977,7 +1977,7 @@ class ASTTypeWithInit(ASTBase):
def get_id_v2(self, objectType=None, symbol=None):
if objectType == 'member':
- return symbol.declaration.name.get_id_v2()
+ return symbol.get_full_nested_name().get_id_v2()
else:
return self.type.get_id_v2()
@@ -2660,6 +2660,10 @@ class Symbol(object):
if symbol is None:
# TODO: maybe search without template args
return None
+ # We have now matched part of a nested name, and need to match more
+ # so even if we should matchSelf before, we definitely shouldn't
+ # even more. (see also issue #2666)
+ matchSelf = False
parentSymbol = symbol
assert False # should have returned in the loop
@@ -3007,10 +3011,9 @@ class DefinitionParser(object):
self.fail('Expected ")" after "..." in '
'parameters_and_qualifiers.')
break
- if paramMode == 'function':
- arg = self._parse_type_with_init(outer=None, named='single')
- else:
- arg = self._parse_type(named=False)
+ # note: it seems that function arguments can always sbe named,
+ # even in function pointers and similar.
+ arg = self._parse_type_with_init(outer=None, named='single')
# TODO: parse default parameters # TODO: didn't we just do that?
args.append(ASTFunctinoParameter(arg))
@@ -3734,7 +3737,7 @@ class CPPObject(ObjectDescription):
id_v1 = None
id_v2 = ast.get_id_v2()
# store them in reverse order, so the newest is first
- ids = [id_v2, id_v1]
+ ids = [id_v2, id_v1]
newestId = ids[0]
assert newestId # shouldn't be None
@@ -3755,8 +3758,14 @@ class CPPObject(ObjectDescription):
else:
# print("[CPP] non-unique name:", name)
pass
- for id in ids:
- if id: # is None when the element didn't exist in that version
+ # always add the newest id
+ assert newestId
+ signode['ids'].append(newestId)
+ # only add compatibility ids when there are no conflicts
+ for id in ids[1:]:
+ if not id: # is None when the element didn't exist in that version
+ continue
+ if id not in self.state.document.ids:
signode['ids'].append(id)
signode['first'] = (not self.names) # hmm, what is this abound?
self.state.document.note_explicit_target(signode)
@@ -3800,6 +3809,15 @@ class CPPObject(ObjectDescription):
self.describe_signature(signode, ast)
return ast
+ def before_content(self):
+ lastSymbol = self.env.ref_context['cpp:last_symbol']
+ assert lastSymbol
+ self.oldParentSymbol = self.env.ref_context['cpp:parent_symbol']
+ self.env.ref_context['cpp:parent_symbol'] = lastSymbol
+
+ def after_content(self):
+ self.env.ref_context['cpp:parent_symbol'] = self.oldParentSymbol
+
class CPPTypeObject(CPPObject):
def get_index_text(self, name):
@@ -3838,15 +3856,6 @@ class CPPClassObject(CPPObject):
def get_index_text(self, name):
return _('%s (C++ class)') % name
- def before_content(self):
- lastSymbol = self.env.ref_context['cpp:last_symbol']
- assert lastSymbol
- self.oldParentSymbol = self.env.ref_context['cpp:parent_symbol']
- self.env.ref_context['cpp:parent_symbol'] = lastSymbol
-
- def after_content(self):
- self.env.ref_context['cpp:parent_symbol'] = self.oldParentSymbol
-
def parse_definition(self, parser):
return parser.parse_declaration("class")
@@ -3858,15 +3867,6 @@ class CPPEnumObject(CPPObject):
def get_index_text(self, name):
return _('%s (C++ enum)') % name
- def before_content(self):
- lastSymbol = self.env.ref_context['cpp:last_symbol']
- assert lastSymbol
- self.oldParentSymbol = self.env.ref_context['cpp:parent_symbol']
- self.env.ref_context['cpp:parent_symbol'] = lastSymbol
-
- def after_content(self):
- self.env.ref_context['cpp:parent_symbol'] = self.oldParentSymbol
-
def parse_definition(self, parser):
ast = parser.parse_declaration("enum")
# self.objtype is set by ObjectDescription in run()
@@ -4123,6 +4123,29 @@ class CPPDomain(Domain):
matchSelf=True)
if s is None or s.declaration is None:
return None, None
+
+ if typ.startswith('cpp:'):
+ typ = typ[4:]
+ if typ == 'func':
+ typ = 'function'
+ declTyp = s.declaration.objectType
+
+ def checkType():
+ if typ == 'any':
+ return True
+ if declTyp == 'templateParam':
+ return True
+ if typ == 'var' or typ == 'member':
+ return declTyp in ['var', 'member']
+ if typ in ['enum', 'enumerator', 'function', 'class']:
+ return declTyp == typ
+ if typ == 'type':
+ return declTyp in ['enum', 'class', 'function', 'type']
+ print("Type is %s" % typ)
+ assert False
+ if not checkType():
+ warner.warn("cpp:%s targets a %s." % (typ, s.declaration.objectType))
+
declaration = s.declaration
fullNestedName = s.get_full_nested_name()
name = text_type(fullNestedName).lstrip(':')
@@ -4162,3 +4185,7 @@ class CPPDomain(Domain):
docname = symbol.docname
newestId = symbol.declaration.get_newest_id()
yield (name, name, objectType, docname, newestId, 1)
+
+
+def setup(app):
+ app.add_domain(CPPDomain)
diff --git a/sphinx/domains/javascript.py b/sphinx/domains/javascript.py
index b5f64022a..ade6e4224 100644
--- a/sphinx/domains/javascript.py
+++ b/sphinx/domains/javascript.py
@@ -234,3 +234,7 @@ class JavaScriptDomain(Domain):
for refname, (docname, type) in list(self.data['objects'].items()):
yield refname, refname, type, docname, \
refname.replace('$', '_S_'), 1
+
+
+def setup(app):
+ app.add_domain(JavaScriptDomain)
diff --git a/sphinx/domains/python.py b/sphinx/domains/python.py
index 1639d8288..9a9bcef16 100644
--- a/sphinx/domains/python.py
+++ b/sphinx/domains/python.py
@@ -771,3 +771,7 @@ class PythonDomain(Domain):
for refname, (docname, type) in iteritems(self.data['objects']):
if type != 'module': # modules are already handled
yield (refname, refname, type, docname, refname, 1)
+
+
+def setup(app):
+ app.add_domain(PythonDomain)
diff --git a/sphinx/domains/rst.py b/sphinx/domains/rst.py
index b11c9450b..526ae18a7 100644
--- a/sphinx/domains/rst.py
+++ b/sphinx/domains/rst.py
@@ -156,3 +156,7 @@ class ReSTDomain(Domain):
def get_objects(self):
for (typ, name), docname in iteritems(self.data['objects']):
yield name, name, typ, docname, typ + '-' + name, 1
+
+
+def setup(app):
+ app.add_domain(ReSTDomain)
diff --git a/sphinx/domains/std.py b/sphinx/domains/std.py
index 997d95ba3..001d9f6d9 100644
--- a/sphinx/domains/std.py
+++ b/sphinx/domains/std.py
@@ -14,7 +14,6 @@ import unicodedata
from six import iteritems
from docutils import nodes
-from docutils.nodes import fully_normalize_name
from docutils.parsers.rst import directives
from docutils.statemachine import ViewList
@@ -585,106 +584,119 @@ class StandardDomain(Domain):
newnode.append(innernode)
return newnode
- def resolve_xref(self, env, fromdocname, builder,
- typ, target, node, contnode):
+ def resolve_xref(self, env, fromdocname, builder, typ, target, node, contnode):
if typ == 'ref':
- if node['refexplicit']:
- # reference to anonymous label; the reference uses
- # the supplied link caption
- docname, labelid = self.data['anonlabels'].get(target, ('', ''))
- sectname = node.astext()
- else:
- # reference to named label; the final node will
- # contain the section name after the label
- docname, labelid, sectname = self.data['labels'].get(target,
- ('', '', ''))
- if not docname:
- return None
-
- return self.build_reference_node(fromdocname, builder,
- docname, labelid, sectname, 'ref')
+ resolver = self._resolve_ref_xref
elif typ == 'numref':
+ resolver = self._resolve_numref_xref
+ elif typ == 'keyword':
+ resolver = self._resolve_keyword_xref
+ elif typ == 'option':
+ resolver = self._resolve_option_xref
+ else:
+ resolver = self._resolve_obj_xref
+
+ return resolver(env, fromdocname, builder, typ, target, node, contnode)
+
+ def _resolve_ref_xref(self, env, fromdocname, builder, typ, target, node, contnode):
+ if node['refexplicit']:
+ # reference to anonymous label; the reference uses
+ # the supplied link caption
docname, labelid = self.data['anonlabels'].get(target, ('', ''))
- if not docname:
- return None
+ sectname = node.astext()
+ else:
+ # reference to named label; the final node will
+ # contain the section name after the label
+ docname, labelid, sectname = self.data['labels'].get(target,
+ ('', '', ''))
+ if not docname:
+ return None
- if env.config.numfig is False:
- env.warn(fromdocname, 'numfig is disabled. :numref: is ignored.',
- lineno=node.line)
- return contnode
+ return self.build_reference_node(fromdocname, builder,
+ docname, labelid, sectname, 'ref')
- target_node = env.get_doctree(docname).ids.get(labelid)
- figtype = self.get_figtype(target_node)
- if figtype is None:
- return None
+ def _resolve_numref_xref(self, env, fromdocname, builder, typ, target, node, contnode):
+ docname, labelid = self.data['anonlabels'].get(target, ('', ''))
+ if not docname:
+ return None
- try:
- figure_id = target_node['ids'][0]
- fignumber = env.toc_fignumbers[docname][figtype][figure_id]
- except (KeyError, IndexError):
- # target_node is found, but fignumber is not assigned.
- # Maybe it is defined in orphaned document.
- env.warn(fromdocname, "no number is assigned for %s: %s" % (figtype, labelid),
- lineno=node.line)
- return contnode
+ if env.config.numfig is False:
+ env.warn_node('numfig is disabled. :numref: is ignored.', node)
+ return contnode
- title = contnode.astext()
- if target == fully_normalize_name(title):
+ target_node = env.get_doctree(docname).ids.get(labelid)
+ figtype = self.get_figtype(target_node)
+ if figtype is None:
+ return None
+
+ try:
+ figure_id = target_node['ids'][0]
+ fignumber = env.toc_fignumbers[docname][figtype][figure_id]
+ except (KeyError, IndexError):
+ # target_node is found, but fignumber is not assigned.
+ # Maybe it is defined in orphaned document.
+ env.warn_node("no number is assigned for %s: %s" % (figtype, labelid), node)
+ return contnode
+
+ try:
+ if node['refexplicit']:
+ title = contnode.astext()
+ else:
title = env.config.numfig_format.get(figtype, '')
- try:
- newtitle = title % '.'.join(map(str, fignumber))
- except TypeError:
- env.warn(fromdocname, 'invalid numfig_format: %s' % title,
- lineno=node.line)
- return None
+ newtitle = title % '.'.join(map(str, fignumber))
+ except TypeError:
+ env.warn_node('invalid numfig_format: %s' % title, node)
+ return None
- return self.build_reference_node(fromdocname, builder,
- docname, labelid, newtitle, 'numref',
- nodeclass=addnodes.number_reference,
- title=title)
- elif typ == 'keyword':
- # keywords are oddballs: they are referenced by named labels
- docname, labelid, _ = self.data['labels'].get(target, ('', '', ''))
- if not docname:
- return None
- return make_refnode(builder, fromdocname, docname,
- labelid, contnode)
- elif typ == 'option':
- progname = node.get('std:program')
- target = target.strip()
- docname, labelid = self.data['progoptions'].get((progname, target), ('', ''))
- if not docname:
- commands = []
- while ws_re.search(target):
- subcommand, target = ws_re.split(target, 1)
- commands.append(subcommand)
- progname = "-".join(commands)
+ return self.build_reference_node(fromdocname, builder,
+ docname, labelid, newtitle, 'numref',
+ nodeclass=addnodes.number_reference,
+ title=title)
- docname, labelid = self.data['progoptions'].get((progname, target),
- ('', ''))
- if docname:
- break
- else:
- return None
+ def _resolve_keyword_xref(self, env, fromdocname, builder, typ, target, node, contnode):
+ # keywords are oddballs: they are referenced by named labels
+ docname, labelid, _ = self.data['labels'].get(target, ('', '', ''))
+ if not docname:
+ return None
+ return make_refnode(builder, fromdocname, docname,
+ labelid, contnode)
- return make_refnode(builder, fromdocname, docname,
- labelid, contnode)
- else:
- objtypes = self.objtypes_for_role(typ) or []
- for objtype in objtypes:
- if (objtype, target) in self.data['objects']:
- docname, labelid = self.data['objects'][objtype, target]
+ def _resolve_option_xref(self, env, fromdocname, builder, typ, target, node, contnode):
+ progname = node.get('std:program')
+ target = target.strip()
+ docname, labelid = self.data['progoptions'].get((progname, target), ('', ''))
+ if not docname:
+ commands = []
+ while ws_re.search(target):
+ subcommand, target = ws_re.split(target, 1)
+ commands.append(subcommand)
+ progname = "-".join(commands)
+
+ docname, labelid = self.data['progoptions'].get((progname, target),
+ ('', ''))
+ if docname:
break
else:
- docname, labelid = '', ''
- if not docname:
return None
- return make_refnode(builder, fromdocname, docname,
- labelid, contnode)
- def resolve_any_xref(self, env, fromdocname, builder, target,
- node, contnode):
+ return make_refnode(builder, fromdocname, docname,
+ labelid, contnode)
+
+ def _resolve_obj_xref(self, env, fromdocname, builder, typ, target, node, contnode):
+ objtypes = self.objtypes_for_role(typ) or []
+ for objtype in objtypes:
+ if (objtype, target) in self.data['objects']:
+ docname, labelid = self.data['objects'][objtype, target]
+ break
+ else:
+ docname, labelid = '', ''
+ if not docname:
+ return None
+ return make_refnode(builder, fromdocname, docname,
+ labelid, contnode)
+
+ def resolve_any_xref(self, env, fromdocname, builder, target, node, contnode):
results = []
ltarget = target.lower() # :ref: lowercases its target automatically
for role in ('ref', 'option'): # do not try "keyword"
@@ -755,3 +767,7 @@ class StandardDomain(Domain):
else:
figtype, _ = self.enumerable_nodes.get(node.__class__, (None, None))
return figtype
+
+
+def setup(app):
+ app.add_domain(StandardDomain)
diff --git a/sphinx/environment.py b/sphinx/environment.py
index 92064f911..e31ebea47 100644
--- a/sphinx/environment.py
+++ b/sphinx/environment.py
@@ -17,6 +17,7 @@ import types
import bisect
import codecs
import string
+import fnmatch
import unicodedata
from os import path
from glob import glob
@@ -75,7 +76,7 @@ default_settings = {
# or changed to properly invalidate pickle files.
#
# NOTE: increase base version by 2 to have distinct numbers for Py2 and 3
-ENV_VERSION = 48 + (sys.version_info[0] - 2)
+ENV_VERSION = 49 + (sys.version_info[0] - 2)
dummy_reporter = Reporter('', 4, 4)
@@ -169,6 +170,7 @@ class BuildEnvironment:
# contains all read docnames
self.dependencies = {} # docname -> set of dependent file
# names, relative to documentation root
+ self.included = set() # docnames included from other documents
self.reread_always = set() # docnames to re-read unconditionally on
# next build
@@ -328,6 +330,20 @@ class BuildEnvironment:
domain.merge_domaindata(docnames, other.domaindata[domainname])
app.emit('env-merge-info', self, docnames, other)
+ def path2doc(self, filename):
+ """Return the docname for the filename if the file is document.
+
+ *filename* should be absolute or relative to the source directory.
+ """
+ if filename.startswith(self.srcdir):
+ filename = filename[len(self.srcdir) + 1:]
+ for suffix in self.config.source_suffix:
+ if fnmatch.fnmatch(filename, '*' + suffix):
+ return filename[:-len(suffix)]
+ else:
+ # the file does not have docname
+ return None
+
def doc2path(self, docname, base=True, suffix=None):
"""Return the filename for the document name.
@@ -387,8 +403,13 @@ class BuildEnvironment:
config.html_extra_path +
['**/_sources', '.#*', '**/.#*', '*.lproj/**']
)
- self.found_docs = set(get_matching_docs(
- self.srcdir, config.source_suffix, exclude_matchers=matchers))
+ self.found_docs = set()
+ for docname in get_matching_docs(self.srcdir, config.source_suffix,
+ exclude_matchers=matchers):
+ if os.access(self.doc2path(docname), os.R_OK):
+ self.found_docs.add(docname)
+ else:
+ self.warn(docname, "document not readable. Ignored.")
# add catalog mo file dependency
for docname in self.found_docs:
@@ -820,6 +841,15 @@ class BuildEnvironment:
"""
self.dependencies.setdefault(self.docname, set()).add(filename)
+ def note_included(self, filename):
+ """Add *filename* as a included from other document.
+
+ This means the document is not orphaned.
+
+ *filename* should be absolute or relative to the source directory.
+ """
+ self.included.add(self.path2doc(filename))
+
def note_reread(self):
"""Add the current document to the list of documents that will
automatically be re-read at the next build.
@@ -1413,7 +1443,10 @@ class BuildEnvironment:
# nodes with length 1 don't have any children anyway
if len(toplevel) > 1:
subtrees = toplevel.traverse(addnodes.toctree)
- toplevel[1][:] = subtrees
+ if subtrees:
+ toplevel[1][:] = subtrees
+ else:
+ toplevel.pop(1)
# resolve all sub-toctrees
for subtocnode in toc.traverse(addnodes.toctree):
if not (subtocnode.get('hidden', False) and
@@ -1459,6 +1492,9 @@ class BuildEnvironment:
_toctree_add_classes(newnode, 1)
self._toctree_prune(newnode, 1, prune and maxdepth or 0, collapse)
+ if len(newnode[-1]) == 0: # No titles found
+ return None
+
# set the target paths in the toctrees (they are not known at TOC
# generation time)
for refnode in newnode.traverse(nodes.reference):
@@ -1488,9 +1524,9 @@ class BuildEnvironment:
typ, target, node, contnode)
# really hardwired reference types
elif typ == 'any':
- newnode = self._resolve_any_reference(builder, node, contnode)
+ newnode = self._resolve_any_reference(builder, refdoc, node, contnode)
elif typ == 'doc':
- newnode = self._resolve_doc_reference(builder, node, contnode)
+ newnode = self._resolve_doc_reference(builder, refdoc, node, contnode)
elif typ == 'citation':
newnode = self._resolve_citation(builder, refdoc, node, contnode)
# no new node found? try the missing-reference event
@@ -1538,10 +1574,10 @@ class BuildEnvironment:
msg = '%r reference target not found: %%(target)s' % typ
self.warn_node(msg % {'target': target}, node, type='ref', subtype=typ)
- def _resolve_doc_reference(self, builder, node, contnode):
+ def _resolve_doc_reference(self, builder, refdoc, node, contnode):
# directly reference to document by source name;
# can be absolute or relative
- docname = docname_join(node['refdoc'], node['reftarget'])
+ docname = docname_join(refdoc, node['reftarget'])
if docname in self.all_docs:
if node['refexplicit']:
# reference with explicit title
@@ -1551,7 +1587,7 @@ class BuildEnvironment:
innernode = nodes.inline(caption, caption)
innernode['classes'].append('doc')
newnode = nodes.reference('', '', internal=True)
- newnode['refuri'] = builder.get_relative_uri(node['refdoc'], docname)
+ newnode['refuri'] = builder.get_relative_uri(refdoc, docname)
newnode.append(innernode)
return newnode
@@ -1574,13 +1610,12 @@ class BuildEnvironment:
# transforms.CitationReference.apply.
del node['ids'][:]
- def _resolve_any_reference(self, builder, node, contnode):
+ def _resolve_any_reference(self, builder, refdoc, node, contnode):
"""Resolve reference generated by the "any" role."""
- refdoc = node['refdoc']
target = node['reftarget']
results = []
# first, try resolving as :doc:
- doc_ref = self._resolve_doc_reference(builder, node, contnode)
+ doc_ref = self._resolve_doc_reference(builder, refdoc, node, contnode)
if doc_ref:
results.append(('doc', doc_ref))
# next, do the standard domain (makes this a priority)
@@ -1931,6 +1966,9 @@ class BuildEnvironment:
if docname == self.config.master_doc:
# the master file is not included anywhere ;)
continue
+ if docname in self.included:
+ # the document is included from other documents
+ continue
if 'orphan' in self.metadata[docname]:
continue
self.warn(docname, 'document isn\'t included in any toctree')
diff --git a/sphinx/errors.py b/sphinx/errors.py
index 8d695c190..5fb77a135 100644
--- a/sphinx/errors.py
+++ b/sphinx/errors.py
@@ -67,7 +67,10 @@ class PycodeError(Exception):
return res
-class SphinxParallelError(Exception):
+class SphinxParallelError(SphinxError):
+
+ category = 'Sphinx parallel build error'
+
def __init__(self, orig_exc, traceback):
self.orig_exc = orig_exc
self.traceback = traceback
diff --git a/sphinx/ext/imgmath.py b/sphinx/ext/imgmath.py
index f8e402be3..927429086 100644
--- a/sphinx/ext/imgmath.py
+++ b/sphinx/ext/imgmath.py
@@ -22,6 +22,7 @@ from six import text_type
from docutils import nodes
import sphinx
+from sphinx.locale import _
from sphinx.errors import SphinxError, ExtensionError
from sphinx.util.png import read_png_depth, write_png_depth
from sphinx.util.osutil import ensuredir, ENOENT, cd
@@ -253,7 +254,9 @@ def html_visit_displaymath(self, node):
self.body.append(self.starttag(node, 'div', CLASS='math'))
self.body.append('')
if node['number']:
- self.body.append('(%s)' % node['number'])
+ self.body.append('(%s)' % node['number'])
+ self.add_permalink_ref(node, _('Permalink to this code'))
+ self.body.append('')
if fname is None:
# something failed -- use text-only as a bad substitute
self.body.append('%s
\n' %
diff --git a/sphinx/ext/intersphinx.py b/sphinx/ext/intersphinx.py
index 8e6573e8a..c43b8ae6a 100644
--- a/sphinx/ext/intersphinx.py
+++ b/sphinx/ext/intersphinx.py
@@ -34,7 +34,8 @@ from os import path
import re
from six import iteritems, string_types
-from six.moves.urllib import parse, request
+from six.moves.urllib import request
+from six.moves.urllib.parse import urlsplit, urlunsplit
from docutils import nodes
from docutils.utils import relative_path
@@ -105,7 +106,7 @@ def read_inventory_v2(f, uri, join, bufsize=16*1024):
for line in split_lines(read_chunks()):
# be careful to handle names with embedded spaces correctly
- m = re.match(r'(?x)(.+?)\s+(\S*:\S*)\s+(\S+)\s+(\S+)\s+(.*)',
+ m = re.match(r'(?x)(.+?)\s+(\S*:\S*)\s+(-?\d+)\s+(\S+)\s+(.*)',
line.rstrip())
if not m:
continue
@@ -145,7 +146,7 @@ def _strip_basic_auth(url):
:rtype: ``tuple``
"""
- url_parts = parse.urlsplit(url)
+ url_parts = urlsplit(url)
username = url_parts.username
password = url_parts.password
frags = list(url_parts)
@@ -154,7 +155,7 @@ def _strip_basic_auth(url):
frags[1] = "%s:%s" % (url_parts.hostname, url_parts.port)
else:
frags[1] = url_parts.hostname
- url = parse.urlunsplit(frags)
+ url = urlunsplit(frags)
return (url, username, password)
@@ -208,12 +209,12 @@ def _get_safe_url(url):
url, username, _ = _strip_basic_auth(url)
if username is not None:
# case: url contained basic auth creds; obscure password
- url_parts = parse.urlsplit(url)
+ url_parts = urlsplit(url)
safe_netloc = '{0}@{1}'.format(username, url_parts.hostname)
# replace original netloc w/ obscured version
frags = list(url_parts)
frags[1] = safe_netloc
- safe_url = parse.urlunsplit(frags)
+ safe_url = urlunsplit(frags)
return safe_url
@@ -237,6 +238,13 @@ def fetch_inventory(app, uri, inv):
'%s: %s' % (inv, err.__class__, err))
return
try:
+ if hasattr(f, 'geturl'):
+ newuri = f.geturl()
+ if newuri.endswith("/" + INVENTORY_FILENAME):
+ newuri = newuri[:-len(INVENTORY_FILENAME) - 1]
+ if uri != newuri and uri != newuri + "/":
+ app.info('intersphinx inventory has moved: %s -> %s' % (uri, newuri))
+ uri = newuri
line = f.readline().rstrip().decode('utf-8')
try:
if line == '# Sphinx inventory version 1':
diff --git a/sphinx/ext/jsmath.py b/sphinx/ext/jsmath.py
index f36e12fed..9fb790e1b 100644
--- a/sphinx/ext/jsmath.py
+++ b/sphinx/ext/jsmath.py
@@ -13,6 +13,7 @@
from docutils import nodes
import sphinx
+from sphinx.locale import _
from sphinx.application import ExtensionError
from sphinx.ext.mathbase import setup_math as mathbase_setup
@@ -34,8 +35,9 @@ def html_visit_displaymath(self, node):
if i == 0:
# necessary to e.g. set the id property correctly
if node['number']:
- self.body.append('(%s)' %
- node['number'])
+ self.body.append('(%s)' % node['number'])
+ self.add_permalink_ref(node, _('Permalink to this code'))
+ self.body.append('')
self.body.append(self.starttag(node, 'div', CLASS='math'))
else:
# but only once!
diff --git a/sphinx/ext/mathbase.py b/sphinx/ext/mathbase.py
index 13a560c0a..ddcec492c 100644
--- a/sphinx/ext/mathbase.py
+++ b/sphinx/ext/mathbase.py
@@ -58,7 +58,7 @@ def wrap_displaymath(math, label, numbering):
begin = r'\begin{align*}%s\!\begin{aligned}' % labeldef
end = r'\end{aligned}\end{align*}'
for part in parts:
- equations.append('%s\\\\\n' % part)
+ equations.append('%s\\\\\n' % part.strip())
return '%s\n%s%s' % (begin, ''.join(equations), end)
diff --git a/sphinx/ext/mathjax.py b/sphinx/ext/mathjax.py
index bdaab55e0..420e2b312 100644
--- a/sphinx/ext/mathjax.py
+++ b/sphinx/ext/mathjax.py
@@ -14,6 +14,7 @@
from docutils import nodes
import sphinx
+from sphinx.locale import _
from sphinx.errors import ExtensionError
from sphinx.ext.mathbase import setup_math as mathbase_setup
@@ -35,7 +36,9 @@ def html_visit_displaymath(self, node):
# necessary to e.g. set the id property correctly
if node['number']:
- self.body.append('(%s)' % node['number'])
+ self.body.append('(%s)' % node['number'])
+ self.add_permalink_ref(node, _('Permalink to this code'))
+ self.body.append('')
self.body.append(self.builder.config.mathjax_display[0])
parts = [prt for prt in node['latex'].split('\n\n') if prt.strip()]
if len(parts) > 1: # Add alignment if there are more than 1 equation
diff --git a/sphinx/ext/napoleon/__init__.py b/sphinx/ext/napoleon/__init__.py
index 9dedc15d7..651355c57 100644
--- a/sphinx/ext/napoleon/__init__.py
+++ b/sphinx/ext/napoleon/__init__.py
@@ -51,16 +51,17 @@ class Config(object):
Attributes
----------
- napoleon_google_docstring : bool, defaults to True
+ napoleon_google_docstring : :obj:`bool` (Defaults to True)
True to parse `Google style`_ docstrings. False to disable support
for Google style docstrings.
- napoleon_numpy_docstring : bool, defaults to True
+ napoleon_numpy_docstring : :obj:`bool` (Defaults to True)
True to parse `NumPy style`_ docstrings. False to disable support
for NumPy style docstrings.
- napoleon_include_init_with_doc : bool, defaults to False
- True to include init methods (i.e. ``__init___``) with
- docstrings in the documentation. False to fall back to Sphinx's
- default behavior.
+ napoleon_include_init_with_doc : :obj:`bool` (Defaults to False)
+ True to list ``__init___`` docstrings separately from the class
+ docstring. False to fall back to Sphinx's default behavior, which
+ considers the ``__init___`` docstring as part of the class
+ documentation.
**If True**::
@@ -72,7 +73,7 @@ class Config(object):
def __init__(self):
# This will NOT be included in the docs
- napoleon_include_private_with_doc : bool, defaults to False
+ napoleon_include_private_with_doc : :obj:`bool` (Defaults to False)
True to include private members (like ``_membername``) with docstrings
in the documentation. False to fall back to Sphinx's default behavior.
@@ -88,7 +89,7 @@ class Config(object):
# This will NOT be included in the docs
pass
- napoleon_include_special_with_doc : bool, defaults to False
+ napoleon_include_special_with_doc : :obj:`bool` (Defaults to False)
True to include special members (like ``__membername__``) with
docstrings in the documentation. False to fall back to Sphinx's
default behavior.
@@ -105,7 +106,7 @@ class Config(object):
# This will NOT be included in the docs
return unicode(self.__class__.__name__)
- napoleon_use_admonition_for_examples : bool, defaults to False
+ napoleon_use_admonition_for_examples : :obj:`bool` (Defaults to False)
True to use the ``.. admonition::`` directive for the **Example** and
**Examples** sections. False to use the ``.. rubric::`` directive
instead. One may look better than the other depending on what HTML
@@ -129,7 +130,7 @@ class Config(object):
This is just a quick example
- napoleon_use_admonition_for_notes : bool, defaults to False
+ napoleon_use_admonition_for_notes : :obj:`bool` (Defaults to False)
True to use the ``.. admonition::`` directive for **Notes** sections.
False to use the ``.. rubric::`` directive instead.
@@ -142,7 +143,7 @@ class Config(object):
--------
:attr:`napoleon_use_admonition_for_examples`
- napoleon_use_admonition_for_references : bool, defaults to False
+ napoleon_use_admonition_for_references : :obj:`bool` (Defaults to False)
True to use the ``.. admonition::`` directive for **References**
sections. False to use the ``.. rubric::`` directive instead.
@@ -150,7 +151,7 @@ class Config(object):
--------
:attr:`napoleon_use_admonition_for_examples`
- napoleon_use_ivar : bool, defaults to False
+ napoleon_use_ivar : :obj:`bool` (Defaults to False)
True to use the ``:ivar:`` role for instance variables. False to use
the ``.. attribute::`` directive instead.
@@ -174,7 +175,7 @@ class Config(object):
Description of `attr1`
- napoleon_use_param : bool, defaults to True
+ napoleon_use_param : :obj:`bool` (Defaults to True)
True to use a ``:param:`` role for each function parameter. False to
use a single ``:parameters:`` role for all the parameters.
@@ -201,21 +202,22 @@ class Config(object):
* **arg2** (*int, optional*) --
Description of `arg2`, defaults to 0
- napoleon_use_keyword : bool, defaults to True
+ napoleon_use_keyword : :obj:`bool` (Defaults to True)
True to use a ``:keyword:`` role for each function keyword argument.
False to use a single ``:keyword arguments:`` role for all the
keywords.
- This behaves similarly to :attr:`napoleon_use_param`. Note unlike docutils,
- ``:keyword:`` and ``:param:`` will not be treated the same way - there will
- be a separate "Keyword Arguments" section, rendered in the same fashion as
- "Parameters" section (type links created if possible)
+ This behaves similarly to :attr:`napoleon_use_param`. Note unlike
+ docutils, ``:keyword:`` and ``:param:`` will not be treated the same
+ way - there will be a separate "Keyword Arguments" section, rendered
+ in the same fashion as "Parameters" section (type links created if
+ possible)
See Also
--------
:attr:`napoleon_use_param`
- napoleon_use_rtype : bool, defaults to True
+ napoleon_use_rtype : :obj:`bool` (Defaults to True)
True to use the ``:rtype:`` role for the return type. False to output
the return type inline with the description.
@@ -295,20 +297,23 @@ def setup(app):
def _patch_python_domain():
- import sphinx.domains.python
- from sphinx.domains.python import PyTypedField
- import sphinx.locale
- l_ = sphinx.locale.lazy_gettext
- for doc_field in sphinx.domains.python.PyObject.doc_field_types:
- if doc_field.name == 'parameter':
- doc_field.names = ('param', 'parameter', 'arg', 'argument')
- break
- sphinx.domains.python.PyObject.doc_field_types.append(
- PyTypedField('keyword', label=l_('Keyword Arguments'),
- names=('keyword', 'kwarg', 'kwparam'),
- typerolename='obj', typenames=('paramtype', 'kwtype'),
- can_collapse=True),
- )
+ try:
+ from sphinx.domains.python import PyTypedField
+ except ImportError:
+ pass
+ else:
+ import sphinx.domains.python
+ import sphinx.locale
+ l_ = sphinx.locale.lazy_gettext
+ for doc_field in sphinx.domains.python.PyObject.doc_field_types:
+ if doc_field.name == 'parameter':
+ doc_field.names = ('param', 'parameter', 'arg', 'argument')
+ break
+ sphinx.domains.python.PyObject.doc_field_types.append(
+ PyTypedField('keyword', label=l_('Keyword Arguments'),
+ names=('keyword', 'kwarg', 'kwparam'),
+ typerolename='obj', typenames=('paramtype', 'kwtype'),
+ can_collapse=True))
def _process_docstring(app, what, name, obj, options, lines):
diff --git a/sphinx/ext/napoleon/docstring.py b/sphinx/ext/napoleon/docstring.py
index c12b75e6d..c3d5bb3d0 100644
--- a/sphinx/ext/napoleon/docstring.py
+++ b/sphinx/ext/napoleon/docstring.py
@@ -26,6 +26,7 @@ _directive_regex = re.compile(r'\.\. \S+::')
_google_section_regex = re.compile(r'^(\s|\w)+:\s*$')
_google_typed_arg_regex = re.compile(r'\s*(.+?)\s*\(\s*(.+?)\s*\)')
_numpy_section_regex = re.compile(r'^[=\-`:\'"~^_*+#<>]{2,}\s*$')
+_single_colon_regex = re.compile(r'(? indent:
+ desc = [''] + desc
+ else:
+ desc = ['', desc[0]] + self._indent(desc_block, 4)
+ return desc
+
def _format_admonition(self, admonition, lines):
lines = self._strip_empty(lines)
if len(lines) == 1:
@@ -333,6 +344,22 @@ class GoogleDocstring(UnicodeMixin):
else:
return [prefix]
+ def _format_docutils_params(self, fields, field_role='param',
+ type_role='type'):
+ lines = []
+ for _name, _type, _desc in fields:
+ _desc = self._strip_empty(_desc)
+ if any(_desc):
+ _desc = self._fix_field_desc(_desc)
+ field = ':%s %s: ' % (field_role, _name)
+ lines.extend(self._format_block(field, _desc))
+ else:
+ lines.append(':%s %s:' % (field_role, _name))
+
+ if _type:
+ lines.append(':%s %s: %s' % (type_role, _name, _type))
+ return lines + ['']
+
def _format_field(self, _name, _type, _desc):
_desc = self._strip_empty(_desc)
has_desc = any(_desc)
@@ -354,9 +381,11 @@ class GoogleDocstring(UnicodeMixin):
field = ''
if has_desc:
- if self._is_list(_desc):
- return [field, ''] + _desc
- return [field + _desc[0]] + _desc[1:]
+ _desc = self._fix_field_desc(_desc)
+ if _desc[0]:
+ return [field + _desc[0]] + _desc[1:]
+ else:
+ return [field] + _desc
else:
return [field]
@@ -393,6 +422,12 @@ class GoogleDocstring(UnicodeMixin):
return i
return len(line)
+ def _get_initial_indent(self, lines):
+ for line in lines:
+ if line:
+ return self._get_indent(line)
+ return 0
+
def _get_min_indent(self, lines):
min_indent = None
for line in lines:
@@ -529,11 +564,10 @@ class GoogleDocstring(UnicodeMixin):
def _parse_keyword_arguments_section(self, section):
fields = self._consume_fields()
if self._config.napoleon_use_keyword:
- return self._generate_docutils_params(
+ return self._format_docutils_params(
fields,
field_role="keyword",
- type_role="kwtype"
- )
+ type_role="kwtype")
else:
return self._format_fields('Keyword Arguments', fields)
@@ -560,26 +594,10 @@ class GoogleDocstring(UnicodeMixin):
def _parse_parameters_section(self, section):
fields = self._consume_fields()
if self._config.napoleon_use_param:
- return self._generate_docutils_params(fields)
+ return self._format_docutils_params(fields)
else:
return self._format_fields('Parameters', fields)
- def _generate_docutils_params(self, fields, field_role='param', type_role='type'):
- lines = []
- for _name, _type, _desc in fields:
- _desc = self._strip_empty(_desc)
- if any(_desc):
- if self._is_list(_desc):
- _desc = [''] + _desc
- field = ':%s %s: ' % (field_role, _name)
- lines.extend(self._format_block(field, _desc))
- else:
- lines.append(':%s %s:' % (field_role, _name))
-
- if _type:
- lines.append(':%s %s: %s' % (type_role, _name, _type))
- return lines + ['']
-
def _parse_raises_section(self, section):
fields = self._consume_fields(parse_type=False, prefer_type=True)
field_type = ':raises:'
@@ -678,11 +696,12 @@ class GoogleDocstring(UnicodeMixin):
if found_colon:
after_colon.append(source)
else:
- if (i % 2) == 0 and ":" in source:
+ m = _single_colon_regex.search(source)
+ if (i % 2) == 0 and m:
found_colon = True
- before, colon, after = source.partition(":")
- before_colon.append(before)
- after_colon.append(after)
+ colon = source[m.start(): m.end()]
+ before_colon.append(source[:m.start()])
+ after_colon.append(source[m.end():])
else:
before_colon.append(source)
@@ -715,31 +734,28 @@ class NumpyDocstring(GoogleDocstring):
Parameters
----------
- docstring : str or List[str]
+ docstring : :obj:`str` or :obj:`list` of :obj:`str`
The docstring to parse, given either as a string or split into
individual lines.
- config : Optional[sphinx.ext.napoleon.Config or sphinx.config.Config]
+ config: :obj:`sphinx.ext.napoleon.Config` or :obj:`sphinx.config.Config`
The configuration settings to use. If not given, defaults to the
config object on `app`; or if `app` is not given defaults to the
- a new `sphinx.ext.napoleon.Config` object.
+ a new :class:`sphinx.ext.napoleon.Config` object.
- See Also
- --------
- :class:`sphinx.ext.napoleon.Config`
Other Parameters
----------------
- app : Optional[sphinx.application.Sphinx]
+ app : :class:`sphinx.application.Sphinx`, optional
Application object representing the Sphinx process.
- what : Optional[str]
+ what : :obj:`str`, optional
A string specifying the type of the object to which the docstring
belongs. Valid values: "module", "class", "exception", "function",
"method", "attribute".
- name : Optional[str]
+ name : :obj:`str`, optional
The fully qualified name of the object.
obj : module, class, exception, function, method, or attribute
The object to which the docstring belongs.
- options : Optional[sphinx.ext.autodoc.Options]
+ options : :class:`sphinx.ext.autodoc.Options`, optional
The options given to the directive: an object with attributes
inherited_members, undoc_members, show_inheritance and noindex that
are True if the flag option of same name was given to the auto
@@ -801,7 +817,7 @@ class NumpyDocstring(GoogleDocstring):
Returns
-------
- List[str]
+ :obj:`list` of :obj:`str`
The lines of the docstring in a list.
"""
diff --git a/sphinx/ext/viewcode.py b/sphinx/ext/viewcode.py
index 89e7a9965..a071c5533 100644
--- a/sphinx/ext/viewcode.py
+++ b/sphinx/ext/viewcode.py
@@ -139,8 +139,8 @@ def collect_pages(app):
# construct a page name for the highlighted source
pagename = '_modules/' + modname.replace('.', '/')
# highlight the source using the builder's highlighter
- if env.config.highlight_language == 'python3':
- lexer = 'python3'
+ if env.config.highlight_language in ('python3', 'default'):
+ lexer = env.config.highlight_language
else:
lexer = 'python'
highlighted = highlighter.highlight_block(code, lexer, linenos=False)
diff --git a/sphinx/io.py b/sphinx/io.py
index 8d9970e80..36ac7bf98 100644
--- a/sphinx/io.py
+++ b/sphinx/io.py
@@ -15,7 +15,7 @@ from six import string_types, text_type
from sphinx.transforms import ApplySourceWorkaround, ExtraTranslatableNodes, Locale, \
CitationReferences, DefaultSubstitutions, MoveModuleTargets, HandleCodeBlocks, \
- AutoNumbering, SortIds, RemoveTranslatableInline
+ AutoNumbering, AutoIndexUpgrader, SortIds, RemoveTranslatableInline
from sphinx.util import import_object, split_docinfo
@@ -59,7 +59,7 @@ class SphinxStandaloneReader(SphinxBaseReader):
"""
transforms = [ApplySourceWorkaround, ExtraTranslatableNodes, Locale, CitationReferences,
DefaultSubstitutions, MoveModuleTargets, HandleCodeBlocks,
- AutoNumbering, SortIds, RemoveTranslatableInline]
+ AutoNumbering, AutoIndexUpgrader, SortIds, RemoveTranslatableInline]
class SphinxI18nReader(SphinxBaseReader):
@@ -112,10 +112,9 @@ class SphinxFileInput(FileInput):
return data.decode(self.encoding, 'sphinx') # py2: decoding
def read(self):
- def get_parser_type(docname):
- path = self.env.doc2path(docname)
+ def get_parser_type(source_path):
for suffix in self.env.config.source_parsers:
- if path.endswith(suffix):
+ if source_path.endswith(suffix):
parser_class = self.env.config.source_parsers[suffix]
if isinstance(parser_class, string_types):
parser_class = import_object(parser_class, 'source parser')
@@ -129,7 +128,7 @@ class SphinxFileInput(FileInput):
self.app.emit('source-read', self.env.docname, arg)
data = arg[0]
docinfo, data = split_docinfo(data)
- if 'restructuredtext' in get_parser_type(self.env.docname):
+ if 'restructuredtext' in get_parser_type(self.source_path):
if self.env.config.rst_epilog:
data = data + '\n' + self.env.config.rst_epilog + '\n'
if self.env.config.rst_prolog:
diff --git a/sphinx/quickstart.py b/sphinx/quickstart.py
index 1fd2bd626..5aa47cb61 100644
--- a/sphinx/quickstart.py
+++ b/sphinx/quickstart.py
@@ -359,6 +359,12 @@ latex_documents = [
#
# latex_appendices = []
+# It false, will not define \strong, \code, \titleref, \crossref ... but only
+# \sphinxstrong, ..., \sphinxtitleref, ... To help avoid clash with user added
+# packages.
+#
+# latex_keep_old_macro_names = True
+
# If false, no module index is generated.
#
# latex_domain_indices = True
@@ -559,8 +565,8 @@ help:
\t@echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter"
\t@echo " latexpdf to make LaTeX files and run them through pdflatex"
\t@echo " latexpdfja to make LaTeX files and run them through platex/dvipdfmx"
-\t@echo " lualatexpdf to make LaTeX files and run them through pdflatex"
-\t@echo " xelatexpdf to make LaTeX files and run them through pdflatex"
+\t@echo " lualatexpdf to make LaTeX files and run them through lualatex"
+\t@echo " xelatexpdf to make LaTeX files and run them through xelatex"
\t@echo " text to make text files"
\t@echo " man to make manual pages"
\t@echo " texinfo to make Texinfo files"
diff --git a/sphinx/search/__init__.py b/sphinx/search/__init__.py
index 0d1f864b3..6e21b2f5f 100644
--- a/sphinx/search/__init__.py
+++ b/sphinx/search/__init__.py
@@ -226,11 +226,13 @@ class IndexBuilder(object):
def __init__(self, env, lang, options, scoring):
self.env = env
- # filename -> title
+ # docname -> title
self._titles = {}
- # stemmed word -> set(filenames)
+ # docname -> filename
+ self._filenames = {}
+ # stemmed word -> set(docname)
self._mapping = {}
- # stemmed words in titles -> set(filenames)
+ # stemmed words in titles -> set(docname)
self._title_mapping = {}
# word -> stemmed word
self._stem_cache = {}
@@ -338,15 +340,16 @@ class IndexBuilder(object):
def freeze(self):
"""Create a usable data structure for serializing."""
- filenames, titles = zip(*sorted(self._titles.items()))
- fn2index = dict((f, i) for (i, f) in enumerate(filenames))
+ docnames, titles = zip(*sorted(self._titles.items()))
+ filenames = [self._filenames.get(docname) for docname in docnames]
+ fn2index = dict((f, i) for (i, f) in enumerate(docnames))
terms, title_terms = self.get_terms(fn2index)
objects = self.get_objects(fn2index) # populates _objtypes
objtypes = dict((v, k[0] + ':' + k[1])
for (k, v) in iteritems(self._objtypes))
objnames = self._objnames
- return dict(filenames=filenames, titles=titles, terms=terms,
+ return dict(docnames=docnames, filenames=filenames, titles=titles, terms=terms,
objects=objects, objtypes=objtypes, objnames=objnames,
titleterms=title_terms, envversion=self.env.version)
@@ -365,9 +368,11 @@ class IndexBuilder(object):
for wordnames in itervalues(self._title_mapping):
wordnames.intersection_update(filenames)
- def feed(self, filename, title, doctree):
+ def feed(self, docname, filename, title, doctree):
"""Feed a doctree to the index."""
- self._titles[filename] = title
+ self._titles[docname] = title
+ self._filenames[docname] = filename
+
visitor = WordCollector(doctree, self.lang)
doctree.walk(visitor)
@@ -383,9 +388,9 @@ class IndexBuilder(object):
for word in visitor.found_title_words:
stemmed_word = stem(word)
if _filter(stemmed_word):
- self._title_mapping.setdefault(stemmed_word, set()).add(filename)
+ self._title_mapping.setdefault(stemmed_word, set()).add(docname)
elif _filter(word): # stemmer must not remove words from search index
- self._title_mapping.setdefault(word, set()).add(filename)
+ self._title_mapping.setdefault(word, set()).add(docname)
for word in visitor.found_words:
stemmed_word = stem(word)
@@ -393,8 +398,7 @@ class IndexBuilder(object):
if not _filter(stemmed_word) and _filter(word):
stemmed_word = word
if stemmed_word not in self._title_mapping and _filter(stemmed_word):
- self._mapping.setdefault(stemmed_word, set()).add(filename)
-
+ self._mapping.setdefault(stemmed_word, set()).add(docname)
def context_for_searchtool(self):
return dict(
diff --git a/sphinx/setup_command.py b/sphinx/setup_command.py
index 128c1415c..7df8bd6e8 100644
--- a/sphinx/setup_command.py
+++ b/sphinx/setup_command.py
@@ -15,6 +15,8 @@ from __future__ import print_function
import sys
import os
+import traceback
+
from distutils.cmd import Command
from distutils.errors import DistutilsOptionError, DistutilsExecError
@@ -71,6 +73,7 @@ class BuildDoc(Command):
('build-dir=', None, 'Build directory'),
('config-dir=', 'c', 'Location of the configuration directory'),
('builder=', 'b', 'The builder to use. Defaults to "html"'),
+ ('warning-is-error', 'W', 'Turn warning into errors'),
('project=', None, 'The documented project\'s name'),
('version=', None, 'The short X.Y version'),
('release=', None, 'The full version, including alpha/beta/rc tags'),
@@ -78,13 +81,17 @@ class BuildDoc(Command):
'replacement for |today|'),
('link-index', 'i', 'Link index.html to the master doc'),
('copyright', None, 'The copyright string'),
+ ('pdb', None, 'Start pdb on exception'),
]
- boolean_options = ['fresh-env', 'all-files', 'link-index']
+ boolean_options = ['fresh-env', 'all-files', 'warning-is-error',
+ 'link-index']
def initialize_options(self):
self.fresh_env = self.all_files = False
+ self.pdb = False
self.source_dir = self.build_dir = None
self.builder = 'html'
+ self.warning_is_error = False
self.project = ''
self.version = ''
self.release = ''
@@ -158,7 +165,8 @@ class BuildDoc(Command):
app = Sphinx(self.source_dir, self.config_dir,
self.builder_target_dir, self.doctree_dir,
self.builder, confoverrides, status_stream,
- freshenv=self.fresh_env)
+ freshenv=self.fresh_env,
+ warningiserror=self.warning_is_error)
try:
app.build(force_all=self.all_files)
@@ -166,13 +174,20 @@ class BuildDoc(Command):
raise DistutilsExecError(
'caused by %s builder.' % app.builder.name)
except Exception as err:
- from docutils.utils import SystemMessage
- if isinstance(err, SystemMessage):
- print(darkred('reST markup error:'), file=sys.stderr)
- print(err.args[0].encode('ascii', 'backslashreplace'),
+ if self.pdb:
+ import pdb
+ print(darkred('Exception occurred while building, starting debugger:'),
file=sys.stderr)
+ traceback.print_exc()
+ pdb.post_mortem(sys.exc_info()[2])
else:
- raise
+ from docutils.utils import SystemMessage
+ if isinstance(err, SystemMessage):
+ print(darkred('reST markup error:'), file=sys.stderr)
+ print(err.args[0].encode('ascii', 'backslashreplace'),
+ file=sys.stderr)
+ else:
+ raise
if self.link_index:
src = app.config.master_doc + app.builder.out_suffix
diff --git a/sphinx/templates/latex/content.tex_t b/sphinx/templates/latex/content.tex_t
new file mode 100644
index 000000000..fb5b1decd
--- /dev/null
+++ b/sphinx/templates/latex/content.tex_t
@@ -0,0 +1,42 @@
+%% Generated by Sphinx.
+\def\sphinxdocclass{<%= docclass %>}
+\newif\ifsphinxKeepOldNames <%= keepoldnames %>
+\documentclass[<%= papersize %>,<%= pointsize %><%= classoptions %>]{<%= wrapperclass %>}
+\ifdefined\pdfpxdimen
+ \let\sphinxpxdimen\pdfpxdimen\else\newdimen\sphinxpxdimen
+\fi \sphinxpxdimen=<%= pxunit %>\relax
+\usepackage{iftex}
+<%= passoptionstopackages %>
+<%= inputenc %>
+<%= utf8extra %>
+<%= cmappkg %>
+<%= fontenc %>
+<%= amsmath %>
+<%= babel %>
+<%= fontpkg %>
+<%= fncychap %>
+<%= longtable %>
+\usepackage{sphinx}
+\usepackage{multirow}
+\usepackage{eqparbox}
+<%= usepackages %>
+<%= contentsname %>
+<%= numfig_format %>
+<%= pageautorefname %>
+<%= tocdepth %>
+<%= secnumdepth %>
+<%= preamble %>
+
+\title{<%= title %>}
+\date{<%= date %>}
+\release{<%= release %>}
+\author{<%= author %>}
+\newcommand{\sphinxlogo}{<%= logo %>}
+\renewcommand{\releasename}{<%= releasename %>}
+<%= makeindex %>
+<%= body %>
+<%= footer %>
+<%= indices %>
+\renewcommand{\indexname}{<%= indexname %>}
+<%= printindex %>
+\end{document}
diff --git a/sphinx/texinputs/Makefile b/sphinx/texinputs/Makefile
index d748006cc..c0676e3ee 100644
--- a/sphinx/texinputs/Makefile
+++ b/sphinx/texinputs/Makefile
@@ -3,6 +3,7 @@
ALLDOCS = $(basename $(wildcard *.tex))
ALLPDF = $(addsuffix .pdf,$(ALLDOCS))
ALLDVI = $(addsuffix .dvi,$(ALLDOCS))
+ALLPS = $(addsuffix .ps,$(ALLDOCS))
# Prefix for archive names
ARCHIVEPRREFIX =
@@ -18,8 +19,7 @@ MAKEINDEX = makeindex
all: $(ALLPDF)
all-pdf: $(ALLPDF)
all-dvi: $(ALLDVI)
-all-ps: all-dvi
- for f in *.dvi; do dvips $$f; done
+all-ps: $(ALLPS)
all-pdf-ja:
for f in *.pdf *.png *.gif *.jpg *.jpeg; do extractbb $$f; done
@@ -70,6 +70,9 @@ xz: tar
$(PDFLATEX) $(LATEXOPTS) '$<'
$(PDFLATEX) $(LATEXOPTS) '$<'
+%.ps: %.dvi
+ dvips '$<'
+
clean:
rm -f *.log *.ind *.aux *.toc *.syn *.idx *.out *.ilg *.pla *.ps *.tar *.tar.gz *.tar.bz2 *.tar.xz $(ALLPDF) $(ALLDVI)
diff --git a/sphinx/texinputs/iftex.sty b/sphinx/texinputs/iftex.sty
new file mode 100755
index 000000000..765146644
--- /dev/null
+++ b/sphinx/texinputs/iftex.sty
@@ -0,0 +1,97 @@
+%%
+%% This is file `iftex.sty',
+
+%%
+%% __________________________________
+%% Copyright © 2010–2013 Persian TeX Group
+%%
+%% License information appended.
+%%
+%%
+\csname iftexloaded\endcsname
+\let\iftexloaded\endinput
+\expandafter\ifx\csname ProvidesPackage\endcsname\relax\else
+ \ProvidesPackage{iftex}
+ [2013/04/04 v0.2 Provides if(tex) conditional for PDFTeX, XeTeX, and LuaTeX]
+\fi
+\def\RequirePDFTeX{%
+ \ifPDFTeX\else
+ \begingroup
+ \errorcontextlines=-1\relax
+ \newlinechar=10\relax
+ \errmessage{^^J
+ ********************************************^^J
+ * PDFTeX is required to compile this document.^^J
+ * Sorry!^^J
+ ********************************************}%
+ \endgroup
+ \fi}
+\def\RequireXeTeX{%
+ \ifXeTeX\else
+ \begingroup
+ \errorcontextlines=-1\relax
+ \newlinechar=10\relax
+ \errmessage{^^J
+ ********************************************^^J
+ * XeTeX is required to compile this document.^^J
+ * Sorry!^^J
+ ********************************************}%
+ \endgroup
+ \fi}
+\def\RequireLuaTeX{%
+ \ifLuaTeX\else
+ \begingroup
+ \errorcontextlines=-1\relax
+ \newlinechar=10\relax
+ \errmessage{^^J
+ ********************************************^^J
+ * LuaTeX is required to compile this document.^^J
+ * Sorry!^^J
+ ********************************************}%
+ \endgroup
+ \fi}
+\expandafter\ifx\csname ifPDFTeX\endcsname\relax\else
+ \expandafter\endinput
+\fi
+\expandafter\ifx\csname ifXeTeX\endcsname\relax\else
+ \expandafter\endinput
+\fi
+\expandafter\ifx\csname ifLuaTeX\endcsname\relax\else
+ \expandafter\endinput
+\fi
+\newif\ifPDFTeX
+\begingroup\expandafter\expandafter\expandafter\endgroup
+\expandafter\ifx\csname pdfmatch\endcsname\relax
+ \PDFTeXfalse
+\else
+ \PDFTeXtrue
+\fi
+\newif\ifXeTeX
+\begingroup\expandafter\expandafter\expandafter\endgroup
+\expandafter\ifx\csname XeTeXinterchartoks\endcsname\relax
+ \XeTeXfalse
+\else
+ \XeTeXtrue
+\fi
+\newif\ifLuaTeX
+\begingroup\expandafter\expandafter\expandafter\endgroup
+\expandafter\ifx\csname directlua\endcsname\relax
+ \LuaTeXfalse
+\else
+ \LuaTeXtrue
+\fi
+%%
+%% Copyright © 2010–2013 by Persian TeX Group
+%%
+%% Distributable under the LaTeX Project Public License,
+%% version 1.3c or higher (your choice). The latest version of
+%% this license is at: http://www.latex-project.org/lppl.txt
+%%
+%% This work is "maintained" (as per LPPL maintenance status)
+%% by Persian TeX Group.
+%%
+%%
+%%
+%%
+%%
+%% End of file `iftex.sty'.
diff --git a/sphinx/texinputs/needspace.sty b/sphinx/texinputs/needspace.sty
new file mode 100644
index 000000000..113d87216
--- /dev/null
+++ b/sphinx/texinputs/needspace.sty
@@ -0,0 +1,35 @@
+
+\NeedsTeXFormat{LaTeX2e}
+\ProvidesPackage{needspace}[2010/09/12 v1.3d reserve vertical space]
+
+\newcommand{\needspace}[1]{%
+ \begingroup
+ \setlength{\dimen@}{#1}%
+ \vskip\z@\@plus\dimen@
+ \penalty -100\vskip\z@\@plus -\dimen@
+ \vskip\dimen@
+ \penalty 9999%
+ \vskip -\dimen@
+ \vskip\z@skip % hide the previous |\vskip| from |\addvspace|
+ \endgroup
+}
+
+\newcommand{\Needspace}{\@ifstar{\@sneedsp@}{\@needsp@}}
+
+\newcommand{\@sneedsp@}[1]{\par \penalty-100\begingroup
+ \setlength{\dimen@}{#1}%
+ \dimen@ii\pagegoal \advance\dimen@ii-\pagetotal
+ \ifdim \dimen@>\dimen@ii
+ \break
+ \fi\endgroup}
+
+\newcommand{\@needsp@}[1]{\par \penalty-100\begingroup
+ \setlength{\dimen@}{#1}%
+ \dimen@ii\pagegoal \advance\dimen@ii-\pagetotal
+ \ifdim \dimen@>\dimen@ii
+ \ifdim \dimen@ii>\z@
+ \vfil
+ \fi
+ \break
+ \fi\endgroup}
+
diff --git a/sphinx/texinputs/newfloat.sty b/sphinx/texinputs/newfloat.sty
deleted file mode 100644
index 47ac5e568..000000000
--- a/sphinx/texinputs/newfloat.sty
+++ /dev/null
@@ -1,737 +0,0 @@
-%%
-%% This is file `newfloat.sty',
-%% generated with the docstrip utility.
-%%
-%% The original source files were:
-%%
-%% newfloat.dtx (with options: `package')
-%%
-%% Copyright (C) 1994-2016 Axel Sommerfeldt (axel.sommerfeldt@f-m.fm)
-%%
-%% http://sourceforge.net/projects/latex-caption/
-%%
-%% --------------------------------------------------------------------------
-%%
-%% This work may be distributed and/or modified under the
-%% conditions of the LaTeX Project Public License, either version 1.3
-%% of this license or (at your option) any later version.
-%% The latest version of this license is in
-%% http://www.latex-project.org/lppl.txt
-%% and version 1.3 or later is part of all distributions of LaTeX
-%% version 2003/12/01 or later.
-%%
-%% This work has the LPPL maintenance status "maintained".
-%%
-%% This Current Maintainer of this work is Axel Sommerfeldt.
-%%
-%% This work consists of the files
-%% CHANGELOG, README, SUMMARY, caption.ins,
-%% caption.dtx, caption2.dtx, caption3.dtx,
-%% bicaption.dtx, ltcaption.dtx, subcaption.dtx,
-%% newfloat.dtx, and totalcount.dtx
-%% the derived files
-%% caption.sty, caption2.sty, caption3.sty,
-%% bicaption.sty, ltcaption.sty, subcaption.sty,
-%% newfloat.sty, and totalcount.sty
-%% and the user manuals
-%% caption-deu.tex, caption-eng.tex, and caption-rus.tex.
-%%
-\NeedsTeXFormat{LaTeX2e}[1994/12/01]
-\def\caption@tempa$Id: #1 #2 #3-#4-#5 #6${%
- \def\caption@tempa{#3/#4/#5 }\def\caption@tempb{#2 }}
-\caption@tempa $Id: newfloat.dtx 109 2015-09-17 09:29:07Z sommerfeldt $
-\ProvidesPackage{newfloat}[\caption@tempa v1.1-\caption@tempb Defining new floating environments (AR)]
-\newcommand*\newfloat@Info[1]{%
- \PackageInfo{newfloat}{#1}}
-\newcommand*\newfloat@InfoNoLine[1]{%
- \newfloat@Info{#1\@gobble}}
-\newcommand*\newfloat@Error[1]{%
- \PackageError{newfloat}{#1}\newfloat@eh}
-\newcommand*\newfloat@eh{%
- If you do not understand this error, please take a closer look\MessageBreak
- at the documentation of the `newfloat' package.\MessageBreak\@ehc}
-\RequirePackage{keyval}[1997/11/10]
-\newcommand*\newfloat@def[2]{%
- \newfloat@ifundefined{#1}{%
- \@namedef{#1}{#2}}}
-\newcommand*\newfloat@let[2]{%
- \newfloat@ifundefined{#1}{%
- \expandafter\let\csname #1\endcsname#2}}
-\newcommand*\newfloat@ifundefined[2]{%
- \@ifundefined{#1}{#2}{%
- \newfloat@Info{%
- \expandafter\string\csname#1\endcsname\space is already defined}}}
-\newcommand*\DeclareFloatingEnvironment{%
- \@testopt\@DeclareFloatingEnvironment{}}
-\@onlypreamble\DeclareFloatingEnvironment
-\def\@DeclareFloatingEnvironment[#1]#2{%
- \newfloat@Info{New float `#2' with options `#1'}%
- \newfloat@ifundefined{c@#2}{\newcounter{#2}}%
- \ifdefined\c@float@type % from float package
- \expandafter\edef\csname ftype@#2\endcsname{\the\value{float@type}}%
- \addtocounter{float@type}{\value{float@type}}%
- \else\ifdefined\c@newflo@tctr % from memoir document class
- \expandafter\edef\csname ftype@#2\endcsname{\the\c@newflo@tctr}%
- \advance\c@newflo@tctr \c@newflo@tctr
- \else
- \ifdefined\newfloat@ftype \else
- \newcount\newfloat@ftype
- \newfloat@ftype=8\relax
- \fi
- \expandafter\xdef\csname ftype@#2\endcsname{\the\newfloat@ftype}%
- \advance\newfloat@ftype\newfloat@ftype
- \fi\fi
- \newfloat@Info{float type `#2'=\@nameuse{ftype@#2}}%
- \newfloat@def{fnum@#2}%
- {\@nameuse{#2name}\nobreakspace\@nameuse{the#2}\@nameuse{autodot}}%
- \newfloat@capitalize\newfloat@Type{#2}%
- \newfloat@let{#2name}{\newfloat@Type}%
- \newfloat@def{fleg#2}{\@nameuse{#2name}}% legend naming (memoir)
- \newfloat@ifundefined{flegtoc#2}{\@namedef{flegtoc#2}##1{}}%
- \ifcsname @tufte@float\endcsname
- \newenvironment{#2}[1][htbp]%
- {\begin{@tufte@float}[##1]{#2}{}}%
- {\end{@tufte@float}}%
- \newenvironment{#2*}[1][htbp]%
- {\begin{@tufte@float}[##1]{#2}{star}}%
- {\end{@tufte@float}}%
- \else
- \newenvironment{#2}{\@float{#2}}{\end@float}%
- \newenvironment{#2*}{\@dblfloat{#2}}{\end@dblfloat}%
- \fi
- \newfloat@def{listof#2}{\newfloat@listof{#2}}%
- \newfloat@def{listof#2s}{\@nameuse{listof#2}}%
- \newfloat@def{listof#2es}{\@nameuse{listof#2s}}%
- \newfloat@def{newfloat@listof#2@hook}{}%
- \ifdefined\l@figure
- \newfloat@let{l@#2}{\l@figure}%
- \else
- \newfloat@def{l@#2}{\@dottedtocline{1}{1.5em}{2.3em}}%
- \fi
- \edef\newfloat@tempa{List of \newfloat@Type s}%
- \newfloat@let{list#2name}{\newfloat@tempa}%
- \expandafter\let\csname fst@#2\endcsname\@undefined
- \newfloat@ifundefined{fps@#2}{\newfloat@setplacement{#2}{tbp}}%
- \newfloat@ifundefined{ext@#2}{\newfloat@setfileext{#2}{lo#2}}%
- \newfloat@setoptions*{#2}{#1}%
- \@expandtwoargs\newfloat@announce{#2}{\@nameuse{ext@#2}}%
- \@ifnextchar[\newfloat@DFE@setname\relax}
-\@onlypreamble\@DeclareFloatingEnvironment
-\def\newfloat@DFE@setname[#1]{%
- \KV@@newfloat@name{#1}%
- \@ifnextchar[\newfloat@DFE@setlistname\relax}
-\@onlypreamble\newfloat@DFE@setname
-\def\newfloat@DFE@setlistname[#1]{%
- \KV@@newfloat@listname{#1}}
-\@onlypreamble\newfloat@DFE@setlistname
-\newcommand*\newfloat@capitalize[2]{%
- \edef\newfloat@tempa{\gdef\noexpand#1{\@car#2\@nil}}%
- \uppercase\expandafter{\newfloat@tempa}%
- \edef\newfloat@tempa{%
- \noexpand\g@addto@macro\noexpand#1{\@cdr#2\@nil}}%
- \newfloat@tempa}
-\newcommand*\newfloat@listof[1]{%
- \@expandtwoargs\newfloat@list@of{#1}{\@nameuse{ext@#1}}}
-\newcommand*\newfloat@list@of[2]{%
- \begingroup
- \expandafter\let\expandafter\listfigurename\csname list#1name\endcsname
- \def\ext@figure{#2}%
- \let\newfloat@starttoc\@starttoc
- \def\@starttoc##1{\newfloat@starttoc{#2}}%
- \let\newfloat@listoftoc\listoftoc
- \def\listoftoc##1{\newfloat@listoftoc{#2}}%
- \@nameuse{newfloat@listof#1@hook}%
- \listoffigures
- \endgroup}
-\newcommand*\newfloat@setoptions{%
- \@ifstar
- {\newfloat@@setoptions\@firstofone}%
- {\newfloat@@setoptions\@gobble}}
-\newcommand*\newfloat@@setoptions[3]{%
- \let\newfloat@within@value\@undefined
- \let\newfloat@chapterlistsgaps@value\@undefined
- #1{\KV@@newfloat@within\newfloat@within@default}% set default value for new floats
- \def\newfloat@type{#2}%
- \setkeys{@newfloat}{#3}%
- \ifx\newfloat@within@value\@undefined \else
- \newfloat@setoption{within}\newfloat@within@value
- \fi
- \ifx\newfloat@chapterlistsgaps@value\@undefined \else
- \newfloat@setoption{chapterlistsgaps}\newfloat@chapterlistsgaps@value
- \fi}
-\newcommand*\newfloat@within@default{%
- \ifcsname c@chapter\endcsname chapter\else none\fi}
-\@onlypreamble\newfloat@within@default
-\newcommand*\newfloat@setoption[1]{%
- \edef\caption@tempa{\noexpand\@nameuse{newfloat@set#1}{\newfloat@type}}%
- \caption@tempa}
-\newcommand*\newfloat@setfileext[2]{%
- \@namedef{ext@#1}{#2}}
-\define@key{@newfloat}{fileext}{%
- \newfloat@setoption{fileext}{#1}}
-\newcommand*\newfloat@setlistname[2]{%
- \@namedef{list#1name}{#2}}
-\define@key{@newfloat}{listname}{%
- \newfloat@setoption{listname}{#1}}
-\newcommand*\newfloat@setname[2]{%
- \newfloat@@setname{#1}{#2}%
- \begingroup
- \ifcsname languagename\endcsname
- \ifcsname captions\languagename\endcsname
- \expandafter\g@addto@macro\csname captions\languagename\endcsname
- {\newfloat@@setname{#1}{#2}}%
- \fi
- \fi
- \endgroup}
-%%\AtBeginDocument{\let\newfloat@setname\newfloat@@setname}
-\newcommand*\newfloat@@setname[2]{%
- \@namedef{#1name}{#2}}
-\define@key{@newfloat}{name}{%
- \newfloat@setoption{name}{#1}}
-\newcommand*\newfloat@setplacement[2]{%
- \@namedef{fps@#1}{#2}}
-\define@key{@newfloat}{placement}{%
- \newfloat@setoption{placement}{#1}}
-\newcommand*\newfloat@setwithin[2]{%
- \ifcsname c@chapter\endcsname
- \@removefromreset{#1}{chapter}%
- \fi
- \@removefromreset{#1}{section}%
- \edef\@tempa{#2}%
- \ifx\@tempa\@empty
- \def\@tempa{none}%
- \fi
- \def\@tempb{none}%
- \ifx\@tempa\@tempb
- \ifcsname c@chapter\endcsname
- \@chapterlistsgap@off{#1}%
- \fi
- \newfloat@@setwithin{#1}{}{}%
- \else
- \def\@tempb{chapter}%
- \ifx\@tempa\@tempb
- \@addtoreset{#1}{chapter}%
- \@chapterlistsgap@on{#1}%
- \newfloat@@setwithin{#1}{\ifnum\c@chapter>\z@ \thechapter.\fi}{\theHchapter.}%
- \else
- \def\@tempb{section}%
- \ifx\@tempa\@tempb
- \@addtoreset{#1}{section}%
- \ifcsname c@chapter\endcsname
- \@addtoreset{#1}{chapter}%
- \@chapterlistsgap@on{#1}%
- \newfloat@@setwithin{#1}{\thesection.}{\theHsection.}%
- \else
- \newfloat@@setwithin{#1}{\ifnum\c@section>\z@ \thesection.\fi}{\theHsection.}%
- \fi
- \else
- \newfloat@Error{Invalid value `#2' for option `within'}%
- \fi
- \fi
- \fi}
-\newcommand*\newfloat@@setwithin[3]{%
- \global\@namedef{the#1}{#2\arabic{#1}}%
- \global\@namedef{theH#1}{#3\arabic{#1}}}
-\define@key{@newfloat}{within}{%
- \def\newfloat@within@value{#1}}
-\newcommand*\newfloat@setwithout[1]{%
- \newfloat@setwithin{#1}{none}}
-\define@key{@newfloat}{without}[]{%
- \def\newfloat@within@value{none}}
-\newcommand*\newfloat@setchapterlistsgaps[2]{%
- \edef\@tempa{#2}%
- \def\@tempb{off}%
- \ifx\@tempa\@tempb
- \@chapterlistsgap@off{#1}%
- \else
- \def\@tempb{on}%
- \ifx\@tempa\@tempb
- \@chapterlistsgap@on{#1}%
- \else
- \newfloat@Error{Invalid value `#2' for option `chapterlistsgaps'}%
- \fi
- \fi}
-\define@key{@newfloat}{chapterlistsgaps}{%
- \def\newfloat@chapterlistsgaps@value{#1}}
-\providecommand*\@removefromreset[2]{{%
- \expandafter\let\csname c@#1\endcsname\@removefromreset
- \def\@elt##1{%
- \expandafter\ifx\csname c@##1\endcsname\@removefromreset
- \else
- \noexpand\@elt{##1}%
- \fi}%
- \expandafter\xdef\csname cl@#2\endcsname{%
- \csname cl@#2\endcsname}}}
-\newcommand*\newfloat@announce[2]{%
- \@cons\newfloat@list{{#1}}%
- \@cons\newfloat@@list{{#1}}%
- \newfloat@ifundefined{newfloat@ext@#2}{%
- \@namedef{newfloat@ext@#2}{#1}%
- \ifcsname c@lofdepth\endcsname
- \newfloat@ifundefined{c@#2depth}{%
- \newcounter{#2depth}%
- \setcounter{#2depth}{1}}%
- \fi
- \ifcsname addtotoclist\endcsname
- \addtotoclist[float]{#2}%
- \newfloat@def{listof#2name}{\@nameuse{list#1name}}%
- \fi
- }%
- \ifcsname contentsuse\endcsname
- \contentsuse{#1}{#2}%
- \fi
- \newfloat@hook{#1}}
-\@onlypreamble\newfloat@announce
-\newcommand*\newfloat@@list{}
-\newcommand*\SetupFloatingEnvironment[1]{%
- \newfloat@addtolist{#1}%
- \newfloat@setoptions{#1}}
-\newcommand\ForEachFloatingEnvironment{%
- \@ifstar
- {\@ForEachFloatingEnvironment\@gobble}%
- {\@ForEachFloatingEnvironment\@iden}}
-\newcommand\@ForEachFloatingEnvironment[2]{%
- \def\@elt##1{#2}%
- \newfloat@list
- \let\@elt\relax
- #1{\newfloat@addtohook{#2}}}
-\providecommand\newfloat@addtohook[1]{%
- \toks@=\expandafter{\newfloat@hook{##1}#1}%
- \edef\@tempa{\def\noexpand\newfloat@hook####1{\the\toks@}}%
- \@tempa}
-\providecommand*\newfloat@hook[1]{}
-\newcommand\PrepareListOf[1]{%
- \expandafter\g@addto@macro\csname newfloat@listof#1@hook\endcsname}
-\@onlypreamble\PrepareListOf
-\newcommand*\newfloat@list{}
-\newcommand*\newfloat@addtolist[1]{%
- \newfloat@ifinlist{#1}{}{%
- \ifcsname ext@#1\endcsname
- \@cons\newfloat@list{{#1}}%
- \@namedef{newfloat@ext@\@nameuse{ext@#1}}{#1}%
- \newfloat@let{@ifchapterlistsgap@#1}{\@iden}%
- \else
- \newfloat@Error{`#1' does not seem to be a floating environment}%
- \fi}}
-\newcommand*\newfloat@ifinlist[1]{%
- \let\next\@secondoftwo
- \begingroup
- \expandafter\let\csname c@#1\endcsname\newfloat@ifinlist
- \def\@elt##1{%
- \expandafter\ifx\csname c@##1\endcsname\newfloat@ifinlist
- \global\let\next\@firstoftwo
- \fi}%
- \newfloat@list
- \endgroup
- \next}
-\ifcsname ext@figure\endcsname
- \newfloat@addtolist{figure}
-\fi
-\ifcsname ext@table\endcsname
- \newfloat@addtolist{table}
-\fi
-\ifcsname @chapter\endcsname
- \providecommand*\@chapterlistsgap{10\p@}%
- \providecommand*\@addchapterlistsgap[2]{%
- \@nameuse{@ifchapterlistsgap@#1}{% if switched on
- \@@addchapterlistsgap{#1}{#2}}}
- \providecommand*\@@addchapterlistsgap[2]{%
- \@ifundefined{@addchapterlistsgap@#2}{% only once per extension
- \@namedef{@addchapterlistsgap@#2}{#1}%
- \@@@addchapterlistsgap{#2}}{}}
- \providecommand*\@@@addchapterlistsgap[1]{%
- \ifdim \@chapterlistsgap>\z@
- \addtocontents{#1}{\protect\addvspace{\@chapterlistsgap}}%
- \fi}
- \providecommand*\@addchapterlistsgaps{%
- \begingroup
- \def\@elt##1{%
- \@expandtwoargs\@addchapterlistsgap{##1}{\@nameuse{ext@##1}}}%
- \newfloat@list
- \endgroup}
- \providecommand*\@chapterlistsgap@off[1]{%
- \expandafter\let\csname @ifchapterlistsgap@#1\endcsname\@gobble
- \ifcsname unsettoc\endcsname
- \@expandtwoargs\unsettoc{\@nameuse{ext@#1}}{chapteratlist}%
- \fi}
- \providecommand*\@chapterlistsgap@on[1]{%
- \expandafter\let\csname @ifchapterlistsgap@#1\endcsname\@iden
- \ifcsname setuptoc\endcsname
- \@expandtwoargs\setuptoc{\@nameuse{ext@#1}}{chapteratlist}%
- \fi}
-\fi
-\define@key{newfloat}{chapterlistsgap}{%
- \renewcommand*\@chapterlistsgap{#1}}
-\define@key{newfloat}{within}{%
- \def\newfloat@within@default{#1}% set new default value
- \def\@elt##1{\newfloat@setwithin{##1}{#1}}%
- \newfloat@list
- \let\@elt\relax}
-\define@key{newfloat}{without}[]{%
- \KV@newfloat@within{none}}
-\def\@elt#1{%
- \define@key{newfloat}{#1name}{%
- \newfloat@setname{#1}{##1}}%
- \define@key{newfloat}{list#1name}{%
- \newfloat@setname{list#1}{##1}}%
- \define@key{newfloat}{#1within}{%
- \newfloat@setwithin{#1}{##1}}%
- \define@key{newfloat}{#1without}[]{%
- \newfloat@setwithout{#1}}%
-}%
-\newfloat@list
-\let\@elt\relax
-\define@key{newfloat}{planb}[true]{%
- \def\@tempa{#1}%
- \def\@tempb{false}%
- \ifx\@tempa\@tempb
- \let\newfloat@ifplanb\@gobble
- \else
- \def\@tempb{true}%
- \ifx\@tempa\@tempb
- \let\newfloat@ifplanb\@iden
- \else
- \newfloat@Error{Invalid value `#1' for option `planb'}%
- \fi
- \fi}
-\define@key{newfloat}{planb-fileext}{%
- \newfloat@Info{Setting Plan B file extension to `#1'}
- \xdef\newfloat@addtocontents@ext{#1}}
-
-\let\@tempc\relax
-\@expandtwoargs\setkeys{newfloat}{planb,\@ptionlist{\@currname.\@currext}}%
-\AtEndOfPackage{\let\@unprocessedoptions\relax}
-\newcommand*\newfloatsetup{\setkeys{newfloat}}
-\newcommand\newfloat@replace@chapter[2]{%
- \begingroup
- \let\if@twocolumn\iffalse
- \let\if@mainmatter\iffalse
- \let\if@thema\iffalse
- \def\@tempa[##1]##2{#1}%
- \ifx\@tempa\@chapter
- \gdef\@chapter[##1]##2{#2}%
- \global\let\newfloat@replace@chapter\@gobbletwo
- \else\ifx\@tempa\Hy@org@chapter
- \gdef\Hy@org@chapter[##1]##2{#2}%
- \global\let\newfloat@replace@chapter\@gobbletwo
- \fi\fi
- \endgroup}
-\ifcsname @chapter\endcsname \else
- \let\newfloat@replace@chapter\@gobbletwo
-\fi
-\newfloat@replace@chapter{%
- \ifnum \c@secnumdepth >\m@ne
- \refstepcounter{chapter}%
- \typeout{\@chapapp\space\thechapter.}%
- \addcontentsline{toc}{chapter}%
- {\protect\numberline{\thechapter}#1}%
- \else
- \addcontentsline{toc}{chapter}{#1}%
- \fi
- \chaptermark{#1}%
- \addtocontents{lof}{\protect\addvspace{10\p@}}%
- \addtocontents{lot}{\protect\addvspace{10\p@}}%
- \if@twocolumn
- \@topnewpage[\@makechapterhead{#2}]%
- \else
- \@makechapterhead{#2}%
- \@afterheading
- \fi
-}{%
- \ifnum \c@secnumdepth >\m@ne
- \refstepcounter{chapter}%
- \typeout{\@chapapp\space\thechapter.}%
- \addcontentsline{toc}{chapter}%
- {\protect\numberline{\thechapter}#1}%
- \else
- \addcontentsline{toc}{chapter}{#1}%
- \fi
- \chaptermark{#1}%
- \@addchapterlistsgaps
- \if@twocolumn
- \@topnewpage[\@makechapterhead{#2}]%
- \else
- \@makechapterhead{#2}%
- \@afterheading
- \fi}
-\newfloat@replace@chapter{%
- \ifnum \c@secnumdepth >\m@ne
- \if@mainmatter
- \refstepcounter{chapter}%
- \typeout{\@chapapp\space\thechapter.}%
- \addcontentsline{toc}{chapter}%
- {\protect\numberline{\thechapter}#1}%
- \else
- \addcontentsline{toc}{chapter}{#1}%
- \fi
- \else
- \addcontentsline{toc}{chapter}{#1}%
- \fi
- \chaptermark{#1}%
- \addtocontents{lof}{\protect\addvspace{10\p@}}%
- \addtocontents{lot}{\protect\addvspace{10\p@}}%
- \if@twocolumn
- \@topnewpage[\@makechapterhead{#2}]%
- \else
- \@makechapterhead{#2}%
- \@afterheading
- \fi
-}{%
- \ifnum \c@secnumdepth >\m@ne
- \if@mainmatter
- \refstepcounter{chapter}%
- \typeout{\@chapapp\space\thechapter.}%
- \addcontentsline{toc}{chapter}%
- {\protect\numberline{\thechapter}#1}%
- \else
- \addcontentsline{toc}{chapter}{#1}%
- \fi
- \else
- \addcontentsline{toc}{chapter}{#1}%
- \fi
- \chaptermark{#1}%
- \@addchapterlistsgaps
- \if@twocolumn
- \@topnewpage[\@makechapterhead{#2}]%
- \else
- \@makechapterhead{#2}%
- \@afterheading
- \fi}
-\newfloat@replace@chapter{%
- \refstepcounter{chapter}%
- \ifnum\c@secnumdepth<\z@ \let\@secnumber\@empty
- \else \let\@secnumber\thechapter \fi
- \typeout{\chaptername\space\@secnumber}%
- \def\@toclevel{0}%
- \ifx\chaptername\appendixname \@tocwriteb\tocappendix{chapter}{#2}%
- \else \@tocwriteb\tocchapter{chapter}{#2}\fi
- \chaptermark{#1}%
- \addtocontents{lof}{\protect\addvspace{10\p@}}%
- \addtocontents{lot}{\protect\addvspace{10\p@}}%
- \@makechapterhead{#2}\@afterheading
-}{%
- \refstepcounter{chapter}%
- \ifnum\c@secnumdepth<\z@ \let\@secnumber\@empty
- \else \let\@secnumber\thechapter \fi
- \typeout{\chaptername\space\@secnumber}%
- \def\@toclevel{0}%
- \ifx\chaptername\appendixname \@tocwriteb\tocappendix{chapter}{#2}%
- \else \@tocwriteb\tocchapter{chapter}{#2}\fi
- \chaptermark{#1}%
- \@addchapterlistsgaps
- \@makechapterhead{#2}\@afterheading}
-\@ifpackageloaded{tocbasic}{%
- \let\newfloat@replace@chapter\@gobbletwo}{}
-\ifcsname insertchapterspace\endcsname
- \renewcommand*\insertchapterspace{\@addchapterlistsgaps}
- \let\newfloat@replace@chapter\@gobbletwo
-\fi
-\newfloat@replace@chapter{%
- \ifnum \c@secnumdepth >\m@ne
- \refstepcounter{chapter}%
- \typeout{\@chapapp\space\thechapter.}%
- \addcontentsline{toc}{chapter}%
- {\protect\numberline{\thechapter}\toc@font0 #1}%
- \else
- \addcontentsline{toc}{chapter}{\toc@font0 #1}%
- \fi
- \chaptermark{#1}%
- \addtocontents{lof}{\protect\addvspace{10\p@}}%
- \addtocontents{lot}{\protect\addvspace{10\p@}}%
- \if@twocolumn
- \@topnewpage[\@makechapterhead{#2}]%
- \else
- \@makechapterhead{#2}%
- \@afterheading
- \fi
-}{%
- \ifnum \c@secnumdepth >\m@ne
- \refstepcounter{chapter}%
- \typeout{\@chapapp\space\thechapter.}%
- \addcontentsline{toc}{chapter}%
- {\protect\numberline{\thechapter}\toc@font0 #1}%
- \else
- \addcontentsline{toc}{chapter}{\toc@font0 #1}%
- \fi
- \chaptermark{#1}%
- \@addchapterlistsgaps
- \if@twocolumn
- \@topnewpage[\@makechapterhead{#2}]%
- \else
- \@makechapterhead{#2}%
- \@afterheading
- \fi}
- % boek(3).cls [2004/06/07 v2.1a NTG LaTeX document class]
-\newfloat@replace@chapter{%
- \ifnum \c@secnumdepth >\m@ne
- \if@mainmatter
- \refstepcounter{chapter}%
- \typeout{\@chapapp\space\thechapter.}%
- \addcontentsline{toc}{chapter}%
- {\protect\numberline{\thechapter}\toc@font0 #1}%
- \else
- \addcontentsline{toc}{chapter}{\toc@font0 #1}%
- \fi
- \else
- \addcontentsline{toc}{chapter}{\toc@font0 #1}%
- \fi
- \chaptermark{#1}%
- \addtocontents{lof}{\protect\addvspace{10\p@}}%
- \addtocontents{lot}{\protect\addvspace{10\p@}}%
- \if@twocolumn
- \@topnewpage[\@makechapterhead{#2}]%
- \else
- \@makechapterhead{#2}%
- \@afterheading
- \fi
-}{%
- \ifnum \c@secnumdepth >\m@ne
- \if@mainmatter
- \refstepcounter{chapter}%
- \typeout{\@chapapp\space\thechapter.}%
- \addcontentsline{toc}{chapter}%
- {\protect\numberline{\thechapter}\toc@font0 #1}%
- \else
- \addcontentsline{toc}{chapter}{\toc@font0 #1}%
- \fi
- \else
- \addcontentsline{toc}{chapter}{\toc@font0 #1}%
- \fi
- \chaptermark{#1}%
- \@addchapterlistsgaps
- \if@twocolumn
- \@topnewpage[\@makechapterhead{#2}]%
- \else
- \@makechapterhead{#2}%
- \@afterheading
- \fi}
-\newfloat@replace@chapter{%
- \ifnum \c@secnumdepth >\m@ne
- \if@mainmatter
- \refstepcounter{chapter}%
- \typeout{\chaptername\space\thechapter.}
- \if@thema
- \ifx\@shortauthor\@empty
- \addcontentsline{toc}{chapter}{%
- \protect\numberline{\thechapter.}#1}%
- \else
- \addcontentsline{toc}{chapter}{%
- \protect\numberline{\thechapter.}%
- \@shortauthor\hfill\mbox{}\vskip\normallineskip #1}%
- \fi
- \else
- \addcontentsline{toc}{chapter}{%
- \protect\numberline{\thechapter.}#1}%
- \fi
- \else
- \addcontentsline{toc}{chapter}{#1}
- \fi
- \else
- \addcontentsline{toc}{chapter}{#1}
- \fi
- \chaptermark{#1}
- \addtocontents{lof}{\protect\addvspace{10pt}}
- \addtocontents{lot}{\protect\addvspace{10pt}}
- \if@twocolumn
- \@topnewpage[\@makechapterhead{#2}]
- \else
- \@makechapterhead{#2}
- \@afterheading
- \fi
-}{%
- \ifnum \c@secnumdepth >\m@ne
- \if@mainmatter
- \refstepcounter{chapter}%
- \typeout{\chaptername\space\thechapter.}%
- \if@thema
- \ifx\@shortauthor\@empty
- \addcontentsline{toc}{chapter}{%
- \protect\numberline{\thechapter.}#1}%
- \else
- \addcontentsline{toc}{chapter}{%
- \protect\numberline{\thechapter.}%
- \@shortauthor\hfill\mbox{}\vskip\normallineskip #1}%
- \fi
- \else
- \addcontentsline{toc}{chapter}{%
- \protect\numberline{\thechapter.}#1}%
- \fi
- \else
- \addcontentsline{toc}{chapter}{#1}%
- \fi
- \else
- \addcontentsline{toc}{chapter}{#1}%
- \fi
- \chaptermark{#1}%
- \@addchapterlistsgaps
- \if@twocolumn
- \@topnewpage[\@makechapterhead{#2}]%
- \else
- \@makechapterhead{#2}%
- \@afterheading
- \fi}
-\ifx\newfloat@replace@chapter\@gobbletwo \else
- \newfloat@InfoNoLine{%
- Unsupported document class, or \noexpand\@chapter\MessageBreak
- was already redefined by another package}
- \newfloat@InfoNoLine{\string\@chapter\space=\space\meaning\@chapter}
- \newfloat@InfoNoLine{\string\Hy@org@chapter\space=\space\meaning\Hy@org@chapter}
- \newfloat@ifplanb{%
- \newfloat@InfoNoLine{Trying Plan B..}%
- \let\newfloat@addtocontents@ORI\addtocontents
- \long\def\addtocontents#1#2{%
- \newfloat@addtocontents{#1}{#2}#2\addvspace\newfloat@nil}%
- \long\def\newfloat@addtocontents#1#2#3\addvspace#4\newfloat@nil{%
- \def\newfloat@tempa{#4}%
- \ifx\newfloat@tempa\@empty
- \newfloat@addtocontents@ORI{#1}{#2}%
- \else
- \ifx\newfloat@addtocontents@ext\@undefined
- \newfloat@Info{Setting Plan B file extension to `#1'...}%
- \xdef\newfloat@addtocontents@ext{#1}%
- \fi
- \edef\newfloat@tempa{#1}%
- \ifx\newfloat@tempa\newfloat@addtocontents@ext
- \begingroup
- \let\addtocontents\newfloat@addtocontents@ORI
- \@addchapterlistsgaps
- \endgroup
- \fi
- \fi}}
-\fi
-\newcommand\newfloat@ForEachNew[2][newfloat@@list]{%
- \AtBeginDocument{%
- \ifcsname#1\endcsname
- \def\@elt##1{#2}%
- \newfloat@@list
- \let\@elt\relax
- \fi}}%
-\@onlypreamble\newfloat@ForEachNew
-%% \begin{macrocode}
-\newfloat@ForEachNew[float@exts]{%
- \@nameuse{@ifchapterlistsgap@#1}{% if switched on
- \let\float@do=\relax
- \edef\@tempa{%
- \noexpand\float@exts{\the\float@exts\float@do{\@nameuse{ext@#1}}}}%
- \@tempa}}
-\newfloat@ForEachNew[FP@floatBegin]{%
- \newcounter{FP@#1C}%
- \newenvironment{FP#1}{\FP@floatBegin{#1}}{\FP@floatEnd}}
-\providecommand*\ext@lstlisting{lol}%
-\newfloat@ForEachNew[@rotfloat]{%
- \newenvironment{sideways#1}{\@rotfloat{#1}}{\end@rotfloat}%
- \newenvironment{sideways#1*}{\@rotdblfloat{#1}}{\end@rotdblfloat}}
-\newcommand*\newfloat@For@SC[2]{%
- \def#1{b}% = \sidecaptionvpos{#2}{b} (v1.6)
- \newenvironment{SC#2}%
- {\SC@float[#1]{#2}}{\endSC@float}%
- \newenvironment{SC#2*}%
- {\SC@dblfloat[#1]{#2}}{\endSC@dblfloat}}
-\@onlypreamble\newfloat@For@SC
-\newfloat@ForEachNew[SC@float]{%
- \expandafter\newfloat@For@SC\csname SC@#1@vpos\endcsname{#1}}
-\newfloat@ForEachNew[wrapfloat]{%
- \newenvironment{wrap#1}{\wrapfloat{#1}}{\endwrapfloat}}
-\endinput
-%%
-%% End of file `newfloat.sty'.
diff --git a/sphinx/texinputs/sphinx.sty b/sphinx/texinputs/sphinx.sty
index 956924e99..e612cf5ef 100644
--- a/sphinx/texinputs/sphinx.sty
+++ b/sphinx/texinputs/sphinx.sty
@@ -6,18 +6,34 @@
%
\NeedsTeXFormat{LaTeX2e}[1995/12/01]
-\ProvidesPackage{sphinx}[2010/01/15 LaTeX package (Sphinx markup)]
+\ProvidesPackage{sphinx}[2016/06/10 LaTeX package (Sphinx markup)]
+% this is the \ltx@ifundefined of ltxcmds.sty, which is loaded by
+% hyperref.sty, but we need it before, and initial ltxcmds.sty
+% as in TL2009/Debian had wrong definition.
+\newcommand{\spx@ifundefined}[1]{%
+ \ifcsname #1\endcsname
+ \expandafter\ifx\csname #1\endcsname\relax
+ \expandafter\expandafter\expandafter\@firstoftwo
+ \else
+ \expandafter\expandafter\expandafter\@secondoftwo
+ \fi
+ \else
+ \expandafter\@firstoftwo
+ \fi
+}
+
+\RequirePackage{graphicx}
\@ifclassloaded{memoir}{}{\RequirePackage{fancyhdr}}
+% for \text macro and \iffirstchoice@ conditional even if amsmath not loaded
+\RequirePackage{amstext}
\RequirePackage{textcomp}
\RequirePackage{titlesec}
\RequirePackage{tabulary}
\RequirePackage{makeidx}
% For framing code-blocks and warning type notices, and shadowing topics
\RequirePackage{framed}
-\newif\ifSphinx@inframed % flag set if we are in a framed environment
-\RequirePackage{ifthen}
% The xcolor package draws better fcolorboxes around verbatim code
\IfFileExists{xcolor.sty}{
\RequirePackage{xcolor}
@@ -26,12 +42,16 @@
}
% For highlighted code.
\RequirePackage{fancyvrb}
+\fvset{fontsize=\small}
% For table captions.
\RequirePackage{threeparttable}
% Handle footnotes in tables.
\RequirePackage{footnote}
\makesavenoteenv{tabulary}
-% For floating figures in the text.
+% For the H specifier. Do not \restylefloat{figure}, it breaks Sphinx code
+% for allowing figures in tables.
+\RequirePackage{float}
+% For floating figures in the text. Better to load after float.
\RequirePackage{wrapfig}
% Separate paragraphs by space by default.
\RequirePackage{parskip}
@@ -61,20 +81,20 @@
\newcount\pdfoutput\pdfoutput=0
\fi
-\RequirePackage{graphicx}
-
% for PDF output, use colors and maximal compression
-\newif\ifsphinxpdfoutput\sphinxpdfoutputfalse
-\ifx\pdfoutput\undefined\else\ifcase\pdfoutput
+\newif\ifsphinxpdfoutput % used in \maketitle
+\ifx\pdfoutput\undefined\else
+ \ifnum\pdfoutput=\z@
\let\py@NormalColor\relax
\let\py@TitleColor\relax
-\else
+ \else
\sphinxpdfoutputtrue
\input{pdfcolor}
\def\py@NormalColor{\color[rgb]{0.0,0.0,0.0}}
\def\py@TitleColor{\color{TitleColor}}
\pdfcompresslevel=9
-\fi\fi
+ \fi
+\fi
% XeLaTeX can do colors, too
\ifx\XeTeXrevision\undefined\else
@@ -109,9 +129,10 @@
% Use this to set the font family for headers and other decor:
\newcommand{\py@HeaderFamily}{\sffamily\bfseries}
+\newcommand{\sphinxSetHeaderFamily}[1]{\renewcommand{\py@HeaderFamily}{#1}}
% Redefine the 'normal' header/footer style when using "fancyhdr" package:
-\@ifundefined{fancyhf}{}{
+\spx@ifundefined{fancyhf}{}{
% Use \pagestyle{normal} as the primary pagestyle for text.
\fancypagestyle{normal}{
\fancyhf{}
@@ -122,9 +143,8 @@
\renewcommand{\headrulewidth}{0.4pt}
\renewcommand{\footrulewidth}{0.4pt}
% define chaptermark with \@chappos when \@chappos is available for Japanese
- \ifx\@chappos\undefined\else
- \def\chaptermark##1{\markboth{\@chapapp\space\thechapter\space\@chappos\space ##1}{}}
- \fi
+ \spx@ifundefined{@chappos}{}
+ {\def\chaptermark##1{\markboth{\@chapapp\space\thechapter\space\@chappos\space ##1}{}}}
}
% Update the plain style so we get the page number & footer line,
% but not a chapter or section title. This is to keep the first
@@ -138,28 +158,45 @@
}
% Some custom font markup commands.
-%
-\newcommand{\strong}[1]{{\textbf{#1}}}
-\newcommand{\code}[1]{\texttt{#1}}
-\newcommand{\bfcode}[1]{\code{\bfseries#1}}
-\newcommand{\email}[1]{\textsf{#1}}
-\newcommand{\tablecontinued}[1]{\textsf{#1}}
-\newcommand{\titleref}[1]{\emph{#1}}
-\newcommand{\menuselection}[1]{\emph{#1}}
-\newcommand{\accelerator}[1]{\underline{#1}}
-\newcommand{\crossref}[1]{\emph{#1}}
-\newcommand{\termref}[1]{\emph{#1}}
+% *** the macros without \sphinx prefix are still defined at bottom of file ***
+\newcommand{\sphinxstrong}[1]{{\textbf{#1}}}
+% let \sphinxcode and \sphinxbfcode use straight quotes. \@noligs patched by upquote,
+% but needs protection in "moving arguments" such as for captions.
+% Use \scantokens to handle e.g. \item[{\sphinxcode{'fontenc'}}]
+\DeclareRobustCommand{\sphinxcode}[1]{{\@noligs\scantokens{\texttt{#1}\relax}}}
+\newcommand{\sphinxbfcode}[1]{\sphinxcode{\bfseries#1}}
+\newcommand{\sphinxemail}[1]{\textsf{#1}}
+\newcommand{\sphinxtablecontinued}[1]{\textsf{#1}}
+\newcommand{\sphinxtitleref}[1]{\emph{#1}}
+\newcommand{\sphinxmenuselection}[1]{\emph{#1}}
+\newcommand{\sphinxaccelerator}[1]{\underline{#1}}
+\newcommand{\sphinxcrossref}[1]{\emph{#1}}
+\newcommand{\sphinxtermref}[1]{\emph{#1}}
+% miscellaneous related to footnotes
\newcommand*{\sphinxAtStartFootnote}{\mbox{ }}
+% Support large numbered footnotes in minipage (cf. admonitions)
+\def\thempfootnote{\arabic{mpfootnote}}
-% Redefine the Verbatim environment to allow border and background colors
-% and to handle the top caption in a non separable by pagebreak way.
-% The original environment is still used for verbatims within tables.
-\let\OriginalVerbatim=\Verbatim
-\let\endOriginalVerbatim=\endVerbatim
+% Preparations for sphinxVerbatim environment, which is a wrapper of fancyvrb
+% Verbatim with framing allowing pagebreaks, with border and background colors
+% and possibly also a top caption, non separable by pagebreak.
-\newcommand\Sphinx@colorbox [2]{%
-% #1 will be \fcolorbox or, for first part of frame: \Sphinx@fcolorbox
+% For maintaining compatibility with Sphinx < 1.5, we define and use these
+% when (unmodified) Verbatim will be needed. But Sphinx >= 1.5 does not modify
+% original Verbatim anyhow.
+\let\OriginalVerbatim \Verbatim
+\let\endOriginalVerbatim\endVerbatim
+
+\newif\ifspx@inframed % flag set if we are already in a framed environment
+\newdimen\sphinxverbatimsep \sphinxverbatimsep \fboxsep % default 3pt
+\newdimen\sphinxverbatimborder\sphinxverbatimborder\fboxrule % default 0.4pt
+\newif\ifsphinxverbatimwithframe \sphinxverbatimwithframetrue
+\newif\ifsphinxverbatimwrapslines \sphinxverbatimwrapslinestrue
+% if forced use of minipage encapsulation is needed (e.g. table cells)
+\newif\ifsphinxverbatimwithminipage \sphinxverbatimwithminipagefalse
+\newcommand\spx@colorbox [2]{%
+% #1 will be \fcolorbox or, for first part of frame: \spx@fcolorbox
% let the framing obey the current indentation (adapted from framed.sty's code).
\hskip\@totalleftmargin
\hskip-\fboxsep\hskip-\fboxrule
@@ -168,100 +205,102 @@
\hskip-\linewidth \hskip-\@totalleftmargin \hskip\columnwidth
}
% use of \color@b@x here is compatible with both xcolor.sty and color.sty
-\def\Sphinx@fcolorbox #1#2%
- {\color@b@x {\fboxsep\z@\color{#1}\Sphinx@VerbatimFBox}{\color{#2}}}%
+\def\spx@fcolorbox #1#2%
+ {\color@b@x {\fboxsep\z@\color{#1}\spx@VerbatimFBox}{\color{#2}}}%
-% The title is specified from outside as macro \SphinxVerbatimTitle.
-% \SphinxVerbatimTitle is reset to empty after each use of Verbatim.
-\newcommand*\SphinxVerbatimTitle {}
+% The title (caption) is specified from outside as macro \sphinxVerbatimTitle.
+% \sphinxVerbatimTitle is reset to empty after each use of Verbatim.
+\newcommand*\sphinxVerbatimTitle {}
+% This box to typeset the caption before framed.sty multiple passes for framing.
+\newbox\spx@VerbatimTitleBox
% Holder macro for labels of literal blocks. Set-up by LaTeX writer.
-\newcommand*\SphinxLiteralBlockLabel {}
-\newcommand*\SphinxSetupCaptionForVerbatim [2]
+\newcommand*\sphinxLiteralBlockLabel {}
+\newcommand*\sphinxSetupCaptionForVerbatim [1]
{%
- \needspace{\literalblockneedspace}%
-% insert a \label via \SphinxLiteralBlockLabel
+ \needspace{\sphinxliteralblockneedspace}%
+% insert a \label via \sphinxLiteralBlockLabel
% reset to normal the color for the literal block caption
% the caption inserts \abovecaptionskip whitespace above itself (usually 10pt)
% there is also \belowcaptionskip but it is usually zero, hence the \smallskip
- \def\SphinxVerbatimTitle
- {\py@NormalColor\captionof{#1}{\SphinxLiteralBlockLabel #2}\smallskip }%
+ \def\sphinxVerbatimTitle
+ {\py@NormalColor
+ \captionof{literalblock}{\sphinxLiteralBlockLabel #1}\smallskip }%
}
% Inspired and adapted from framed.sty's \CustomFBox with extra handling
-% of a non separable by pagebreak caption, and controlled counter stepping.
-\newif\ifSphinx@myfirstframedpass
-
-\long\def\Sphinx@VerbatimFBox#1{%
+% of a non separable by pagebreak caption.
+\long\def\spx@VerbatimFBox#1{%
\leavevmode
\begingroup
- % framed.sty does some measuring but this macro adds possibly a caption
- % use amsmath conditional to inhibit the caption counter stepping after
- % first pass
- \ifSphinx@myfirstframedpass\else\firstchoice@false\fi
\setbox\@tempboxa\hbox{\kern\fboxsep{#1}\kern\fboxsep}%
\hbox
{\lower\dimexpr\fboxrule+\fboxsep+\dp\@tempboxa
\hbox{%
- \vbox{\ifx\SphinxVerbatimTitle\empty\else
+ \vbox{\ifvoid\spx@VerbatimTitleBox\else
% add the caption in a centered way above possibly indented frame
% hide its width from framed.sty's measuring step
% note that the caption brings \abovecaptionskip top vertical space
\moveright\dimexpr\fboxrule+.5\wd\@tempboxa
- \hb@xt@\z@{\hss\begin{minipage}{\wd\@tempboxa}%
- \SphinxVerbatimTitle
- \end{minipage}\hss}\fi
- \hrule\@height\fboxrule\relax
- \hbox{\vrule\@width\fboxrule\relax
+ \hb@xt@\z@{\hss\unhcopy\spx@VerbatimTitleBox\hss}\fi
+ % draw frame border _latest_ to avoid pdf viewer issue
+ \kern\fboxrule
+ \hbox{\kern\fboxrule
\vbox{\vskip\fboxsep\copy\@tempboxa\vskip\fboxsep}%
- \vrule\@width\fboxrule\relax}%
- \hrule\@height\fboxrule\relax}%
+ \kern-\wd\@tempboxa\kern-\fboxrule
+ \vrule\@width\fboxrule
+ \kern\wd\@tempboxa
+ \vrule\@width\fboxrule}%
+ \kern-\dimexpr\fboxsep+\ht\@tempboxa+\dp\@tempboxa
+ +\fboxsep+\fboxrule\relax
+ \hrule\@height\fboxrule
+ \kern\dimexpr\fboxsep+\ht\@tempboxa+\dp\@tempboxa+\fboxsep\relax
+ \hrule\@height\fboxrule}%
}}%
\endgroup
- \global\Sphinx@myfirstframedpassfalse
}
% For linebreaks inside Verbatim environment from package fancyvrb.
-\newbox\Sphinxcontinuationbox
-\newbox\Sphinxvisiblespacebox
+\newbox\sphinxcontinuationbox
+\newbox\sphinxvisiblespacebox
% These are user customizable e.g. from latex_elements's preamble key.
% Use of \textvisiblespace for compatibility with XeTeX/LuaTeX/fontspec.
-\newcommand*\Sphinxvisiblespace {\textcolor{red}{\textvisiblespace}}
-\newcommand*\Sphinxcontinuationsymbol {\textcolor{red}{\llap{\tiny$\m@th\hookrightarrow$}}}
-\newcommand*\Sphinxcontinuationindent {3ex }
-\newcommand*\Sphinxafterbreak {\kern\Sphinxcontinuationindent\copy\Sphinxcontinuationbox}
+\newcommand*\sphinxvisiblespace {\textcolor{red}{\textvisiblespace}}
+\newcommand*\sphinxcontinuationsymbol {\textcolor{red}{\llap{\tiny$\m@th\hookrightarrow$}}}
+\newcommand*\sphinxcontinuationindent {3ex }
+\newcommand*\sphinxafterbreak {\kern\sphinxcontinuationindent\copy\sphinxcontinuationbox}
% Take advantage of the already applied Pygments mark-up to insert
% potential linebreaks for TeX processing.
% {, <, #, %, $, ' and ": go to next line.
% _, }, ^, &, >, - and ~: stay at end of broken line.
% Use of \textquotesingle for straight quote.
-\newcommand*\Sphinxbreaksatspecials {%
- \def\PYGZus{\discretionary{\char`\_}{\Sphinxafterbreak}{\char`\_}}%
- \def\PYGZob{\discretionary{}{\Sphinxafterbreak\char`\{}{\char`\{}}%
- \def\PYGZcb{\discretionary{\char`\}}{\Sphinxafterbreak}{\char`\}}}%
- \def\PYGZca{\discretionary{\char`\^}{\Sphinxafterbreak}{\char`\^}}%
- \def\PYGZam{\discretionary{\char`\&}{\Sphinxafterbreak}{\char`\&}}%
- \def\PYGZlt{\discretionary{}{\Sphinxafterbreak\char`\<}{\char`\<}}%
- \def\PYGZgt{\discretionary{\char`\>}{\Sphinxafterbreak}{\char`\>}}%
- \def\PYGZsh{\discretionary{}{\Sphinxafterbreak\char`\#}{\char`\#}}%
- \def\PYGZpc{\discretionary{}{\Sphinxafterbreak\char`\%}{\char`\%}}%
- \def\PYGZdl{\discretionary{}{\Sphinxafterbreak\char`\$}{\char`\$}}%
- \def\PYGZhy{\discretionary{\char`\-}{\Sphinxafterbreak}{\char`\-}}%
- \def\PYGZsq{\discretionary{}{\Sphinxafterbreak\textquotesingle}{\textquotesingle}}%
- \def\PYGZdq{\discretionary{}{\Sphinxafterbreak\char`\"}{\char`\"}}%
- \def\PYGZti{\discretionary{\char`\~}{\Sphinxafterbreak}{\char`\~}}%
+\newcommand*\sphinxbreaksatspecials {%
+ \def\PYGZus{\discretionary{\char`\_}{\sphinxafterbreak}{\char`\_}}%
+ \def\PYGZob{\discretionary{}{\sphinxafterbreak\char`\{}{\char`\{}}%
+ \def\PYGZcb{\discretionary{\char`\}}{\sphinxafterbreak}{\char`\}}}%
+ \def\PYGZca{\discretionary{\char`\^}{\sphinxafterbreak}{\char`\^}}%
+ \def\PYGZam{\discretionary{\char`\&}{\sphinxafterbreak}{\char`\&}}%
+ \def\PYGZlt{\discretionary{}{\sphinxafterbreak\char`\<}{\char`\<}}%
+ \def\PYGZgt{\discretionary{\char`\>}{\sphinxafterbreak}{\char`\>}}%
+ \def\PYGZsh{\discretionary{}{\sphinxafterbreak\char`\#}{\char`\#}}%
+ \def\PYGZpc{\discretionary{}{\sphinxafterbreak\char`\%}{\char`\%}}%
+ \def\PYGZdl{\discretionary{}{\sphinxafterbreak\char`\$}{\char`\$}}%
+ \def\PYGZhy{\discretionary{\char`\-}{\sphinxafterbreak}{\char`\-}}%
+ \def\PYGZsq{\discretionary{}{\sphinxafterbreak\textquotesingle}{\textquotesingle}}%
+ \def\PYGZdq{\discretionary{}{\sphinxafterbreak\char`\"}{\char`\"}}%
+ \def\PYGZti{\discretionary{\char`\~}{\sphinxafterbreak}{\char`\~}}%
}
% Some characters . , ; ? ! / are not pygmentized.
% This macro makes them "active" and they will insert potential linebreaks
-\newcommand*\Sphinxbreaksatpunct {%
- \lccode`\~`\.\lowercase{\def~}{\discretionary{\char`\.}{\Sphinxafterbreak}{\char`\.}}%
- \lccode`\~`\,\lowercase{\def~}{\discretionary{\char`\,}{\Sphinxafterbreak}{\char`\,}}%
- \lccode`\~`\;\lowercase{\def~}{\discretionary{\char`\;}{\Sphinxafterbreak}{\char`\;}}%
- \lccode`\~`\:\lowercase{\def~}{\discretionary{\char`\:}{\Sphinxafterbreak}{\char`\:}}%
- \lccode`\~`\?\lowercase{\def~}{\discretionary{\char`\?}{\Sphinxafterbreak}{\char`\?}}%
- \lccode`\~`\!\lowercase{\def~}{\discretionary{\char`\!}{\Sphinxafterbreak}{\char`\!}}%
- \lccode`\~`\/\lowercase{\def~}{\discretionary{\char`\/}{\Sphinxafterbreak}{\char`\/}}%
+\newcommand*\sphinxbreaksatpunct {%
+ \lccode`\~`\.\lowercase{\def~}{\discretionary{\char`\.}{\sphinxafterbreak}{\char`\.}}%
+ \lccode`\~`\,\lowercase{\def~}{\discretionary{\char`\,}{\sphinxafterbreak}{\char`\,}}%
+ \lccode`\~`\;\lowercase{\def~}{\discretionary{\char`\;}{\sphinxafterbreak}{\char`\;}}%
+ \lccode`\~`\:\lowercase{\def~}{\discretionary{\char`\:}{\sphinxafterbreak}{\char`\:}}%
+ \lccode`\~`\?\lowercase{\def~}{\discretionary{\char`\?}{\sphinxafterbreak}{\char`\?}}%
+ \lccode`\~`\!\lowercase{\def~}{\discretionary{\char`\!}{\sphinxafterbreak}{\char`\!}}%
+ \lccode`\~`\/\lowercase{\def~}{\discretionary{\char`\/}{\sphinxafterbreak}{\char`\/}}%
\catcode`\.\active
\catcode`\,\active
\catcode`\;\active
@@ -272,42 +311,55 @@
\lccode`\~`\~
}
-\renewcommand{\Verbatim}[1][1]{%
+% needed to create wrapper environments of fancyvrb's Verbatim
+\newcommand*{\sphinxVerbatimEnvironment}{\gdef\FV@EnvironName{sphinxVerbatim}}
+% Sphinx <1.5 optional argument was in fact mandatory. It is now really
+% optional and handled by original Verbatim.
+\newenvironment{sphinxVerbatim}{%
% quit horizontal mode if we are still in a paragraph
\par
% list starts new par, but we don't want it to be set apart vertically
\parskip\z@skip
% first, let's check if there is a caption
- \ifx\SphinxVerbatimTitle\empty
+ \ifx\sphinxVerbatimTitle\empty
\addvspace\z@% counteract possible previous negative skip (French lists!)
\smallskip
% there was no caption. Check if nevertheless a label was set.
- \ifx\SphinxLiteralBlockLabel\empty\else
+ \ifx\sphinxLiteralBlockLabel\empty\else
% we require some space to be sure hyperlink target from \phantomsection
% will not be separated from upcoming verbatim by a page break
- \needspace{\literalblockwithoutcaptionneedspace}%
- \phantomsection\SphinxLiteralBlockLabel
+ \needspace{\sphinxliteralblockwithoutcaptionneedspace}%
+ \phantomsection\sphinxLiteralBlockLabel
\fi
+ \setbox\spx@VerbatimTitleBox\box\voidb@x
+ \else
+ % non-empty \sphinxVerbatimTitle has label inside it (in case there is one)
+ \setbox\spx@VerbatimTitleBox
+ \hbox{\begin{minipage}{\linewidth}%
+ \sphinxVerbatimTitle
+ \end{minipage}}%
\fi
- % non-empty \SphinxVerbatimTitle has label inside it (in case there is one)
+ \fboxsep\sphinxverbatimsep \fboxrule\sphinxverbatimborder
+ % setting borderwidth to zero is simplest for no-frame effect with same pagebreaks
+ \ifsphinxverbatimwithframe\else\fboxrule\z@\fi
% Customize framed.sty \MakeFramed to glue caption to literal block
- \global\Sphinx@myfirstframedpasstrue
- % via \Sphinx@fcolorbox, will use \Sphinx@VerbatimFBox which inserts title
- \def\FrameCommand {\Sphinx@colorbox\Sphinx@fcolorbox }%
+ % via \spx@fcolorbox, will use \spx@VerbatimFBox which inserts title
+ \def\FrameCommand {\spx@colorbox\spx@fcolorbox }%
\let\FirstFrameCommand\FrameCommand
% for mid pages and last page portion of (long) split frame:
- \def\MidFrameCommand{\Sphinx@colorbox\fcolorbox }%
+ \def\MidFrameCommand{\spx@colorbox\fcolorbox }%
\let\LastFrameCommand\MidFrameCommand
+ \ifsphinxverbatimwrapslines
% fancyvrb's Verbatim puts each input line in (unbreakable) horizontal boxes.
% This customization wraps each line from the input in a \vtop, thus
% allowing it to wrap and display on two or more lines in the latex output.
% - The codeline counter will be increased only once.
% - The wrapped material will not break across pages, it is impossible
% to achieve this without extensive rewrite of fancyvrb.
- % - The (not used in Sphinx) obeytabs option to Verbatim is
+ % - The (not used in sphinx) obeytabs option to Verbatim is
% broken by this change (showtabs and tabspace work).
- \sbox\Sphinxcontinuationbox {\Sphinxcontinuationsymbol}%
- \sbox\Sphinxvisiblespacebox {\FV@SetupFont\Sphinxvisiblespace}%
+ \sbox\sphinxcontinuationbox {\sphinxcontinuationsymbol}%
+ \sbox\sphinxvisiblespacebox {\FV@SetupFont\sphinxvisiblespace}%
\def\FancyVerbFormatLine ##1{\hsize\linewidth
\vtop{\raggedright\hyphenpenalty\z@\exhyphenpenalty\z@
\doublehyphendemerits\z@\finalhyphendemerits\z@
@@ -318,74 +370,100 @@
% Stretch/shrink are however usually zero for typewriter font.
\def\FV@Space {%
\nobreak\hskip\z@ plus\fontdimen3\font minus\fontdimen4\font
- \discretionary{\copy\Sphinxvisiblespacebox}{\Sphinxafterbreak}
+ \discretionary{\copy\sphinxvisiblespacebox}{\sphinxafterbreak}
{\kern\fontdimen2\font}%
}%
% Allow breaks at special characters using \PYG... macros.
- \Sphinxbreaksatspecials
+ \sphinxbreaksatspecials
+ % Breaks at punctuation characters . , ; ? ! and / (needs catcode activation)
+ \def\FancyVerbCodes{\sphinxbreaksatpunct}%
+ \fi % end of conditional code for wrapping long code lines
+ % go around fancyvrb's check of \@currenvir
+ \let\VerbatimEnvironment\sphinxVerbatimEnvironment
+ % go around fancyvrb's check of current list depth
+ \def\@toodeep {\advance\@listdepth\@ne}%
% The list environment is needed to control perfectly the vertical space.
% Note: \OuterFrameSep used by framed.sty is later set to \topsep hence 0pt.
% - if caption: vertical space above caption = (\abovecaptionskip + D) with
% D = \baselineskip-\FrameHeightAdjust, and then \smallskip above frame.
% - if no caption: (\smallskip + D) above frame. By default D=6pt.
- \list{}{%
- \setlength\parskip{0pt}%
- \setlength\itemsep{0ex}%
- \setlength\topsep{0ex}%
- \setlength\parsep{0pt}% let's not forget this one!
- \setlength\partopsep{0pt}%
- \setlength\leftmargin{0pt}%
- }%
- \item
- % use a minipage if we are already inside a framed environment
- \relax\ifSphinx@inframed\noindent\begin{\minipage}{\linewidth}\fi
+ % Use trivlist rather than list to avoid possible "too deeply nested" error.
+ \itemsep \z@skip
+ \topsep \z@skip
+ \partopsep \z@skip% trivlist will set \parsep to \parskip = zero (see above)
+ % \leftmargin will be set to zero by trivlist
+ \rightmargin\z@
+ \parindent \z@% becomes \itemindent. Default zero, but perhaps overwritten.
+ \trivlist\item\relax
+ \ifsphinxverbatimwithminipage\spx@inframedtrue\fi
+ % use a minipage if we are already inside a framed environment
+ \ifspx@inframed\noindent\begin{minipage}{\linewidth}\fi
\MakeFramed {% adapted over from framed.sty's snugshade environment
- \advance\hsize-\width\@totalleftmargin\z@\linewidth\hsize
- \@setminipage }%
- \small
+ \advance\hsize-\width\@totalleftmargin\z@\linewidth\hsize\@setminipage
+ }%
% For grid placement from \strut's in \FancyVerbFormatLine
\lineskip\z@skip
- % Breaks at punctuation characters . , ; ? ! and / need catcode=\active
- \OriginalVerbatim[#1,codes*=\Sphinxbreaksatpunct]%
+ % will fetch its optional arguments if any
+ \OriginalVerbatim
}
-\renewcommand{\endVerbatim}{%
+{%
\endOriginalVerbatim
- \par\unskip\@minipagefalse\endMakeFramed
- \ifSphinx@inframed\end{minipage}\fi
- \endlist
- % LaTeX environments always revert local changes on exit, here e.g. \parskip
+ \par\unskip\@minipagefalse\endMakeFramed % from framed.sty snugshade
+ \ifspx@inframed\end{minipage}\fi
+ \endtrivlist
}
+\newenvironment {sphinxVerbatimNoFrame}
+ {\sphinxverbatimwithframefalse
+ % needed for fancyvrb as literal code will end in \end{sphinxVerbatimNoFrame}
+ \def\sphinxVerbatimEnvironment{\gdef\FV@EnvironName{sphinxVerbatimNoFrame}}%
+ \begin{sphinxVerbatim}}
+ {\end{sphinxVerbatim}}
+\newenvironment {sphinxVerbatimintable}
+ {% don't use a frame if in a table cell
+ \sphinxverbatimwithframefalse
+ \sphinxverbatimwithminipagetrue
+ % counteract longtable redefinition of caption
+ \let\caption\sphinxfigcaption
+ % reduce above caption space if in a table cell
+ \abovecaptionskip\smallskipamount
+ \def\sphinxVerbatimEnvironment{\gdef\FV@EnvironName{sphinxVerbatimintable}}%
+ \begin{sphinxVerbatim}}
+ {\end{sphinxVerbatim}}
% define macro to frame contents and add shadow on right and bottom
-\def\Sphinx@shadowsep {5\p@} % \p@ means "pt "
-\def\Sphinx@shadowsize {4\p@}
-\def\Sphinx@shadowrule {\fboxrule}
-\long\def\Sphinx@ShadowFBox#1{%
+% use public names for customizable lengths
+\newlength\sphinxshadowsep \setlength\sphinxshadowsep {5pt}
+\newlength\sphinxshadowsize \setlength\sphinxshadowsize {4pt}
+\newlength\sphinxshadowrule
+% this uses \fboxrule value at loading time of sphinx.sty (0.4pt normally)
+\setlength\sphinxshadowrule {\fboxrule}
+
+\long\def\spx@ShadowFBox#1{%
\leavevmode\begingroup
% first we frame the box #1
\setbox\@tempboxa
- \hbox{\vrule\@width\Sphinx@shadowrule
- \vbox{\hrule\@height\Sphinx@shadowrule
- \kern\Sphinx@shadowsep
- \hbox{\kern\Sphinx@shadowsep #1\kern\Sphinx@shadowsep}%
- \kern\Sphinx@shadowsep
- \hrule\@height\Sphinx@shadowrule}%
- \vrule\@width\Sphinx@shadowrule}%
+ \hbox{\vrule\@width\sphinxshadowrule
+ \vbox{\hrule\@height\sphinxshadowrule
+ \kern\sphinxshadowsep
+ \hbox{\kern\sphinxshadowsep #1\kern\sphinxshadowsep}%
+ \kern\sphinxshadowsep
+ \hrule\@height\sphinxshadowrule}%
+ \vrule\@width\sphinxshadowrule}%
% Now we add the shadow, like \shadowbox from fancybox.sty would do
- \dimen@\dimexpr.5\Sphinx@shadowrule+\Sphinx@shadowsize\relax
+ \dimen@\dimexpr.5\sphinxshadowrule+\sphinxshadowsize\relax
\hbox{\vbox{\offinterlineskip
- \hbox{\copy\@tempboxa\kern-.5\Sphinx@shadowrule
+ \hbox{\copy\@tempboxa\kern-.5\sphinxshadowrule
% add shadow on right side
- \lower\Sphinx@shadowsize
+ \lower\sphinxshadowsize
\hbox{\vrule\@height\ht\@tempboxa \@width\dimen@}%
}%
\kern-\dimen@ % shift back vertically to bottom of frame
% and add shadow at bottom
- \moveright\Sphinx@shadowsize
+ \moveright\sphinxshadowsize
\vbox{\hrule\@width\wd\@tempboxa \@height\dimen@}%
}%
% move left by the size of right shadow so shadow adds no width
- \kern-\Sphinx@shadowsize
+ \kern-\sphinxshadowsize
}%
\endgroup
}
@@ -394,10 +472,10 @@
% works well inside Lists and Quote-like environments
% produced by ``topic'' directive (or local contents)
% could nest if LaTeX writer authorized it
-\newenvironment{SphinxShadowBox}
- {\def\FrameCommand {\Sphinx@ShadowFBox }%
+\newenvironment{sphinxShadowBox}
+ {\def\FrameCommand {\spx@ShadowFBox }%
% configure framed.sty not to add extra vertical spacing
- \OuterFrameSep \z@skip
+ \spx@ifundefined{OuterFrameSep}{}{\OuterFrameSep\z@skip}%
% the \trivlist will add the vertical spacing on top and bottom which is
% typical of center environment as used in Sphinx <= 1.4.1
% the \noindent has the effet of an extra blank line on top, to
@@ -406,8 +484,8 @@
\def\FrameHeightAdjust {\baselineskip}%
\trivlist\item\noindent
% use a minipage if we are already inside a framed environment
- \ifSphinx@inframed\begin{minipage}{\linewidth}\fi
- \MakeFramed {\Sphinx@inframedtrue
+ \ifspx@inframed\begin{minipage}{\linewidth}\fi
+ \MakeFramed {\spx@inframedtrue
% framed.sty puts into "\width" the added width (=2shadowsep+2shadowrule)
% adjust \hsize to what the contents must use
\advance\hsize-\width
@@ -433,7 +511,7 @@
\fi
\@minipagefalse
\endMakeFramed
- \ifSphinx@inframed\end{minipage}\fi
+ \ifspx@inframed\end{minipage}\fi
\endtrivlist
}
@@ -474,25 +552,25 @@
}{\end{list}}
% \optional is used for ``[, arg]``, i.e. desc_optional nodes.
-\newcommand{\optional}[1]{%
+\newcommand{\sphinxoptional}[1]{%
{\textnormal{\Large[}}{#1}\hspace{0.5mm}{\textnormal{\Large]}}}
\newlength{\py@argswidth}
\newcommand{\py@sigparams}[2]{%
- \parbox[t]{\py@argswidth}{#1\code{)}#2}}
+ \parbox[t]{\py@argswidth}{#1\sphinxcode{)}#2}}
\newcommand{\pysigline}[1]{\item[#1]\nopagebreak}
\newcommand{\pysiglinewithargsret}[3]{%
- \settowidth{\py@argswidth}{#1\code{(}}%
+ \settowidth{\py@argswidth}{#1\sphinxcode{(}}%
\addtolength{\py@argswidth}{-2\py@argswidth}%
\addtolength{\py@argswidth}{\linewidth}%
- \item[#1\code{(}\py@sigparams{#2}{#3}]}
+ \item[#1\sphinxcode{(}\py@sigparams{#2}{#3}]}
% Production lists
%
\newenvironment{productionlist}{
-% \def\optional##1{{\Large[}##1{\Large]}}
- \def\production##1##2{\\\code{##1}&::=&\code{##2}}
- \def\productioncont##1{\\& &\code{##1}}
+% \def\sphinxoptional##1{{\Large[}##1{\Large]}}
+ \def\production##1##2{\\\sphinxcode{##1}&::=&\sphinxcode{##2}}
+ \def\productioncont##1{\\& &\sphinxcode{##1}}
\parindent=2em
\indent
\setlength{\LTpre}{0pt}
@@ -503,29 +581,79 @@
}
% Notices / Admonitions
-%
+% Some are quite plain
+\newenvironment{sphinxlightbox}{%
+ \par\allowbreak
+ \noindent{\color{spx@notice@bordercolor}%
+ \rule{\linewidth}{\spx@notice@border}}\par\nobreak
+ {\parskip\z@skip\noindent}%
+ }
+ {%
+ \par
+ % counteract previous possible negative skip (French lists!):
+ % (we can't cancel that any earlier \vskip introduced a potential pagebreak)
+ \ifdim\lastskip<\z@\vskip-\lastskip\fi
+ \nobreak\vbox{\noindent\kern\@totalleftmargin
+ {\color{spx@notice@bordercolor}%
+ \rule[\dimexpr.4\baselineskip-\spx@notice@border\relax]
+ {\linewidth}{\spx@notice@border}}\hss}\allowbreak
+ }% end of sphinxlightbox environment definition
+% may be renewenvironment'd by user for complete customization
+\newenvironment{sphinxnote}[1]
+ {\begin{sphinxlightbox}\sphinxstrong{#1} }{\end{sphinxlightbox}}
+\newenvironment{sphinxhint}[1]
+ {\begin{sphinxlightbox}\sphinxstrong{#1} }{\end{sphinxlightbox}}
+\newenvironment{sphinximportant}[1]
+ {\begin{sphinxlightbox}\sphinxstrong{#1} }{\end{sphinxlightbox}}
+\newenvironment{sphinxtip}[1]
+ {\begin{sphinxlightbox}\sphinxstrong{#1} }{\end{sphinxlightbox}}
+% or user may just customize the bordercolor and the border width
+% re-use \definecolor if change needed, and \renewcommand for rule width
+\definecolor{sphinxnotebordercolor}{rgb}{0,0,0}
+\definecolor{sphinxhintbordercolor}{rgb}{0,0,0}
+\definecolor{sphinximportantbordercolor}{rgb}{0,0,0}
+\definecolor{sphinxtipbordercolor}{rgb}{0,0,0}
+\newcommand{\sphinxnoteborder}{0.5pt}
+\newcommand{\sphinxhintborder}{0.5pt}
+\newcommand{\sphinximportantborder}{0.5pt}
+\newcommand{\sphinxtipborder}{0.5pt}
+% these are needed for common handling by notice environment of lightbox
+% and heavybox but they are currently not used by lightbox environment
+\definecolor{sphinxnotebgcolor}{rgb}{1,1,1}
+\definecolor{sphinxhintbgcolor}{rgb}{1,1,1}
+\definecolor{sphinximportantbgcolor}{rgb}{1,1,1}
+\definecolor{sphinxtipbgcolor}{rgb}{1,1,1}
+
+% Others get more distinction
+\newdimen\spx@notice@border
% Code adapted from framed.sty's "snugshade" environment.
% Nesting works (inner frames do not allow page breaks).
-\newcommand{\py@heavybox}{\par
- \setlength{\FrameRule}{\p@}% 1pt
+\newenvironment{sphinxheavybox}{\par
+ \setlength{\FrameRule}{\spx@notice@border}%
\setlength{\FrameSep}{\dimexpr.6\baselineskip-\FrameRule\relax}
% configure framed.sty's parameters to obtain same vertical spacing
% as for "light" boxes. We need for this to manually insert parskip glue and
% revert a skip done by framed before the frame.
- \setlength{\OuterFrameSep}{0pt}
+ \spx@ifundefined{OuterFrameSep}{}{\OuterFrameSep\z@skip}%
\vspace{\FrameHeightAdjust}
% copied/adapted from framed.sty's snugshade
\def\FrameCommand##1{\hskip\@totalleftmargin
- \fboxsep\FrameSep \fboxrule\FrameRule\fbox{##1}%
+ \fboxsep\FrameSep \fboxrule\FrameRule
+ \fcolorbox{spx@notice@bordercolor}{spx@notice@bgcolor}{##1}%
\hskip-\linewidth \hskip-\@totalleftmargin \hskip\columnwidth}%
% use a minipage if we are already inside a framed environment
- \ifSphinx@inframed
+ \ifspx@inframed
\noindent\begin{minipage}{\linewidth}
\else
- \vspace{\parskip}
+ % handle case where notice is first thing in a list item (or is quoted)
+ \if@inlabel
+ \noindent\par\vspace{-\baselineskip}
+ \else
+ \vspace{\parskip}
+ \fi
\fi
- \MakeFramed {\Sphinx@inframedtrue
+ \MakeFramed {\spx@inframedtrue
\advance\hsize-\width \@totalleftmargin\z@ \linewidth\hsize
% minipage initialization copied from LaTeX source code.
\@pboxswfalse
@@ -536,58 +664,66 @@
\@minipagerestore
\@setminipage }%
}
-\newcommand{\py@endheavybox}{%
+ {%
\par\unskip
% handles footnotes
\ifvoid\@mpfootins\else
\vskip\skip\@mpfootins\normalcolor\footnoterule\unvbox\@mpfootins
\fi
- \@minipagefalse\endMakeFramed
- \ifSphinx@inframed\end{minipage}\fi
+ \@minipagefalse
+ \endMakeFramed
+ \ifspx@inframed\end{minipage}\fi
% arrange for similar spacing below frame as for "light" boxes.
\vskip .4\baselineskip
- }
+ }% end of sphinxheavybox environment definition
+% may be renewenvironment'd by user for complete customization
+\newenvironment{sphinxwarning}[1]
+ {\begin{sphinxheavybox}\sphinxstrong{#1} }{\end{sphinxheavybox}}
+\newenvironment{sphinxcaution}[1]
+ {\begin{sphinxheavybox}\sphinxstrong{#1} }{\end{sphinxheavybox}}
+\newenvironment{sphinxattention}[1]
+ {\begin{sphinxheavybox}\sphinxstrong{#1} }{\end{sphinxheavybox}}
+\newenvironment{sphinxdanger}[1]
+ {\begin{sphinxheavybox}\sphinxstrong{#1} }{\end{sphinxheavybox}}
+\newenvironment{sphinxerror}[1]
+ {\begin{sphinxheavybox}\sphinxstrong{#1} }{\end{sphinxheavybox}}
+% or just re-do \definecolor for colours, \renewcommand for frame width
+\definecolor{sphinxwarningbordercolor}{rgb}{0,0,0}
+\definecolor{sphinxcautionbordercolor}{rgb}{0,0,0}
+\definecolor{sphinxattentionbordercolor}{rgb}{0,0,0}
+\definecolor{sphinxdangerbordercolor}{rgb}{0,0,0}
+\definecolor{sphinxerrorbordercolor}{rgb}{0,0,0}
+\definecolor{sphinxwarningbgcolor}{rgb}{1,1,1}
+\definecolor{sphinxcautionbgcolor}{rgb}{1,1,1}
+\definecolor{sphinxattentionbgcolor}{rgb}{1,1,1}
+\definecolor{sphinxdangerbgcolor}{rgb}{1,1,1}
+\definecolor{sphinxerrorbgcolor}{rgb}{1,1,1}
+\newcommand{\sphinxwarningborder}{1pt}
+\newcommand{\sphinxcautionborder}{1pt}
+\newcommand{\sphinxattentionborder}{1pt}
+\newcommand{\sphinxdangerborder}{1pt}
+\newcommand{\sphinxerrorborder}{1pt}
-\newcommand{\py@lightbox}{%
- \par\allowbreak
- \noindent\rule{\linewidth}{0.5pt}\par\nobreak
- {\parskip\z@skip\noindent}%
- }
-\newcommand{\py@endlightbox}{%
- \par
- % counteract previous possible negative skip (French lists!):
- % (we can't cancel that any earlier \vskip introduced a potential pagebreak)
- \ifdim\lastskip<\z@\vskip-\lastskip\fi
- \nobreak\vbox{\noindent\rule[.4\baselineskip]{\linewidth}{0.5pt}}\allowbreak
- }
+% the \colorlet of xcolor (if at all loaded) is overkill for our use case
+\newcommand{\sphinxcolorlet}[2]
+ {\expandafter\let\csname\@backslashchar color@#1\expandafter\endcsname
+ \csname\@backslashchar color@#2\endcsname }
-% Some are quite plain:
-\newcommand{\py@noticestart@note}{\py@lightbox}
-\newcommand{\py@noticeend@note}{\py@endlightbox}
-\newcommand{\py@noticestart@hint}{\py@lightbox}
-\newcommand{\py@noticeend@hint}{\py@endlightbox}
-\newcommand{\py@noticestart@important}{\py@lightbox}
-\newcommand{\py@noticeend@important}{\py@endlightbox}
-\newcommand{\py@noticestart@tip}{\py@lightbox}
-\newcommand{\py@noticeend@tip}{\py@endlightbox}
-
-% Others gets more visible distinction:
-\newcommand{\py@noticestart@warning}{\py@heavybox}
-\newcommand{\py@noticeend@warning}{\py@endheavybox}
-\newcommand{\py@noticestart@caution}{\py@heavybox}
-\newcommand{\py@noticeend@caution}{\py@endheavybox}
-\newcommand{\py@noticestart@attention}{\py@heavybox}
-\newcommand{\py@noticeend@attention}{\py@endheavybox}
-\newcommand{\py@noticestart@danger}{\py@heavybox}
-\newcommand{\py@noticeend@danger}{\py@endheavybox}
-\newcommand{\py@noticestart@error}{\py@heavybox}
-\newcommand{\py@noticeend@error}{\py@endheavybox}
-
-\newenvironment{notice}[2]{
- \def\py@noticetype{#1}
- \csname py@noticestart@#1\endcsname
- \strong{#2}
-}{\csname py@noticeend@\py@noticetype\endcsname}
+% the main dispatch for all types of notices
+\newenvironment{sphinxadmonition}{\begin{notice}}{\end{notice}}
+% use of ``notice'' is for backwards compatibility and will be removed in
+% future release; sphinxadmonition environment will be defined directly.
+\newenvironment{notice}[2]{% #1=type, #2=heading
+ % can't use #1 directly in definition of end part
+ \def\spx@noticetype {#1}%
+ % set parameters of heavybox/lightbox
+ \sphinxcolorlet{spx@notice@bordercolor}{sphinx#1bordercolor}%
+ \sphinxcolorlet{spx@notice@bgcolor}{sphinx#1bgcolor}%
+ \setlength\spx@notice@border {\dimexpr\csname sphinx#1border\endcsname\relax}%
+ % start specific environment, passing the heading as argument
+ \begin{sphinx#1}{#2}}
+ % in end part, need to go around a LaTeX's "feature"
+ {\edef\spx@temp{\noexpand\end{sphinx\spx@noticetype}}\spx@temp}
% Allow the release number to be specified independently of the
% \date{}. This allows the date to reflect the document's date and
@@ -616,7 +752,7 @@
% This sets up the fancy chapter headings that make the documents look
% at least a little better than the usual LaTeX output.
%
-\@ifundefined{ChTitleVar}{}{
+\spx@ifundefined{ChTitleVar}{}{
\ChNameVar{\raggedleft\normalsize\py@HeaderFamily}
\ChNumVar{\raggedleft \bfseries\Large\py@HeaderFamily}
\ChTitleVar{\raggedleft \textrm{\Huge\py@HeaderFamily}}
@@ -656,7 +792,7 @@
% The following is stuff copied from docutils' latex writer.
%
-\newcommand{\optionlistlabel}[1]{\bf #1 \hfill}
+\newcommand{\optionlistlabel}[1]{\normalfont\bfseries #1 \hfill}% \bf deprecated
\newenvironment{optionlist}[1]
{\begin{list}{}
{\setlength{\labelwidth}{#1}
@@ -678,26 +814,29 @@
\raggedright}
{\end{list}}
-% Redefine includgraphics for avoiding images larger than the screen size
-% If the size is not specified.
+% Re-define \includegraphics to resize images larger than the line width
+% if the size is not specified.
+% Warning: future version of Sphinx will not modify original \includegraphics,
+% Below custom code will be direct definition of \sphinxincludegraphics, with
+% \py@Oldincludegraphics replaced by direct use of original \includegraphics.
\let\py@Oldincludegraphics\includegraphics
-
-\newbox\image@box%
-\newdimen\image@width%
-\renewcommand\includegraphics[2][\@empty]{%
- \ifx#1\@empty%
- \setbox\image@box=\hbox{\py@Oldincludegraphics{#2}}%
- \image@width\wd\image@box%
- \ifdim \image@width>\linewidth%
- \setbox\image@box=\hbox{\py@Oldincludegraphics[width=\linewidth]{#2}}%
- \box\image@box%
- \else%
- \py@Oldincludegraphics{#2}%
- \fi%
- \else%
+\newbox\spx@image@box
+\renewcommand*{\includegraphics}[2][\@empty]{%
+ \ifx\@empty #1% attention, #1 could be bb.., bad if first after \ifx
+ \setbox\spx@image@box=\hbox{\py@Oldincludegraphics{#2}}%
+ \ifdim \wd\spx@image@box>\linewidth
+ \py@Oldincludegraphics[width=\linewidth]{#2}%
+ \else
+ \leavevmode\box\spx@image@box
+ \fi
+ \else
\py@Oldincludegraphics[#1]{#2}%
- \fi%
+ \fi
}
+% Writer will put \sphinxincludegraphics in LaTeX source, and with this,
+% documents which used their own modified \includegraphics will compile
+% as before. But see warning above.
+\newcommand*{\sphinxincludegraphics}{\includegraphics}
% to make pdf with correct encoded bookmarks in Japanese
% this should precede the hyperref package
@@ -745,12 +884,12 @@
\fi%
}
-\providecommand*{\DUprovidelength}[2]{
- \ifthenelse{\isundefined{#1}}{\newlength{#1}\setlength{#1}{#2}}{}
+\providecommand*{\DUprovidelength}[2]{%
+ \ifdefined#1\else\newlength{#1}\setlength{#1}{#2}\fi
}
\DUprovidelength{\DUlineblockindent}{2.5em}
-\ifthenelse{\isundefined{\DUlineblock}}{
+\ifdefined\DUlineblock\else
\newenvironment{DUlineblock}[1]{%
\list{}{\setlength{\partopsep}{\parskip}
\addtolength{\partopsep}{\baselineskip}
@@ -761,8 +900,7 @@
\raggedright
}
{\endlist}
-}{}
-
+\fi
% From footmisc.sty: allows footnotes in titles
\let\FN@sf@@footnote\footnote
@@ -813,18 +951,79 @@
}
\fi
-% Define literal-block environment
-\RequirePackage{newfloat}
-\DeclareFloatingEnvironment{literal-block}
-\ifx\thechapter\undefined
- \SetupFloatingEnvironment{literal-block}{within=section,placement=h}
-\else
- \SetupFloatingEnvironment{literal-block}{within=chapter,placement=h}
-\fi
-\SetupFloatingEnvironment{literal-block}{name=List}
+% for captions of literal blocks
+\newcounter{literalblock}
+\spx@ifundefined{c@chapter}
+ {\@addtoreset{literalblock}{section}
+ \def\theliteralblock {\ifnum\c@section>\z@ \thesection.\fi\arabic{literalblock}}
+ \def\theHliteralblock {\theHsection.\arabic{literalblock}}}
+ {\@addtoreset{literalblock}{chapter}
+ \def\theliteralblock {\ifnum\c@chapter>\z@ \thechapter.\fi\arabic{literalblock}}
+ \def\theHliteralblock {\theHchapter.\arabic{literalblock}}}
+% at start of caption title
+\newcommand*{\fnum@literalblock}{\literalblockname\nobreakspace\theliteralblock}
+% this will be overwritten in document preamble by Babel translation
+\newcommand*{\literalblockname}{Listing }
+% file extension needed for \caption's good functioning, the file is created
+% only if a \listof{literalblock}{foo} command is encountered, which is
+% analogous to \listoffigures, but for the code listings (foo = chosen title.)
+\newcommand*{\ext@literalblock}{lol}
+
% control caption around literal-block
\RequirePackage{capt-of}
\RequirePackage{needspace}
% if the left page space is less than \literalblockneedspace, insert page-break
-\newcommand{\literalblockneedspace}{5\baselineskip}
-\newcommand{\literalblockwithoutcaptionneedspace}{1.5\baselineskip}
+\newcommand{\sphinxliteralblockneedspace}{5\baselineskip}
+\newcommand{\sphinxliteralblockwithoutcaptionneedspace}{1.5\baselineskip}
+
+% figure in table
+\newenvironment{sphinxfigure-in-table}[1][\linewidth]{%
+ \def\@captype{figure}%
+ \begin{minipage}{#1}%
+}{\end{minipage}}
+% store original \caption macro for use with figures in longtable and tabulary
+\AtBeginDocument{\let\spx@originalcaption\caption}
+\newcommand*\sphinxfigcaption
+ {\ifx\equation$%$% this is trick to identify tabulary first pass
+ \firstchoice@false\else\firstchoice@true\fi
+ \spx@originalcaption }
+
+% by default, also define macros with the no-prefix names
+\ifsphinxKeepOldNames
+ \typeout{** (sphinx) defining (legacy) text style macros without \string\sphinx\space prefix}
+ \typeout{** if clashes with packages, set latex_keep_old_macro_names=False in conf.py}
+ \@for\@tempa:=strong,bfcode,email,tablecontinued,titleref,%
+ menuselection,accelerator,crossref,termref,optional\do
+{% first, check if command with no prefix already exists
+ \expandafter\newcommand\csname\@tempa\endcsname{}%
+ % if no error give it the meaning defined so far with \sphinx prefix
+ \expandafter\let\csname\@tempa\expandafter\endcsname
+ \csname sphinx\@tempa\endcsname
+ % redefine the \sphinx prefixed macro to expand to non-prefixed one
+ \expandafter\def\csname sphinx\@tempa\expandafter\endcsname
+ \expandafter{\csname\@tempa\endcsname}%
+}
+ % robustified case needs special treatment
+ \newcommand\code{}\let\code\relax
+ \DeclareRobustCommand{\code}[1]{{\@noligs\scantokens{\texttt{#1}\relax}}}
+ \def\sphinxcode{\code}%
+\fi
+
+% additional customizable styling
+\newcommand*{\sphinxstyleindexentry}{\texttt}
+\newcommand{\sphinxstyleindexextra}[1]{ \emph{(#1)}}
+\newcommand*{\sphinxstyleindexpageref}{, \pageref}
+\newcommand{\sphinxstyletopictitle}[1]{\textbf{#1}\par\medskip}
+\let\sphinxstylesidebartitle\sphinxstyletopictitle
+\newcommand*{\sphinxstyleothertitle}{\textbf}
+\newcommand{\sphinxstylesidebarsubtitle}[1]{~\\\textbf{#1} \smallskip}
+\newcommand*{\sphinxstylethead}{\textsf}
+\newcommand*{\sphinxstyleemphasis}{\emph}
+\newcommand{\sphinxstyleliteralemphasis}[1]{\emph{\texttt{#1}}}
+\newcommand*{\sphinxstylestrong}{\textbf}
+\newcommand{\sphinxstyleliteralstrong}[1]{\textbf{\texttt{#1}}}
+\newcommand*{\sphinxstyleabbreviation}{\textsc}
+\newcommand*{\sphinxstyleliteralintitle}{\texttt}
+
+% stylesheet for highlighting with pygments
+\RequirePackage{sphinxhighlight}
diff --git a/sphinx/texinputs/sphinxhowto.cls b/sphinx/texinputs/sphinxhowto.cls
index 8607ef8c4..8d5c59232 100644
--- a/sphinx/texinputs/sphinxhowto.cls
+++ b/sphinx/texinputs/sphinxhowto.cls
@@ -35,30 +35,31 @@
% Change the title page to look a bit better, and fit in with the fncychap
% ``Bjarne'' style a bit better.
%
-\renewcommand{\maketitle}{
- \rule{\textwidth}{1pt}
+\renewcommand{\maketitle}{%
+ \noindent\rule{\textwidth}{1pt}\ifsphinxpdfoutput\newline\null\fi\par
\ifsphinxpdfoutput
\begingroup
% These \defs are required to deal with multi-line authors; it
% changes \\ to ', ' (comma-space), making it pass muster for
% generating document info in the PDF file.
- \def\\{, }
- \def\and{and }
+ \def\\{, }%
+ \def\and{and }%
\pdfinfo{
/Author (\@author)
/Title (\@title)
- }
+ }%
\endgroup
\fi
\begin{flushright}
- \sphinxlogo%
- {\rm\Huge\py@HeaderFamily \@title} \par
- {\em\large\py@HeaderFamily \py@release\releaseinfo} \par
+ \sphinxlogo
+ \py@HeaderFamily
+ {\Huge \@title }\par
+ {\itshape\large \py@release \releaseinfo}\par
\vspace{25pt}
- {\Large\py@HeaderFamily
+ {\Large
\begin{tabular}[t]{c}
\@author
- \end{tabular}} \par
+ \end{tabular}}\par
\vspace{25pt}
\@date \par
\py@authoraddress \par
diff --git a/sphinx/texinputs/sphinxmanual.cls b/sphinx/texinputs/sphinxmanual.cls
index b576b673e..f20449449 100644
--- a/sphinx/texinputs/sphinxmanual.cls
+++ b/sphinx/texinputs/sphinxmanual.cls
@@ -43,26 +43,27 @@
\begin{titlepage}%
\let\footnotesize\small
\let\footnoterule\relax
- \rule{\textwidth}{1pt}%
+ \noindent\rule{\textwidth}{1pt}\ifsphinxpdfoutput\newline\null\fi\par
\ifsphinxpdfoutput
\begingroup
% These \defs are required to deal with multi-line authors; it
% changes \\ to ', ' (comma-space), making it pass muster for
% generating document info in the PDF file.
- \def\\{, }
- \def\and{and }
+ \def\\{, }%
+ \def\and{and }%
\pdfinfo{
/Author (\@author)
/Title (\@title)
- }
+ }%
\endgroup
\fi
\begin{flushright}%
- \sphinxlogo%
- {\rm\Huge\py@HeaderFamily \@title \par}%
- {\em\LARGE\py@HeaderFamily \py@release\releaseinfo \par}
+ \sphinxlogo
+ \py@HeaderFamily
+ {\Huge \@title \par}
+ {\itshape\LARGE \py@release\releaseinfo \par}
\vfill
- {\LARGE\py@HeaderFamily
+ {\LARGE
\begin{tabular}[t]{c}
\@author
\end{tabular}
@@ -76,52 +77,27 @@
\end{flushright}%\par
\@thanks
\end{titlepage}%
- \cleardoublepage%
\setcounter{footnote}{0}%
\let\thanks\relax\let\maketitle\relax
%\gdef\@thanks{}\gdef\@author{}\gdef\@title{}
}
-
-% Catch the end of the {abstract} environment, but here make sure the abstract
-% is followed by a blank page if the 'openright' option is used.
-%
-\let\py@OldEndAbstract=\endabstract
-\renewcommand{\endabstract}{
- \if@openright
- \ifodd\value{page}
- \typeout{Adding blank page after the abstract.}
- \vfil\pagebreak
- \fi
- \fi
- \py@OldEndAbstract
-}
-
-% This wraps the \tableofcontents macro with all the magic to get the spacing
-% right and have the right number of pages if the 'openright' option has been
-% used. This eliminates a fair amount of crud in the individual document files.
-%
\let\py@OldTableofcontents=\tableofcontents
\renewcommand{\tableofcontents}{%
+ % before resetting page counter, let's do the right thing.
+ \if@openright\cleardoublepage\else\clearpage\fi
\pagenumbering{roman}%
- \setcounter{page}{1}%
- \pagebreak%
\pagestyle{plain}%
- {%
- \parskip = 0mm%
- \py@OldTableofcontents%
- \if@openright%
- \ifodd\value{page}%
- \typeout{Adding blank page after the table of contents.}%
- \pagebreak\hspace{0pt}%
- \fi%
- \fi%
- \cleardoublepage%
- }%
+ \begingroup
+ \parskip \z@skip
+ \py@OldTableofcontents
+ \endgroup
+ % before resetting page counter, let's do the right thing.
+ \if@openright\cleardoublepage\else\clearpage\fi
\pagenumbering{arabic}%
- \@ifundefined{fancyhf}{}{\pagestyle{normal}}%
+ \ifdefined\fancyhf\pagestyle{normal}\fi
}
-\pagenumbering{alph}
+\pagenumbering{alph}% avoid hyperref "duplicate destination" warnings
% 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.
@@ -134,7 +110,7 @@
% For a report document class this environment is a chapter.
\let\py@OldThebibliography=\thebibliography
\renewcommand{\thebibliography}[1]{
- \cleardoublepage
+ \if@openright\cleardoublepage\else\clearpage\fi
\phantomsection
\py@OldThebibliography{1}
\addcontentsline{toc}{chapter}{\bibname}
@@ -146,7 +122,7 @@
\@ifclassloaded{memoir}{}{
\let\py@OldTheindex=\theindex
\renewcommand{\theindex}{
- \cleardoublepage
+ \if@openright\cleardoublepage\else\clearpage\fi
\phantomsection
\py@OldTheindex
\addcontentsline{toc}{chapter}{\indexname}
diff --git a/sphinx/texinputs/tabulary.sty b/sphinx/texinputs/tabulary.sty
index 11fdf7428..03e07ec2a 100644
--- a/sphinx/texinputs/tabulary.sty
+++ b/sphinx/texinputs/tabulary.sty
@@ -14,7 +14,7 @@
%%
\NeedsTeXFormat{LaTeX2e}
\ProvidesPackage{tabulary}
- [2008/12/01 v0.9 tabulary package (DPC)]
+ [2014/06/11 v0.10 tabulary package (DPC) + footnote patch (sphinx)]
\RequirePackage{array}
\catcode`\Z=14
\DeclareOption{debugshow}{\catcode`\Z=9\relax}
@@ -354,6 +354,7 @@ Z \message{^^JTotal:\the\@tempdima^^J}%
\expandafter\let\expandafter\color\expandafter\relax
\expandafter\let\expandafter\CT@column@color\expandafter\relax
\expandafter\let\expandafter\CT@row@color\expandafter\relax
+ \expandafter\let\expandafter\CT@cell@color\expandafter\relax
\@mkpream{#1}}
\let\TY@@mkpream\@mkpream
\def\TY@classz{%
@@ -396,6 +397,7 @@ Z \message{^^JTotal:\the\@tempdima^^J}%
\CT@setup
\CT@column@color
\CT@row@color
+ \CT@cell@color
\CT@do@color
\endgroup
\@tempdima\ht\z@
diff --git a/sphinx/themes/agogo/static/bgfooter.png b/sphinx/themes/agogo/static/bgfooter.png
index 9ce5bdd90..b7c7cadd4 100644
Binary files a/sphinx/themes/agogo/static/bgfooter.png and b/sphinx/themes/agogo/static/bgfooter.png differ
diff --git a/sphinx/themes/agogo/static/bgtop.png b/sphinx/themes/agogo/static/bgtop.png
index a0d4709ba..05740880f 100644
Binary files a/sphinx/themes/agogo/static/bgtop.png and b/sphinx/themes/agogo/static/bgtop.png differ
diff --git a/sphinx/themes/basic/layout.html b/sphinx/themes/basic/layout.html
index 1afc4a0bf..f8ff477c7 100644
--- a/sphinx/themes/basic/layout.html
+++ b/sphinx/themes/basic/layout.html
@@ -91,7 +91,8 @@
VERSION: '{{ release|e }}',
COLLAPSE_INDEX: false,
FILE_SUFFIX: '{{ '' if no_search_suffix else file_suffix }}',
- HAS_SOURCE: {{ has_source|lower }}
+ HAS_SOURCE: {{ has_source|lower }},
+ SOURCELINK_SUFFIX: '{{ sourcelink_suffix }}'
};
{%- for scriptfile in script_files %}
diff --git a/sphinx/themes/basic/static/basic.css_t b/sphinx/themes/basic/static/basic.css_t
index cdc703b09..585e992a5 100644
--- a/sphinx/themes/basic/static/basic.css_t
+++ b/sphinx/themes/basic/static/basic.css_t
@@ -585,6 +585,16 @@ span.eqno {
float: right;
}
+span.eqno a.headerlink {
+ position: relative;
+ left: 0px;
+ z-index: 1;
+}
+
+div.math:hover a.headerlink {
+ visibility: visible;
+}
+
/* -- printout stylesheet --------------------------------------------------- */
@media print {
diff --git a/sphinx/themes/basic/static/comment-bright.png b/sphinx/themes/basic/static/comment-bright.png
index 551517b8c..15e27edb1 100644
Binary files a/sphinx/themes/basic/static/comment-bright.png and b/sphinx/themes/basic/static/comment-bright.png differ
diff --git a/sphinx/themes/basic/static/comment-close.png b/sphinx/themes/basic/static/comment-close.png
index 09b54be46..4d91bcf57 100644
Binary files a/sphinx/themes/basic/static/comment-close.png and b/sphinx/themes/basic/static/comment-close.png differ
diff --git a/sphinx/themes/basic/static/comment.png b/sphinx/themes/basic/static/comment.png
index 92feb52b8..dfbc0cbd5 100644
Binary files a/sphinx/themes/basic/static/comment.png and b/sphinx/themes/basic/static/comment.png differ
diff --git a/sphinx/themes/basic/static/down-pressed.png b/sphinx/themes/basic/static/down-pressed.png
index 7c30d004b..5756c8cad 100644
Binary files a/sphinx/themes/basic/static/down-pressed.png and b/sphinx/themes/basic/static/down-pressed.png differ
diff --git a/sphinx/themes/basic/static/down.png b/sphinx/themes/basic/static/down.png
index f48098a43..1b3bdad2c 100644
Binary files a/sphinx/themes/basic/static/down.png and b/sphinx/themes/basic/static/down.png differ
diff --git a/sphinx/themes/basic/static/file.png b/sphinx/themes/basic/static/file.png
index 254c60bfb..a858a410e 100644
Binary files a/sphinx/themes/basic/static/file.png and b/sphinx/themes/basic/static/file.png differ
diff --git a/sphinx/themes/basic/static/minus.png b/sphinx/themes/basic/static/minus.png
index 0f22b16b0..d96755fda 100644
Binary files a/sphinx/themes/basic/static/minus.png and b/sphinx/themes/basic/static/minus.png differ
diff --git a/sphinx/themes/basic/static/plus.png b/sphinx/themes/basic/static/plus.png
index 0cfe084cf..7107cec93 100644
Binary files a/sphinx/themes/basic/static/plus.png and b/sphinx/themes/basic/static/plus.png differ
diff --git a/sphinx/themes/basic/static/searchtools.js_t b/sphinx/themes/basic/static/searchtools.js_t
index af0e21a37..cf899ef85 100644
--- a/sphinx/themes/basic/static/searchtools.js_t
+++ b/sphinx/themes/basic/static/searchtools.js_t
@@ -260,7 +260,8 @@ var Search = {
displayNextItem();
});
} else if (DOCUMENTATION_OPTIONS.HAS_SOURCE) {
- $.ajax({url: DOCUMENTATION_OPTIONS.URL_ROOT + '_sources/' + item[0] + '.txt',
+ var suffix = DOCUMENTATION_OPTIONS.SOURCELINK_SUFFIX;
+ $.ajax({url: DOCUMENTATION_OPTIONS.URL_ROOT + '_sources/' + item[5] + (item[5].endsWith(suffix) ? '' : suffix),
dataType: "text",
complete: function(jqxhr, textstatus) {
var data = jqxhr.responseText;
@@ -299,6 +300,7 @@ var Search = {
*/
performObjectSearch : function(object, otherterms) {
var filenames = this._index.filenames;
+ var docnames = this._index.docnames;
var objects = this._index.objects;
var objnames = this._index.objnames;
var titles = this._index.titles;
@@ -352,7 +354,7 @@ var Search = {
} else {
score += Scorer.objPrioDefault;
}
- results.push([filenames[match[0]], fullname, '#'+anchor, descr, score]);
+ results.push([docnames[match[0]], fullname, '#'+anchor, descr, score, filenames[match[0]]]);
}
}
}
@@ -364,6 +366,7 @@ var Search = {
* search for full-text terms in the index
*/
performTermsSearch : function(searchterms, excluded, terms, titleterms) {
+ var docnames = this._index.docnames;
var filenames = this._index.filenames;
var titles = this._index.titles;
@@ -438,7 +441,7 @@ var Search = {
// select one (max) score for the file.
// for better ranking, we should calculate ranking by using words statistics like basic tf-idf...
var score = $u.max($u.map(fileMap[file], function(w){return scoreMap[file][w]}));
- results.push([filenames[file], titles[file], '', null, score]);
+ results.push([docnames[file], titles[file], '', null, score, filenames[file]]);
}
}
return results;
diff --git a/sphinx/themes/basic/static/up-pressed.png b/sphinx/themes/basic/static/up-pressed.png
index 99e721096..acee3b68e 100644
Binary files a/sphinx/themes/basic/static/up-pressed.png and b/sphinx/themes/basic/static/up-pressed.png differ
diff --git a/sphinx/themes/basic/static/up.png b/sphinx/themes/basic/static/up.png
index 26de002e8..2a940a7da 100644
Binary files a/sphinx/themes/basic/static/up.png and b/sphinx/themes/basic/static/up.png differ
diff --git a/sphinx/themes/bizstyle/static/background_b01.png b/sphinx/themes/bizstyle/static/background_b01.png
index d262745b4..353f26dde 100644
Binary files a/sphinx/themes/bizstyle/static/background_b01.png and b/sphinx/themes/bizstyle/static/background_b01.png differ
diff --git a/sphinx/themes/haiku/static/alert_info_32.png b/sphinx/themes/haiku/static/alert_info_32.png
index 05b4fe898..ea4d1baf7 100644
Binary files a/sphinx/themes/haiku/static/alert_info_32.png and b/sphinx/themes/haiku/static/alert_info_32.png differ
diff --git a/sphinx/themes/haiku/static/alert_warning_32.png b/sphinx/themes/haiku/static/alert_warning_32.png
index f13611cde..a687c3dca 100644
Binary files a/sphinx/themes/haiku/static/alert_warning_32.png and b/sphinx/themes/haiku/static/alert_warning_32.png differ
diff --git a/sphinx/themes/haiku/static/bg-page.png b/sphinx/themes/haiku/static/bg-page.png
index 0103ee1a7..fe0a6dc89 100644
Binary files a/sphinx/themes/haiku/static/bg-page.png and b/sphinx/themes/haiku/static/bg-page.png differ
diff --git a/sphinx/themes/haiku/static/bullet_orange.png b/sphinx/themes/haiku/static/bullet_orange.png
index ad5d02f34..1cb8097ce 100644
Binary files a/sphinx/themes/haiku/static/bullet_orange.png and b/sphinx/themes/haiku/static/bullet_orange.png differ
diff --git a/sphinx/themes/pyramid/static/dialog-note.png b/sphinx/themes/pyramid/static/dialog-note.png
index 708682114..5a6336d11 100644
Binary files a/sphinx/themes/pyramid/static/dialog-note.png and b/sphinx/themes/pyramid/static/dialog-note.png differ
diff --git a/sphinx/themes/pyramid/static/dialog-seealso.png b/sphinx/themes/pyramid/static/dialog-seealso.png
index a27a0fcba..97553a8b7 100644
Binary files a/sphinx/themes/pyramid/static/dialog-seealso.png and b/sphinx/themes/pyramid/static/dialog-seealso.png differ
diff --git a/sphinx/themes/pyramid/static/dialog-todo.png b/sphinx/themes/pyramid/static/dialog-todo.png
index 9caa91e8a..cfbc28088 100644
Binary files a/sphinx/themes/pyramid/static/dialog-todo.png and b/sphinx/themes/pyramid/static/dialog-todo.png differ
diff --git a/sphinx/themes/pyramid/static/dialog-topic.png b/sphinx/themes/pyramid/static/dialog-topic.png
index 2ac57475c..a75afeaaf 100644
Binary files a/sphinx/themes/pyramid/static/dialog-topic.png and b/sphinx/themes/pyramid/static/dialog-topic.png differ
diff --git a/sphinx/themes/pyramid/static/dialog-warning.png b/sphinx/themes/pyramid/static/dialog-warning.png
index 4f598b12b..8bb7d8d35 100644
Binary files a/sphinx/themes/pyramid/static/dialog-warning.png and b/sphinx/themes/pyramid/static/dialog-warning.png differ
diff --git a/sphinx/themes/pyramid/static/headerbg.png b/sphinx/themes/pyramid/static/headerbg.png
index 0596f2020..e1051af48 100644
Binary files a/sphinx/themes/pyramid/static/headerbg.png and b/sphinx/themes/pyramid/static/headerbg.png differ
diff --git a/sphinx/themes/pyramid/static/middlebg.png b/sphinx/themes/pyramid/static/middlebg.png
index b3a89f4e5..5ee55db25 100644
Binary files a/sphinx/themes/pyramid/static/middlebg.png and b/sphinx/themes/pyramid/static/middlebg.png differ
diff --git a/sphinx/themes/scrolls/static/darkmetal.png b/sphinx/themes/scrolls/static/darkmetal.png
index 3ed486d5c..49c82f301 100644
Binary files a/sphinx/themes/scrolls/static/darkmetal.png and b/sphinx/themes/scrolls/static/darkmetal.png differ
diff --git a/sphinx/themes/scrolls/static/headerbg.png b/sphinx/themes/scrolls/static/headerbg.png
index 0c5b3657c..ef15cc09c 100644
Binary files a/sphinx/themes/scrolls/static/headerbg.png and b/sphinx/themes/scrolls/static/headerbg.png differ
diff --git a/sphinx/themes/scrolls/static/logo.png b/sphinx/themes/scrolls/static/logo.png
index 3dc573e0f..354aded6b 100644
Binary files a/sphinx/themes/scrolls/static/logo.png and b/sphinx/themes/scrolls/static/logo.png differ
diff --git a/sphinx/themes/scrolls/static/metal.png b/sphinx/themes/scrolls/static/metal.png
index e51010b5f..c29cd9eca 100644
Binary files a/sphinx/themes/scrolls/static/metal.png and b/sphinx/themes/scrolls/static/metal.png differ
diff --git a/sphinx/themes/scrolls/static/navigation.png b/sphinx/themes/scrolls/static/navigation.png
index 5be5b3183..89c447a29 100644
Binary files a/sphinx/themes/scrolls/static/navigation.png and b/sphinx/themes/scrolls/static/navigation.png differ
diff --git a/sphinx/themes/scrolls/static/watermark.png b/sphinx/themes/scrolls/static/watermark.png
index 903a96edb..d71dc4bbe 100644
Binary files a/sphinx/themes/scrolls/static/watermark.png and b/sphinx/themes/scrolls/static/watermark.png differ
diff --git a/sphinx/themes/scrolls/static/watermark_blur.png b/sphinx/themes/scrolls/static/watermark_blur.png
index 022690062..9fc0b6d31 100644
Binary files a/sphinx/themes/scrolls/static/watermark_blur.png and b/sphinx/themes/scrolls/static/watermark_blur.png differ
diff --git a/sphinx/themes/sphinxdoc/static/contents.png b/sphinx/themes/sphinxdoc/static/contents.png
index 7fb82154a..6c59aa1f9 100644
Binary files a/sphinx/themes/sphinxdoc/static/contents.png and b/sphinx/themes/sphinxdoc/static/contents.png differ
diff --git a/sphinx/themes/sphinxdoc/static/navigation.png b/sphinx/themes/sphinxdoc/static/navigation.png
index 1081dc143..fda6cd29e 100644
Binary files a/sphinx/themes/sphinxdoc/static/navigation.png and b/sphinx/themes/sphinxdoc/static/navigation.png differ
diff --git a/sphinx/theming.py b/sphinx/theming.py
index 539184115..42e4448db 100644
--- a/sphinx/theming.py
+++ b/sphinx/theming.py
@@ -133,9 +133,8 @@ class Theme(object):
dirname = path.dirname(name)
if not path.isdir(path.join(self.themedir, dirname)):
os.makedirs(path.join(self.themedir, dirname))
- fp = open(path.join(self.themedir, name), 'wb')
- fp.write(tinfo.read(name))
- fp.close()
+ with open(path.join(self.themedir, name), 'wb') as fp:
+ fp.write(tinfo.read(name))
self.themeconf = configparser.RawConfigParser()
self.themeconf.read(path.join(self.themedir, THEMECONF))
diff --git a/sphinx/transforms.py b/sphinx/transforms.py
index abeab7dab..cb4a5779b 100644
--- a/sphinx/transforms.py
+++ b/sphinx/transforms.py
@@ -170,6 +170,24 @@ class ApplySourceWorkaround(Transform):
apply_source_workaround(n)
+class AutoIndexUpgrader(Transform):
+ """
+ Detect old style; 4 column based indices and automatically upgrade to new style.
+ """
+ default_priority = 210
+
+ def apply(self):
+ env = self.document.settings.env
+ for node in self.document.traverse(addnodes.index):
+ if 'entries' in node and any(len(entry) == 4 for entry in node['entries']):
+ msg = ('4 column based index found. '
+ 'It might be a bug of extensions you use: %r' % node['entries'])
+ env.warn_node(msg, node)
+ for i, entry in enumerate(node['entries']):
+ if len(entry) == 4:
+ node['entries'][i] = entry + (None,)
+
+
class ExtraTranslatableNodes(Transform):
"""
make nodes translatable
diff --git a/sphinx/util/__init__.py b/sphinx/util/__init__.py
index 0c823fb1a..a0dababc8 100644
--- a/sphinx/util/__init__.py
+++ b/sphinx/util/__init__.py
@@ -18,7 +18,7 @@ import posixpath
import traceback
import unicodedata
from os import path
-from codecs import open, BOM_UTF8
+from codecs import BOM_UTF8
from collections import deque
from six import iteritems, text_type, binary_type
@@ -32,6 +32,7 @@ import jinja2
import sphinx
from sphinx.errors import PycodeError, SphinxParallelError, ExtensionError
from sphinx.util.console import strip_colors
+from sphinx.util.fileutil import copy_asset_file
from sphinx.util.osutil import fs_encoding
# import other utilities; partly for backwards compatibility, so don't
@@ -148,7 +149,7 @@ class FilenameUniqDict(dict):
def copy_static_entry(source, targetdir, builder, context={},
exclude_matchers=(), level=0):
- """Copy a HTML builder static_path entry from source to targetdir.
+ """[DEPRECATED] Copy a HTML builder static_path entry from source to targetdir.
Handles all possible cases of files, directories and subdirectories.
"""
@@ -158,16 +159,7 @@ def copy_static_entry(source, targetdir, builder, context={},
if matcher(relpath):
return
if path.isfile(source):
- target = path.join(targetdir, path.basename(source))
- if source.lower().endswith('_t') and builder.templates:
- # templated!
- fsrc = open(source, 'r', encoding='utf-8')
- fdst = open(target[:-2], 'w', encoding='utf-8')
- fdst.write(builder.templates.render_string(fsrc.read(), context))
- fsrc.close()
- fdst.close()
- else:
- copyfile(source, target)
+ copy_asset_file(source, targetdir, context, builder.templates)
elif path.isdir(source):
if not path.isdir(targetdir):
os.mkdir(targetdir)
@@ -181,37 +173,6 @@ def copy_static_entry(source, targetdir, builder, context={},
builder, context, level=level+1,
exclude_matchers=exclude_matchers)
-
-def copy_extra_entry(source, targetdir, exclude_matchers=()):
- """Copy a HTML builder extra_path entry from source to targetdir.
-
- Handles all possible cases of files, directories and subdirectories.
- """
- def excluded(path):
- relpath = relative_path(os.path.dirname(source), path)
- return any(matcher(relpath) for matcher in exclude_matchers)
-
- def copy_extra_file(source_, targetdir_):
- if not excluded(source_):
- target = path.join(targetdir_, os.path.basename(source_))
- copyfile(source_, target)
-
- if os.path.isfile(source):
- copy_extra_file(source, targetdir)
- return
-
- for root, dirs, files in os.walk(source):
- reltargetdir = os.path.join(targetdir, relative_path(source, root))
- for dir in dirs[:]:
- if excluded(os.path.join(root, dir)):
- dirs.remove(dir)
- else:
- target = os.path.join(reltargetdir, dir)
- if not path.exists(target):
- os.mkdir(target)
- for file in files:
- copy_extra_file(os.path.join(root, file), reltargetdir)
-
_DEBUG_HEADER = '''\
# Sphinx version: %s
# Python version: %s (%s)
diff --git a/sphinx/util/fileutil.py b/sphinx/util/fileutil.py
new file mode 100644
index 000000000..d11ae9f1b
--- /dev/null
+++ b/sphinx/util/fileutil.py
@@ -0,0 +1,80 @@
+# -*- coding: utf-8 -*-
+"""
+ sphinx.util.fileutil
+ ~~~~~~~~~~~~~~~~~~~~
+
+ File utility functions for Sphinx.
+
+ :copyright: Copyright 2007-2016 by the Sphinx team, see AUTHORS.
+ :license: BSD, see LICENSE for details.
+"""
+import os
+import codecs
+import posixpath
+from docutils.utils import relative_path
+from sphinx.util.osutil import copyfile, ensuredir, walk
+
+
+def copy_asset_file(source, destination, context=None, renderer=None):
+ """Copy an asset file to destination.
+
+ On copying, it expands the template variables if context argument is given and
+ the asset is a template file.
+
+ :param source: The path to source file
+ :param destination: The path to destination file or directory
+ :param context: The template variables. If not given, template files are simply copied
+ :param renderer: The template engine. If not given, SphinxRenderer is used by default
+ """
+ if not os.path.exists(source):
+ return
+
+ if os.path.exists(destination) and os.path.isdir(destination):
+ # Use source filename if destination points a directory
+ destination = os.path.join(destination, os.path.basename(source))
+
+ if source.lower().endswith('_t') and context:
+ if renderer is None:
+ from sphinx.util.template import SphinxRenderer
+ renderer = SphinxRenderer()
+
+ with codecs.open(source, 'r', encoding='utf-8') as fsrc:
+ with codecs.open(destination[:-2], 'w', encoding='utf-8') as fdst:
+ fdst.write(renderer.render_string(fsrc.read(), context))
+ else:
+ copyfile(source, destination)
+
+
+def copy_asset(source, destination, excluded=lambda path: False, context=None, renderer=None):
+ """Copy asset files to destination recursively.
+
+ On copying, it expands the template variables if context argument is given and
+ the asset is a template file.
+
+ :param source: The path to source file or directory
+ :param destination: The path to destination directory
+ :param excluded: The matcher to determine the given path should be copied or not
+ :param context: The template variables. If not given, template files are simply copied
+ :param renderer: The template engine. If not given, SphinxRenderer is used by default
+ """
+ if not os.path.exists(source):
+ return
+
+ ensuredir(destination)
+ if os.path.isfile(source):
+ copy_asset_file(source, destination, context, renderer)
+ return
+
+ for root, dirs, files in walk(source):
+ reldir = relative_path(source, root)
+ for dir in dirs[:]:
+ if excluded(posixpath.join(reldir, dir)):
+ dirs.remove(dir)
+ else:
+ ensuredir(posixpath.join(destination, reldir, dir))
+
+ for filename in files:
+ if not excluded(posixpath.join(reldir, filename)):
+ copy_asset_file(posixpath.join(root, filename),
+ posixpath.join(destination, reldir),
+ context, renderer)
diff --git a/sphinx/util/inspect.py b/sphinx/util/inspect.py
index 5dc2008c8..1c6e4e151 100644
--- a/sphinx/util/inspect.py
+++ b/sphinx/util/inspect.py
@@ -20,7 +20,7 @@ from sphinx.util import force_decode
# relatively import this module
inspect = __import__('inspect')
-memory_address_re = re.compile(r' at 0x[0-9a-f]{8,16}(?=>$)')
+memory_address_re = re.compile(r' at 0x[0-9a-f]{8,16}(?=>)')
if PY3:
@@ -108,6 +108,10 @@ def safe_getattr(obj, name, *defargs):
try:
return getattr(obj, name, *defargs)
except Exception:
+ # sometimes accessing a property raises an exception (e.g.
+ # NotImplementedError), so let's try to read the attribute directly
+ if name in obj.__dict__:
+ return obj.__dict__[name]
# this is a catch-all for all the weird things that some modules do
# with attribute access
if defargs:
diff --git a/sphinx/util/matching.py b/sphinx/util/matching.py
index 91fda6378..fc7750be9 100644
--- a/sphinx/util/matching.py
+++ b/sphinx/util/matching.py
@@ -62,6 +62,27 @@ def compile_matchers(patterns):
return [re.compile(_translate_pattern(pat)).match for pat in patterns]
+class Matcher(object):
+ """A pattern matcher for Multiple shell-style glob patterns.
+
+ Note: this modifies the patterns to work with copy_asset().
+ For example, "**/index.rst" matches with "index.rst"
+ """
+
+ def __init__(self, patterns):
+ expanded = [pat[3:] for pat in patterns if pat.startswith('**/')]
+ self.patterns = compile_matchers(patterns + expanded)
+
+ def __call__(self, string):
+ return self.match(string)
+
+ def match(self, string):
+ return any(pat(string) for pat in self.patterns)
+
+
+DOTFILES = Matcher(['**/.*'])
+
+
_pat_cache = {}
diff --git a/sphinx/util/osutil.py b/sphinx/util/osutil.py
index 585dc6104..0de6d8472 100644
--- a/sphinx/util/osutil.py
+++ b/sphinx/util/osutil.py
@@ -17,6 +17,7 @@ import time
import errno
import locale
import shutil
+import filecmp
from os import path
import contextlib
@@ -141,13 +142,16 @@ def copytimes(source, dest):
def copyfile(source, dest):
- """Copy a file and its modification times, if possible."""
- shutil.copyfile(source, dest)
- try:
- # don't do full copystat because the source may be read-only
- copytimes(source, dest)
- except OSError:
- pass
+ """Copy a file and its modification times, if possible.
+
+ Note: ``copyfile`` skips copying if the file has not been changed"""
+ if not path.exists(dest) or not filecmp.cmp(source, dest):
+ shutil.copyfile(source, dest)
+ try:
+ # don't do full copystat because the source may be read-only
+ copytimes(source, dest)
+ except OSError:
+ pass
no_fn_re = re.compile(r'[^a-zA-Z0-9_-]')
diff --git a/sphinx/util/template.py b/sphinx/util/template.py
new file mode 100644
index 000000000..b89a4c960
--- /dev/null
+++ b/sphinx/util/template.py
@@ -0,0 +1,57 @@
+# -*- coding: utf-8 -*-
+"""
+ sphinx.util.template
+ ~~~~~~~~~~~~~~~~~~~~
+
+ Templates utility functions for Sphinx.
+
+ :copyright: Copyright 2007-2016 by the Sphinx team, see AUTHORS.
+ :license: BSD, see LICENSE for details.
+"""
+
+import os
+from jinja2.sandbox import SandboxedEnvironment
+
+from sphinx import package_dir
+from sphinx.jinja2glue import SphinxFileSystemLoader
+
+
+class BaseRenderer(object):
+ def __init__(self, loader=None):
+ self.env = SandboxedEnvironment(loader=loader)
+ self.env.filters['repr'] = repr
+
+ def render(self, template_name, context):
+ return self.env.get_template(template_name).render(context)
+
+ def render_string(self, source, context):
+ return self.env.from_string(source).render(context)
+
+
+class FileRenderer(BaseRenderer):
+ def __init__(self, search_path):
+ loader = SphinxFileSystemLoader(search_path)
+ super(FileRenderer, self).__init__(loader)
+
+ @classmethod
+ def render_from_file(cls, filename, context):
+ dirname = os.path.dirname(filename)
+ basename = os.path.basename(filename)
+ return cls(dirname).render(basename, context)
+
+
+class SphinxRenderer(FileRenderer):
+ def __init__(self):
+ super(SphinxRenderer, self).__init__(os.path.join(package_dir, 'templates'))
+
+
+class LaTeXRenderer(SphinxRenderer):
+ def __init__(self):
+ super(LaTeXRenderer, self).__init__()
+
+ # use JSP/eRuby like tagging instead because curly bracket; the default
+ # tagging of jinja2 is not good for LaTeX sources.
+ self.env.variable_start_string = '<%='
+ self.env.variable_end_string = '%>'
+ self.env.block_start_string = '<%'
+ self.env.block_end_string = '%>'
diff --git a/sphinx/websupport/search/__init__.py b/sphinx/websupport/search/__init__.py
index 844a3b468..80b5a3535 100644
--- a/sphinx/websupport/search/__init__.py
+++ b/sphinx/websupport/search/__init__.py
@@ -34,19 +34,20 @@ class BaseSearch(object):
"""
pass
- def feed(self, pagename, title, doctree):
+ def feed(self, pagename, filename, title, doctree):
"""Called by the builder to add a doctree to the index. Converts the
`doctree` to text and passes it to :meth:`add_document`. You probably
won't want to override this unless you need access to the `doctree`.
Override :meth:`add_document` instead.
:param pagename: the name of the page to be indexed
+ :param filename: the name of the original source file
:param title: the title of the page to be indexed
:param doctree: is the docutils doctree representation of the page
"""
- self.add_document(pagename, title, doctree.astext())
+ self.add_document(pagename, filename, title, doctree.astext())
- def add_document(self, pagename, title, text):
+ def add_document(self, pagename, filename, title, text):
"""Called by :meth:`feed` to add a document to the search index.
This method should should do everything necessary to add a single
document to the search index.
@@ -59,6 +60,7 @@ class BaseSearch(object):
query.
:param pagename: the name of the page being indexed
+ :param filename: the name of the original source file
:param title: the page's title
:param text: the full text of the page
"""
diff --git a/sphinx/websupport/search/nullsearch.py b/sphinx/websupport/search/nullsearch.py
index 9e990b1cf..4d0db9553 100644
--- a/sphinx/websupport/search/nullsearch.py
+++ b/sphinx/websupport/search/nullsearch.py
@@ -17,7 +17,7 @@ class NullSearch(BaseSearch):
"""A search adapter that does nothing. Used when no search adapter
is specified.
"""
- def feed(self, pagename, title, doctree):
+ def feed(self, pagename, filename, title, doctree):
pass
def query(self, q):
diff --git a/sphinx/websupport/search/whooshsearch.py b/sphinx/websupport/search/whooshsearch.py
index 4b0769f50..f31dc4d52 100644
--- a/sphinx/websupport/search/whooshsearch.py
+++ b/sphinx/websupport/search/whooshsearch.py
@@ -44,7 +44,7 @@ class WhooshSearch(BaseSearch):
def finish_indexing(self):
self.index_writer.commit()
- def add_document(self, pagename, title, text):
+ def add_document(self, pagename, filename, title, text):
self.index_writer.add_document(path=text_type(pagename),
title=title,
text=text)
diff --git a/sphinx/writers/latex.py b/sphinx/writers/latex.py
index c72aff7b1..85014ef2a 100644
--- a/sphinx/writers/latex.py
+++ b/sphinx/writers/latex.py
@@ -28,42 +28,10 @@ from sphinx.locale import admonitionlabels, _
from sphinx.util import split_into
from sphinx.util.i18n import format_date
from sphinx.util.nodes import clean_astext, traverse_parent
+from sphinx.util.template import LaTeXRenderer
from sphinx.util.texescape import tex_escape_map, tex_replace_map
from sphinx.util.smartypants import educate_quotes_latex
-HEADER = r'''%% Generated by Sphinx.
-\def\sphinxdocclass{%(docclass)s}
-\documentclass[%(papersize)s,%(pointsize)s%(classoptions)s]{%(wrapperclass)s}
-\usepackage{iftex}
-%(passoptionstopackages)s
-%(inputenc)s
-%(utf8extra)s
-%(cmappkg)s
-%(fontenc)s
-%(amsmath)s
-%(babel)s
-%(fontpkg)s
-%(fncychap)s
-%(longtable)s
-\usepackage{sphinx}
-\usepackage{multirow}
-\usepackage{eqparbox}
-%(usepackages)s
-%(contentsname)s
-%(numfig_format)s
-%(pageautorefname)s
-%(tocdepth)s
-%(secnumdepth)s
-%(preamble)s
-
-\title{%(title)s}
-\date{%(date)s}
-\release{%(release)s}
-\author{%(author)s}
-\newcommand{\sphinxlogo}{%(logo)s}
-\renewcommand{\releasename}{%(releasename)s}
-%(makeindex)s
-'''
BEGIN_DOC = r'''
\begin{document}
@@ -72,12 +40,8 @@ BEGIN_DOC = r'''
%(tableofcontents)s
'''
-FOOTER = r'''
-\renewcommand{\indexname}{%(indexname)s}
-%(printindex)s
-\end{document}
-'''
+DEFAULT_TEMPLATE = 'latex/content.tex_t'
URI_SCHEMES = ('mailto:', 'http:', 'https:', 'ftp:')
SECNUMDEPTH = 3
@@ -266,29 +230,28 @@ class Table(object):
self.longtable = False
-def width_to_latex_length(length_str):
- """Convert `length_str` with rst length to LaTeX length.
-
- This function is copied from docutils' latex writer
- """
- match = re.match('(\d*\.?\d*)\s*(\S*)', length_str)
- if not match:
- return length_str
- value, unit = match.groups()[:2]
- if unit in ('', 'pt'):
- length_str = '%sbp' % value # convert to 'bp'
- # percentage: relate to current line width
- elif unit == '%':
- length_str = '%.3f\\linewidth' % (float(value)/100.0)
-
- return length_str
-
-
def escape_abbr(text):
"""Adjust spacing after abbreviations."""
return re.sub('\.(?=\s|$)', '.\\@', text)
+def rstdim_to_latexdim(width_str):
+ """Convert `width_str` with rst length to LaTeX length."""
+ match = re.match('^(\d*\.?\d*)\s*(\S*)$', width_str)
+ if not match:
+ raise ValueError
+ res = width_str
+ amount, unit = match.groups()[:2]
+ float(amount) # validate amount is float
+ if unit in ('', "px"):
+ res = "%s\\sphinxpxdimen" % amount
+ elif unit == 'pt':
+ res = '%sbp' % amount # convert to 'bp'
+ elif unit == "%":
+ res = "%.3f\\linewidth" % (float(amount) / 100.0)
+ return res
+
+
class LaTeXTranslator(nodes.NodeVisitor):
sectionnames = ["part", "chapter", "section", "subsection",
"subsubsection", "paragraph", "subparagraph"]
@@ -298,15 +261,16 @@ class LaTeXTranslator(nodes.NodeVisitor):
default_elements = {
'papersize': 'letterpaper',
'pointsize': '10pt',
+ 'pxunit': '49336sp',
'classoptions': '',
'extraclassoptions': '',
'passoptionstopackages': '',
'inputenc': ('\\ifPDFTeX\n'
' \\usepackage[utf8]{inputenc}\n'
- '\\else\\fi'),
+ '\\fi'),
'utf8extra': ('\\ifdefined\\DeclareUnicodeCharacter\n'
' \\DeclareUnicodeCharacter{00A0}{\\nobreakspace}\n'
- '\\else\\fi'),
+ '\\fi'),
'cmappkg': '\\usepackage{cmap}',
'fontenc': '\\usepackage[T1]{fontenc}',
'amsmath': '\\usepackage{amsmath,amssymb,amstext}',
@@ -371,29 +335,24 @@ class LaTeXTranslator(nodes.NodeVisitor):
if document.settings.docclass == 'howto':
self.top_sectionlevel = 2
else:
- if builder.config.latex_use_parts:
- self.top_sectionlevel = 0
- else:
- self.top_sectionlevel = 1
+ self.top_sectionlevel = 1
# sort out some elements
- papersize = builder.config.latex_paper_size + 'paper'
- if papersize == 'paper': # e.g. command line "-D latex_paper_size="
- papersize = 'letterpaper'
-
self.elements = self.default_elements.copy()
self.elements.update({
'wrapperclass': self.format_docclass(document.settings.docclass),
- 'papersize': papersize,
- 'pointsize': builder.config.latex_font_size,
# if empty, the title is set to the first section title
'title': document.settings.title,
'release': builder.config.release,
'author': document.settings.author,
'releasename': _('Release'),
- 'preamble': builder.config.latex_preamble,
'indexname': _('Index'),
})
+ # set-up boolean for sphinx.sty
+ if builder.config.latex_keep_old_macro_names:
+ self.elements['keepoldnames'] = '\\sphinxKeepOldNamestrue'
+ else:
+ self.elements['keepoldnames'] = '\\sphinxKeepOldNamesfalse'
if document.settings.docclass == 'howto':
docclass = builder.config.latex_docclass.get('howto', 'article')
else:
@@ -405,7 +364,8 @@ class LaTeXTranslator(nodes.NodeVisitor):
self.elements['date'] = format_date(builder.config.today_fmt or _('%b %d, %Y'),
language=builder.config.language)
if builder.config.latex_logo:
- self.elements['logo'] = '\\includegraphics{%s}\\par' % \
+ # no need for \\noindent here, used in flushright
+ self.elements['logo'] = '\\sphinxincludegraphics{%s}\\par' % \
path.basename(builder.config.latex_logo)
# setup babel
self.babel = ExtBabel(builder.config.language)
@@ -458,6 +418,7 @@ class LaTeXTranslator(nodes.NodeVisitor):
self.elements['contentsname'] = \
self.babel_renewcommand('\\contentsname', document.settings.contentsname)
# allow the user to override them all
+ self.check_latex_elements()
self.elements.update(builder.config.latex_elements)
if self.elements['extraclassoptions']:
self.elements['classoptions'] += ',' + \
@@ -505,6 +466,12 @@ class LaTeXTranslator(nodes.NodeVisitor):
def pop_hyperlink_ids(self, figtype):
return self.next_hyperlink_ids.pop(figtype, set())
+ def check_latex_elements(self):
+ for key in self.builder.config.latex_elements:
+ if key not in self.elements:
+ msg = _("Unknown configure key: latex_elements[%r] is ignored.")
+ self.builder.warn(msg % key)
+
def restrict_footnote(self, node):
if self.footnote_restricted is False:
self.footnote_restricted = node
@@ -526,12 +493,11 @@ class LaTeXTranslator(nodes.NodeVisitor):
return docclass
def astext(self):
- return (HEADER % self.elements +
- self.highlighter.get_stylesheet() +
- u''.join(self.body) +
- '\n' + self.elements['footer'] + '\n' +
- self.generate_indices() +
- FOOTER % self.elements)
+ self.elements.update({
+ 'body': u''.join(self.body),
+ 'indices': self.generate_indices()
+ })
+ return LaTeXRenderer().render(DEFAULT_TEMPLATE, self.elements)
def hypertarget(self, id, withdoc=True, anchor=True):
if withdoc:
@@ -605,9 +571,9 @@ class LaTeXTranslator(nodes.NodeVisitor):
if len(codeblock) == 1:
pass # FIXME
else:
- ret.append('\\SetupFloatingEnvironment{literal-block}{name=%s}\n' %
- escape_abbr(text_type(codeblock[0]).translate(tex_escape_map)))
- if table[1]:
+ definition = escape_abbr(text_type(codeblock[0]).translate(tex_escape_map))
+ ret.append(self.babel_renewcommand('\\literalblockname', definition))
+ if codeblock[1]:
pass # FIXME
return ''.join(ret)
@@ -625,11 +591,11 @@ class LaTeXTranslator(nodes.NodeVisitor):
for entry in entries:
if not entry[3]:
continue
- ret.append('\\item {\\texttt{%s}}' % self.encode(entry[0]))
+ ret.append('\\item {\\sphinxstyleindexentry{%s}}' % self.encode(entry[0]))
if entry[4]:
# add "extra" info
- ret.append(' \\emph{(%s)}' % self.encode(entry[4]))
- ret.append(', \\pageref{%s:%s}\n' %
+ ret.append('\\sphinxstyleindexextra{%s}' % self.encode(entry[4]))
+ ret.append('\\sphinxstyleindexpageref{%s:%s}\n' %
(entry[2], self.idescape(entry[3])))
ret.append('\\end{theindex}\n')
@@ -743,11 +709,11 @@ class LaTeXTranslator(nodes.NodeVisitor):
def visit_topic(self, node):
self.in_minipage = 1
- self.body.append('\n\\begin{SphinxShadowBox}\n')
+ self.body.append('\n\\begin{sphinxShadowBox}\n')
def depart_topic(self, node):
self.in_minipage = 0
- self.body.append('\\end{SphinxShadowBox}\n')
+ self.body.append('\\end{sphinxShadowBox}\n')
visit_sidebar = visit_topic
depart_sidebar = depart_topic
@@ -817,9 +783,12 @@ class LaTeXTranslator(nodes.NodeVisitor):
self.context[-1] += self.hypertarget(id, anchor=False)
self.next_section_ids.clear()
- elif isinstance(parent, (nodes.topic, nodes.sidebar)):
- self.body.append(r'\textbf{')
- self.context.append('}\n\n\medskip\n\n')
+ elif isinstance(parent, nodes.topic):
+ self.body.append(r'\sphinxstyletopictitle{')
+ self.context.append('}\n')
+ elif isinstance(parent, nodes.sidebar):
+ self.body.append(r'\sphinxstylesidebartitle{')
+ self.context.append('}\n')
elif isinstance(parent, nodes.Admonition):
self.body.append('{')
self.context.append('}\n')
@@ -831,7 +800,7 @@ class LaTeXTranslator(nodes.NodeVisitor):
'encountered title node not in section, topic, table, '
'admonition or sidebar',
(self.curfilestack[-1], node.line or ''))
- self.body.append('\\textbf{')
+ self.body.append('\\sphinxstyleothertitle{')
self.context.append('}\n')
self.in_title = 1
@@ -845,8 +814,8 @@ class LaTeXTranslator(nodes.NodeVisitor):
def visit_subtitle(self, node):
if isinstance(node.parent, nodes.sidebar):
- self.body.append('~\\\\\n\\textbf{')
- self.context.append('}\n\\smallskip\n')
+ self.body.append('\\sphinxstylesidebarsubtitle{')
+ self.context.append('}\n')
else:
self.context.append('')
@@ -878,7 +847,7 @@ class LaTeXTranslator(nodes.NodeVisitor):
self.body.append('}')
def visit_desc_addname(self, node):
- self.body.append(r'\code{')
+ self.body.append(r'\sphinxcode{')
self.literal_whitespace += 1
def depart_desc_addname(self, node):
@@ -898,7 +867,7 @@ class LaTeXTranslator(nodes.NodeVisitor):
self.body.append(r'}')
def visit_desc_name(self, node):
- self.body.append(r'\bfcode{')
+ self.body.append(r'\sphinxbfcode{')
self.no_contractions += 1
self.literal_whitespace += 1
@@ -929,13 +898,13 @@ class LaTeXTranslator(nodes.NodeVisitor):
self.body.append('}')
def visit_desc_optional(self, node):
- self.body.append(r'\optional{')
+ self.body.append(r'\sphinxoptional{')
def depart_desc_optional(self, node):
self.body.append('}')
def visit_desc_annotation(self, node):
- self.body.append(r'\strong{')
+ self.body.append(r'\sphinxstrong{')
def depart_desc_annotation(self, node):
self.body.append('}')
@@ -949,7 +918,7 @@ class LaTeXTranslator(nodes.NodeVisitor):
pass
def visit_seealso(self, node):
- self.body.append(u'\n\n\\strong{%s:}\n\n' % admonitionlabels['seealso'])
+ self.body.append(u'\n\n\\sphinxstrong{%s:}\n\n' % admonitionlabels['seealso'])
def depart_seealso(self, node):
self.body.append("\n\n")
@@ -972,9 +941,9 @@ class LaTeXTranslator(nodes.NodeVisitor):
def visit_collected_footnote(self, node):
self.in_footnote += 1
if 'footnotetext' in node:
- self.body.append('\\footnotetext[%s]{\sphinxAtStartFootnote%%' % node['number'])
+ self.body.append('\\footnotetext[%s]{\sphinxAtStartFootnote\n' % node['number'])
else:
- self.body.append('\\footnote[%s]{\sphinxAtStartFootnote%%' % node['number'])
+ self.body.append('\\footnote[%s]{\sphinxAtStartFootnote\n' % node['number'])
def depart_collected_footnote(self, node):
self.body.append('}')
@@ -1022,23 +991,23 @@ class LaTeXTranslator(nodes.NodeVisitor):
self.body.append('\n\\begin{longtable}')
endmacro = '\\end{longtable}\n\n'
elif self.table.has_verbatim:
- self.body.append('\n\\begin{tabular}')
+ self.body.append('\n\\noindent\\begin{tabular}')
endmacro = '\\end{tabular}\n\n'
elif self.table.has_problematic and not self.table.colspec:
# if the user has given us tabularcolumns, accept them and use
# tabulary nevertheless
- self.body.append('\n\\begin{tabular}')
+ self.body.append('\n\\noindent\\begin{tabular}')
endmacro = '\\end{tabular}\n\n'
else:
- self.body.append('\n\\begin{tabulary}{\\linewidth}')
+ self.body.append('\n\\noindent\\begin{tabulary}{\\linewidth}')
endmacro = '\\end{tabulary}\n\n'
if self.table.colspec:
self.body.append(self.table.colspec)
else:
if self.table.has_problematic:
- colwidth = 0.95 / self.table.colcount
- colspec = ('p{%.3f\\linewidth}|' % colwidth) * \
- self.table.colcount
+ colspec = ('*{%d}{p{\\dimexpr(\\linewidth-\\arrayrulewidth)/%d'
+ '-2\\tabcolsep-\\arrayrulewidth\\relax}|}' %
+ (self.table.colcount, self.table.colcount))
self.body.append('{|' + colspec + '}\n')
elif self.table.longtable:
self.body.append('{|' + ('l|' * self.table.colcount) + '}\n')
@@ -1143,28 +1112,28 @@ class LaTeXTranslator(nodes.NodeVisitor):
self.remember_multirow[self.table.col] -= 1
if self.remember_multirowcol.get(self.table.col, 0):
extracols = self.remember_multirowcol[self.table.col]
- self.body.append(' \\multicolumn{')
+ self.body.append('\\multicolumn{')
self.body.append(str(extracols + 1))
- self.body.append('}{|l|}{}')
+ self.body.append('}{|l|}{}\\relax ')
self.table.col += extracols
- self.body.append(' & ')
+ self.body.append('&')
else:
- self.body.append(' & ')
+ self.body.append('&')
self.table.col += 1
context = ''
if 'morecols' in node:
- self.body.append(' \\multicolumn{')
+ self.body.append('\\multicolumn{')
self.body.append(str(node.get('morecols') + 1))
if self.table.col == 1:
- self.body.append('}{|l|}{')
+ self.body.append('}{|l|}{\\relax ')
else:
- self.body.append('}{l|}{')
- context += '}'
+ self.body.append('}{l|}{\\relax ')
+ context += '\\unskip}\\relax '
if 'morerows' in node:
- self.body.append(' \\multirow{')
+ self.body.append('\\multirow{')
self.body.append(str(node.get('morerows') + 1))
- self.body.append('}{*}{')
- context += '}'
+ self.body.append('}{*}{\\relax ')
+ context += '\\unskip}\\relax '
self.remember_multirow[self.table.col] = node.get('morerows')
if 'morecols' in node:
if 'morerows' in node:
@@ -1181,17 +1150,17 @@ class LaTeXTranslator(nodes.NodeVisitor):
if len(node) == 1 and isinstance(node[0], nodes.paragraph) and node.astext() == '':
pass
else:
- self.body.append('\\textsf{\\relax ')
- context += '}'
+ self.body.append('\\sphinxstylethead{\\relax ')
+ context += '\\unskip}\\relax '
while self.remember_multirow.get(self.table.col + 1, 0):
self.table.col += 1
self.remember_multirow[self.table.col] -= 1
- context += ' & '
+ context += '&'
if self.remember_multirowcol.get(self.table.col, 0):
extracols = self.remember_multirowcol[self.table.col]
- context += ' \\multicolumn{'
+ context += '\\multicolumn{'
context += str(extracols + 1)
- context += '}{l|}{}'
+ context += '}{l|}{}\\relax '
self.table.col += extracols
if len(node.traverse(nodes.paragraph)) >= 2:
self.table.has_problematic = True
@@ -1314,12 +1283,15 @@ class LaTeXTranslator(nodes.NodeVisitor):
depart_field_body = depart_definition
def visit_paragraph(self, node):
- # insert blank line, if the paragraph follows a non-paragraph node in a compound
index = node.parent.index(node)
if (index > 0 and isinstance(node.parent, nodes.compound) and
not isinstance(node.parent[index - 1], nodes.paragraph) and
not isinstance(node.parent[index - 1], nodes.compound)):
+ # insert blank line, if the paragraph follows a non-paragraph node in a compound
self.body.append('\\noindent\n')
+ elif index == 0 and isinstance(node.parent, nodes.footnote):
+ # don't insert blank line, if the paragraph is first child of a footnote
+ pass
else:
self.body.append('\n')
@@ -1354,18 +1326,10 @@ class LaTeXTranslator(nodes.NodeVisitor):
pass
def latex_image_length(self, width_str):
- match = re.match('(\d*\.?\d*)\s*(\S*)', width_str)
- if not match:
- # fallback
- return width_str
- res = width_str
- amount, unit = match.groups()[:2]
- if not unit or unit == "px":
- # pixels: let LaTeX alone
- return None
- elif unit == "%":
- res = "%.3f\\linewidth" % (float(amount) / 100.0)
- return res
+ try:
+ return rstdim_to_latexdim(width_str)
+ except ValueError:
+ self.builder.warn('dimension unit %s is invalid. Ignored.' % width_str)
def is_inline(self, node):
"""Check whether a node represents an inline element."""
@@ -1409,7 +1373,7 @@ class LaTeXTranslator(nodes.NodeVisitor):
except KeyError:
pass
if not is_inline:
- pre.append('\n')
+ pre.append('\n\\noindent')
post.append('\n')
pre.reverse()
if node['uri'] in self.builder.images:
@@ -1427,7 +1391,14 @@ class LaTeXTranslator(nodes.NodeVisitor):
if include_graphics_options:
options = '[%s]' % ','.join(include_graphics_options)
base, ext = path.splitext(uri)
- self.body.append('\\includegraphics%s{{%s}%s}' % (options, base, ext))
+ if self.in_title and base:
+ # Lowercase tokens forcely because some fncychap themes capitalize
+ # the options of \sphinxincludegraphics unexpectly (ex. WIDTH=...).
+ self.body.append('\\lowercase{\\sphinxincludegraphics%s}{{%s}%s}' %
+ (options, base, ext))
+ else:
+ self.body.append('\\sphinxincludegraphics%s{{%s}%s}' %
+ (options, base, ext))
self.body.extend(post)
def depart_image(self, node):
@@ -1444,13 +1415,26 @@ class LaTeXTranslator(nodes.NodeVisitor):
isinstance(node.children[0], nodes.image) and
node.children[0]['ids']):
ids += self.hypertarget(node.children[0]['ids'][0], anchor=False)
- if node.get('align', '') in ('left', 'right'):
+ if self.table:
+ # TODO: support align option
if 'width' in node:
- length = width_to_latex_length(node['width'])
+ length = self.latex_image_length(node['width'])
+ if length:
+ self.body.append('\\begin{sphinxfigure-in-table}[%s]\n'
+ '\\centering\n' % length)
else:
- length = '0pt'
+ self.body.append('\\begin{sphinxfigure-in-table}\n\\centering\n')
+ if any(isinstance(child, nodes.caption) for child in node):
+ self.body.append('\\capstart')
+ self.context.append(ids + '\\end{sphinxfigure-in-table}\\relax\n')
+ elif node.get('align', '') in ('left', 'right'):
+ length = None
+ if 'width' in node:
+ length = self.latex_image_length(node['width'])
+ elif 'width' in node[0]:
+ length = self.latex_image_length(node[0]['width'])
self.body.append('\\begin{wrapfigure}{%s}{%s}\n\\centering' %
- (node['align'] == 'right' and 'r' or 'l', length))
+ (node['align'] == 'right' and 'r' or 'l', length or '0pt'))
self.context.append(ids + '\\end{wrapfigure}\n')
elif self.in_minipage:
if ('align' not in node.attributes or
@@ -1483,9 +1467,11 @@ class LaTeXTranslator(nodes.NodeVisitor):
def visit_caption(self, node):
self.in_caption += 1
if self.in_container_literal_block:
- self.body.append('\\SphinxSetupCaptionForVerbatim{literal-block}{')
+ self.body.append('\\sphinxSetupCaptionForVerbatim{')
elif self.in_minipage and isinstance(node.parent, nodes.figure):
self.body.append('\\captionof{figure}{')
+ elif self.table and node.parent.tagname == 'figure':
+ self.body.append('\\sphinxfigcaption{')
else:
self.body.append('\\caption{')
@@ -1500,19 +1486,19 @@ class LaTeXTranslator(nodes.NodeVisitor):
self.body.append('}')
def visit_admonition(self, node):
- self.body.append('\n\\begin{notice}{note}')
+ self.body.append('\n\\begin{sphinxadmonition}{note}')
def depart_admonition(self, node):
- self.body.append('\\end{notice}\n')
+ self.body.append('\\end{sphinxadmonition}\n')
def _make_visit_admonition(name):
def visit_admonition(self, node):
- self.body.append(u'\n\\begin{notice}{%s}{%s:}' %
+ self.body.append(u'\n\\begin{sphinxadmonition}{%s}{%s:}' %
(name, admonitionlabels[name]))
return visit_admonition
def _depart_named_admonition(self, node):
- self.body.append('\\end{notice}\n')
+ self.body.append('\\end{sphinxadmonition}\n')
visit_attention = _make_visit_admonition('attention')
depart_attention = _depart_named_admonition
@@ -1683,9 +1669,9 @@ class LaTeXTranslator(nodes.NodeVisitor):
# don't add a pageref for glossary terms
self.context.append('}}}')
# mark up as termreference
- self.body.append(r'\termref{')
+ self.body.append(r'\sphinxtermref{')
else:
- self.body.append(r'\crossref{')
+ self.body.append(r'\sphinxcrossref{')
if self.builder.config.latex_show_pagerefs and not \
self.in_production_list:
self.context.append('}}} (%s)' % self.hyperpageref(id))
@@ -1726,36 +1712,36 @@ class LaTeXTranslator(nodes.NodeVisitor):
pass
def visit_emphasis(self, node):
- self.body.append(r'\emph{')
+ self.body.append(r'\sphinxstyleemphasis{')
def depart_emphasis(self, node):
self.body.append('}')
def visit_literal_emphasis(self, node):
- self.body.append(r'\emph{\texttt{')
+ self.body.append(r'\sphinxstyleliteralemphasis{')
self.no_contractions += 1
def depart_literal_emphasis(self, node):
- self.body.append('}}')
+ self.body.append('}')
self.no_contractions -= 1
def visit_strong(self, node):
- self.body.append(r'\textbf{')
+ self.body.append(r'\sphinxstylestrong{')
def depart_strong(self, node):
self.body.append('}')
def visit_literal_strong(self, node):
- self.body.append(r'\textbf{\texttt{')
+ self.body.append(r'\sphinxstyleliteralstrong{')
self.no_contractions += 1
def depart_literal_strong(self, node):
- self.body.append('}}')
+ self.body.append('}')
self.no_contractions -= 1
def visit_abbreviation(self, node):
abbr = node.astext()
- self.body.append(r'\textsc{')
+ self.body.append(r'\sphinxstyleabbreviation{')
# spell out the explanation once
if node.hasattr('explanation') and abbr not in self.handled_abbrs:
self.context.append('} (%s)' % self.encode(node['explanation']))
@@ -1773,7 +1759,7 @@ class LaTeXTranslator(nodes.NodeVisitor):
return self.depart_literal_emphasis(node)
def visit_title_reference(self, node):
- self.body.append(r'\titleref{')
+ self.body.append(r'\sphinxtitleref{')
def depart_title_reference(self, node):
self.body.append('}')
@@ -1799,9 +1785,9 @@ class LaTeXTranslator(nodes.NodeVisitor):
def visit_literal(self, node):
self.no_contractions += 1
if self.in_title:
- self.body.append(r'\texttt{')
+ self.body.append(r'\sphinxstyleliteralintitle{')
else:
- self.body.append(r'\code{')
+ self.body.append(r'\sphinxcode{')
def depart_literal(self, node):
self.no_contractions -= 1
@@ -1849,7 +1835,7 @@ class LaTeXTranslator(nodes.NodeVisitor):
ids += self.hypertarget(node['ids'][0], anchor=False)
# LaTeX code will insert \phantomsection prior to \label
if ids:
- self.body.append('\n\\def\\SphinxLiteralBlockLabel{' + ids + '}')
+ self.body.append('\n\\def\\sphinxLiteralBlockLabel{' + ids + '}')
code = node.astext()
lang = self.hlsettingstack[-1][0]
linenos = code.count('\n') >= self.hlsettingstack[-1][1] - 1
@@ -1873,18 +1859,22 @@ class LaTeXTranslator(nodes.NodeVisitor):
**highlight_args)
# workaround for Unicode issue
hlcode = hlcode.replace(u'€', u'@texteuro[]')
- # must use original Verbatim environment and "tabular" environment
+ # if in table raise verbatim flag to avoid "tabulary" environment
+ # and opt for sphinxVerbatimintable to handle caption & long lines
if self.table:
- hlcode = hlcode.replace('\\begin{Verbatim}',
- '\\begin{OriginalVerbatim}')
self.table.has_problematic = True
self.table.has_verbatim = True
+ hlcode = hlcode.replace('\\begin{Verbatim}',
+ '\\begin{sphinxVerbatimintable}')
+ else:
+ hlcode = hlcode.replace('\\begin{Verbatim}',
+ '\\begin{sphinxVerbatim}')
# get consistent trailer
hlcode = hlcode.rstrip()[:-14] # strip \end{Verbatim}
- self.body.append('\n' + hlcode + '\\end{%sVerbatim}\n' %
- (self.table and 'Original' or ''))
+ self.body.append('\n' + hlcode + '\\end{sphinxVerbatim%s}\n' %
+ (self.table and 'intable' or ''))
if ids:
- self.body.append('\\let\\SphinxLiteralBlockLabel\empty\n')
+ self.body.append('\\let\\sphinxLiteralBlockLabel\empty\n')
raise nodes.SkipNode
def depart_literal_block(self, node):
@@ -2010,10 +2000,10 @@ class LaTeXTranslator(nodes.NodeVisitor):
def visit_inline(self, node):
classes = node.get('classes', [])
if classes in [['menuselection'], ['guilabel']]:
- self.body.append(r'\menuselection{')
+ self.body.append(r'\sphinxmenuselection{')
self.context.append('}')
elif classes in [['accelerator']]:
- self.body.append(r'\accelerator{')
+ self.body.append(r'\sphinxaccelerator{')
self.context.append('}')
elif classes and not self.in_title:
self.body.append(r'\DUrole{%s}{' % ','.join(classes))
@@ -2047,13 +2037,13 @@ class LaTeXTranslator(nodes.NodeVisitor):
ids += self.hypertarget(node['ids'][0], anchor=False)
# define label for use in caption.
if ids:
- self.body.append('\n\\def\\SphinxLiteralBlockLabel{' + ids + '}\n')
+ self.body.append('\n\\def\\sphinxLiteralBlockLabel{' + ids + '}\n')
def depart_container(self, node):
if node.get('literal_block'):
self.in_container_literal_block -= 1
- self.body.append('\\let\\SphinxVerbatimTitle\\empty\n')
- self.body.append('\\let\\SphinxLiteralBlockLabel\\empty\n')
+ self.body.append('\\let\\sphinxVerbatimTitle\\empty\n')
+ self.body.append('\\let\\sphinxLiteralBlockLabel\\empty\n')
def visit_decoration(self, node):
pass
diff --git a/test-reqs.txt b/test-reqs.txt
index 582afe69f..690174b7d 100644
--- a/test-reqs.txt
+++ b/test-reqs.txt
@@ -13,3 +13,4 @@ alabaster
sphinx_rtd_theme
imagesize
requests
+html5lib
diff --git a/tests/coverage.py b/tests/coverage.py
index f9341d8ba..cd36e218a 100755
--- a/tests/coverage.py
+++ b/tests/coverage.py
@@ -472,10 +472,9 @@ class coverage:
def save(self):
if self.usecache and self.cache:
self.canonicalize_filenames()
- cache = open(self.cache, 'wb')
import marshal
- marshal.dump(self.cexecuted, cache)
- cache.close()
+ with open(self.cache, 'wb') as cache:
+ marshal.dump(self.cexecuted, cache)
# restore(). Restore coverage data from the coverage cache (if it exists).
@@ -488,10 +487,9 @@ class coverage:
def restore_file(self, file_name):
try:
- cache = open(file_name, 'rb')
import marshal
- cexecuted = marshal.load(cache)
- cache.close()
+ with open(file_name, 'rb') as cache:
+ cexecuted = marshal.load(cache)
if isinstance(cexecuted, dict):
return cexecuted
else:
@@ -614,8 +612,8 @@ class coverage:
)
filename = filename[:-1]
if not source:
- sourcef = open(filename, 'rU')
- source = sourcef.read()
+ with open(filename, 'rU') as sourcef:
+ source = sourcef.read()
try:
lines, excluded_lines, line_map = self.find_executable_statements(
source, exclude=self.exclude_re
@@ -625,8 +623,6 @@ class coverage:
"Couldn't parse '%s' as Python source: '%s' at line %d" %
(filename, synerr.msg, synerr.lineno)
)
- if sourcef:
- sourcef.close()
result = filename, lines, excluded_lines, line_map
self.analysis_cache[morf] = result
return result
diff --git a/tests/path.py b/tests/path.py
index 901c9ce96..959b54875 100755
--- a/tests/path.py
+++ b/tests/path.py
@@ -206,10 +206,13 @@ class path(text_type):
class _repr_text(text_type):
def __repr__(self):
return self._repr
+
+
class _repr_bin(binary_type):
def __repr__(self):
return self._repr
+
def repr_as(string, repr_):
wrapper = _repr_text if isinstance(string, text_type) else _repr_bin
proxy = wrapper(string)
diff --git a/tests/root/img.foo.png b/tests/root/img.foo.png
index 4c8f89929..a97e86d66 100644
Binary files a/tests/root/img.foo.png and b/tests/root/img.foo.png differ
diff --git a/tests/root/img.png b/tests/root/img.png
index 4c8f89929..a97e86d66 100644
Binary files a/tests/root/img.png and b/tests/root/img.png differ
diff --git a/tests/root/markup.txt b/tests/root/markup.txt
index cc1fa2a63..77f245a6f 100644
--- a/tests/root/markup.txt
+++ b/tests/root/markup.txt
@@ -220,6 +220,13 @@ Tables with multirow and multicol:
| |
+----+
+.. list-table::
+ :header-rows: 0
+
+ * - .. figure:: img.png
+
+ figure in table
+
Figures
-------
@@ -246,6 +253,12 @@ Figures
figure with align & figwidth option
+.. figure:: rimg.png
+ :align: right
+ :width: 3cm
+
+ figure with align & width option
+
Version markup
--------------
diff --git a/tests/root/rimg.png b/tests/root/rimg.png
index 1081dc143..fda6cd29e 100644
Binary files a/tests/root/rimg.png and b/tests/root/rimg.png differ
diff --git a/tests/root/subdir/img.png b/tests/root/subdir/img.png
index 4c8f89929..a97e86d66 100644
Binary files a/tests/root/subdir/img.png and b/tests/root/subdir/img.png differ
diff --git a/tests/root/subdir/simg.png b/tests/root/subdir/simg.png
index 4c8f89929..a97e86d66 100644
Binary files a/tests/root/subdir/simg.png and b/tests/root/subdir/simg.png differ
diff --git a/tests/root/testtheme/static/staticimg.png b/tests/root/testtheme/static/staticimg.png
index 1081dc143..fda6cd29e 100644
Binary files a/tests/root/testtheme/static/staticimg.png and b/tests/root/testtheme/static/staticimg.png differ
diff --git a/tests/roots/test-add_enumerable_node/rimg.png b/tests/roots/test-add_enumerable_node/rimg.png
index 1081dc143..fda6cd29e 100644
Binary files a/tests/roots/test-add_enumerable_node/rimg.png and b/tests/roots/test-add_enumerable_node/rimg.png differ
diff --git a/tests/roots/test-config/conf.py b/tests/roots/test-config/conf.py
index b6075e5cb..1e583d1e0 100644
--- a/tests/roots/test-config/conf.py
+++ b/tests/roots/test-config/conf.py
@@ -1,4 +1,4 @@
-from sphinx.config import string_classes
+from sphinx.config import string_classes, ENUM
value1 = 123 # wrong type
value2 = 123 # lambda with wrong type
@@ -45,3 +45,4 @@ def setup(app):
app.add_config_value('value14', None, False, string_classes)
app.add_config_value('value15', u'unicode', False)
app.add_config_value('value16', u'unicode', False)
+ app.add_config_value('value17', 'default', False, ENUM('default', 'one', 'two'))
diff --git a/tests/roots/test-footnotes/rimg.png b/tests/roots/test-footnotes/rimg.png
index 1081dc143..fda6cd29e 100644
Binary files a/tests/roots/test-footnotes/rimg.png and b/tests/roots/test-footnotes/rimg.png differ
diff --git a/tests/roots/test-html_extra_path/conf.py b/tests/roots/test-html_assets/conf.py
similarity index 63%
rename from tests/roots/test-html_extra_path/conf.py
rename to tests/roots/test-html_assets/conf.py
index 53ee62197..a17e417a3 100644
--- a/tests/roots/test-html_extra_path/conf.py
+++ b/tests/roots/test-html_assets/conf.py
@@ -1,6 +1,9 @@
# -*- coding: utf-8 -*-
master_doc = 'index'
+project = 'Sphinx'
+version = '1.4.4'
+html_static_path = ['static', 'subdir']
html_extra_path = ['extra', 'subdir']
exclude_patterns = ['**/_build', '**/.htpasswd']
diff --git a/tests/roots/test-html_extra_path/extra/.htaccess b/tests/roots/test-html_assets/extra/.htaccess
similarity index 100%
rename from tests/roots/test-html_extra_path/extra/.htaccess
rename to tests/roots/test-html_assets/extra/.htaccess
diff --git a/tests/roots/test-html_extra_path/extra/.htpasswd b/tests/roots/test-html_assets/extra/.htpasswd
similarity index 100%
rename from tests/roots/test-html_extra_path/extra/.htpasswd
rename to tests/roots/test-html_assets/extra/.htpasswd
diff --git a/tests/roots/test-html_assets/extra/API.html_t b/tests/roots/test-html_assets/extra/API.html_t
new file mode 100644
index 000000000..34ecd9df1
--- /dev/null
+++ b/tests/roots/test-html_assets/extra/API.html_t
@@ -0,0 +1 @@
+{{ project }}-{{ version }}
diff --git a/tests/roots/test-html_extra_path/extra/css/style.css b/tests/roots/test-html_assets/extra/css/style.css
similarity index 100%
rename from tests/roots/test-html_extra_path/extra/css/style.css
rename to tests/roots/test-html_assets/extra/css/style.css
diff --git a/tests/roots/test-html_assets/extra/rimg.png b/tests/roots/test-html_assets/extra/rimg.png
new file mode 100644
index 000000000..fda6cd29e
Binary files /dev/null and b/tests/roots/test-html_assets/extra/rimg.png differ
diff --git a/tests/roots/test-html_extra_path/extra/API.html_t b/tests/roots/test-html_assets/extra/subdir/.htaccess
similarity index 100%
rename from tests/roots/test-html_extra_path/extra/API.html_t
rename to tests/roots/test-html_assets/extra/subdir/.htaccess
diff --git a/tests/roots/test-html_extra_path/subdir/_build/index.html b/tests/roots/test-html_assets/extra/subdir/.htpasswd
similarity index 100%
rename from tests/roots/test-html_extra_path/subdir/_build/index.html
rename to tests/roots/test-html_assets/extra/subdir/.htpasswd
diff --git a/tests/roots/test-html_extra_path/index.rst b/tests/roots/test-html_assets/index.rst
similarity index 100%
rename from tests/roots/test-html_extra_path/index.rst
rename to tests/roots/test-html_assets/index.rst
diff --git a/tests/roots/test-html_assets/static/.htaccess b/tests/roots/test-html_assets/static/.htaccess
new file mode 100644
index 000000000..e69de29bb
diff --git a/tests/roots/test-html_assets/static/.htpasswd b/tests/roots/test-html_assets/static/.htpasswd
new file mode 100644
index 000000000..e69de29bb
diff --git a/tests/roots/test-html_assets/static/API.html_t b/tests/roots/test-html_assets/static/API.html_t
new file mode 100644
index 000000000..34ecd9df1
--- /dev/null
+++ b/tests/roots/test-html_assets/static/API.html_t
@@ -0,0 +1 @@
+{{ project }}-{{ version }}
diff --git a/tests/roots/test-html_assets/static/css/style.css b/tests/roots/test-html_assets/static/css/style.css
new file mode 100644
index 000000000..e69de29bb
diff --git a/tests/roots/test-html_assets/static/rimg.png b/tests/roots/test-html_assets/static/rimg.png
new file mode 100644
index 000000000..fda6cd29e
Binary files /dev/null and b/tests/roots/test-html_assets/static/rimg.png differ
diff --git a/tests/roots/test-html_assets/static/subdir/.htaccess b/tests/roots/test-html_assets/static/subdir/.htaccess
new file mode 100644
index 000000000..e69de29bb
diff --git a/tests/roots/test-html_assets/static/subdir/.htpasswd b/tests/roots/test-html_assets/static/subdir/.htpasswd
new file mode 100644
index 000000000..e69de29bb
diff --git a/tests/roots/test-html_assets/subdir/_build/index.html b/tests/roots/test-html_assets/subdir/_build/index.html
new file mode 100644
index 000000000..e69de29bb
diff --git a/tests/roots/test-html_assets/subdir/background.png b/tests/roots/test-html_assets/subdir/background.png
new file mode 100644
index 000000000..fda6cd29e
Binary files /dev/null and b/tests/roots/test-html_assets/subdir/background.png differ
diff --git a/tests/roots/test-html_extra_path/extra/rimg.png b/tests/roots/test-html_extra_path/extra/rimg.png
deleted file mode 100644
index 1081dc143..000000000
Binary files a/tests/roots/test-html_extra_path/extra/rimg.png and /dev/null differ
diff --git a/tests/roots/test-html_extra_path/subdir/background.png b/tests/roots/test-html_extra_path/subdir/background.png
deleted file mode 100644
index 1081dc143..000000000
Binary files a/tests/roots/test-html_extra_path/subdir/background.png and /dev/null differ
diff --git a/tests/roots/test-image-glob/img.ja.png b/tests/roots/test-image-glob/img.ja.png
index 4c8f89929..a97e86d66 100644
Binary files a/tests/roots/test-image-glob/img.ja.png and b/tests/roots/test-image-glob/img.ja.png differ
diff --git a/tests/roots/test-image-glob/img.png b/tests/roots/test-image-glob/img.png
index 4c8f89929..a97e86d66 100644
Binary files a/tests/roots/test-image-glob/img.png and b/tests/roots/test-image-glob/img.png differ
diff --git a/tests/roots/test-image-glob/img.zh.png b/tests/roots/test-image-glob/img.zh.png
index 4c8f89929..a97e86d66 100644
Binary files a/tests/roots/test-image-glob/img.zh.png and b/tests/roots/test-image-glob/img.zh.png differ
diff --git a/tests/roots/test-image-glob/rimg.png b/tests/roots/test-image-glob/rimg.png
index 1081dc143..fda6cd29e 100644
Binary files a/tests/roots/test-image-glob/rimg.png and b/tests/roots/test-image-glob/rimg.png differ
diff --git a/tests/roots/test-image-glob/rimg.xx.png b/tests/roots/test-image-glob/rimg.xx.png
index 1081dc143..fda6cd29e 100644
Binary files a/tests/roots/test-image-glob/rimg.xx.png and b/tests/roots/test-image-glob/rimg.xx.png differ
diff --git a/tests/roots/test-image-glob/subdir/rimg.png b/tests/roots/test-image-glob/subdir/rimg.png
index 1081dc143..fda6cd29e 100644
Binary files a/tests/roots/test-image-glob/subdir/rimg.png and b/tests/roots/test-image-glob/subdir/rimg.png differ
diff --git a/tests/roots/test-image-glob/subdir/rimg.xx.png b/tests/roots/test-image-glob/subdir/rimg.xx.png
index 1081dc143..fda6cd29e 100644
Binary files a/tests/roots/test-image-glob/subdir/rimg.xx.png and b/tests/roots/test-image-glob/subdir/rimg.xx.png differ
diff --git a/tests/roots/test-image-glob/testimäge.png b/tests/roots/test-image-glob/testimäge.png
index 4c8f89929..a97e86d66 100644
Binary files a/tests/roots/test-image-glob/testimäge.png and b/tests/roots/test-image-glob/testimäge.png differ
diff --git a/tests/roots/test-image-in-section/pic.png b/tests/roots/test-image-in-section/pic.png
index 1081dc143..fda6cd29e 100644
Binary files a/tests/roots/test-image-in-section/pic.png and b/tests/roots/test-image-in-section/pic.png differ
diff --git a/tests/roots/test-intl/i18n.png b/tests/roots/test-intl/i18n.png
index 4c8f89929..a97e86d66 100644
Binary files a/tests/roots/test-intl/i18n.png and b/tests/roots/test-intl/i18n.png differ
diff --git a/tests/roots/test-intl/img.png b/tests/roots/test-intl/img.png
index 4c8f89929..a97e86d66 100644
Binary files a/tests/roots/test-intl/img.png and b/tests/roots/test-intl/img.png differ
diff --git a/tests/roots/test-numfig/rimg.png b/tests/roots/test-numfig/rimg.png
index 1081dc143..fda6cd29e 100644
Binary files a/tests/roots/test-numfig/rimg.png and b/tests/roots/test-numfig/rimg.png differ
diff --git a/tests/run.py b/tests/run.py
index b4bbf9822..7b750ca92 100755
--- a/tests/run.py
+++ b/tests/run.py
@@ -16,6 +16,7 @@ import sys
import traceback
from path import path
+import nose
testroot = os.path.dirname(__file__) or '.'
sys.path.insert(0, os.path.abspath(os.path.join(testroot, os.path.pardir)))
@@ -23,7 +24,7 @@ sys.path.insert(0, os.path.abspath(os.path.join(testroot, os.path.pardir)))
# check dependencies before testing
print('Checking dependencies...')
for modname in ('nose', 'mock', 'six', 'docutils', 'jinja2', 'pygments',
- 'snowballstemmer', 'babel'):
+ 'snowballstemmer', 'babel', 'html5lib'):
try:
__import__(modname)
except ImportError as err:
@@ -47,5 +48,4 @@ tempdir.makedirs()
print('Running Sphinx test suite (with Python %s)...' % sys.version.split()[0])
sys.stdout.flush()
-import nose
nose.main()
diff --git a/tests/test_api_translator.py b/tests/test_api_translator.py
index 8f0f88a1d..e8cfcb458 100644
--- a/tests/test_api_translator.py
+++ b/tests/test_api_translator.py
@@ -67,7 +67,7 @@ def test_html_with_set_translator_for_html_and_html_translator_class(
assert translator_class.__name__ == 'ConfHTMLTranslator'
-## this test break test_websupport.test_comments test. why?
+# this test break test_websupport.test_comments test. why?
# @with_app(
# buildername='dirhtml',
# srcdir=(test_roots / 'test-api-set-translator'),
diff --git a/tests/test_application.py b/tests/test_application.py
index 7bc970c9d..ad4f84870 100644
--- a/tests/test_application.py
+++ b/tests/test_application.py
@@ -14,7 +14,7 @@ from docutils import nodes
from sphinx.application import ExtensionError
from sphinx.domains import Domain
-from util import with_app, raises_msg
+from util import with_app, raises_msg, strip_escseq
@with_app()
@@ -60,14 +60,21 @@ def test_output(app, status, warning):
old_count = app._warncount
app.warn("Bad news!")
- assert warning.getvalue() == "WARNING: Bad news!\n"
+ assert strip_escseq(warning.getvalue()) == "WARNING: Bad news!\n"
assert app._warncount == old_count + 1
@with_app()
def test_extensions(app, status, warning):
app.setup_extension('shutil')
- assert warning.getvalue().startswith("WARNING: extension 'shutil'")
+ assert strip_escseq(warning.getvalue()).startswith("WARNING: extension 'shutil'")
+
+
+@with_app()
+def test_extension_in_blacklist(app, status, warning):
+ app.setup_extension('sphinxjp.themecore')
+ msg = strip_escseq(warning.getvalue())
+ assert msg.startswith("WARNING: the extension 'sphinxjp.themecore' was")
@with_app()
diff --git a/tests/test_autodoc.py b/tests/test_autodoc.py
index 183484846..747746478 100644
--- a/tests/test_autodoc.py
+++ b/tests/test_autodoc.py
@@ -11,7 +11,7 @@
"""
# "raises" imported for usage by autodoc
-from util import TestApp, Struct, raises, SkipTest
+from util import TestApp, Struct, raises, SkipTest # NOQA
from nose.tools import with_setup, eq_
from six import StringIO
@@ -22,6 +22,7 @@ from sphinx.ext.autodoc import AutoDirective, add_documenter, \
app = None
+
def setup_module():
global app
app = TestApp()
@@ -38,6 +39,7 @@ def teardown_module():
directive = options = None
+
def setup_test():
global options, directive
global processed_docstrings, processed_signatures, _warnings
@@ -73,19 +75,19 @@ def setup_test():
_warnings = []
+processed_docstrings = []
+processed_signatures = []
+
def warnfunc(msg):
_warnings.append(msg)
-processed_docstrings = []
-
def process_docstring(app, what, name, obj, options, lines):
processed_docstrings.append((what, name))
if name == 'bar':
lines.extend(['42', ''])
-processed_signatures = []
def process_signature(app, what, name, obj, options, args, retann):
processed_signatures.append((what, name))
@@ -164,25 +166,28 @@ def test_format_signature():
# test for functions
def f(a, b, c=1, **d):
pass
+
def g(a='\n'):
pass
assert formatsig('function', 'f', f, None, None) == '(a, b, c=1, **d)'
assert formatsig('function', 'f', f, 'a, b, c, d', None) == '(a, b, c, d)'
- assert formatsig('function', 'f', f, None, 'None') == \
- '(a, b, c=1, **d) -> None'
+ assert formatsig('function', 'f', f, None, 'None') == '(a, b, c=1, **d) -> None'
assert formatsig('function', 'g', g, None, None) == r"(a='\\n')"
# test for classes
class D:
pass
+
class E(object):
pass
# no signature for classes without __init__
for C in (D, E):
assert formatsig('class', 'D', C, None, None) == ''
+
class F:
def __init__(self, a, b=None):
pass
+
class G(F, object):
pass
for C in (F, G):
@@ -191,6 +196,7 @@ def test_format_signature():
# __init__ have signature at first line of docstring
directive.env.config.autoclass_content = 'both'
+
class F2:
'''some docstring for F2.'''
def __init__(self, *args, **kw):
@@ -211,8 +217,10 @@ def test_format_signature():
class H:
def foo1(self, b, *c):
pass
+
def foo2(b, *c):
pass
+
def foo3(self, d='\n'):
pass
assert formatsig('method', 'H.foo', H.foo1, None, None) == '(b, *c)'
@@ -431,6 +439,7 @@ def test_docstring_processing():
lid = app.connect('autodoc-process-docstring',
cut_lines(1, 1, ['function']))
+
def f():
"""
first line
@@ -441,6 +450,7 @@ def test_docstring_processing():
app.disconnect(lid)
lid = app.connect('autodoc-process-docstring', between('---', ['function']))
+
def g():
"""
first line
@@ -452,8 +462,9 @@ def test_docstring_processing():
assert process('function', 'g', g) == ['second line', '']
app.disconnect(lid)
- lid = app.connect('autodoc-process-docstring', between('---', ['function'],
- exclude=True))
+ lid = app.connect('autodoc-process-docstring',
+ between('---', ['function'], exclude=True))
+
def h():
"""
first line
@@ -522,7 +533,7 @@ def test_new_documenter():
def assert_result_contains(item, objtype, name, **kw):
inst = AutoDirective._registry[objtype](directive, name)
inst.generate(**kw)
- #print '\n'.join(directive.result)
+ # print '\n'.join(directive.result)
assert len(_warnings) == 0, _warnings
assert item in directive.result
del directive.result[:]
@@ -535,6 +546,7 @@ def test_new_documenter():
def test_attrgetter_using():
def assert_getter_works(objtype, name, obj, attrs=[], **kw):
getattr_spy = []
+
def special_getattr(obj, name, *defargs):
if name in attrs:
getattr_spy.append((obj, name))
@@ -556,12 +568,10 @@ def test_attrgetter_using():
options.members = ALL
options.inherited_members = False
- assert_getter_works('class', 'test_autodoc.Class', Class,
- ['meth'])
+ assert_getter_works('class', 'test_autodoc.Class', Class, ['meth'])
options.inherited_members = True
- assert_getter_works('class', 'test_autodoc.Class', Class,
- ['meth', 'inheritedmeth'])
+ assert_getter_works('class', 'test_autodoc.Class', Class, ['meth', 'inheritedmeth'])
@with_setup(setup_test)
@@ -578,7 +588,7 @@ def test_generate():
inst = AutoDirective._registry[objtype](directive, name)
inst.generate(**kw)
assert directive.result
- #print '\n'.join(directive.result)
+ # print '\n'.join(directive.result)
assert len(_warnings) == 0, _warnings
del directive.result[:]
@@ -586,13 +596,12 @@ def test_generate():
del processed_docstrings[:]
del processed_signatures[:]
assert_works(objtype, name, **kw)
- assert set(processed_docstrings) | set(processed_signatures) == \
- set(items)
+ assert set(processed_docstrings) | set(processed_signatures) == set(items)
def assert_result_contains(item, objtype, name, **kw):
inst = AutoDirective._registry[objtype](directive, name)
inst.generate(**kw)
- #print '\n'.join(directive.result)
+ # print '\n'.join(directive.result)
assert len(_warnings) == 0, _warnings
assert item in directive.result
del directive.result[:]
@@ -604,17 +613,17 @@ def test_generate():
assert len(_warnings) == 0, _warnings
items = list(reversed(items))
lineiter = iter(directive.result)
- #for line in directive.result:
- # if line.strip():
- # print repr(line)
+ # for line in directive.result:
+ # if line.strip():
+ # print repr(line)
while items:
item = items.pop()
for line in lineiter:
if line == item:
break
else: # ran out of items!
- assert False, 'item %r not found in result or not in the ' \
- ' correct order' % item
+ assert False, ('item %r not found in result or not in the '
+ ' correct order' % item)
del directive.result[:]
options.members = []
@@ -824,19 +833,19 @@ def test_generate():
'module', 'test_autodoc')
# --- generate fodder ------------
-import six, sys
-
__all__ = ['Class']
#: documentation for the integer
integer = 1
+
class CustomEx(Exception):
"""My custom exception."""
def f(self):
"""Exception method."""
+
class CustomDataDescriptor(object):
"""Descriptor class docstring."""
@@ -852,6 +861,7 @@ class CustomDataDescriptor(object):
"""Function."""
return "The Answer"
+
def _funky_classmethod(name, b, c, d, docstring=None):
"""Generates a classmethod for a class from a template by filling out
some arguments."""
@@ -863,6 +873,7 @@ def _funky_classmethod(name, b, c, d, docstring=None):
function.__doc__ = docstring
return classmethod(function)
+
class Base(object):
def inheritedmeth(self):
"""Inherited function."""
@@ -908,10 +919,10 @@ class Class(Base):
roger = _funky_classmethod("roger", 2, 3, 4)
moore = _funky_classmethod("moore", 9, 8, 7,
- docstring="moore(a, e, f) -> happiness")
+ docstring="moore(a, e, f) -> happiness")
def __init__(self, arg):
- self.inst_attr_inline = None #: an inline documented instance attr
+ self.inst_attr_inline = None #: an inline documented instance attr
#: a documented instance attribute
self.inst_attr_comment = None
self.inst_attr_string = None
@@ -928,6 +939,7 @@ class Class(Base):
class CustomDict(dict):
"""Docstring."""
+
def function(foo, *args, **kwds):
"""
Return spam.
@@ -977,14 +989,17 @@ First line of docstring
"""
return 456
+
class StrRepr(str):
def __repr__(self):
return self
+
class AttCls(object):
a1 = StrRepr('hello\nworld')
a2 = None
+
class InstAttCls(object):
"""Class with documented class and instance attributes."""
diff --git a/tests/test_autodoc_py35.py b/tests/test_autodoc_py35.py
index 9bacc3d65..43cda2260 100644
--- a/tests/test_autodoc_py35.py
+++ b/tests/test_autodoc_py35.py
@@ -11,6 +11,8 @@
"""
# "raises" imported for usage by autodoc
+import six
+import sys
from util import TestApp, Struct, raises, SkipTest
from nose.tools import with_setup, eq_
@@ -22,6 +24,7 @@ from sphinx.ext.autodoc import AutoDirective, add_documenter, \
app = None
+
def setup_module():
global app
app = TestApp()
@@ -38,6 +41,7 @@ def teardown_module():
directive = options = None
+
def setup_test():
global options, directive
global processed_docstrings, processed_signatures, _warnings
@@ -73,19 +77,19 @@ def setup_test():
_warnings = []
+processed_docstrings = []
+processed_signatures = []
+
def warnfunc(msg):
_warnings.append(msg)
-processed_docstrings = []
-
def process_docstring(app, what, name, obj, options, lines):
processed_docstrings.append((what, name))
if name == 'bar':
lines.extend(['42', ''])
-processed_signatures = []
def process_signature(app, what, name, obj, options, args, retann):
processed_signatures.append((what, name))
@@ -116,7 +120,7 @@ def test_generate():
inst = AutoDirective._registry[objtype](directive, name)
inst.generate(**kw)
assert directive.result
- #print '\n'.join(directive.result)
+ # print '\n'.join(directive.result)
assert len(_warnings) == 0, _warnings
del directive.result[:]
@@ -124,13 +128,12 @@ def test_generate():
del processed_docstrings[:]
del processed_signatures[:]
assert_works(objtype, name, **kw)
- assert set(processed_docstrings) | set(processed_signatures) == \
- set(items)
+ assert set(processed_docstrings) | set(processed_signatures) == set(items)
def assert_result_contains(item, objtype, name, **kw):
inst = AutoDirective._registry[objtype](directive, name)
inst.generate(**kw)
- #print '\n'.join(directive.result)
+ # print '\n'.join(directive.result)
assert len(_warnings) == 0, _warnings
assert item in directive.result
del directive.result[:]
@@ -142,17 +145,17 @@ def test_generate():
assert len(_warnings) == 0, _warnings
items = list(reversed(items))
lineiter = iter(directive.result)
- #for line in directive.result:
- # if line.strip():
- # print repr(line)
+ # for line in directive.result:
+ # if line.strip():
+ # print repr(line)
while items:
item = items.pop()
for line in lineiter:
if line == item:
break
else: # ran out of items!
- assert False, 'item %r not found in result or not in the ' \
- ' correct order' % item
+ assert False, ('item %r not found in result or not in the '
+ ' correct order' % item)
del directive.result[:]
options.members = []
@@ -233,19 +236,19 @@ def test_generate():
# --- generate fodder ------------
-import six, sys
-
__all__ = ['Class']
#: documentation for the integer
integer = 1
+
class CustomEx(Exception):
"""My custom exception."""
def f(self):
"""Exception method."""
+
class CustomDataDescriptor(object):
"""Descriptor class docstring."""
@@ -261,6 +264,7 @@ class CustomDataDescriptor(object):
"""Function."""
return "The Answer"
+
def _funky_classmethod(name, b, c, d, docstring=None):
"""Generates a classmethod for a class from a template by filling out
some arguments."""
@@ -272,6 +276,7 @@ def _funky_classmethod(name, b, c, d, docstring=None):
function.__doc__ = docstring
return classmethod(function)
+
class Base(object):
def inheritedmeth(self):
"""Inherited function."""
@@ -322,10 +327,10 @@ class Class(Base):
roger = _funky_classmethod("roger", 2, 3, 4)
moore = _funky_classmethod("moore", 9, 8, 7,
- docstring="moore(a, e, f) -> happiness")
+ docstring="moore(a, e, f) -> happiness")
def __init__(self, arg):
- self.inst_attr_inline = None #: an inline documented instance attr
+ self.inst_attr_inline = None #: an inline documented instance attr
#: a documented instance attribute
self.inst_attr_comment = None
self.inst_attr_string = None
diff --git a/tests/test_build.py b/tests/test_build.py
index 1c0d55e1b..95910f60b 100644
--- a/tests/test_build.py
+++ b/tests/test_build.py
@@ -15,6 +15,7 @@ import pickle
from docutils import nodes
from textwrap import dedent
from sphinx.errors import SphinxError
+import sphinx.builders.linkcheck
from util import with_app, rootdir, tempdir, SkipTest, TestApp
@@ -31,7 +32,6 @@ class MockOpener(object):
url = req.url
return result()
-import sphinx.builders.linkcheck
sphinx.builders.linkcheck.opener = MockOpener()
diff --git a/tests/test_build_applehelp.py b/tests/test_build_applehelp.py
index 66b24e1bd..de2b5d032 100644
--- a/tests/test_build_applehelp.py
+++ b/tests/test_build_applehelp.py
@@ -11,7 +11,6 @@
:license: BSD, see LICENSE for details.
"""
-import os
import plistlib
from util import with_app
diff --git a/tests/test_build_gettext.py b/tests/test_build_gettext.py
index 22fec975e..2dc62b838 100644
--- a/tests/test_build_gettext.py
+++ b/tests/test_build_gettext.py
@@ -114,7 +114,7 @@ def test_gettext_index_entries(app, status, warning):
"Exception",
"Statement",
"Builtin",
- ]
+ ]
for expect in expected_msgids:
assert expect in msgids
msgids.remove(expect)
diff --git a/tests/test_build_html.py b/tests/test_build_html.py
index 87ea8c595..aac5757d9 100644
--- a/tests/test_build_html.py
+++ b/tests/test_build_html.py
@@ -13,34 +13,37 @@ import os
import re
from six import PY3, iteritems
-from six.moves import html_entities
from sphinx import __display_version__
-from util import remove_unicode_literals, gen_with_app, with_app
-from etree13 import ElementTree as ET
+from util import remove_unicode_literals, gen_with_app, with_app, strip_escseq
+from etree13 import ElementTree
+from html5lib import getTreeBuilder, HTMLParser
+TREE_BUILDER = getTreeBuilder('etree', implementation=ElementTree)
+HTML_PARSER = HTMLParser(TREE_BUILDER, namespaceHTMLElements=False)
+
ENV_WARNINGS = """\
(%(root)s/autodoc_fodder.py:docstring of autodoc_fodder\\.MarkupError:2: \
WARNING: Explicit markup ends without a blank line; unexpected \
unindent\\.\\n?
-)?%(root)s/images.txt:9: WARNING: image file not readable: foo.png
-%(root)s/images.txt:23: WARNING: nonlocal image URI found: \
+)?%(root)s/images.txt:\\d+: WARNING: image file not readable: foo.png
+%(root)s/images.txt:\\d+3: WARNING: nonlocal image URI found: \
http://www.python.org/logo.png
-%(root)s/includes.txt:\\d*: WARNING: Encoding 'utf-8-sig' used for \
+%(root)s/includes.txt:\\d+: WARNING: Encoding 'utf-8-sig' used for \
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/markup.txt:373: WARNING: invalid single index entry u'')?
-(%(root)s/undecodable.txt:3: WARNING: undecodable source characters, replacing \
+%(root)s/includes.txt:\\d+: WARNING: download file not readable: .*?nonexisting.png
+(%(root)s/markup.txt:\\d+: WARNING: invalid single index entry u'')?
+(%(root)s/undecodable.txt:\\d+: WARNING: undecodable source characters, replacing \
with "\\?": b?'here: >>>(\\\\|/)xbb<<<'
)?"""
HTML_WARNINGS = ENV_WARNINGS + """\
-%(root)s/images.txt:20: WARNING: no matching candidate for image URI u'foo.\\*'
-%(root)s/markup.txt:285: WARNING: Could not lex literal_block as "c". Highlighting skipped.
-%(root)s/footnote.txt:60: WARNING: citation not found: missing
-%(root)s/markup.txt:164: WARNING: unknown option: &option
+%(root)s/images.txt:\\d+: WARNING: no matching candidate for image URI u'foo.\\*'
+%(root)s/markup.txt:\\d+: WARNING: Could not lex literal_block as "c". Highlighting skipped.
+%(root)s/footnote.txt:\\d+: WARNING: citation not found: missing
+%(root)s/markup.txt:\\d+: WARNING: unknown option: &option
"""
if PY3:
@@ -65,6 +68,7 @@ HTML_XPATH = {
(".//img[@src='_images/img1.png']", ''),
(".//img[@src='_images/simg.png']", ''),
(".//img[@src='_images/svgimg.svg']", ''),
+ (".//a[@href='_sources/images.txt']", ''),
],
'subdir/images.html': [
(".//img[@src='../_images/img1.png']", ''),
@@ -174,7 +178,7 @@ HTML_XPATH = {
# ``seealso`` directive
(".//div/p[@class='first admonition-title']", 'See also'),
# a ``hlist`` directive
- (".//table[@class='hlist']/tr/td/ul/li", '^This$'),
+ (".//table[@class='hlist']/tbody/tr/td/ul/li", '^This$'),
# a ``centered`` directive
(".//p[@class='centered']/strong", 'LICENSE'),
# a glossary
@@ -315,25 +319,11 @@ HTML_XPATH = {
],
'otherext.html': [
(".//h1", "Generated section"),
+ (".//a[@href='_sources/otherext.foo.txt']", ''),
]
}
-class NslessParser(ET.XMLParser):
- """XMLParser that throws away namespaces in tag names."""
-
- def _fixname(self, key):
- try:
- return self._names[key]
- except KeyError:
- name = key
- br = name.find('}')
- if br > 0:
- name = name[br+1:]
- self._names[key] = name = self._fixtext(name)
- return name
-
-
def check_xpath(etree, fname, path, check, be_found=True):
nodes = list(etree.findall(path))
if check is None:
@@ -396,7 +386,7 @@ def check_extra_entries(outdir):
tags=['testtag'])
def test_html_output(app, status, warning):
app.builder.build_all()
- html_warnings = warning.getvalue().replace(os.sep, '/')
+ html_warnings = strip_escseq(warning.getvalue().replace(os.sep, '/'))
html_warnings_exp = HTML_WARNINGS % {
'root': re.escape(app.srcdir.replace(os.sep, '/'))}
assert re.match(html_warnings_exp + '$', html_warnings), \
@@ -405,10 +395,8 @@ def test_html_output(app, status, warning):
'--- Got:\n' + html_warnings
for fname, paths in iteritems(HTML_XPATH):
- parser = NslessParser()
- parser.entity.update(html_entities.entitydefs)
with (app.outdir / fname).open('rb') as fp:
- etree = ET.parse(fp, parser)
+ etree = HTML_PARSER.parse(fp)
for path, check in paths:
yield check_xpath, etree, fname, path, check
@@ -455,10 +443,8 @@ def test_tocdepth(app, status, warning):
}
for fname, paths in iteritems(expects):
- parser = NslessParser()
- parser.entity.update(html_entities.entitydefs)
with (app.outdir / fname).open('rb') as fp:
- etree = ET.parse(fp, parser)
+ etree = HTML_PARSER.parse(fp)
for xpath, check, be_found in paths:
yield check_xpath, etree, fname, xpath, check, be_found
@@ -497,10 +483,8 @@ def test_tocdepth_singlehtml(app, status, warning):
}
for fname, paths in iteritems(expects):
- parser = NslessParser()
- parser.entity.update(html_entities.entitydefs)
with (app.outdir / fname).open('rb') as fp:
- etree = ET.parse(fp, parser)
+ etree = HTML_PARSER.parse(fp)
for xpath, check, be_found in paths:
yield check_xpath, etree, fname, xpath, check, be_found
@@ -553,10 +537,8 @@ def test_numfig_disabled(app, status, warning):
}
for fname, paths in iteritems(expects):
- parser = NslessParser()
- parser.entity.update(html_entities.entitydefs)
with (app.outdir / fname).open('rb') as fp:
- etree = ET.parse(fp, parser)
+ etree = HTML_PARSER.parse(fp)
for xpath, check, be_found in paths:
yield check_xpath, etree, fname, xpath, check, be_found
@@ -596,7 +578,7 @@ def test_numfig_without_numbered_toctree(app, status, warning):
(".//li/a/span", '^Table:6$', True),
(".//li/a/span", '^Listing 9$', True),
(".//li/a/span", '^Code-6$', True),
- ],
+ ],
'foo.html': [
(".//div[@class='figure']/p[@class='caption']/"
"span[@class='caption-number']", '^Fig. 1 $', True),
@@ -622,7 +604,7 @@ def test_numfig_without_numbered_toctree(app, status, warning):
"span[@class='caption-number']", '^Listing 3 $', True),
(".//div[@class='code-block-caption']/"
"span[@class='caption-number']", '^Listing 4 $', True),
- ],
+ ],
'bar.html': [
(".//div[@class='figure']/p[@class='caption']/"
"span[@class='caption-number']", '^Fig. 5 $', True),
@@ -654,10 +636,8 @@ def test_numfig_without_numbered_toctree(app, status, warning):
}
for fname, paths in iteritems(expects):
- parser = NslessParser()
- parser.entity.update(html_entities.entitydefs)
with (app.outdir / fname).open('rb') as fp:
- etree = ET.parse(fp, parser)
+ etree = HTML_PARSER.parse(fp)
for xpath, check, be_found in paths:
yield check_xpath, etree, fname, xpath, check, be_found
@@ -693,7 +673,7 @@ def test_numfig_with_numbered_toctree(app, status, warning):
(".//li/a/span", '^Table:2.2$', True),
(".//li/a/span", '^Listing 1$', True),
(".//li/a/span", '^Code-2.2$', True),
- ],
+ ],
'foo.html': [
(".//div[@class='figure']/p[@class='caption']/"
"span[@class='caption-number']", '^Fig. 1.1 $', True),
@@ -719,7 +699,7 @@ def test_numfig_with_numbered_toctree(app, status, warning):
"span[@class='caption-number']", '^Listing 1.3 $', True),
(".//div[@class='code-block-caption']/"
"span[@class='caption-number']", '^Listing 1.4 $', True),
- ],
+ ],
'bar.html': [
(".//div[@class='figure']/p[@class='caption']/"
"span[@class='caption-number']", '^Fig. 2.1 $', True),
@@ -751,10 +731,8 @@ def test_numfig_with_numbered_toctree(app, status, warning):
}
for fname, paths in iteritems(expects):
- parser = NslessParser()
- parser.entity.update(html_entities.entitydefs)
with (app.outdir / fname).open('rb') as fp:
- etree = ET.parse(fp, parser)
+ etree = HTML_PARSER.parse(fp)
for xpath, check, be_found in paths:
yield check_xpath, etree, fname, xpath, check, be_found
@@ -793,7 +771,7 @@ def test_numfig_with_prefix(app, status, warning):
(".//li/a/span", '^Table:2.2$', True),
(".//li/a/span", '^Code-1$', True),
(".//li/a/span", '^Code-2.2$', True),
- ],
+ ],
'foo.html': [
(".//div[@class='figure']/p[@class='caption']/"
"span[@class='caption-number']", '^Figure:1.1 $', True),
@@ -819,7 +797,7 @@ def test_numfig_with_prefix(app, status, warning):
"span[@class='caption-number']", '^Code-1.3 $', True),
(".//div[@class='code-block-caption']/"
"span[@class='caption-number']", '^Code-1.4 $', True),
- ],
+ ],
'bar.html': [
(".//div[@class='figure']/p[@class='caption']/"
"span[@class='caption-number']", '^Figure:2.1 $', True),
@@ -851,10 +829,8 @@ def test_numfig_with_prefix(app, status, warning):
}
for fname, paths in iteritems(expects):
- parser = NslessParser()
- parser.entity.update(html_entities.entitydefs)
with (app.outdir / fname).open('rb') as fp:
- etree = ET.parse(fp, parser)
+ etree = HTML_PARSER.parse(fp)
for xpath, check, be_found in paths:
yield check_xpath, etree, fname, xpath, check, be_found
@@ -890,7 +866,7 @@ def test_numfig_with_secnum_depth(app, status, warning):
(".//li/a/span", '^Table:2.1.2$', True),
(".//li/a/span", '^Listing 1$', True),
(".//li/a/span", '^Code-2.1.2$', True),
- ],
+ ],
'foo.html': [
(".//div[@class='figure']/p[@class='caption']/"
"span[@class='caption-number']", '^Fig. 1.1 $', True),
@@ -916,7 +892,7 @@ def test_numfig_with_secnum_depth(app, status, warning):
"span[@class='caption-number']", '^Listing 1.1.2 $', True),
(".//div[@class='code-block-caption']/"
"span[@class='caption-number']", '^Listing 1.2.1 $', True),
- ],
+ ],
'bar.html': [
(".//div[@class='figure']/p[@class='caption']/"
"span[@class='caption-number']", '^Fig. 2.1.1 $', True),
@@ -948,10 +924,8 @@ def test_numfig_with_secnum_depth(app, status, warning):
}
for fname, paths in iteritems(expects):
- parser = NslessParser()
- parser.entity.update(html_entities.entitydefs)
with (app.outdir / fname).open('rb') as fp:
- etree = ET.parse(fp, parser)
+ etree = HTML_PARSER.parse(fp)
for xpath, check, be_found in paths:
yield check_xpath, etree, fname, xpath, check, be_found
@@ -980,10 +954,8 @@ def test_enumerable_node(app, status, warning):
}
for fname, paths in iteritems(expects):
- parser = NslessParser()
- parser.entity.update(html_entities.entitydefs)
with (app.outdir / fname).open('rb') as fp:
- etree = ET.parse(fp, parser)
+ etree = HTML_PARSER.parse(fp)
for xpath, check, be_found in paths:
yield check_xpath, etree, fname, xpath, check, be_found
@@ -996,18 +968,32 @@ def test_jsmath(app, status, warning):
assert '\na^2 + b^2 = c^2
' in content
assert '\n\\begin{split}a + 1 < b\\end{split}
' in content
- assert ('(1)\n'
- 'e^{i\\pi} = 1
' in content)
+ assert (u'(1)'
+ u'\ne^{i\\pi} = 1
' in content)
assert ('(2)\n'
'e^{ix} = \\cos x + i\\sin x
' in content)
assert '\nn \\in \\mathbb N
' in content
assert '\na + 1 < b
' in content
-@with_app(buildername='html', testroot='html_extra_path')
-def test_html_extra_path(app, status, warning):
+@with_app(buildername='html', testroot='html_assets')
+def test_html_assets(app, status, warning):
app.builder.build_all()
+ # html_static_path
+ assert not (app.outdir / '_static' / '.htaccess').exists()
+ assert not (app.outdir / '_static' / '.htpasswd').exists()
+ assert (app.outdir / '_static' / 'API.html').exists()
+ assert (app.outdir / '_static' / 'API.html').text() == 'Sphinx-1.4.4'
+ assert (app.outdir / '_static' / 'css/style.css').exists()
+ assert (app.outdir / '_static' / 'rimg.png').exists()
+ assert not (app.outdir / '_static' / '_build/index.html').exists()
+ assert (app.outdir / '_static' / 'background.png').exists()
+ assert not (app.outdir / '_static' / 'subdir' / '.htaccess').exists()
+ assert not (app.outdir / '_static' / 'subdir' / '.htpasswd').exists()
+
+ # html_extra_path
assert (app.outdir / '.htaccess').exists()
assert not (app.outdir / '.htpasswd').exists()
assert (app.outdir / 'API.html_t').exists()
@@ -1015,3 +1001,17 @@ def test_html_extra_path(app, status, warning):
assert (app.outdir / 'rimg.png').exists()
assert not (app.outdir / '_build/index.html').exists()
assert (app.outdir / 'background.png').exists()
+ assert (app.outdir / 'subdir' / '.htaccess').exists()
+ assert not (app.outdir / 'subdir' / '.htpasswd').exists()
+
+
+@with_app(buildername='html', confoverrides={'html_sourcelink_suffix': ''})
+def test_html_sourcelink_suffix(app, status, warning):
+ app.builder.build_all()
+ content_otherext = (app.outdir / 'otherext.html').text()
+ content_images = (app.outdir / 'images.html').text()
+
+ assert ' g)', 'f', '1f')
+
def test_member_definitions():
check('member', ' const std::string & name = 42',
@@ -397,11 +402,11 @@ def test_templates():
"RK18c_string_view_baseIK4Char6TraitsE")
-#def test_print():
-# # used for getting all the ids out for checking
-# for a in ids:
-# print(a)
-# raise DefinitionError("")
+# def test_print():
+# # used for getting all the ids out for checking
+# for a in ids:
+# print(a)
+# raise DefinitionError("")
@with_app(testroot='domain-cpp', confoverrides={'add_function_parentheses': True})
diff --git a/tests/test_domain_rst.py b/tests/test_domain_rst.py
index c1f8c6caa..0d6dab5d8 100644
--- a/tests/test_domain_rst.py
+++ b/tests/test_domain_rst.py
@@ -11,8 +11,8 @@
from sphinx.domains.rst import parse_directive
-def test_parse_directive():
+def test_parse_directive():
s = parse_directive(u' foö ')
assert s == (u'foö', '')
diff --git a/tests/test_ext_githubpages.py b/tests/test_ext_githubpages.py
index 65276df7a..f74ed5315 100644
--- a/tests/test_ext_githubpages.py
+++ b/tests/test_ext_githubpages.py
@@ -9,8 +9,6 @@
:license: BSD, see LICENSE for details.
"""
-import re
-
from util import with_app
diff --git a/tests/test_ext_ifconfig.py b/tests/test_ext_ifconfig.py
index 56e31acae..4ae043f7f 100644
--- a/tests/test_ext_ifconfig.py
+++ b/tests/test_ext_ifconfig.py
@@ -9,8 +9,6 @@
:license: BSD, see LICENSE for details.
"""
-import re
-
from util import with_app
diff --git a/tests/test_ext_intersphinx.py b/tests/test_ext_intersphinx.py
index 13b5d1aff..90987a3ef 100644
--- a/tests/test_ext_intersphinx.py
+++ b/tests/test_ext_intersphinx.py
@@ -43,6 +43,7 @@ module2 py:module 0 foo.html#module-$ -
module1.func py:function 1 sub/foo.html#$ -
CFunc c:function 2 cfunc.html#CFunc -
a term std:term -1 glossary.html#term-a-term -
+a term including:colon std:term -1 glossary.html#term-a-term-including-colon -
'''.encode('utf-8'))
@@ -78,6 +79,8 @@ def test_read_inventory_v2():
assert invdata1['c:function']['CFunc'][2] == '/util/cfunc.html#CFunc'
assert invdata1['std:term']['a term'][2] == \
'/util/glossary.html#term-a-term'
+ assert invdata1['std:term']['a term including:colon'][2] == \
+ '/util/glossary.html#term-a-term-including-colon'
@with_app()
diff --git a/tests/test_ext_math.py b/tests/test_ext_math.py
index 87219c294..4b168b40c 100644
--- a/tests/test_ext_math.py
+++ b/tests/test_ext_math.py
@@ -28,6 +28,7 @@ def test_imgmath_png(app, status, warning):
'\s*alt="a\^2\+b\^2=c\^2"/>\s*
\s*')
assert re.search(html, content, re.S)
+
@with_app('html', testroot='ext-math',
confoverrides={'extensions': ['sphinx.ext.imgmath'],
'imgmath_image_format': 'svg'})
@@ -43,6 +44,7 @@ def test_imgmath_svg(app, status, warning):
'\s*alt="a\^2\+b\^2=c\^2"/>\s*\s*')
assert re.search(html, content, re.S)
+
@with_app('html', testroot='ext-math',
confoverrides={'extensions': ['sphinx.ext.mathjax']})
def test_mathjax_align(app, status, warning):
@@ -54,6 +56,7 @@ def test_mathjax_align(app, status, warning):
r'V \&= \\frac\{4\}\{3\} \\pi r\^3\\end\{aligned\}\\end\{align\} \\\]')
assert re.search(html, content, re.S)
+
@with_app('html', testroot='ext-math',
confoverrides={'math_number_all': True,
'extensions': ['sphinx.ext.mathjax']})
@@ -65,6 +68,7 @@ def test_math_number_all_mathjax(app, status, warning):
r'\(1\)\\\[a\^2\+b\^2=c\^2\\\]')
assert re.search(html, content, re.S)
+
@with_app('latex', testroot='ext-math',
confoverrides={'extensions': ['sphinx.ext.mathjax']})
def test_math_number_all_latex(app, status, warning):
diff --git a/tests/test_ext_napoleon_docstring.py b/tests/test_ext_napoleon_docstring.py
index ece55ebe4..b6f16b26b 100644
--- a/tests/test_ext_napoleon_docstring.py
+++ b/tests/test_ext_napoleon_docstring.py
@@ -329,7 +329,9 @@ Returns:
codecode
"""
expected = """
-:returns: foo::
+:returns:
+
+ foo::
codecode
codecode
diff --git a/tests/test_highlighting.py b/tests/test_highlighting.py
index 176565f62..328abdf31 100644
--- a/tests/test_highlighting.py
+++ b/tests/test_highlighting.py
@@ -65,7 +65,7 @@ def test_detect_interactive():
def test_lexer_options():
bridge = PygmentsBridge('html')
- ret = bridge.highlight_block('//comment', 'php', opts={'startinline' : True})
+ ret = bridge.highlight_block('//comment', 'php', opts={'startinline': True})
assert '//comment' in ret
diff --git a/tests/test_intl.py b/tests/test_intl.py
index 47a51589d..b31f1678b 100644
--- a/tests/test_intl.py
+++ b/tests/test_intl.py
@@ -680,7 +680,7 @@ def test_xml_builder(app, status, warning):
def test_additional_targets_should_not_be_translated(app, status, warning):
app.builder.build_all()
- ## literalblock.txt
+ # [literalblock.txt]
result = (app.outdir / 'literalblock.html').text(encoding='utf-8')
# title should be translated
@@ -707,7 +707,7 @@ def test_additional_targets_should_not_be_translated(app, status, warning):
"""# sys importing""")
yield assert_count(expected_expr, result, 1)
- ## raw.txt
+ # [raw.txt]
result = (app.outdir / 'raw.html').text(encoding='utf-8')
@@ -715,7 +715,7 @@ def test_additional_targets_should_not_be_translated(app, status, warning):
expected_expr = """"""
yield assert_count(expected_expr, result, 1)
- ## figure.txt
+ # [figure.txt]
result = (app.outdir / 'figure.html').text(encoding='utf-8')
@@ -741,7 +741,7 @@ def test_additional_targets_should_not_be_translated(app, status, warning):
def test_additional_targets_should_be_translated(app, status, warning):
app.builder.build_all()
- ## literalblock.txt
+ # [literalblock.txt]
result = (app.outdir / 'literalblock.html').text(encoding='utf-8')
# title should be translated
@@ -768,7 +768,7 @@ def test_additional_targets_should_be_translated(app, status, warning):
"""# SYS IMPORTING""")
yield assert_count(expected_expr, result, 1)
- ## raw.txt
+ # [raw.txt]
result = (app.outdir / 'raw.html').text(encoding='utf-8')
@@ -776,7 +776,7 @@ def test_additional_targets_should_be_translated(app, status, warning):
expected_expr = """"""
yield assert_count(expected_expr, result, 1)
- ## figure.txt
+ # [figure.txt]
result = (app.outdir / 'figure.html').text(encoding='utf-8')
diff --git a/tests/test_markup.py b/tests/test_markup.py
index d12138692..102235e1d 100644
--- a/tests/test_markup.py
+++ b/tests/test_markup.py
@@ -41,6 +41,7 @@ def setup_module():
def teardown_module():
app.cleanup()
+
# since we're not resolving the markup afterwards, these nodes may remain
class ForgivingTranslator:
def visit_pending_xref(self, node):
@@ -74,11 +75,12 @@ def verify_re(rst, html_expected, latex_expected):
if latex_expected:
latex_translator = ForgivingLaTeXTranslator(document, app.builder)
- latex_translator.first_document = -1 # don't write \begin{document}
+ latex_translator.first_document = -1 # don't write \begin{document}
document.walkabout(latex_translator)
latex_translated = ''.join(latex_translator.body).strip()
assert re.match(latex_expected, latex_translated), 'from ' + repr(rst)
+
def verify(rst, html_expected, latex_expected):
if html_expected:
html_expected = re.escape(html_expected) + '$'
@@ -91,32 +93,32 @@ def test_inline():
# correct interpretation of code with whitespace
_html = (''
'code sample
')
- yield verify_re, '``code sample``', _html, r'\\code{code sample}'
- yield verify_re, ':samp:`code sample`', _html, r'\\code{code sample}'
+ yield verify_re, '``code sample``', _html, r'\\sphinxcode{code sample}'
+ yield verify_re, ':samp:`code sample`', _html, r'\\sphinxcode{code sample}'
# interpolation of braces in samp and file roles (HTML only)
yield (verify, ':samp:`a{b}c`',
'a'
'b'
'c
',
- '\\code{a\\emph{b}c}')
+ '\\sphinxcode{a\\sphinxstyleemphasis{b}c}')
# interpolation of arrows in menuselection
yield (verify, ':menuselection:`a --> b`',
u'',
- '\\menuselection{a \\(\\rightarrow\\) b}')
+ '\\sphinxmenuselection{a \\(\\rightarrow\\) b}')
# interpolation of ampersands in guilabel/menuselection
yield (verify, ':guilabel:`&Foo -&&- &Bar`',
u'Foo '
'-&- Bar
',
- r'\menuselection{\accelerator{F}oo -\&- \accelerator{B}ar}')
+ r'\sphinxmenuselection{\sphinxaccelerator{F}oo -\&- \sphinxaccelerator{B}ar}')
# non-interpolation of dashes in option role
yield (verify_re, ':option:`--with-option`',
''
'--with-option
$',
- r'\\code{-{-}with-option}$')
+ r'\\sphinxcode{-{-}with-option}$')
# verify smarty-pants quotes
yield verify, '"John"', '“John”
', "``John''"
@@ -124,12 +126,13 @@ def test_inline():
yield (verify, '``"John"``',
''
'"John"
',
- '\\code{"John"}')
+ '\\sphinxcode{"John"}')
# verify classes for inline roles
yield (verify, ':manpage:`mp(1)`',
'mp(1)
',
- '\\emph{\\texttt{mp(1)}}')
+ '\\sphinxstyleliteralemphasis{mp(1)}')
+
def test_latex_escaping():
# correct escaping in normal mode
@@ -137,9 +140,9 @@ def test_latex_escaping():
r'\(\Gamma\)\textbackslash{}\(\infty\)\$')
# in verbatim code fragments
yield (verify, u'::\n\n @Γ\\∞${}', None,
- u'\\begin{Verbatim}[commandchars=\\\\\\{\\}]\n'
+ u'\\begin{sphinxVerbatim}[commandchars=\\\\\\{\\}]\n'
u'@\\(\\Gamma\\)\\PYGZbs{}\\(\\infty\\)\\PYGZdl{}\\PYGZob{}\\PYGZcb{}\n'
- u'\\end{Verbatim}')
+ u'\\end{sphinxVerbatim}')
# in URIs
yield (verify_re, u'`test `_', None,
r'\\href{http://example.com/~me/}{test}.*')
diff --git a/tests/test_search.py b/tests/test_search.py
index 3edcf06e8..63d78df46 100644
--- a/tests/test_search.py
+++ b/tests/test_search.py
@@ -21,6 +21,7 @@ from util import with_app
settings = parser = None
+
def setup_module():
global settings, parser
optparser = frontend.OptionParser(components=(rst.Parser,))
@@ -45,13 +46,14 @@ FILE_CONTENTS = '''\
test that non-comments are indexed: fermion
'''
+
def test_wordcollector():
doc = utils.new_document(b'test data', settings)
doc['file'] = 'dummy'
parser.parse(FILE_CONTENTS, doc)
ix = IndexBuilder(None, 'en', {}, None)
- ix.feed('filename', 'title', doc)
+ ix.feed('docname', 'filename', 'title', doc)
assert 'boson' not in ix._mapping
assert 'fermion' in ix._mapping
diff --git a/tests/test_searchadapters.py b/tests/test_searchadapters.py
index f6a389fea..e8c5c9364 100644
--- a/tests/test_searchadapters.py
+++ b/tests/test_searchadapters.py
@@ -41,7 +41,7 @@ def search_adapter_helper(adapter):
# Make sure documents are properly updated by the search adapter.
s.init_indexing(changed=['markup'])
- s.add_document(u'markup', u'title', u'SomeLongRandomWord')
+ s.add_document(u'markup', u'filename', u'title', u'SomeLongRandomWord')
s.finish_indexing()
# Now a search for "Epigraph" should return zero results.
results = s.query(u'Epigraph')
diff --git a/tests/test_setup_command.py b/tests/test_setup_command.py
index 77c9ade46..c92f6220f 100644
--- a/tests/test_setup_command.py
+++ b/tests/test_setup_command.py
@@ -108,3 +108,25 @@ def test_build_sphinx_return_nonzero_status(pkgroot, proc):
print(out)
print(err)
assert proc.returncode != 0, 'expect non-zero status for setup.py'
+
+
+@with_setup_command(root)
+def test_build_sphinx_warning_return_zero_status(pkgroot, proc):
+ srcdir = (pkgroot / 'doc')
+ (srcdir / 'contents.txt').write_text(
+ 'See :ref:`unexisting-reference-label`')
+ out, err = proc.communicate()
+ print(out)
+ print(err)
+ assert proc.returncode == 0
+
+
+@with_setup_command(root, '--warning-is-error')
+def test_build_sphinx_warning_is_error_return_nonzero_status(pkgroot, proc):
+ srcdir = (pkgroot / 'doc')
+ (srcdir / 'contents.txt').write_text(
+ 'See :ref:`unexisting-reference-label`')
+ out, err = proc.communicate()
+ print(out)
+ print(err)
+ assert proc.returncode != 0, 'expect non-zero status for setup.py'
diff --git a/tests/test_util_fileutil.py b/tests/test_util_fileutil.py
new file mode 100644
index 000000000..a56543614
--- /dev/null
+++ b/tests/test_util_fileutil.py
@@ -0,0 +1,114 @@
+# -*- coding: utf-8 -*-
+"""
+ test_util_fileutil
+ ~~~~~~~~~~~~~~~~~~
+
+ Tests sphinx.util.fileutil functions.
+
+ :copyright: Copyright 2007-2016 by the Sphinx team, see AUTHORS.
+ :license: BSD, see LICENSE for details.
+"""
+from sphinx.util.fileutil import copy_asset, copy_asset_file
+from sphinx.jinja2glue import BuiltinTemplateLoader
+
+from mock import Mock
+from util import with_tempdir
+
+
+class DummyTemplateLoader(BuiltinTemplateLoader):
+ def __init__(self):
+ BuiltinTemplateLoader.__init__(self)
+ builder = Mock()
+ builder.config.templates_path = []
+ builder.app.translater = None
+ self.init(builder)
+
+
+@with_tempdir
+def test_copy_asset_file(tmpdir):
+ renderer = DummyTemplateLoader()
+
+ # copy normal file
+ src = (tmpdir / 'asset.txt')
+ src.write_text('# test data')
+ dest = (tmpdir / 'output.txt')
+
+ copy_asset_file(src, dest)
+ assert dest.exists()
+ assert src.text() == dest.text()
+
+ # copy template file
+ src = (tmpdir / 'asset.txt_t')
+ src.write_text('# {{var1}} data')
+ dest = (tmpdir / 'output.txt_t')
+
+ copy_asset_file(src, dest, {'var1': 'template'}, renderer)
+ assert not dest.exists()
+ assert (tmpdir / 'output.txt').exists()
+ assert (tmpdir / 'output.txt').text() == '# template data'
+
+ # copy template file to subdir
+ src = (tmpdir / 'asset.txt_t')
+ src.write_text('# {{var1}} data')
+ subdir1 = (tmpdir / 'subdir')
+ subdir1.makedirs()
+
+ copy_asset_file(src, subdir1, {'var1': 'template'}, renderer)
+ assert (subdir1 / 'asset.txt').exists()
+ assert (subdir1 / 'asset.txt').text() == '# template data'
+
+ # copy template file without context
+ src = (tmpdir / 'asset.txt_t')
+ subdir2 = (tmpdir / 'subdir2')
+ subdir2.makedirs()
+
+ copy_asset_file(src, subdir2)
+ assert not (subdir2 / 'asset.txt').exists()
+ assert (subdir2 / 'asset.txt_t').exists()
+ assert (subdir2 / 'asset.txt_t').text() == '# {{var1}} data'
+
+
+@with_tempdir
+def test_copy_asset(tmpdir):
+ renderer = DummyTemplateLoader()
+
+ # prepare source files
+ source = (tmpdir / 'source')
+ source.makedirs()
+ (source / 'index.rst').write_text('index.rst')
+ (source / 'foo.rst_t').write_text('{{var1}}.rst')
+ (source / '_static').makedirs()
+ (source / '_static' / 'basic.css').write_text('basic.css')
+ (source / '_templates').makedirs()
+ (source / '_templates' / 'layout.html').write_text('layout.html')
+ (source / '_templates' / 'sidebar.html_t').write_text('sidebar: {{var2}}')
+
+ # copy a single file
+ assert not (tmpdir / 'test1').exists()
+ copy_asset(source / 'index.rst', tmpdir / 'test1')
+ assert (tmpdir / 'test1').exists()
+ assert (tmpdir / 'test1/index.rst').exists()
+
+ # copy directories
+ destdir = tmpdir / 'test2'
+ copy_asset(source, destdir, context=dict(var1='bar', var2='baz'), renderer=renderer)
+ assert (destdir / 'index.rst').exists()
+ assert (destdir / 'foo.rst').exists()
+ assert (destdir / 'foo.rst').text() == 'bar.rst'
+ assert (destdir / '_static' / 'basic.css').exists()
+ assert (destdir / '_templates' / 'layout.html').exists()
+ assert (destdir / '_templates' / 'sidebar.html').exists()
+ assert (destdir / '_templates' / 'sidebar.html').text() == 'sidebar: baz'
+
+ # copy with exclusion
+ def excluded(path):
+ return ('sidebar.html' in path or 'basic.css' in path)
+
+ destdir = tmpdir / 'test3'
+ copy_asset(source, destdir, excluded,
+ context=dict(var1='bar', var2='baz'), renderer=renderer)
+ assert (destdir / 'index.rst').exists()
+ assert (destdir / 'foo.rst').exists()
+ assert not (destdir / '_static' / 'basic.css').exists()
+ assert (destdir / '_templates' / 'layout.html').exists()
+ assert not (destdir / '_templates' / 'sidebar.html').exists()
diff --git a/tests/test_util_i18n.py b/tests/test_util_i18n.py
index 6ff988c81..3e0cfd5f3 100644
--- a/tests/test_util_i18n.py
+++ b/tests/test_util_i18n.py
@@ -47,7 +47,7 @@ def test_catalog_outdated(dir):
mo_file.write_text('#')
assert not cat.is_outdated() # if mo is exist and newer than po
- os.utime(mo_file, (os.stat(mo_file).st_mtime - 10,) * 2) # to be outdate
+ os.utime(mo_file, (os.stat(mo_file).st_mtime - 10,) * 2) # to be outdate
assert cat.is_outdated() # if mo is exist and older than po
@@ -213,6 +213,7 @@ def test_format_date():
assert i18n.format_date(format, date=datet) == 'Feb 7, 2016, 5:11:17 AM'
assert i18n.format_date(format, date=date) == 'Feb 7, 2016'
+
def test_get_filename_for_language():
app = TestApp()
diff --git a/tests/test_util_matching.py b/tests/test_util_matching.py
new file mode 100644
index 000000000..9e99a5322
--- /dev/null
+++ b/tests/test_util_matching.py
@@ -0,0 +1,91 @@
+# -*- coding: utf-8 -*-
+"""
+ test_util_matching
+ ~~~~~~~~~~~~~~~~~~
+
+ Tests sphinx.util.matching functions.
+
+ :copyright: Copyright 2007-2016 by the Sphinx team, see AUTHORS.
+ :license: BSD, see LICENSE for details.
+"""
+from sphinx.util.matching import compile_matchers, Matcher
+
+
+def test_compile_matchers():
+ # exact matching
+ pat = compile_matchers(['hello.py']).pop()
+ assert pat('hello.py')
+ assert not pat('hello-py')
+ assert not pat('subdir/hello.py')
+
+ # wild card (*)
+ pat = compile_matchers(['hello.*']).pop()
+ assert pat('hello.py')
+ assert pat('hello.rst')
+
+ pat = compile_matchers(['*.py']).pop()
+ assert pat('hello.py')
+ assert pat('world.py')
+ assert not pat('subdir/hello.py')
+
+ # wild card (**)
+ pat = compile_matchers(['hello.**']).pop()
+ assert pat('hello.py')
+ assert pat('hello.rst')
+ assert pat('hello.py/world.py')
+
+ pat = compile_matchers(['**.py']).pop()
+ assert pat('hello.py')
+ assert pat('world.py')
+ assert pat('subdir/hello.py')
+
+ pat = compile_matchers(['**/hello.py']).pop()
+ assert not pat('hello.py')
+ assert pat('subdir/hello.py')
+ assert pat('subdir/subdir/hello.py')
+
+ # wild card (?)
+ pat = compile_matchers(['hello.?']).pop()
+ assert pat('hello.c')
+ assert not pat('hello.py')
+
+ # pattern ([...])
+ pat = compile_matchers(['hello[12\\].py']).pop()
+ assert pat('hello1.py')
+ assert pat('hello2.py')
+ assert pat('hello\\.py')
+ assert not pat('hello3.py')
+
+ pat = compile_matchers(['hello[^12].py']).pop() # "^" is not negative identifier
+ assert pat('hello1.py')
+ assert pat('hello2.py')
+ assert pat('hello^.py')
+ assert not pat('hello3.py')
+
+ # negative pattern ([!...])
+ pat = compile_matchers(['hello[!12].py']).pop()
+ assert not pat('hello1.py')
+ assert not pat('hello2.py')
+ assert not pat('hello/.py') # negative pattern does not match to "/"
+ assert pat('hello3.py')
+
+ # non patterns
+ pat = compile_matchers(['hello[.py']).pop()
+ assert pat('hello[.py')
+ assert not pat('hello.py')
+
+ pat = compile_matchers(['hello[].py']).pop()
+ assert pat('hello[].py')
+ assert not pat('hello.py')
+
+ pat = compile_matchers(['hello[!].py']).pop()
+ assert pat('hello[!].py')
+ assert not pat('hello.py')
+
+
+def test_Matcher():
+ matcher = Matcher(['hello.py', '**/world.py'])
+ assert matcher('hello.py')
+ assert not matcher('subdir/hello.py')
+ assert matcher('world.py')
+ assert matcher('subdir/world.py')
diff --git a/tests/test_util_nodes.py b/tests/test_util_nodes.py
index a41af3cc8..e7a4b7e90 100644
--- a/tests/test_util_nodes.py
+++ b/tests/test_util_nodes.py
@@ -87,7 +87,6 @@ def test_extract_messages():
nodes.rubric, 1,
)
-
text = dedent(
"""
| spam
@@ -100,7 +99,6 @@ def test_extract_messages():
nodes.line, 2,
)
-
text = dedent(
"""
section
@@ -118,7 +116,6 @@ def test_extract_messages():
nodes.line, 2,
)
-
text = dedent(
"""
* | **Title 1**
diff --git a/tests/test_writer_latex.py b/tests/test_writer_latex.py
new file mode 100644
index 000000000..72eb7ed2a
--- /dev/null
+++ b/tests/test_writer_latex.py
@@ -0,0 +1,36 @@
+# -*- coding: utf-8 -*-
+"""
+ test_writer_latex
+ ~~~~~~~~~~~~~~~~
+
+ Test the LaTeX writer
+
+ :copyright: Copyright 2007-2016 by the Sphinx team, see AUTHORS.
+ :license: BSD, see LICENSE for details.
+"""
+from __future__ import print_function
+from sphinx.writers.latex import rstdim_to_latexdim
+
+from util import raises
+
+
+def test_rstdim_to_latexdim():
+ # Length units docutils supported
+ # http://docutils.sourceforge.net/docs/ref/rst/restructuredtext.html#length-units
+ assert rstdim_to_latexdim('160em') == '160em'
+ assert rstdim_to_latexdim('160px') == '160\\sphinxpxdimen'
+ assert rstdim_to_latexdim('160in') == '160in'
+ assert rstdim_to_latexdim('160cm') == '160cm'
+ assert rstdim_to_latexdim('160mm') == '160mm'
+ assert rstdim_to_latexdim('160pt') == '160bp'
+ assert rstdim_to_latexdim('160pc') == '160pc'
+ assert rstdim_to_latexdim('30%') == '0.300\\linewidth'
+ assert rstdim_to_latexdim('160') == '160\\sphinxpxdimen'
+
+ # flaot values
+ assert rstdim_to_latexdim('160.0em') == '160.0em'
+ assert rstdim_to_latexdim('.5em') == '.5em'
+
+ # unknown values (it might be generated by 3rd party extension)
+ raises(ValueError, rstdim_to_latexdim, 'unknown')
+ assert rstdim_to_latexdim('160.0unknown') == '160.0unknown'
diff --git a/tests/util.py b/tests/util.py
index b3f5e01d9..27b41bc15 100644
--- a/tests/util.py
+++ b/tests/util.py
@@ -26,7 +26,7 @@ from sphinx.theming import Theme
from sphinx.ext.autodoc import AutoDirective
from sphinx.pycode import ModuleAnalyzer
-from path import path, repr_as
+from path import path, repr_as # NOQA
try:
# Python >=3.3
@@ -110,6 +110,7 @@ except ImportError:
def assert_in(x, thing, msg=''):
if x not in thing:
assert False, msg or '%r is not in %r' % (x, thing)
+
def assert_not_in(x, thing, msg=''):
if x in thing:
assert False, msg or '%r is in %r' % (x, thing)
@@ -308,3 +309,7 @@ def find_files(root, suffix=None):
for f in [f for f in files if not suffix or f.endswith(suffix)]:
fpath = dirpath / f
yield os.path.relpath(fpath, root)
+
+
+def strip_escseq(text):
+ return re.sub('\x1b.*?m', '', text)
diff --git a/tox.ini b/tox.ini
index 8fcb7b177..b646fd285 100644
--- a/tox.ini
+++ b/tox.ini
@@ -6,6 +6,7 @@ deps=
nose
sqlalchemy
whoosh
+ html5lib
setenv =
SPHINX_TEST_TEMPDIR = {envdir}/testbuild
commands=
diff --git a/utils/check_sources.py b/utils/check_sources.py
index 16bc918cb..18d444057 100755
--- a/utils/check_sources.py
+++ b/utils/check_sources.py
@@ -223,11 +223,8 @@ def main(argv):
print("Checking %s..." % fn)
try:
- f = open(fn, 'rb')
- try:
+ with open(fn, 'rb') as f:
lines = list(f)
- finally:
- f.close()
except (IOError, OSError) as err:
print("%s: cannot open: %s" % (fn, err))
num += 1
diff --git a/utils/reindent.py b/utils/reindent.py
index ef53fe8ca..ee13a634a 100755
--- a/utils/reindent.py
+++ b/utils/reindent.py
@@ -40,11 +40,13 @@ you'd prefer. You can always use the --nobackup option to prevent this.
"""
from __future__ import print_function
-__version__ = "1"
-
-import tokenize
-import os, shutil
+import os
import sys
+import shutil
+import tokenize
+from six.ranges import range
+
+__version__ = "1"
if sys.version_info >= (3, 0):
def tokens(readline, tokeneater):
@@ -58,11 +60,13 @@ recurse = 0
dryrun = 0
makebackup = True
+
def usage(msg=None):
if msg is not None:
print(msg, file=sys.stderr)
print(__doc__, file=sys.stderr)
+
def errprint(*args):
sep = ""
for arg in args:
@@ -70,12 +74,13 @@ def errprint(*args):
sep = " "
sys.stderr.write("\n")
+
def main():
import getopt
global verbose, recurse, dryrun, makebackup
try:
opts, args = getopt.getopt(sys.argv[1:], "drnvh",
- ["dryrun", "recurse", "nobackup", "verbose", "help"])
+ ["dryrun", "recurse", "nobackup", "verbose", "help"])
except getopt.error as msg:
usage(msg)
return
@@ -99,6 +104,7 @@ def main():
for arg in args:
check(arg)
+
def check(file):
if os.path.isdir(file) and not os.path.islink(file):
if verbose:
@@ -108,8 +114,8 @@ def check(file):
fullname = os.path.join(file, name)
if ((recurse and os.path.isdir(fullname) and
not os.path.islink(fullname) and
- not os.path.split(fullname)[1].startswith("."))
- or name.lower().endswith(".py")):
+ not os.path.split(fullname)[1].startswith(".")) or
+ name.lower().endswith(".py")):
check(fullname)
return
@@ -121,8 +127,8 @@ def check(file):
errprint("%s: I/O Error: %s" % (file, str(msg)))
return
- r = Reindenter(f)
- f.close()
+ with f:
+ r = Reindenter(f)
if r.run():
if verbose:
print("changed.")
@@ -134,9 +140,8 @@ def check(file):
shutil.copyfile(file, bak)
if verbose:
print("backed up", file, "to", bak)
- f = open(file, "w")
- r.write(f)
- f.close()
+ with open(file, "w") as f:
+ r.write(f)
if verbose:
print("wrote new", file)
return True
@@ -145,6 +150,7 @@ def check(file):
print("unchanged.")
return False
+
def _rstrip(line, JUNK='\n \t'):
"""Return line stripped of trailing spaces, tabs, newlines.
@@ -158,8 +164,8 @@ def _rstrip(line, JUNK='\n \t'):
i -= 1
return line[:i]
-class Reindenter:
+class Reindenter:
def __init__(self, f):
self.find_stmt = 1 # next token begins a fresh stmt?
self.level = 0 # current indent level
@@ -212,21 +218,21 @@ class Reindenter:
want = have2want.get(have, -1)
if want < 0:
# Then it probably belongs to the next real stmt.
- for j in xrange(i+1, len(stats)-1):
+ for j in range(i+1, len(stats)-1):
jline, jlevel = stats[j]
if jlevel >= 0:
if have == getlspace(lines[jline]):
want = jlevel * 4
break
- if want < 0: # Maybe it's a hanging
- # comment like this one,
+ if want < 0: # Maybe it's a hanging
+ # comment like this one,
# in which case we should shift it like its base
# line got shifted.
- for j in xrange(i-1, -1, -1):
+ for j in range(i-1, -1, -1):
jline, jlevel = stats[j]
if jlevel >= 0:
- want = have + getlspace(after[jline-1]) - \
- getlspace(lines[jline])
+ want = (have + getlspace(after[jline-1]) -
+ getlspace(lines[jline]))
break
if want < 0:
# Still no luck -- leave it alone.
@@ -301,6 +307,7 @@ class Reindenter:
if line: # not endmarker
self.stats.append((position[0], self.level))
+
# Count number of leading blanks.
def getlspace(line):
i, n = 0, len(line)
diff --git a/utils/release-checklist b/utils/release-checklist
index 8efe980db..3dd52158c 100644
--- a/utils/release-checklist
+++ b/utils/release-checklist
@@ -1,22 +1,26 @@
Release checklist
=================
+* Open https://travis-ci.org/sphinx-doc/sphinx/branches and check stable branch is green
* Check `git status`
* Run `make style-check`
* Run `tx pull -a -f` in sphinx/locale if final major release
* Update version info in sphinx/__init__.py
* Update release date in CHANGES
-* `git commit`
+* `git commit -am 'Bump to x.y.z final'`
* `make clean`
-* `python setup.py release bdist_wheel sdist upload --identify=[your key]`
+* `python setup.py release bdist_wheel sdist upload --identity=[your key]`
* Check PyPI release page for obvious errors
* `git tag` with version number
* Merge default into stable if final major release
-* `git push stable --tags`
+* `git push origin stable --tags`
* Open https://readthedocs.org/dashboard/sphinx/versions/ and enable the released version
* Add new version/milestone to tracker categories
* Write announcement and send to sphinx-dev, sphinx-users and python-announce
* Update version info, add new CHANGES entry for next version
-* `git commit`
-* `git push`
+* `git commit -am 'Bump version'`
+* `git push origin stable`
+* `git checkout master`
+* `git merge stable`
+* `git push origin master`
* Update `sphinx-doc-translations `_