mirror of
https://github.com/sphinx-doc/sphinx.git
synced 2025-02-25 18:55:22 -06:00
Merge branch 'master' into 789_escape_braces_on_samp_role
This commit is contained in:
commit
0ea06e40ca
13
CHANGES
13
CHANGES
@ -23,6 +23,8 @@ Incompatible changes
|
||||
:py:meth:`.Sphinx.add_transform()`
|
||||
* #4827: All ``substitution_definition`` nodes are removed from doctree on
|
||||
reading phase
|
||||
* ``docutils.conf`` on ``$HOME`` and ``/etc`` directories are ignored. Only
|
||||
``docutils.conf`` on confdir is refered.
|
||||
* #789: ``:samp:`` role supports to escape curly braces with backslash
|
||||
|
||||
Deprecated
|
||||
@ -44,6 +46,14 @@ Deprecated
|
||||
* ``app.override_domain()`` is deprecated
|
||||
* ``app.add_stylesheet()`` is deprecated
|
||||
* ``sphinx.versioning.prepare()`` is deprecated
|
||||
* ``Config.__init__()`` has changed; the *dirname*, *filename* and *tags*
|
||||
argument has been deprecated
|
||||
* ``Config.check_types()`` is deprecated
|
||||
* ``Config.check_unicode()`` is deprecated
|
||||
* ``sphinx.application.CONFIG_FILENAME`` is deprecated
|
||||
* ``highlightlang`` directive is deprecated
|
||||
* ``env.read_doc()`` is deprecated
|
||||
* ``env.write_doctree()`` is deprecated
|
||||
|
||||
For more details, see `deprecation APIs list
|
||||
<http://www.sphinx-doc.org/en/master/extdev/index.html#deprecated-apis>`_
|
||||
@ -75,6 +85,9 @@ Features added
|
||||
* Improve warning messages during including (refs: #4818)
|
||||
* LaTeX: separate customizability of :rst:role:`guilabel` and
|
||||
:rst:role:`menuselection` (refs: #4830)
|
||||
* Add ``Config.read()`` classmethod to create a new config object from
|
||||
configuration file
|
||||
* #4866: Wrap graphviz diagrams in ``<div>`` tag
|
||||
|
||||
Bugs fixed
|
||||
----------
|
||||
|
@ -6,7 +6,7 @@
|
||||
:target: https://pypi.org/project/Sphinx/
|
||||
:alt: Package on PyPi
|
||||
|
||||
.. image:: https://readthedocs.org/projects/sphinx/badge/
|
||||
.. image:: https://readthedocs.org/projects/sphinx/badge/?version=master
|
||||
:target: http://www.sphinx-doc.org/
|
||||
:alt: Documentation Status
|
||||
|
||||
|
@ -10,17 +10,17 @@ Sphinx documentation contents
|
||||
usage/installation
|
||||
usage/quickstart
|
||||
usage/restructuredtext/index
|
||||
usage/markdown
|
||||
usage/configuration
|
||||
|
||||
intro
|
||||
man/index
|
||||
builders
|
||||
config
|
||||
intl
|
||||
theming
|
||||
setuptools
|
||||
templating
|
||||
latex
|
||||
markdown
|
||||
extensions
|
||||
extdev/index
|
||||
websupport
|
||||
|
@ -116,11 +116,42 @@ The following is a list of deprecated interface.
|
||||
- (will be) Removed
|
||||
- Alternatives
|
||||
|
||||
* - :rst:dir:`highlightlang`
|
||||
- 1.8
|
||||
- 4.0
|
||||
- :rst:dir:`highlight`
|
||||
|
||||
* - :meth:`~sphinx.application.Sphinx.add_stylesheet()`
|
||||
- 1.8
|
||||
- 4.0
|
||||
- :meth:`~sphinx.application.Sphinx.add_css_file()`
|
||||
|
||||
* - ``sphinx.application.CONFIG_FILENAME``
|
||||
- 1.8
|
||||
- 3.0
|
||||
- ``sphinx.config.CONFIG_FILENAME``
|
||||
|
||||
* - ``Config.check_unicode()``
|
||||
- 1.8
|
||||
- 3.0
|
||||
- ``sphinx.config.check_unicode()``
|
||||
|
||||
* - ``Config.check_types()``
|
||||
- 1.8
|
||||
- 3.0
|
||||
- ``sphinx.config.check_confval_types()``
|
||||
|
||||
* - ``dirname``, ``filename`` and ``tags`` arguments of
|
||||
``Config.__init__()``
|
||||
- 1.8
|
||||
- 3.0
|
||||
- ``Config.read()``
|
||||
|
||||
* - The value of :confval:`html_search_options`
|
||||
- 1.8
|
||||
- 3.0
|
||||
- see :confval:`html_search_options`
|
||||
|
||||
* - ``sphinx.versioning.prepare()``
|
||||
- 1.8
|
||||
- 3.0
|
||||
@ -172,6 +203,11 @@ The following is a list of deprecated interface.
|
||||
- 3.0
|
||||
- ``Builder.read()``
|
||||
|
||||
* - ``BuildEnvironment.read_doc()``
|
||||
- 1.8
|
||||
- 3.0
|
||||
- ``Builder.read_doc()``
|
||||
|
||||
* - ``BuildEnvironment._read_serial()``
|
||||
- 1.8
|
||||
- 3.0
|
||||
@ -182,6 +218,11 @@ The following is a list of deprecated interface.
|
||||
- 3.0
|
||||
- ``Builder.read()``
|
||||
|
||||
* - ``BuildEnvironment.write_doctree()``
|
||||
- 1.8
|
||||
- 3.0
|
||||
- ``Builder.write_doctree()``
|
||||
|
||||
* - ``sphinx.locale.l_()``
|
||||
- 1.8
|
||||
- 3.0
|
||||
|
@ -1,4 +1,4 @@
|
||||
.. highlightlang:: python
|
||||
.. highlight:: python
|
||||
|
||||
.. _latex:
|
||||
|
||||
|
@ -1,45 +0,0 @@
|
||||
.. highlightlang:: python
|
||||
|
||||
.. _markdown:
|
||||
|
||||
Markdown support
|
||||
================
|
||||
|
||||
`Markdown <https://daringfireball.net/projects/markdown/>`__ is a lightweight markup language with a simplistic plain
|
||||
text formatting syntax.
|
||||
It exists in many syntactically different *flavors*.
|
||||
To support Markdown-based documentation, Sphinx can use
|
||||
`recommonmark <https://recommonmark.readthedocs.io/en/latest/index.html>`__.
|
||||
recommonmark is a Docutils bridge to `CommonMark-py <https://github.com/rtfd/CommonMark-py>`__, a
|
||||
Python package for parsing the `CommonMark <http://commonmark.org/>`__ Markdown flavor.
|
||||
|
||||
|
||||
Configuration
|
||||
-------------
|
||||
|
||||
To configure your Sphinx project for Markdown support, proceed as follows:
|
||||
|
||||
#. Install recommonmark:
|
||||
|
||||
::
|
||||
|
||||
pip install recommonmark
|
||||
|
||||
#. Add the Markdown parser to the ``source_parsers`` configuration variable in your Sphinx configuration file:
|
||||
|
||||
::
|
||||
|
||||
source_parsers = {
|
||||
'.md': 'recommonmark.parser.CommonMarkParser',
|
||||
}
|
||||
|
||||
You can replace `.md` with a filename extension of your choice.
|
||||
|
||||
#. Add the Markdown filename extension to the ``source_suffix`` configuration variable:
|
||||
|
||||
::
|
||||
|
||||
source_suffix = ['.rst', '.md']
|
||||
|
||||
#. You can further configure recommonmark to allow custom syntax that standard CommonMark doesn't support. Read more in
|
||||
the `recommonmark documentation <https://recommonmark.readthedocs.io/en/latest/auto_structify.html>`__.
|
@ -1,4 +1,4 @@
|
||||
.. highlightlang:: python
|
||||
.. highlight:: python
|
||||
|
||||
HTML theming support
|
||||
====================
|
||||
|
@ -1,9 +1,10 @@
|
||||
.. highlightlang:: python
|
||||
.. highlight:: python
|
||||
|
||||
.. _build-config:
|
||||
|
||||
The build configuration file
|
||||
============================
|
||||
=============
|
||||
Configuration
|
||||
=============
|
||||
|
||||
.. module:: conf
|
||||
:synopsis: Build configuration file.
|
||||
@ -14,11 +15,10 @@ and contains (almost) all configuration needed to customize Sphinx input
|
||||
and output behavior.
|
||||
|
||||
An optional file `docutils.conf`_ can be added to the configuration
|
||||
directory to adjust `Docutils`_ configuration if not otherwise overriden or
|
||||
directory to adjust `Docutils`_ configuration if not otherwise overridden or
|
||||
set by Sphinx.
|
||||
|
||||
.. _`docutils`: http://docutils.sourceforge.net/
|
||||
|
||||
.. _`docutils.conf`: http://docutils.sourceforge.net/docs/user/config.html
|
||||
|
||||
The configuration file is executed as Python code at build time (using
|
||||
@ -36,8 +36,8 @@ Important points to note:
|
||||
``"sphinx.builders.Builder"`` means the ``Builder`` class in the
|
||||
``sphinx.builders`` module.
|
||||
|
||||
* Remember that document names use ``/`` as the path separator and don't contain
|
||||
the file name extension.
|
||||
* Remember that document names use ``/`` as the path separator and don't
|
||||
contain the file name extension.
|
||||
|
||||
* Since :file:`conf.py` is read as a Python file, the usual rules apply for
|
||||
encodings and Unicode support: declare the encoding using an encoding cookie
|
||||
@ -82,8 +82,8 @@ General configuration
|
||||
That way, you can load an extension called ``extname`` from the subdirectory
|
||||
``sphinxext``.
|
||||
|
||||
The configuration file itself can be an extension; for that, you only need to
|
||||
provide a :func:`setup` function in it.
|
||||
The configuration file itself can be an extension; for that, you only need
|
||||
to provide a :func:`setup` function in it.
|
||||
|
||||
.. confval:: source_suffix
|
||||
|
||||
@ -136,7 +136,8 @@ General configuration
|
||||
|
||||
.. note::
|
||||
|
||||
Read more about how to use Markdown with Sphinx at :ref:`markdown`.
|
||||
Refer to :doc:`/usage/markdown` for more information on using Markdown
|
||||
with Sphinx.
|
||||
|
||||
.. versionadded:: 1.3
|
||||
|
||||
@ -151,9 +152,10 @@ General configuration
|
||||
|
||||
.. confval:: exclude_patterns
|
||||
|
||||
A list of glob-style patterns that should be excluded when looking for source
|
||||
files. [1]_ They are matched against the source file names relative to the
|
||||
source directory, using slashes as directory separators on all platforms.
|
||||
A list of glob-style patterns that should be excluded when looking for
|
||||
source files. [1]_ They are matched against the source file names relative
|
||||
to the source directory, using slashes as directory separators on all
|
||||
platforms.
|
||||
|
||||
Example patterns:
|
||||
|
||||
@ -181,10 +183,10 @@ General configuration
|
||||
|
||||
.. confval:: template_bridge
|
||||
|
||||
A string with the fully-qualified name of a callable (or simply a class) that
|
||||
returns an instance of :class:`~sphinx.application.TemplateBridge`. This
|
||||
instance is then used to render HTML documents, and possibly the output of
|
||||
other builders (currently the changes builder). (Note that the template
|
||||
A string with the fully-qualified name of a callable (or simply a class)
|
||||
that returns an instance of :class:`~sphinx.application.TemplateBridge`.
|
||||
This instance is then used to render HTML documents, and possibly the output
|
||||
of other builders (currently the changes builder). (Note that the template
|
||||
bridge must be made theme-aware if HTML themes are to be used.)
|
||||
|
||||
.. confval:: rst_epilog
|
||||
@ -247,9 +249,9 @@ General configuration
|
||||
|
||||
.. confval:: keep_warnings
|
||||
|
||||
If true, keep warnings as "system message" paragraphs in the built documents.
|
||||
Regardless of this setting, warnings are always written to the standard error
|
||||
stream when ``sphinx-build`` is run.
|
||||
If true, keep warnings as "system message" paragraphs in the built
|
||||
documents. Regardless of this setting, warnings are always written to the
|
||||
standard error stream when ``sphinx-build`` is run.
|
||||
|
||||
The default is ``False``, the pre-0.5 behavior was to always keep them.
|
||||
|
||||
@ -302,8 +304,8 @@ General configuration
|
||||
.. confval:: needs_sphinx
|
||||
|
||||
If set to a ``major.minor`` version string like ``'1.1'``, Sphinx will
|
||||
compare it with its version and refuse to build if it is too old. Default is
|
||||
no requirement.
|
||||
compare it with its version and refuse to build if it is too old. Default
|
||||
is no requirement.
|
||||
|
||||
.. versionadded:: 1.0
|
||||
|
||||
@ -312,8 +314,8 @@ General configuration
|
||||
|
||||
.. confval:: needs_extensions
|
||||
|
||||
This value can be a dictionary specifying version requirements for extensions
|
||||
in :confval:`extensions`, e.g. ``needs_extensions =
|
||||
This value can be a dictionary specifying version requirements for
|
||||
extensions in :confval:`extensions`, e.g. ``needs_extensions =
|
||||
{'sphinxcontrib.something': '1.5'}``. The version strings should be in the
|
||||
form ``major.minor``. Requirements do not have to be specified for all
|
||||
extensions, only for those you want to check.
|
||||
@ -351,10 +353,10 @@ General configuration
|
||||
|
||||
.. confval:: nitpick_ignore
|
||||
|
||||
A list of ``(type, target)`` tuples (by default empty) that should be ignored
|
||||
when generating warnings in "nitpicky mode". Note that ``type`` should
|
||||
include the domain name if present. Example entries would be ``('py:func',
|
||||
'int')`` or ``('envvar', 'LD_LIBRARY_PATH')``.
|
||||
A list of ``(type, target)`` tuples (by default empty) that should be
|
||||
ignored when generating warnings in "nitpicky mode". Note that ``type``
|
||||
should include the domain name if present. Example entries would be
|
||||
``('py:func', 'int')`` or ``('envvar', 'LD_LIBRARY_PATH')``.
|
||||
|
||||
.. versionadded:: 1.1
|
||||
|
||||
@ -366,8 +368,8 @@ General configuration
|
||||
|
||||
.. note::
|
||||
|
||||
The LaTeX builder always assigns numbers whether this option is enabled or
|
||||
not.
|
||||
The LaTeX builder always assigns numbers whether this option is enabled
|
||||
or not.
|
||||
|
||||
.. versionadded:: 1.3
|
||||
|
||||
@ -375,7 +377,7 @@ General configuration
|
||||
|
||||
A dictionary mapping ``'figure'``, ``'table'``, ``'code-block'`` and
|
||||
``'section'`` to strings that are used for format of figure numbers.
|
||||
As a special character, `%s` will be replaced to figure number.
|
||||
As a special character, ``%s`` will be replaced to figure number.
|
||||
|
||||
Default is to use ``'Fig. %s'`` for ``'figure'``, ``'Table %s'`` for
|
||||
``'table'``, ``'Listing %s'`` for ``'code-block'`` and ``'Section'`` for
|
||||
@ -474,6 +476,7 @@ General configuration
|
||||
|
||||
.. versionadded:: 1.5
|
||||
|
||||
|
||||
Project information
|
||||
-------------------
|
||||
|
||||
@ -513,7 +516,7 @@ Project information
|
||||
* Otherwise, the current time is formatted using :func:`time.strftime` and
|
||||
the format given in :confval:`today_fmt`.
|
||||
|
||||
The default is no :confval:`today` and a :confval:`today_fmt` of ``'%B %d,
|
||||
The default is now :confval:`today` and a :confval:`today_fmt` of ``'%B %d,
|
||||
%Y'`` (or, if translation is enabled with :confval:`language`, an equivalent
|
||||
format for the selected locale).
|
||||
|
||||
@ -527,7 +530,7 @@ Project information
|
||||
|
||||
.. versionchanged:: 1.4
|
||||
The default is now ``'default'``. It is similar to ``'python3'``;
|
||||
it is mostly a superset of ``'python'``. but it fallbacks to
|
||||
it is mostly a superset of ``'python'`` but it fallbacks to
|
||||
``'none'`` without warning if failed. ``'python3'`` and other
|
||||
languages will emit warning if failed. If you prefer Python 2
|
||||
only highlighting, you can set it back to ``'python'``.
|
||||
@ -544,7 +547,8 @@ Project information
|
||||
.. confval:: pygments_style
|
||||
|
||||
The style name to use for Pygments highlighting of source code. If not set,
|
||||
either the theme's default style or ``'sphinx'`` is selected for HTML output.
|
||||
either the theme's default style or ``'sphinx'`` is selected for HTML
|
||||
output.
|
||||
|
||||
.. versionchanged:: 0.3
|
||||
If the value is a fully-qualified name of a custom Pygments style class,
|
||||
@ -579,8 +583,8 @@ Project information
|
||||
|
||||
.. confval:: trim_footnote_reference_space
|
||||
|
||||
Trim spaces before footnote references that are necessary for the reST parser
|
||||
to recognize the footnote, but do not look too nice in the output.
|
||||
Trim spaces before footnote references that are necessary for the reST
|
||||
parser to recognize the footnote, but do not look too nice in the output.
|
||||
|
||||
.. versionadded:: 0.6
|
||||
|
||||
@ -767,6 +771,7 @@ documentation on :ref:`intl` for details.
|
||||
.. versionchanged:: 1.5
|
||||
Added ``{path}`` and ``{basename}`` tokens.
|
||||
|
||||
|
||||
.. _html-options:
|
||||
|
||||
Options for HTML output
|
||||
@ -778,7 +783,7 @@ that use Sphinx's HTMLWriter class.
|
||||
.. confval:: html_theme
|
||||
|
||||
The "theme" that the HTML output should use. See the :doc:`section about
|
||||
theming <theming>`. The default is ``'alabaster'``.
|
||||
theming </theming>`. The default is ``'alabaster'``.
|
||||
|
||||
.. versionadded:: 0.6
|
||||
|
||||
@ -800,11 +805,12 @@ that use Sphinx's HTMLWriter class.
|
||||
|
||||
.. confval:: html_style
|
||||
|
||||
The style sheet to use for HTML pages. A file of that name must exist either
|
||||
in Sphinx's :file:`static/` path, or in one of the custom paths given in
|
||||
:confval:`html_static_path`. Default is the stylesheet given by the selected
|
||||
theme. If you only want to add or override a few things compared to the
|
||||
theme's stylesheet, use CSS ``@import`` to import the theme's stylesheet.
|
||||
The style sheet to use for HTML pages. A file of that name must exist
|
||||
either in Sphinx's :file:`static/` path, or in one of the custom paths given
|
||||
in :confval:`html_static_path`. Default is the stylesheet given by the
|
||||
selected theme. If you only want to add or override a few things compared
|
||||
to the theme's stylesheet, use CSS ``@import`` to import the theme's
|
||||
stylesheet.
|
||||
|
||||
.. confval:: html_title
|
||||
|
||||
@ -815,8 +821,8 @@ that use Sphinx's HTMLWriter class.
|
||||
|
||||
.. confval:: html_short_title
|
||||
|
||||
A shorter "title" for the HTML docs. This is used in for links in the header
|
||||
and in the HTML Help docs. If not given, it defaults to the value of
|
||||
A shorter "title" for the HTML docs. This is used in for links in the
|
||||
header and in the HTML Help docs. If not given, it defaults to the value of
|
||||
:confval:`html_title`.
|
||||
|
||||
.. versionadded:: 0.4
|
||||
@ -909,9 +915,9 @@ that use Sphinx's HTMLWriter class.
|
||||
.. versionadded:: 1.2
|
||||
|
||||
.. versionchanged:: 1.4
|
||||
The dotfiles in the extra directory will be copied to the output directory.
|
||||
And it refers :confval:`exclude_patterns` on copying extra files and
|
||||
directories, and ignores if path matches to patterns.
|
||||
The dotfiles in the extra directory will be copied to the output
|
||||
directory. And it refers :confval:`exclude_patterns` on copying extra
|
||||
files and directories, and ignores if path matches to patterns.
|
||||
|
||||
.. confval:: html_last_updated_fmt
|
||||
|
||||
@ -1066,12 +1072,12 @@ that use Sphinx's HTMLWriter class.
|
||||
|
||||
.. confval:: html_use_opensearch
|
||||
|
||||
If nonempty, an `OpenSearch <http://www.opensearch.org/Home>`_ description file will be
|
||||
output, and all pages will contain a ``<link>`` tag referring to it. Since
|
||||
OpenSearch doesn't support relative URLs for its search page location, the
|
||||
value of this option must be the base URL from which these documents are
|
||||
served (without trailing slash), e.g. ``"https://docs.python.org"``. The
|
||||
default is ``''``.
|
||||
If nonempty, an `OpenSearch <http://www.opensearch.org/Home>`_ description
|
||||
file will be output, and all pages will contain a ``<link>`` tag referring
|
||||
to it. Since OpenSearch doesn't support relative URLs for its search page
|
||||
location, the value of this option must be the base URL from which these
|
||||
documents are served (without trailing slash), e.g.
|
||||
``"https://docs.python.org"``. The default is ``''``.
|
||||
|
||||
.. confval:: html_file_suffix
|
||||
|
||||
@ -1178,25 +1184,27 @@ that use Sphinx's HTMLWriter class.
|
||||
The Japanese support has these options:
|
||||
|
||||
:type:
|
||||
_`type` is dotted module path string to specify Splitter implementation which
|
||||
should be derived from :class:`sphinx.search.ja.BaseSplitter`.
|
||||
If not specified or None is specified, ``'sphinx.search.ja.DefaultSplitter'`` will
|
||||
be used.
|
||||
_`type` is dotted module path string to specify Splitter implementation
|
||||
which should be derived from :class:`sphinx.search.ja.BaseSplitter`. If
|
||||
not specified or None is specified,
|
||||
``'sphinx.search.ja.DefaultSplitter'`` will be used.
|
||||
|
||||
You can choose from these modules:
|
||||
|
||||
:'sphinx.search.ja.DefaultSplitter':
|
||||
TinySegmenter algorithm. This is default splitter.
|
||||
:'sphinx.search.ja.MeCabSplitter':
|
||||
MeCab binding. To use this splitter, 'mecab' python binding or dynamic link
|
||||
library ('libmecab.so' for linux, 'libmecab.dll' for windows) is required.
|
||||
MeCab binding. To use this splitter, 'mecab' python binding or dynamic
|
||||
link library ('libmecab.so' for linux, 'libmecab.dll' for windows) is
|
||||
required.
|
||||
:'sphinx.search.ja.JanomeSplitter':
|
||||
Janome binding. To use this splitter,
|
||||
`Janome <https://pypi.org/project/Janome/>`_ is required.
|
||||
|
||||
To keep compatibility, ``'mecab'``, ``'janome'`` and ``'default'`` are also
|
||||
acceptable. However it will be deprecated in Sphinx-1.6.
|
||||
|
||||
.. deprecated:: 1.6
|
||||
``'mecab'``, ``'janome'`` and ``'default'`` is deprecated.
|
||||
To keep compatibility, ``'mecab'``, ``'janome'`` and ``'default'`` are
|
||||
also acceptable.
|
||||
|
||||
Other option values depend on splitter value which you choose.
|
||||
|
||||
@ -1206,8 +1214,8 @@ that use Sphinx's HTMLWriter class.
|
||||
:dict:
|
||||
_`dict option` is the dictionary to use for the MeCab algorithm.
|
||||
:lib:
|
||||
_`lib option` is the library name for finding the MeCab library via ctypes if
|
||||
the Python binding is not installed.
|
||||
_`lib option` is the library name for finding the MeCab library via
|
||||
ctypes if the Python binding is not installed.
|
||||
|
||||
For example::
|
||||
|
||||
@ -1219,17 +1227,17 @@ that use Sphinx's HTMLWriter class.
|
||||
}
|
||||
|
||||
Options for ``'janome'``:
|
||||
:user_dic: _`user_dic option` is the user dictionary file path for Janome.
|
||||
:user_dic:
|
||||
_`user_dic option` is the user dictionary file path for Janome.
|
||||
:user_dic_enc:
|
||||
_`user_dic_enc option` is the encoding for the user dictionary file specified by
|
||||
``user_dic`` option. Default is 'utf8'.
|
||||
_`user_dic_enc option` is the encoding for the user dictionary file
|
||||
specified by ``user_dic`` option. Default is 'utf8'.
|
||||
|
||||
.. versionadded:: 1.1
|
||||
|
||||
.. versionchanged:: 1.4
|
||||
html_search_options for Japanese is re-organized and any custom splitter can be
|
||||
used by `type`_ settings.
|
||||
|
||||
html_search_options for Japanese is re-organized and any custom splitter
|
||||
can be used by `type`_ settings.
|
||||
|
||||
The Chinese support has these options:
|
||||
|
||||
@ -1255,10 +1263,12 @@ that use Sphinx's HTMLWriter class.
|
||||
|
||||
.. confval:: html_experimental_html5_writer
|
||||
|
||||
Output is processed with HTML5 writer. This feature needs docutils 0.13 or newer. Default is ``False``.
|
||||
Output is processed with HTML5 writer. This feature needs docutils 0.13 or
|
||||
newer. Default is ``False``.
|
||||
|
||||
.. versionadded:: 1.6
|
||||
|
||||
|
||||
.. _htmlhelp-options:
|
||||
|
||||
Options for HTML help output
|
||||
@ -1268,6 +1278,7 @@ Options for HTML help output
|
||||
|
||||
Output file base name for HTML help builder. Default is ``'pydoc'``.
|
||||
|
||||
|
||||
.. _applehelp-options:
|
||||
|
||||
Options for Apple Help output
|
||||
@ -1313,8 +1324,8 @@ HTML builder, so the HTML options also apply where appropriate.
|
||||
|
||||
.. confval:: applehelp_icon
|
||||
|
||||
The help bundle icon file, or ``None`` for no icon. According to Apple’s
|
||||
documentation, this should be a 16-by-16 pixel version of the application’s
|
||||
The help bundle icon file, or ``None`` for no icon. According to Apple's
|
||||
documentation, this should be a 16-by-16 pixel version of the application's
|
||||
icon with a transparent background, saved as a PNG file.
|
||||
|
||||
.. confval:: applehelp_kb_product
|
||||
@ -1328,14 +1339,14 @@ HTML builder, so the HTML options also apply where appropriate.
|
||||
e.g. ``https://example.com/kbsearch.py?p='product'&q='query'&l='lang'``.
|
||||
Help Viewer will replace the values ``'product'``, ``'query'`` and
|
||||
``'lang'`` at runtime with the contents of :confval:`applehelp_kb_product`,
|
||||
the text entered by the user in the search box and the user’s system
|
||||
the text entered by the user in the search box and the user's system
|
||||
language respectively.
|
||||
|
||||
Defaults to ``None`` for no remote search.
|
||||
|
||||
.. confval:: applehelp_remote_url
|
||||
|
||||
The URL for remote content. You can place a copy of your Help Book’s
|
||||
The URL for remote content. You can place a copy of your Help Book's
|
||||
``Resources`` folder at this location and Help Viewer will attempt to use
|
||||
it to fetch updated content.
|
||||
|
||||
@ -1450,8 +1461,8 @@ the `Dublin Core metadata <http://dublincore.org/>`_.
|
||||
|
||||
The HTML theme for the epub output. Since the default themes are not
|
||||
optimized for small screen space, using the same theme for HTML and epub
|
||||
output is usually not wise. This defaults to ``'epub'``, a theme designed to
|
||||
save visual space.
|
||||
output is usually not wise. This defaults to ``'epub'``, a theme designed
|
||||
to save visual space.
|
||||
|
||||
.. confval:: epub_theme_options
|
||||
|
||||
@ -1498,9 +1509,9 @@ the `Dublin Core metadata <http://dublincore.org/>`_.
|
||||
|
||||
.. confval:: epub_publisher
|
||||
|
||||
The publisher of the document. This is put in the Dublin Core metadata. You
|
||||
may use any sensible string, e.g. the project homepage. The defaults to the
|
||||
:confval:`author` option.
|
||||
The publisher of the document. This is put in the Dublin Core metadata.
|
||||
You may use any sensible string, e.g. the project homepage. The defaults to
|
||||
the :confval:`author` option.
|
||||
|
||||
.. confval:: epub_copyright
|
||||
|
||||
@ -1525,9 +1536,9 @@ the `Dublin Core metadata <http://dublincore.org/>`_.
|
||||
|
||||
A unique identifier for the document. This is put in the Dublin Core
|
||||
metadata. You may use a
|
||||
`XML's Name format <https://www.w3.org/TR/REC-xml/#NT-NameStartChar>`_ string.
|
||||
You can't use hyphen, period, numbers as a first character.
|
||||
The default value is ``'unknown'``.
|
||||
`XML's Name format <https://www.w3.org/TR/REC-xml/#NT-NameStartChar>`_
|
||||
string. You can't use hyphen, period, numbers as a first character. The
|
||||
default value is ``'unknown'``.
|
||||
|
||||
.. confval:: epub_cover
|
||||
|
||||
@ -1681,12 +1692,14 @@ the `Dublin Core metadata <http://dublincore.org/>`_.
|
||||
|
||||
.. [#] https://developer.mozilla.org/en-US/docs/Web/CSS/writing-mode
|
||||
|
||||
|
||||
.. _latex-options:
|
||||
|
||||
Options for LaTeX output
|
||||
------------------------
|
||||
|
||||
These options influence LaTeX output. See further :doc:`latex`.
|
||||
These options influence LaTeX output. Refer to :doc:`/latex` for more
|
||||
information.
|
||||
|
||||
.. confval:: latex_engine
|
||||
|
||||
@ -1734,7 +1747,8 @@ These options influence LaTeX output. See further :doc:`latex`.
|
||||
they are to be inserted literally.
|
||||
* *author*: Author for the LaTeX document. The same LaTeX markup caveat as
|
||||
for *title* applies. Use ``\\and`` to separate multiple authors, as in:
|
||||
``'John \\and Sarah'`` (backslashes must be Python-escaped to reach LaTeX).
|
||||
``'John \\and Sarah'`` (backslashes must be Python-escaped to reach
|
||||
LaTeX).
|
||||
* *documentclass*: Normally, one of ``'manual'`` or ``'howto'`` (provided
|
||||
by Sphinx and based on ``'report'``, resp. ``'article'``; Japanese
|
||||
documents use ``'jsbook'``, resp. ``'jreport'``.) "howto" (non-Japanese)
|
||||
@ -1746,7 +1760,8 @@ These options influence LaTeX output. See further :doc:`latex`.
|
||||
* *toctree_only*: Must be ``True`` or ``False``. If true, the *startdoc*
|
||||
document itself is not included in the output, only the documents
|
||||
referenced by it via TOC trees. With this option, you can put extra stuff
|
||||
in the master document that shows up in the HTML, but not the LaTeX output.
|
||||
in the master document that shows up in the HTML, but not the LaTeX
|
||||
output.
|
||||
|
||||
.. versionadded:: 1.2
|
||||
In the past including your own document class required you to prepend the
|
||||
@ -1843,29 +1858,34 @@ These options influence LaTeX output. See further :doc:`latex`.
|
||||
``'papersize'``
|
||||
Paper size option of the document class (``'a4paper'`` or
|
||||
``'letterpaper'``), default ``'letterpaper'``.
|
||||
|
||||
``'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 ``'0.75bp'`` which achieves
|
||||
``96px=1in`` (in TeX ``1in = 72bp = 72.27pt``.) To obtain for
|
||||
example ``100px=1in`` use ``'0.01in'`` or ``'0.7227pt'`` (the latter
|
||||
leads to TeX computing a more precise value, due to the smaller unit
|
||||
used in the specification); for ``72px=1in``,
|
||||
simply use ``'1bp'``; for ``90px=1in``, use ``'0.8bp'`` or ``'0.803pt'``.
|
||||
used in the specification); for ``72px=1in``, simply use ``'1bp'``; for
|
||||
``90px=1in``, use ``'0.8bp'`` or ``'0.803pt'``.
|
||||
|
||||
.. versionadded:: 1.5
|
||||
|
||||
``'sphinxsetup'``
|
||||
A comma separated list of ``key=value`` package options for the Sphinx
|
||||
LaTeX style, default empty. See :doc:`latex`.
|
||||
LaTeX style, default empty. See :doc:`/latex`.
|
||||
|
||||
.. versionadded:: 1.5
|
||||
|
||||
``'passoptionstopackages'``
|
||||
A string which will be positioned early in the preamble, designed to
|
||||
contain ``\\PassOptionsToPackage{options}{foo}`` commands. Default empty.
|
||||
|
||||
.. versionadded:: 1.4
|
||||
|
||||
``'babel'``
|
||||
"babel" package inclusion, default ``'\\usepackage{babel}'`` (the
|
||||
suitable document language string is passed as class option, and
|
||||
@ -1877,6 +1897,7 @@ These options influence LaTeX output. See further :doc:`latex`.
|
||||
is ``'\\usepackage{polyglossia}\n\\setmainlanguage{<language>}'``.
|
||||
.. versionchanged:: 1.6
|
||||
``'lualatex'`` uses same default setting as ``'xelatex'``
|
||||
|
||||
``'fontpkg'``
|
||||
Font package inclusion, default ``'\\usepackage{times}'`` (which uses
|
||||
Times for text, Helvetica for sans serif and Courier for code-blocks).
|
||||
@ -1906,12 +1927,15 @@ These options influence LaTeX output. See further :doc:`latex`.
|
||||
the "Bjarne" style uses numbers spelled out in English). Other
|
||||
"fncychap" styles you can try are "Lenny", "Glenn", "Conny", "Rejne" and
|
||||
"Bjornstrup". You can also set this to ``''`` to disable fncychap.
|
||||
|
||||
``'preamble'``
|
||||
Additional preamble content, default empty. See :doc:`latex`.
|
||||
Additional preamble content, default empty. See :doc:`/latex`.
|
||||
|
||||
``'atendofbody'``
|
||||
Additional document content (right before the indices), default empty.
|
||||
|
||||
.. versionadded:: 1.5
|
||||
|
||||
``'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
|
||||
@ -1920,6 +1944,7 @@ These options influence LaTeX output. See further :doc:`latex`.
|
||||
and position figures strictly in the order they appear in the source.
|
||||
|
||||
.. versionadded:: 1.3
|
||||
|
||||
``'footer'``
|
||||
Additional footer content (before the indices), default empty.
|
||||
|
||||
@ -1936,6 +1961,7 @@ These options influence LaTeX output. See further :doc:`latex`.
|
||||
.. versionadded:: 1.2
|
||||
.. versionchanged:: 1.6
|
||||
Added this documentation.
|
||||
|
||||
``'maxlistdepth'``
|
||||
LaTeX allows by default at most 6 levels for nesting list and
|
||||
quote-like environments, with at most 4 enumerated lists, and 4 bullet
|
||||
@ -1953,6 +1979,7 @@ These options influence LaTeX output. See further :doc:`latex`.
|
||||
dedicated commands of this LaTeX package.
|
||||
|
||||
.. versionadded:: 1.5
|
||||
|
||||
``'inputenc'``
|
||||
"inputenc" package inclusion, defaults to
|
||||
``'\\usepackage[utf8]{inputenc}'`` when using pdflatex.
|
||||
@ -1961,10 +1988,12 @@ These options influence LaTeX output. See further :doc:`latex`.
|
||||
.. versionchanged:: 1.4.3
|
||||
Previously ``'\\usepackage[utf8]{inputenc}'`` was used for all
|
||||
compilers.
|
||||
|
||||
``'cmappkg'``
|
||||
"cmap" package inclusion, default ``'\\usepackage{cmap}'``.
|
||||
|
||||
.. versionadded:: 1.2
|
||||
|
||||
``'fontenc'``
|
||||
"fontenc" package inclusion, default ``'\\usepackage[T1]{fontenc}'``.
|
||||
|
||||
@ -1973,6 +2002,7 @@ These options influence LaTeX output. See further :doc:`latex`.
|
||||
:confval:`latex_engine` is ``'xelatex'``.
|
||||
.. versionchanged:: 1.6
|
||||
``'lualatex'`` also uses ``fontspec`` per default.
|
||||
|
||||
``'geometry'``
|
||||
"geometry" package inclusion, the default definition is:
|
||||
|
||||
@ -2003,6 +2033,7 @@ These options influence LaTeX output. See further :doc:`latex`.
|
||||
width will be set to an integer multiple of the *zenkaku* width, and
|
||||
the text height to an integer multiple of the baseline. See the
|
||||
:ref:`hmargin <latexsphinxsetuphmargin>` documentation for more.
|
||||
|
||||
``'hyperref'``
|
||||
"hyperref" package inclusion; also loads package "hypcap" and issues
|
||||
``\urlstyle{same}``. This is done after :file:`sphinx.sty` file is
|
||||
@ -2014,15 +2045,17 @@ These options influence LaTeX output. See further :doc:`latex`.
|
||||
|
||||
.. versionadded:: 1.5
|
||||
Previously this was done from inside :file:`sphinx.sty`.
|
||||
|
||||
``'maketitle'``
|
||||
"maketitle" call, default ``'\\maketitle'`` (but it has been
|
||||
redefined by the Sphinx ``manual`` and ``howto`` classes.) Override
|
||||
if you want to
|
||||
generate a differently-styled title page.
|
||||
if you want to generate a differently-styled title page.
|
||||
|
||||
``'releasename'``
|
||||
value that prefixes ``'release'`` element on title page, default
|
||||
``'Release'``. As for *title* and *author* used in the tuples of
|
||||
:confval:`latex_documents`, it is inserted as LaTeX markup.
|
||||
|
||||
``'tableofcontents'``
|
||||
"tableofcontents" call, default ``'\\sphinxtableofcontents'`` (it is a
|
||||
wrapper of unmodified ``\tableofcontents``, which may itself be
|
||||
@ -2035,6 +2068,7 @@ These options influence LaTeX output. See further :doc:`latex`.
|
||||
Previously the meaning of ``\tableofcontents`` itself was modified
|
||||
by Sphinx. This created an incompatibility with dedicated packages
|
||||
modifying it also such as "tocloft" or "etoc".
|
||||
|
||||
``'transition'``
|
||||
Commands used to display transitions, default
|
||||
``'\n\n\\bigskip\\hrule\\bigskip\n\n'``. Override if you want to
|
||||
@ -2043,12 +2077,14 @@ These options influence LaTeX output. See further :doc:`latex`.
|
||||
.. versionadded:: 1.2
|
||||
.. versionchanged:: 1.6
|
||||
Remove unneeded ``{}`` after ``\\hrule``.
|
||||
|
||||
``'printindex'``
|
||||
"printindex" call, the last thing in the file, default
|
||||
``'\\printindex'``. Override if you want to generate the index
|
||||
differently or append some content after the index. For example
|
||||
``'\\footnotesize\\raggedright\\printindex'`` is advisable when the
|
||||
index is full of long entries.
|
||||
|
||||
``'fvset'``
|
||||
Customization of ``fancyvrb`` LaTeX package. Defaults to
|
||||
``'\\fvset{fontsize=\\small}'``, because default font (Courier) used in
|
||||
@ -2059,6 +2095,7 @@ These options influence LaTeX output. See further :doc:`latex`.
|
||||
one unified typeface family (Latin Modern OpenType).
|
||||
|
||||
.. versionadded:: 1.8
|
||||
|
||||
* Keys that are set by other options and therefore should not be overridden
|
||||
are:
|
||||
|
||||
@ -2087,19 +2124,20 @@ These options influence LaTeX output. See further :doc:`latex`.
|
||||
|
||||
.. confval:: latex_additional_files
|
||||
|
||||
A list of file names, relative to the configuration directory, to copy to the
|
||||
build directory when building LaTeX output. This is useful to copy files
|
||||
that Sphinx doesn't copy automatically, e.g. if they are referenced in custom
|
||||
LaTeX added in ``latex_elements``. Image files that are referenced in source
|
||||
files (e.g. via ``.. image::``) are copied automatically.
|
||||
A list of file names, relative to the configuration directory, to copy to
|
||||
the build directory when building LaTeX output. This is useful to copy
|
||||
files that Sphinx doesn't copy automatically, e.g. if they are referenced in
|
||||
custom LaTeX added in ``latex_elements``. Image files that are referenced
|
||||
in source files (e.g. via ``.. image::``) are copied automatically.
|
||||
|
||||
You have to make sure yourself that the filenames don't collide with those of
|
||||
any automatically copied files.
|
||||
You have to make sure yourself that the filenames don't collide with those
|
||||
of any automatically copied files.
|
||||
|
||||
.. versionadded:: 0.6
|
||||
|
||||
.. versionchanged:: 1.2
|
||||
This overrides the files which is provided from Sphinx such as sphinx.sty.
|
||||
This overrides the files which is provided from Sphinx such as
|
||||
``sphinx.sty``.
|
||||
|
||||
|
||||
.. _text-options:
|
||||
@ -2141,8 +2179,8 @@ These options influence text output.
|
||||
|
||||
.. confval:: text_secnumber_suffix
|
||||
|
||||
Suffix for section numbers in text output. Default: ``". "``. Set to ``" "``
|
||||
to suppress the final dot on section numbers.
|
||||
Suffix for section numbers in text output. Default: ``". "``. Set to
|
||||
``" "`` to suppress the final dot on section numbers.
|
||||
|
||||
.. versionadded:: 1.7
|
||||
|
||||
@ -2160,20 +2198,27 @@ These options influence manual page output.
|
||||
must be a list of tuples ``(startdocname, name, description, authors,
|
||||
section)``, where the items are:
|
||||
|
||||
* *startdocname*: document name that is the "root" of the manual page. All
|
||||
documents referenced by it in TOC trees will be included in the manual file
|
||||
too. (If you want one master manual page, use your :confval:`master_doc`
|
||||
here.)
|
||||
* *name*: name of the manual page. This should be a short string without
|
||||
spaces or special characters. It is used to determine the file name as
|
||||
well as the name of the manual page (in the NAME section).
|
||||
* *description*: description of the manual page. This is used in the NAME
|
||||
section.
|
||||
* *authors*: A list of strings with authors, or a single string. Can be an
|
||||
empty string or list if you do not want to automatically generate an
|
||||
AUTHORS section in the manual page.
|
||||
* *section*: The manual page section. Used for the output file name as well
|
||||
as in the manual page header.
|
||||
*startdocname*
|
||||
Document name that is the "root" of the manual page. All documents
|
||||
referenced by it in TOC trees will be included in the manual file too.
|
||||
(If you want one master manual page, use your :confval:`master_doc` here.)
|
||||
|
||||
*name*
|
||||
Name of the manual page. This should be a short string without spaces or
|
||||
special characters. It is used to determine the file name as well as the
|
||||
name of the manual page (in the NAME section).
|
||||
|
||||
*description*
|
||||
Description of the manual page. This is used in the NAME section.
|
||||
|
||||
*authors*
|
||||
A list of strings with authors, or a single string. Can be an empty
|
||||
string or list if you do not want to automatically generate an AUTHORS
|
||||
section in the manual page.
|
||||
|
||||
*section*
|
||||
The manual page section. Used for the output file name as well as in the
|
||||
manual page header.
|
||||
|
||||
.. versionadded:: 1.0
|
||||
|
||||
@ -2198,27 +2243,38 @@ These options influence Texinfo output.
|
||||
author, dir_entry, description, category, toctree_only)``, where the items
|
||||
are:
|
||||
|
||||
* *startdocname*: document name that is the "root" of the Texinfo file. All
|
||||
documents referenced by it in TOC trees will be included in the Texinfo
|
||||
file too. (If you want only one Texinfo file, use your
|
||||
:confval:`master_doc` here.)
|
||||
* *targetname*: file name (no extension) of the Texinfo file in the output
|
||||
directory.
|
||||
* *title*: Texinfo document title. Can be empty to use the title of the
|
||||
*startdoc*. Inserted as Texinfo markup, so special characters like @ and
|
||||
{} will need to be escaped to be inserted literally.
|
||||
* *author*: Author for the Texinfo document. Inserted as Texinfo markup.
|
||||
Use ``@*`` to separate multiple authors, as in: ``'John@*Sarah'``.
|
||||
* *dir_entry*: The name that will appear in the top-level ``DIR`` menu file.
|
||||
* *description*: Descriptive text to appear in the top-level ``DIR`` menu
|
||||
file.
|
||||
* *category*: Specifies the section which this entry will appear in the
|
||||
top-level ``DIR`` menu file.
|
||||
* *toctree_only*: Must be ``True`` or ``False``. If true, the *startdoc*
|
||||
document itself is not included in the output, only the documents
|
||||
referenced by it via TOC trees. With this option, you can put extra stuff
|
||||
in the master document that shows up in the HTML, but not the Texinfo
|
||||
output.
|
||||
*startdocname*
|
||||
Document name that is the "root" of the Texinfo file. All documents
|
||||
referenced by it in TOC trees will be included in the Texinfo file too.
|
||||
(If you want only one Texinfo file, use your :confval:`master_doc` here.)
|
||||
|
||||
*targetname*
|
||||
File name (no extension) of the Texinfo file in the output directory.
|
||||
|
||||
*title*
|
||||
Texinfo document title. Can be empty to use the title of the *startdoc*.
|
||||
Inserted as Texinfo markup, so special characters like ``@`` and ``{}``
|
||||
will need to be escaped to be inserted literally.
|
||||
|
||||
*author*
|
||||
Author for the Texinfo document. Inserted as Texinfo markup. Use ``@*``
|
||||
to separate multiple authors, as in: ``'John@*Sarah'``.
|
||||
|
||||
*dir_entry*
|
||||
The name that will appear in the top-level ``DIR`` menu file.
|
||||
|
||||
*description*
|
||||
Descriptive text to appear in the top-level ``DIR`` menu file.
|
||||
|
||||
*category*
|
||||
Specifies the section which this entry will appear in the top-level
|
||||
``DIR`` menu file.
|
||||
|
||||
*toctree_only*
|
||||
Must be ``True`` or ``False``. If true, the *startdoc* document itself is
|
||||
not included in the output, only the documents referenced by it via TOC
|
||||
trees. With this option, you can put extra stuff in the master document
|
||||
that shows up in the HTML, but not the Texinfo output.
|
||||
|
||||
.. versionadded:: 1.1
|
||||
|
||||
@ -2304,7 +2360,8 @@ builder, the HTML options also apply where appropriate.
|
||||
|
||||
.. confval:: qthelp_basename
|
||||
|
||||
The basename for the qthelp file. It defaults to the :confval:`project` name.
|
||||
The basename for the qthelp file. It defaults to the :confval:`project`
|
||||
name.
|
||||
|
||||
.. confval:: qthelp_namespace
|
||||
|
||||
@ -2369,7 +2426,7 @@ Options for the linkcheck builder
|
||||
A list of regular expressions that match URIs that should skip checking
|
||||
the validity of anchors in links. This allows skipping entire sites, where
|
||||
anchors are used to control dynamic pages, or just specific anchors within
|
||||
a page, where javascript is used to add anchors dynamically, or use the
|
||||
a page, where JavaScript is used to add anchors dynamically, or use the
|
||||
fragment as part of to trigger an internal REST request. Default is
|
||||
``["/#!"]``.
|
||||
|
||||
@ -2390,8 +2447,8 @@ Options for the XML builder
|
||||
|
||||
.. [1] A note on available globbing syntax: you can use the standard shell
|
||||
constructs ``*``, ``?``, ``[...]`` and ``[!...]`` with the feature that
|
||||
these all don't match slashes. A double star ``**`` can be used to match
|
||||
any sequence of characters *including* slashes.
|
||||
these all don't match slashes. A double star ``**`` can be used to
|
||||
match any sequence of characters *including* slashes.
|
||||
|
||||
|
||||
.. _cpp-config:
|
||||
@ -2401,29 +2458,32 @@ Options for the C++ domain
|
||||
|
||||
.. confval:: cpp_index_common_prefix
|
||||
|
||||
A list of prefixes that will be ignored when sorting C++ objects in the global index.
|
||||
For example ``['awesome_lib::']``.
|
||||
A list of prefixes that will be ignored when sorting C++ objects in the
|
||||
global index. For example ``['awesome_lib::']``.
|
||||
|
||||
.. versionadded:: 1.5
|
||||
|
||||
.. confval:: cpp_id_attributes
|
||||
|
||||
A list of strings that the parser additionally should accept as attributes.
|
||||
This can for example be used when attributes have been ``#define`` d for portability.
|
||||
This can for example be used when attributes have been ``#define`` d for
|
||||
portability.
|
||||
|
||||
.. versionadded:: 1.5
|
||||
|
||||
.. confval:: cpp_paren_attributes
|
||||
|
||||
A list of strings that the parser additionally should accept as attributes with one argument.
|
||||
That is, if ``my_align_as`` is in the list, then ``my_align_as(X)`` is parsed as an attribute
|
||||
for all strings ``X`` that have balanced brances (``()``, ``[]``, and ``{}``).
|
||||
This can for example be used when attributes have been ``#define`` d for portability.
|
||||
A list of strings that the parser additionally should accept as attributes
|
||||
with one argument. That is, if ``my_align_as`` is in the list, then
|
||||
``my_align_as(X)`` is parsed as an attribute for all strings ``X`` that have
|
||||
balanced brances (``()``, ``[]``, and ``{}``). This can for example be used
|
||||
when attributes have been ``#define`` d for portability.
|
||||
|
||||
.. versionadded:: 1.5
|
||||
|
||||
|
||||
Example of configuration file
|
||||
=============================
|
||||
|
||||
.. literalinclude:: _static/conf.py.txt
|
||||
.. literalinclude:: /_static/conf.py.txt
|
||||
:language: python
|
47
doc/usage/markdown.rst
Normal file
47
doc/usage/markdown.rst
Normal file
@ -0,0 +1,47 @@
|
||||
.. highlight:: python
|
||||
|
||||
.. _markdown:
|
||||
|
||||
========
|
||||
Markdown
|
||||
========
|
||||
|
||||
`Markdown`__ is a lightweight markup language with a simplistic plain text
|
||||
formatting syntax. It exists in many syntactically different *flavors*. To
|
||||
support Markdown-based documentation, Sphinx can use `recommonmark`__.
|
||||
recommonmark is a Docutils bridge to `CommonMark-py`__, a Python package for
|
||||
parsing the `CommonMark`__ Markdown flavor.
|
||||
|
||||
__ https://daringfireball.net/projects/markdown/
|
||||
__ https://recommonmark.readthedocs.io/en/latest/index.html
|
||||
__ https://github.com/rtfd/CommonMark-py
|
||||
__ http://commonmark.org/
|
||||
|
||||
Configuration
|
||||
-------------
|
||||
|
||||
To configure your Sphinx project for Markdown support, proceed as follows:
|
||||
|
||||
#. Install *recommonmark*::
|
||||
|
||||
pip install recommonmark
|
||||
|
||||
#. Add the Markdown parser to the ``source_parsers`` configuration variable in
|
||||
your Sphinx configuration file::
|
||||
|
||||
source_parsers = {
|
||||
'.md': 'recommonmark.parser.CommonMarkParser',
|
||||
}
|
||||
|
||||
You can replace ``.md`` with a filename extension of your choice.
|
||||
|
||||
#. Add the Markdown filename extension to the ``source_suffix`` configuration
|
||||
variable::
|
||||
|
||||
source_suffix = ['.rst', '.md']
|
||||
|
||||
#. You can further configure *recommonmark* to allow custom syntax that
|
||||
standard *CommonMark* doesn't support. Read more in the `recommonmark
|
||||
documentation`__.
|
||||
|
||||
__ https://recommonmark.readthedocs.io/en/latest/auto_structify.html
|
@ -236,7 +236,8 @@ so on. The file is saved in UTF-8 by default, as indicated by the encoding
|
||||
declaration in the first line. If you use non-ASCII characters in any string
|
||||
value, you need to use Python Unicode strings (like ``project = u'Exposé'``).
|
||||
|
||||
|more| See :ref:`build-config` for documentation of all available config values.
|
||||
|more| See :doc:`/usage/configuration` for documentation of all available
|
||||
config values.
|
||||
|
||||
|
||||
.. todo:: Move this entire doc to a different section
|
||||
|
@ -1,4 +1,4 @@
|
||||
.. highlightlang:: rst
|
||||
.. highlight:: rst
|
||||
|
||||
.. _rst-primer:
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
.. highlightlang:: rst
|
||||
.. highlight:: rst
|
||||
|
||||
===========
|
||||
Field Lists
|
||||
|
@ -26,14 +26,13 @@ from six.moves import cStringIO
|
||||
|
||||
import sphinx
|
||||
from sphinx import package_dir, locale
|
||||
from sphinx.config import Config
|
||||
from sphinx.config import Config, check_unicode
|
||||
from sphinx.config import CONFIG_FILENAME # NOQA # for compatibility (RemovedInSphinx30)
|
||||
from sphinx.deprecation import (
|
||||
RemovedInSphinx20Warning, RemovedInSphinx30Warning, RemovedInSphinx40Warning
|
||||
)
|
||||
from sphinx.environment import BuildEnvironment
|
||||
from sphinx.errors import (
|
||||
ApplicationError, ConfigError, ExtensionError, VersionRequirementError
|
||||
)
|
||||
from sphinx.errors import ApplicationError, ConfigError, VersionRequirementError
|
||||
from sphinx.events import EventManager
|
||||
from sphinx.locale import __
|
||||
from sphinx.registry import SphinxComponentRegistry
|
||||
@ -110,7 +109,6 @@ builtin_extensions = (
|
||||
'alabaster',
|
||||
) # type: Tuple[unicode, ...]
|
||||
|
||||
CONFIG_FILENAME = 'conf.py'
|
||||
ENV_PICKLE_FILENAME = 'environment.pickle'
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
@ -189,10 +187,11 @@ class Sphinx(object):
|
||||
|
||||
# read config
|
||||
self.tags = Tags(tags)
|
||||
self.config = Config(self.confdir, CONFIG_FILENAME,
|
||||
confoverrides or {}, self.tags)
|
||||
self.config.check_unicode()
|
||||
# defer checking types until i18n has been initialized
|
||||
if self.confdir is None:
|
||||
self.config = Config({}, confoverrides or {})
|
||||
else:
|
||||
self.config = Config.read(self.confdir, confoverrides or {}, self.tags)
|
||||
check_unicode(self.config)
|
||||
|
||||
# initialize some limited config variables before initialize i18n and loading
|
||||
# extensions
|
||||
@ -250,8 +249,6 @@ class Sphinx(object):
|
||||
|
||||
# create the builder
|
||||
self.builder = self.create_builder(buildername)
|
||||
# check all configuration values for permissible types
|
||||
self.config.check_types()
|
||||
# set up the build environment
|
||||
self._init_env(freshenv)
|
||||
# set up the builder
|
||||
@ -561,8 +558,6 @@ class Sphinx(object):
|
||||
"""
|
||||
logger.debug('[app] adding config value: %r',
|
||||
(name, default, rebuild) + ((types,) if types else ())) # type: ignore
|
||||
if name in self.config:
|
||||
raise ExtensionError(__('Config value %r already present') % name)
|
||||
if rebuild in (False, True):
|
||||
rebuild = rebuild and 'env' or ''
|
||||
self.config.add(name, default, rebuild, types)
|
||||
|
@ -9,19 +9,23 @@
|
||||
:license: BSD, see LICENSE for details.
|
||||
"""
|
||||
|
||||
import time
|
||||
import warnings
|
||||
from os import path
|
||||
|
||||
from docutils import nodes
|
||||
from six.moves import cPickle as pickle
|
||||
|
||||
from sphinx.deprecation import RemovedInSphinx20Warning
|
||||
from sphinx.environment import BuildEnvironment
|
||||
from sphinx.environment.adapters.asset import ImageAdapter
|
||||
from sphinx.errors import SphinxError
|
||||
from sphinx.io import read_doc
|
||||
from sphinx.locale import __
|
||||
from sphinx.util import i18n, import_object, logging, status_iterator
|
||||
from sphinx.util import i18n, import_object, logging, rst, status_iterator
|
||||
from sphinx.util.build_phase import BuildPhase
|
||||
from sphinx.util.console import bold # type: ignore
|
||||
from sphinx.util.docutils import sphinx_domains
|
||||
from sphinx.util.i18n import find_catalog
|
||||
from sphinx.util.osutil import SEP, ensuredir, relative_uri, relpath
|
||||
from sphinx.util.parallel import ParallelTasks, SerialTasks, make_chunks, \
|
||||
@ -478,7 +482,7 @@ class Builder(object):
|
||||
# remove all inventory entries for that file
|
||||
self.app.emit('env-purge-doc', self.env, docname)
|
||||
self.env.clear_doc(docname)
|
||||
self.env.read_doc(docname, self.app)
|
||||
self.read_doc(docname)
|
||||
|
||||
def _read_parallel(self, docnames, nproc):
|
||||
# type: (List[unicode], int) -> None
|
||||
@ -491,7 +495,7 @@ class Builder(object):
|
||||
# type: (List[unicode]) -> unicode
|
||||
self.env.app = self.app
|
||||
for docname in docs:
|
||||
self.env.read_doc(docname, self.app)
|
||||
self.read_doc(docname)
|
||||
# allow pickling self to send it back
|
||||
return BuildEnvironment.dumps(self.env)
|
||||
|
||||
@ -511,6 +515,47 @@ class Builder(object):
|
||||
logger.info(bold('waiting for workers...'))
|
||||
tasks.join()
|
||||
|
||||
def read_doc(self, docname):
|
||||
# type: (unicode) -> None
|
||||
"""Parse a file and add/update inventory entries for the doctree."""
|
||||
self.env.prepare_settings(docname)
|
||||
|
||||
# Add confdir/docutils.conf to dependencies list if exists
|
||||
docutilsconf = path.join(self.confdir, 'docutils.conf')
|
||||
if path.isfile(docutilsconf):
|
||||
self.env.note_dependency(docutilsconf)
|
||||
|
||||
with sphinx_domains(self.env), rst.default_role(docname, self.config.default_role):
|
||||
doctree = read_doc(self.app, self.env, self.env.doc2path(docname))
|
||||
|
||||
# store time of reading, for outdated files detection
|
||||
# (Some filesystems have coarse timestamp resolution;
|
||||
# therefore time.time() can be older than filesystem's timestamp.
|
||||
# For example, FAT32 has 2sec timestamp resolution.)
|
||||
self.env.all_docs[docname] = max(time.time(),
|
||||
path.getmtime(self.env.doc2path(docname)))
|
||||
|
||||
# cleanup
|
||||
self.env.temp_data.clear()
|
||||
self.env.ref_context.clear()
|
||||
|
||||
self.write_doctree(docname, doctree)
|
||||
|
||||
def write_doctree(self, docname, doctree):
|
||||
# type: (unicode, nodes.Node) -> None
|
||||
"""Write the doctree to a file."""
|
||||
# make it picklable
|
||||
doctree.reporter = None
|
||||
doctree.transformer = None
|
||||
doctree.settings.warning_stream = None
|
||||
doctree.settings.env = None
|
||||
doctree.settings.record_dependencies = None
|
||||
|
||||
doctree_filename = self.env.doc2path(docname, self.env.doctreedir, '.doctree')
|
||||
ensuredir(path.dirname(doctree_filename))
|
||||
with open(doctree_filename, 'wb') as f:
|
||||
pickle.dump(doctree, f, pickle.HIGHEST_PROTOCOL)
|
||||
|
||||
def write(self, build_docnames, updated_docnames, method='update'):
|
||||
# type: (Iterable[unicode], Sequence[unicode], unicode) -> None
|
||||
if build_docnames is None or build_docnames == ['__all__']:
|
||||
|
@ -355,7 +355,7 @@ class StandaloneHTMLBuilder(Builder):
|
||||
continue
|
||||
|
||||
if '://' not in filename:
|
||||
filename = path.join('_static', filename)
|
||||
filename = posixpath.join('_static', filename)
|
||||
|
||||
self.css_files.append(Stylesheet(filename, **attrs)) # type: ignore
|
||||
|
||||
|
@ -323,7 +323,7 @@ def setup(app):
|
||||
app.add_config_value('latex_appendices', [], None)
|
||||
app.add_config_value('latex_use_latex_multicolumn', False, None)
|
||||
app.add_config_value('latex_toplevel_sectioning', None, None,
|
||||
ENUM('part', 'chapter', 'section'))
|
||||
ENUM(None, 'part', 'chapter', 'section'))
|
||||
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)
|
||||
|
@ -269,7 +269,7 @@ class QtHelpBuilder(StandaloneHTMLBuilder):
|
||||
resourcedir = root.startswith((staticdir, imagesdir))
|
||||
for fn in sorted(files):
|
||||
if (resourcedir and not fn.endswith('.js')) or fn.endswith('.html'):
|
||||
filename = path.join(root, fn)[olen:]
|
||||
filename = posixpath.join(root, fn)[olen:]
|
||||
project_files.append(filename)
|
||||
|
||||
return project_files
|
||||
|
@ -293,7 +293,8 @@ def build_main(argv=sys.argv[1:]): # type: ignore
|
||||
|
||||
app = None
|
||||
try:
|
||||
with patch_docutils(), docutils_namespace():
|
||||
confdir = args.confdir or args.sourcedir
|
||||
with patch_docutils(confdir), docutils_namespace():
|
||||
app = Sphinx(args.sourcedir, args.confdir, args.outputdir,
|
||||
args.doctreedir, args.builder, confoverrides, status,
|
||||
warning, args.freshenv, args.warningiserror,
|
||||
|
248
sphinx/config.py
248
sphinx/config.py
@ -11,13 +11,15 @@
|
||||
|
||||
import re
|
||||
import traceback
|
||||
import warnings
|
||||
from collections import OrderedDict
|
||||
from os import path, getenv
|
||||
from typing import Any, NamedTuple, Union
|
||||
|
||||
from six import PY2, PY3, iteritems, string_types, binary_type, text_type, integer_types
|
||||
|
||||
from sphinx.errors import ConfigError
|
||||
from sphinx.deprecation import RemovedInSphinx30Warning
|
||||
from sphinx.errors import ConfigError, ExtensionError
|
||||
from sphinx.locale import _, __
|
||||
from sphinx.util import logging
|
||||
from sphinx.util.i18n import format_date
|
||||
@ -26,28 +28,15 @@ from sphinx.util.pycompat import execfile_, NoneType
|
||||
|
||||
if False:
|
||||
# For type annotation
|
||||
from typing import Any, Callable, Dict, Iterable, Iterator, List, Tuple, Union # NOQA
|
||||
from typing import Any, Callable, Dict, Generator, Iterator, List, Tuple, Union # NOQA
|
||||
from sphinx.application import Sphinx # NOQA
|
||||
from sphinx.util.tags import Tags # NOQA
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
nonascii_re = re.compile(br'[\x80-\xff]')
|
||||
CONFIG_FILENAME = 'conf.py'
|
||||
copyright_year_re = re.compile(r'^((\d{4}-)?)(\d{4})(?=[ ,])')
|
||||
|
||||
CONFIG_SYNTAX_ERROR = __("There is a syntax error in your configuration file: %s")
|
||||
if PY3:
|
||||
CONFIG_SYNTAX_ERROR += __("\nDid you change the syntax from 2.x to 3.x?")
|
||||
CONFIG_ERROR = __("There is a programable error in your configuration file:\n\n%s")
|
||||
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_PERMITTED_TYPE_WARNING = __("The config value `{name}' has type `{current.__name__}', "
|
||||
"expected to {permitted}.")
|
||||
CONFIG_TYPE_WARNING = __("The config value `{name}' has type `{current.__name__}', "
|
||||
"defaults to `{default.__name__}'.")
|
||||
|
||||
if PY3:
|
||||
unicode = str # special alias for static typing...
|
||||
|
||||
@ -155,30 +144,30 @@ class Config(object):
|
||||
'env'),
|
||||
) # type: Dict[unicode, Tuple]
|
||||
|
||||
def __init__(self, dirname, filename, overrides, tags):
|
||||
# type: (unicode, unicode, Dict, Tags) -> None
|
||||
def __init__(self, *args):
|
||||
# type: (Any) -> None
|
||||
if len(args) == 4:
|
||||
# old style arguments: (dirname, filename, overrides, tags)
|
||||
warnings.warn('The argument of Config() class has been changed. '
|
||||
'Use Config.read() to read configuration from conf.py.',
|
||||
RemovedInSphinx30Warning)
|
||||
dirname, filename, overrides, tags = args
|
||||
if dirname is None:
|
||||
config = {} # type: Dict[unicode, Any]
|
||||
else:
|
||||
config = eval_config_file(path.join(dirname, filename), tags)
|
||||
else:
|
||||
# new style arguments: (config={}, overrides={})
|
||||
if len(args) == 0:
|
||||
config, overrides = {}, {}
|
||||
elif len(args) == 1:
|
||||
config, overrides = args[0], {}
|
||||
else:
|
||||
config, overrides = args[:2]
|
||||
|
||||
self.overrides = overrides
|
||||
self.values = Config.config_values.copy()
|
||||
config = {} # type: Dict[unicode, Any]
|
||||
if dirname is not None:
|
||||
config_file = path.join(dirname, filename)
|
||||
config['__file__'] = config_file
|
||||
config['tags'] = tags
|
||||
with cd(dirname):
|
||||
# we promise to have the config dir as current dir while the
|
||||
# config file is executed
|
||||
try:
|
||||
execfile_(filename, config)
|
||||
except SyntaxError as err:
|
||||
raise ConfigError(CONFIG_SYNTAX_ERROR % err)
|
||||
except SystemExit:
|
||||
raise ConfigError(CONFIG_EXIT_ERROR)
|
||||
except Exception:
|
||||
raise ConfigError(CONFIG_ERROR % traceback.format_exc())
|
||||
|
||||
self._raw_config = config
|
||||
# these two must be preinitialized because extensions can add their
|
||||
# own config values
|
||||
self.setup = config.get('setup', None) # type: Callable
|
||||
|
||||
if 'extensions' in overrides:
|
||||
@ -188,69 +177,25 @@ class Config(object):
|
||||
config['extensions'] = overrides.pop('extensions')
|
||||
self.extensions = config.get('extensions', []) # type: List[unicode]
|
||||
|
||||
# correct values of copyright year that are not coherent with
|
||||
# the SOURCE_DATE_EPOCH environment variable (if set)
|
||||
# See https://reproducible-builds.org/specs/source-date-epoch/
|
||||
if getenv('SOURCE_DATE_EPOCH') is not None:
|
||||
for k in ('copyright', 'epub_copyright'):
|
||||
if k in config:
|
||||
config[k] = copyright_year_re.sub(r'\g<1>%s' % format_date('%Y'),
|
||||
config[k])
|
||||
@classmethod
|
||||
def read(cls, confdir, overrides=None, tags=None):
|
||||
# type: (unicode, Dict, Tags) -> Config
|
||||
"""Create a Config object from configuration file."""
|
||||
filename = path.join(confdir, CONFIG_FILENAME)
|
||||
namespace = eval_config_file(filename, tags)
|
||||
return cls(namespace, overrides or {})
|
||||
|
||||
def check_types(self):
|
||||
# type: () -> None
|
||||
# check all values for deviation from the default value's type, since
|
||||
# that can result in TypeErrors all over the place
|
||||
# NB. since config values might use _() we have to wait with calling
|
||||
# this method until i18n is initialized
|
||||
for name in self._raw_config:
|
||||
if name not in self.values:
|
||||
continue # we don't know a default value
|
||||
settings = self.values[name]
|
||||
default, dummy_rebuild = settings[:2]
|
||||
permitted = settings[2] if len(settings) == 3 else ()
|
||||
|
||||
if hasattr(default, '__call__'):
|
||||
default = default(self) # could invoke _()
|
||||
if default is None and not permitted:
|
||||
continue # neither inferrable nor expliclitly permitted types
|
||||
current = self[name]
|
||||
if permitted is Any:
|
||||
# any type of value is accepted
|
||||
pass
|
||||
elif isinstance(permitted, ENUM):
|
||||
if not permitted.match(current):
|
||||
logger.warning(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
|
||||
|
||||
if permitted:
|
||||
logger.warning(CONFIG_PERMITTED_TYPE_WARNING.format(
|
||||
name=name, current=type(current),
|
||||
permitted=str([cls.__name__ for cls in permitted])))
|
||||
else:
|
||||
logger.warning(CONFIG_TYPE_WARNING.format(
|
||||
name=name, current=type(current), default=type(default)))
|
||||
warnings.warn('Config.check_types() is deprecated. Use check_confval_types() instead.',
|
||||
RemovedInSphinx30Warning)
|
||||
check_confval_types(None, self)
|
||||
|
||||
def check_unicode(self):
|
||||
# type: () -> None
|
||||
# check all string values for non-ASCII characters in bytestrings,
|
||||
# since that can result in UnicodeErrors all over the place
|
||||
for name, value in iteritems(self._raw_config):
|
||||
if isinstance(value, binary_type) and nonascii_re.search(value):
|
||||
logger.warning(__('the config value %r is set to a string with non-ASCII '
|
||||
'characters; this can lead to Unicode errors occurring. '
|
||||
'Please use Unicode strings, e.g. %r.'), name, u'Content')
|
||||
warnings.warn('Config.check_unicode() is deprecated. Use check_unicode() instead.',
|
||||
RemovedInSphinx30Warning)
|
||||
check_unicode(self)
|
||||
|
||||
def convert_overrides(self, name, value):
|
||||
# type: (unicode, Any) -> Any
|
||||
@ -346,19 +291,49 @@ class Config(object):
|
||||
return name in self.values
|
||||
|
||||
def __iter__(self):
|
||||
# type: () -> Iterable[ConfigValue]
|
||||
# type: () -> Generator[ConfigValue, None, None]
|
||||
for name, value in iteritems(self.values):
|
||||
yield ConfigValue(name, getattr(self, name), value[1]) # type: ignore
|
||||
|
||||
def add(self, name, default, rebuild, types):
|
||||
# type: (unicode, Any, Union[bool, unicode], Any) -> None
|
||||
if name in self.values:
|
||||
raise ExtensionError(__('Config value %r already present') % name)
|
||||
else:
|
||||
self.values[name] = (default, rebuild, types)
|
||||
|
||||
def filter(self, rebuild):
|
||||
# type: (Union[unicode, List[unicode]]) -> Iterator[ConfigValue]
|
||||
if isinstance(rebuild, string_types):
|
||||
rebuild = [rebuild]
|
||||
return (value for value in self if value.rebuild in rebuild) # type: ignore
|
||||
return (value for value in self if value.rebuild in rebuild)
|
||||
|
||||
|
||||
def eval_config_file(filename, tags):
|
||||
# type: (unicode, Tags) -> Dict[unicode, Any]
|
||||
"""Evaluate a config file."""
|
||||
namespace = {} # type: Dict[unicode, Any]
|
||||
namespace['__file__'] = filename
|
||||
namespace['tags'] = tags
|
||||
|
||||
with cd(path.dirname(filename)):
|
||||
# during executing config file, current dir is changed to ``confdir``.
|
||||
try:
|
||||
execfile_(filename, namespace)
|
||||
except SyntaxError as err:
|
||||
msg = __("There is a syntax error in your configuration file: %s")
|
||||
if PY3:
|
||||
msg += __("\nDid you change the syntax from 2.x to 3.x?")
|
||||
raise ConfigError(msg % err)
|
||||
except SystemExit:
|
||||
msg = __("The configuration file (or one of the modules it imports) "
|
||||
"called sys.exit()")
|
||||
raise ConfigError(msg)
|
||||
except Exception:
|
||||
msg = __("There is a programable error in your configuration file:\n\n%s")
|
||||
raise ConfigError(msg % traceback.format_exc())
|
||||
|
||||
return namespace
|
||||
|
||||
|
||||
def convert_source_suffix(app, config):
|
||||
@ -400,10 +375,91 @@ def init_numfig_format(app, config):
|
||||
config.numfig_format = numfig_format # type: ignore
|
||||
|
||||
|
||||
def correct_copyright_year(app, config):
|
||||
# type: (Sphinx, Config) -> None
|
||||
"""correct values of copyright year that are not coherent with
|
||||
the SOURCE_DATE_EPOCH environment variable (if set)
|
||||
|
||||
See https://reproducible-builds.org/specs/source-date-epoch/
|
||||
"""
|
||||
if getenv('SOURCE_DATE_EPOCH') is not None:
|
||||
for k in ('copyright', 'epub_copyright'):
|
||||
if k in config:
|
||||
replace = r'\g<1>%s' % format_date('%Y')
|
||||
config[k] = copyright_year_re.sub(replace, config[k]) # type: ignore
|
||||
|
||||
|
||||
def check_confval_types(app, config):
|
||||
# type: (Sphinx, Config) -> None
|
||||
"""check all values for deviation from the default value's type, since
|
||||
that can result in TypeErrors all over the place NB.
|
||||
"""
|
||||
for confval in config:
|
||||
settings = config.values[confval.name]
|
||||
default = settings[0]
|
||||
annotations = settings[2] if len(settings) == 3 else ()
|
||||
|
||||
if hasattr(default, '__call__'):
|
||||
default = default(config) # evaluate default value
|
||||
if default is None and not annotations:
|
||||
continue # neither inferrable nor expliclitly annotated types
|
||||
|
||||
if annotations is Any:
|
||||
# any type of value is accepted
|
||||
pass
|
||||
elif isinstance(annotations, ENUM):
|
||||
if not annotations.match(confval.value):
|
||||
msg = __("The config value `{name}` has to be a one of {candidates}, "
|
||||
"but `{current}` is given.")
|
||||
logger.warning(msg.format(name=confval.name,
|
||||
current=confval.value,
|
||||
candidates=annotations.candidates))
|
||||
else:
|
||||
if type(confval.value) is type(default):
|
||||
continue
|
||||
if type(confval.value) in annotations:
|
||||
continue
|
||||
|
||||
common_bases = (set(type(confval.value).__bases__ + (type(confval.value),)) &
|
||||
set(type(default).__bases__))
|
||||
common_bases.discard(object)
|
||||
if common_bases:
|
||||
continue # at least we share a non-trivial base class
|
||||
|
||||
if annotations:
|
||||
msg = __("The config value `{name}' has type `{current.__name__}', "
|
||||
"expected to {permitted}.")
|
||||
logger.warning(msg.format(name=confval.name,
|
||||
current=type(confval.value),
|
||||
permitted=str([c.__name__ for c in annotations])))
|
||||
else:
|
||||
msg = __("The config value `{name}' has type `{current.__name__}', "
|
||||
"defaults to `{default.__name__}'.")
|
||||
logger.warning(msg.format(name=confval.name,
|
||||
current=type(confval.value),
|
||||
default=type(default)))
|
||||
|
||||
|
||||
def check_unicode(config):
|
||||
# type: (Config) -> None
|
||||
"""check all string values for non-ASCII characters in bytestrings,
|
||||
since that can result in UnicodeErrors all over the place
|
||||
"""
|
||||
nonascii_re = re.compile(br'[\x80-\xff]')
|
||||
|
||||
for name, value in iteritems(config._raw_config):
|
||||
if isinstance(value, binary_type) and nonascii_re.search(value):
|
||||
logger.warning(__('the config value %r is set to a string with non-ASCII '
|
||||
'characters; this can lead to Unicode errors occurring. '
|
||||
'Please use Unicode strings, e.g. %r.'), name, u'Content')
|
||||
|
||||
|
||||
def setup(app):
|
||||
# type: (Sphinx) -> Dict[unicode, Any]
|
||||
app.connect('config-inited', convert_source_suffix)
|
||||
app.connect('config-inited', init_numfig_format)
|
||||
app.connect('config-inited', correct_copyright_year)
|
||||
app.connect('config-inited', check_confval_types)
|
||||
|
||||
return {
|
||||
'version': 'builtin',
|
||||
|
@ -9,6 +9,7 @@
|
||||
|
||||
import codecs
|
||||
import sys
|
||||
import warnings
|
||||
from difflib import unified_diff
|
||||
|
||||
from docutils import nodes
|
||||
@ -17,6 +18,7 @@ from docutils.statemachine import ViewList
|
||||
from six import text_type
|
||||
|
||||
from sphinx import addnodes
|
||||
from sphinx.deprecation import RemovedInSphinx40Warning
|
||||
from sphinx.locale import __
|
||||
from sphinx.util import logging
|
||||
from sphinx.util import parselinenos
|
||||
@ -59,6 +61,17 @@ class Highlight(SphinxDirective):
|
||||
linenothreshold=linenothreshold)]
|
||||
|
||||
|
||||
class HighlightLang(Highlight):
|
||||
"""highlightlang directive (deprecated)"""
|
||||
|
||||
def run(self):
|
||||
# type: () -> List[nodes.Node]
|
||||
warnings.warn('highlightlang directive is deprecated. '
|
||||
'Please use highlight directive instead.',
|
||||
RemovedInSphinx40Warning)
|
||||
return Highlight.run(self)
|
||||
|
||||
|
||||
def dedent_lines(lines, dedent, location=None):
|
||||
# type: (List[unicode], int, Any) -> List[unicode]
|
||||
if not dedent:
|
||||
@ -462,7 +475,7 @@ class LiteralInclude(SphinxDirective):
|
||||
def setup(app):
|
||||
# type: (Sphinx) -> Dict[unicode, Any]
|
||||
directives.register_directive('highlight', Highlight)
|
||||
directives.register_directive('highlightlang', Highlight) # old
|
||||
directives.register_directive('highlightlang', HighlightLang)
|
||||
directives.register_directive('code-block', CodeBlock)
|
||||
directives.register_directive('sourcecode', CodeBlock)
|
||||
directives.register_directive('literalinclude', LiteralInclude)
|
||||
|
@ -12,14 +12,12 @@
|
||||
import os
|
||||
import re
|
||||
import sys
|
||||
import time
|
||||
import types
|
||||
import warnings
|
||||
from collections import defaultdict
|
||||
from copy import copy
|
||||
from os import path
|
||||
|
||||
from docutils.frontend import OptionParser
|
||||
from docutils.utils import Reporter, get_source_line
|
||||
from six import BytesIO, class_types, next
|
||||
from six.moves import cPickle as pickle
|
||||
@ -29,16 +27,15 @@ from sphinx.deprecation import RemovedInSphinx20Warning, RemovedInSphinx30Warnin
|
||||
from sphinx.environment.adapters.indexentries import IndexEntries
|
||||
from sphinx.environment.adapters.toctree import TocTree
|
||||
from sphinx.errors import SphinxError, ExtensionError
|
||||
from sphinx.io import read_doc
|
||||
from sphinx.locale import __
|
||||
from sphinx.transforms import SphinxTransformer
|
||||
from sphinx.util import get_matching_docs, FilenameUniqDict
|
||||
from sphinx.util import logging, rst
|
||||
from sphinx.util.docutils import sphinx_domains, WarningStream
|
||||
from sphinx.util import logging
|
||||
from sphinx.util.docutils import WarningStream
|
||||
from sphinx.util.i18n import find_catalog_files
|
||||
from sphinx.util.matching import compile_matchers
|
||||
from sphinx.util.nodes import is_translatable
|
||||
from sphinx.util.osutil import SEP, ensuredir, relpath
|
||||
from sphinx.util.osutil import SEP, relpath
|
||||
from sphinx.util.websupport import is_commentable
|
||||
|
||||
if False:
|
||||
@ -556,33 +553,6 @@ class BuildEnvironment(object):
|
||||
self.temp_data['default_domain'] = \
|
||||
self.domains.get(self.config.primary_domain)
|
||||
|
||||
def read_doc(self, docname, app=None):
|
||||
# type: (unicode, Sphinx) -> None
|
||||
"""Parse a file and add/update inventory entries for the doctree."""
|
||||
self.prepare_settings(docname)
|
||||
|
||||
docutilsconf = path.join(self.srcdir, 'docutils.conf')
|
||||
# read docutils.conf from source dir, not from current dir
|
||||
OptionParser.standard_config_files[1] = docutilsconf
|
||||
if path.isfile(docutilsconf):
|
||||
self.note_dependency(docutilsconf)
|
||||
|
||||
with sphinx_domains(self), rst.default_role(docname, self.config.default_role):
|
||||
doctree = read_doc(self.app, self, self.doc2path(docname))
|
||||
|
||||
# store time of reading, for outdated files detection
|
||||
# (Some filesystems have coarse timestamp resolution;
|
||||
# therefore time.time() can be older than filesystem's timestamp.
|
||||
# For example, FAT32 has 2sec timestamp resolution.)
|
||||
self.all_docs[docname] = max(
|
||||
time.time(), path.getmtime(self.doc2path(docname)))
|
||||
|
||||
# cleanup
|
||||
self.temp_data.clear()
|
||||
self.ref_context.clear()
|
||||
|
||||
self.write_doctree(docname, doctree)
|
||||
|
||||
# utilities to use while reading a document
|
||||
|
||||
@property
|
||||
@ -685,21 +655,6 @@ class BuildEnvironment(object):
|
||||
doctree.reporter = Reporter(self.doc2path(docname), 2, 5, stream=WarningStream())
|
||||
return doctree
|
||||
|
||||
def write_doctree(self, docname, doctree):
|
||||
# type: (unicode, nodes.Node) -> None
|
||||
"""Write the doctree to a file."""
|
||||
# make it picklable
|
||||
doctree.reporter = None
|
||||
doctree.transformer = None
|
||||
doctree.settings.warning_stream = None
|
||||
doctree.settings.env = None
|
||||
doctree.settings.record_dependencies = None
|
||||
|
||||
doctree_filename = self.doc2path(docname, self.doctreedir, '.doctree')
|
||||
ensuredir(path.dirname(doctree_filename))
|
||||
with open(doctree_filename, 'wb') as f:
|
||||
pickle.dump(doctree, f, pickle.HIGHEST_PROTOCOL)
|
||||
|
||||
def get_and_resolve_doctree(self, docname, builder, doctree=None,
|
||||
prune_toctrees=True, includehidden=False):
|
||||
# type: (unicode, Builder, nodes.Node, bool, bool) -> nodes.Node
|
||||
@ -849,6 +804,19 @@ class BuildEnvironment(object):
|
||||
RemovedInSphinx30Warning)
|
||||
return self.app.builder._read_parallel(docnames, nproc)
|
||||
|
||||
def read_doc(self, docname, app=None):
|
||||
# type: (unicode, Sphinx) -> None
|
||||
warnings.warn('env.read_doc() is deprecated. Please use builder.read_doc() instead.',
|
||||
RemovedInSphinx30Warning)
|
||||
self.app.builder.read_doc(docname)
|
||||
|
||||
def write_doctree(self, docname, doctree):
|
||||
# type: (unicode, nodes.Node) -> None
|
||||
warnings.warn('env.write_doctree() is deprecated. '
|
||||
'Please use builder.write_doctree() instead.',
|
||||
RemovedInSphinx30Warning)
|
||||
self.app.builder.write_doctree(docname, doctree)
|
||||
|
||||
@property
|
||||
def _nitpick_ignore(self):
|
||||
# type: () -> List[unicode]
|
||||
|
@ -20,8 +20,8 @@ from docutils.statemachine import ViewList
|
||||
from six import iteritems, itervalues, text_type, class_types, string_types
|
||||
|
||||
import sphinx
|
||||
from sphinx.application import ExtensionError
|
||||
from sphinx.deprecation import RemovedInSphinx20Warning
|
||||
from sphinx.errors import ExtensionError
|
||||
from sphinx.ext.autodoc.importer import mock, import_object, get_object_members
|
||||
from sphinx.ext.autodoc.importer import _MockImporter # to keep compatibility # NOQA
|
||||
from sphinx.ext.autodoc.inspector import format_annotation, formatargspec # to keep compatibility # NOQA
|
||||
|
@ -290,21 +290,27 @@ def render_dot_html(self, node, code, options, prefix='graphviz',
|
||||
self.body.append('<div align="%s" class="align-%s">' %
|
||||
(node['align'], node['align']))
|
||||
if format == 'svg':
|
||||
svgtag = '''<object data="%s" type="image/svg+xml">
|
||||
<p class="warning">%s</p></object>\n''' % (fname, alt)
|
||||
self.body.append(svgtag)
|
||||
self.body.append('<div class="graphviz">')
|
||||
self.body.append('<object data="%s" type="image/svg+xml" %s>\n' %
|
||||
(fname, imgcss))
|
||||
self.body.append('<p class="warning">%s</p>' % alt)
|
||||
self.body.append('</object></div>\n')
|
||||
else:
|
||||
with codecs.open(outfn + '.map', 'r', encoding='utf-8') as mapfile: # type: ignore
|
||||
imgmap = ClickableMapDefinition(outfn + '.map', mapfile.read(), dot=code)
|
||||
if imgmap.clickable:
|
||||
# has a map
|
||||
self.body.append('<img src="%s" alt="%s" usemap="#%s" %s/>\n' %
|
||||
self.body.append('<div class="graphviz">')
|
||||
self.body.append('<img src="%s" alt="%s" usemap="#%s" %s/>' %
|
||||
(fname, alt, imgmap.id, imgcss))
|
||||
self.body.append('</div>\n')
|
||||
self.body.append(imgmap.generate_clickable_map())
|
||||
else:
|
||||
# nothing in image map
|
||||
self.body.append('<img src="%s" alt="%s" %s/>\n' %
|
||||
self.body.append('<div class="graphviz">')
|
||||
self.body.append('<img src="%s" alt="%s" %s/>' %
|
||||
(fname, alt, imgcss))
|
||||
self.body.append('</div>\n')
|
||||
if 'align' in node:
|
||||
self.body.append('</div>\n')
|
||||
|
||||
|
@ -57,7 +57,7 @@ class IfConfig(Directive):
|
||||
|
||||
def process_ifconfig_nodes(app, doctree, docname):
|
||||
# type: (Sphinx, nodes.Node, unicode) -> None
|
||||
ns = dict((confval.name, confval.value) for confval in app.config) # type: ignore
|
||||
ns = dict((confval.name, confval.value) for confval in app.config)
|
||||
ns.update(app.config.__dict__.copy())
|
||||
ns['builder'] = app.builder.name
|
||||
for node in doctree.traverse(ifconfig):
|
||||
|
@ -13,7 +13,7 @@
|
||||
from docutils import nodes
|
||||
|
||||
import sphinx
|
||||
from sphinx.application import ExtensionError
|
||||
from sphinx.errors import ExtensionError
|
||||
from sphinx.ext.mathbase import get_node_equation_number
|
||||
from sphinx.ext.mathbase import setup_math as mathbase_setup
|
||||
from sphinx.locale import _
|
||||
|
@ -20,6 +20,7 @@
|
||||
import os
|
||||
import re
|
||||
import sys
|
||||
import warnings
|
||||
|
||||
from six import iteritems, PY3
|
||||
|
||||
@ -35,6 +36,7 @@ try:
|
||||
except ImportError:
|
||||
janome_module = False
|
||||
|
||||
from sphinx.deprecation import RemovedInSphinx30Warning
|
||||
from sphinx.errors import SphinxError, ExtensionError
|
||||
from sphinx.search import SearchLanguage
|
||||
from sphinx.util import import_object
|
||||
@ -556,9 +558,12 @@ class SearchJapanese(SearchLanguage):
|
||||
|
||||
def init(self, options):
|
||||
# type: (Dict) -> None
|
||||
type = options.get('type', 'default')
|
||||
type = options.get('type', 'sphinx.search.ja.DefaultSplitter')
|
||||
if type in self.splitters:
|
||||
dotted_path = self.splitters[type]
|
||||
warnings.warn('html_search_options["type"]: %s is deprecated. '
|
||||
'Please give "%s" instead.' % (type, dotted_path),
|
||||
RemovedInSphinx30Warning)
|
||||
else:
|
||||
dotted_path = type
|
||||
try:
|
||||
|
@ -179,7 +179,8 @@ class BuildDoc(Command):
|
||||
app = None
|
||||
|
||||
try:
|
||||
with patch_docutils(), docutils_namespace():
|
||||
confdir = self.config_dir or self.source_dir
|
||||
with patch_docutils(confdir), docutils_namespace():
|
||||
app = Sphinx(self.source_dir, self.config_dir,
|
||||
builder_target_dir, self.doctree_dir,
|
||||
builder, confoverrides, status_stream,
|
||||
|
@ -10,16 +10,17 @@
|
||||
"""
|
||||
from __future__ import absolute_import
|
||||
|
||||
import os
|
||||
import re
|
||||
import types
|
||||
import warnings
|
||||
from contextlib import contextmanager
|
||||
from copy import copy
|
||||
from distutils.version import LooseVersion
|
||||
from os import path
|
||||
|
||||
import docutils
|
||||
from docutils import nodes
|
||||
from docutils.languages import get_language
|
||||
from docutils.parsers.rst import Directive, directives, roles, convert_directive_function
|
||||
from docutils.statemachine import StateMachine
|
||||
from docutils.utils import Reporter
|
||||
@ -34,7 +35,7 @@ report_re = re.compile('^(.+?:(?:\\d+)?): \\((DEBUG|INFO|WARNING|ERROR|SEVERE)/(
|
||||
|
||||
if False:
|
||||
# For type annotation
|
||||
from typing import Any, Callable, Generator, Iterator, List, Set, Tuple # NOQA
|
||||
from typing import Any, Callable, Generator, List, Set, Tuple # NOQA
|
||||
from docutils.statemachine import State, ViewList # NOQA
|
||||
from sphinx.config import Config # NOQA
|
||||
from sphinx.environment import BuildEnvironment # NOQA
|
||||
@ -47,7 +48,7 @@ additional_nodes = set() # type: Set[nodes.Node]
|
||||
|
||||
@contextmanager
|
||||
def docutils_namespace():
|
||||
# type: () -> Iterator[None]
|
||||
# type: () -> Generator[None, None, None]
|
||||
"""Create namespace for reST parsers."""
|
||||
try:
|
||||
_directives = copy(directives._directives)
|
||||
@ -94,29 +95,53 @@ def unregister_node(node):
|
||||
delattr(nodes.SparseNodeVisitor, 'depart_' + node.__name__)
|
||||
|
||||
|
||||
def patched_get_language(language_code, reporter=None):
|
||||
# type: (unicode, Reporter) -> Any
|
||||
"""A wrapper for docutils.languages.get_language().
|
||||
@contextmanager
|
||||
def patched_get_language():
|
||||
# type: () -> Generator[None, None, None]
|
||||
"""Patch docutils.languages.get_language() temporarily.
|
||||
|
||||
This ignores the second argument ``reporter`` to suppress warnings.
|
||||
refs: https://github.com/sphinx-doc/sphinx/issues/3788
|
||||
"""
|
||||
from docutils.languages import get_language
|
||||
|
||||
def patched_get_language(language_code, reporter=None):
|
||||
# type: (unicode, Reporter) -> Any
|
||||
return get_language(language_code)
|
||||
|
||||
|
||||
@contextmanager
|
||||
def patch_docutils():
|
||||
# type: () -> Iterator[None]
|
||||
"""Patch to docutils temporarily."""
|
||||
try:
|
||||
docutils.languages.get_language = patched_get_language
|
||||
|
||||
yield
|
||||
finally:
|
||||
# restore original implementations
|
||||
docutils.languages.get_language = get_language
|
||||
|
||||
|
||||
@contextmanager
|
||||
def using_user_docutils_conf(confdir):
|
||||
# type: (unicode) -> Generator[None, None, None]
|
||||
"""Let docutils know the location of ``docutils.conf`` for Sphinx."""
|
||||
try:
|
||||
docutilsconfig = os.environ.get('DOCUTILSCONFIG', None)
|
||||
if confdir:
|
||||
os.environ['DOCUTILSCONFIG'] = path.join(path.abspath(confdir), 'docutils.conf') # type: ignore # NOQA
|
||||
|
||||
yield
|
||||
finally:
|
||||
if docutilsconfig is None:
|
||||
os.environ.pop('DOCUTILSCONFIG')
|
||||
else:
|
||||
os.environ['DOCUTILSCONFIG'] = docutilsconfig
|
||||
|
||||
|
||||
@contextmanager
|
||||
def patch_docutils(confdir=None):
|
||||
# type: (unicode) -> Generator[None, None, None]
|
||||
"""Patch to docutils temporarily."""
|
||||
with patched_get_language(), using_user_docutils_conf(confdir):
|
||||
yield
|
||||
|
||||
|
||||
class ElementLookupError(Exception):
|
||||
pass
|
||||
|
||||
@ -257,7 +282,7 @@ def directive_helper(obj, has_content=None, argument_spec=None, **option_spec):
|
||||
|
||||
@contextmanager
|
||||
def switch_source_input(state, content):
|
||||
# type: (State, ViewList) -> Generator
|
||||
# type: (State, ViewList) -> Generator[None, None, None]
|
||||
"""Switch current source input of state temporarily."""
|
||||
try:
|
||||
# remember the original ``get_source_and_line()`` method
|
||||
|
@ -74,6 +74,10 @@ def copy_asset(source, destination, excluded=lambda path: False, context=None, r
|
||||
if not os.path.exists(source):
|
||||
return
|
||||
|
||||
if renderer is None:
|
||||
from sphinx.util.template import SphinxRenderer
|
||||
renderer = SphinxRenderer()
|
||||
|
||||
ensuredir(destination)
|
||||
if os.path.isfile(source):
|
||||
copy_asset_file(source, destination, context, renderer)
|
||||
|
@ -17,14 +17,14 @@ from contextlib import contextmanager
|
||||
|
||||
from docutils import nodes
|
||||
from docutils.utils import get_source_line
|
||||
from six import PY2, StringIO
|
||||
from six import PY2, StringIO, text_type
|
||||
|
||||
from sphinx.errors import SphinxWarning
|
||||
from sphinx.util.console import colorize
|
||||
|
||||
if False:
|
||||
# For type annotation
|
||||
from typing import Any, Dict, Generator, IO, List, Tuple, Union # NOQA
|
||||
from typing import Any, Dict, Generator, IO, List, Tuple, Union, Optional # NOQA
|
||||
from docutils import nodes # NOQA
|
||||
from sphinx.application import Sphinx # NOQA
|
||||
|
||||
@ -94,6 +94,36 @@ def convert_serializable(records):
|
||||
r.location = get_node_location(location) # type: ignore
|
||||
|
||||
|
||||
def get_full_module_name(node):
|
||||
# type: (nodes.Node) -> str
|
||||
"""
|
||||
return full module dotted path like: 'docutils.nodes.paragraph'
|
||||
|
||||
:param nodes.Node node: target node
|
||||
:return: full module dotted path
|
||||
"""
|
||||
return '{}.{}'.format(node.__module__, node.__class__.__name__)
|
||||
|
||||
|
||||
def repr_domxml(node, length=80):
|
||||
# type: (nodes.Node, Optional[int]) -> unicode
|
||||
"""
|
||||
return DOM XML representation of the specified node like:
|
||||
'<paragraph translatable="False"><inline classes="versionmodified">New in version...'
|
||||
|
||||
:param nodes.Node node: target node
|
||||
:param int length:
|
||||
length of return value to be striped. if false-value is specified, repr_domxml
|
||||
returns full of DOM XML representation.
|
||||
:return: DOM XML representation
|
||||
"""
|
||||
# text = node.asdom().toxml() # #4919 crush if node has secnumber with tuple value
|
||||
text = text_type(node) # workaround for #4919
|
||||
if length and len(text) > length:
|
||||
text = text[:length] + '...'
|
||||
return text
|
||||
|
||||
|
||||
class SphinxWarningLogRecord(logging.LogRecord):
|
||||
"""Log record class supporting location"""
|
||||
location = None # type: Any
|
||||
|
@ -21,7 +21,7 @@ from sphinx.util import logging
|
||||
|
||||
if False:
|
||||
# For type annotation
|
||||
from typing import Any, Callable, Iterable, List, Set, Tuple, Union # NOQA
|
||||
from typing import Any, Callable, Iterable, List, Set, Tuple # NOQA
|
||||
from sphinx.builders import Builder # NOQA
|
||||
from sphinx.utils.tags import Tags # NOQA
|
||||
|
||||
@ -41,13 +41,19 @@ def apply_source_workaround(node):
|
||||
# * rawsource of term node will have: ``term text : classifier1 : classifier2``
|
||||
# * rawsource of classifier node will be None
|
||||
if isinstance(node, nodes.classifier) and not node.rawsource:
|
||||
logger.debug('[i18n] PATCH: %r to have source, line and rawsource: %s',
|
||||
logging.get_full_module_name(node), logging.repr_domxml(node))
|
||||
definition_list_item = node.parent
|
||||
node.source = definition_list_item.source
|
||||
node.line = definition_list_item.line - 1
|
||||
node.rawsource = node.astext() # set 'classifier1' (or 'classifier2')
|
||||
if isinstance(node, nodes.image) and node.source is None:
|
||||
logger.debug('[i18n] PATCH: %r to have source, line: %s',
|
||||
logging.get_full_module_name(node), logging.repr_domxml(node))
|
||||
node.source, node.line = node.parent.source, node.parent.line
|
||||
if isinstance(node, nodes.term):
|
||||
logger.debug('[i18n] PATCH: %r to have rawsource: %s',
|
||||
logging.get_full_module_name(node), logging.repr_domxml(node))
|
||||
# strip classifier from rawsource of term
|
||||
for classifier in reversed(node.parent.traverse(nodes.classifier)):
|
||||
node.rawsource = re.sub(r'\s*:\s*%s' % re.escape(classifier.astext()),
|
||||
@ -67,6 +73,8 @@ def apply_source_workaround(node):
|
||||
nodes.image, # #3093 image directive in substitution
|
||||
nodes.field_name, # #3335 field list syntax
|
||||
))):
|
||||
logger.debug('[i18n] PATCH: %r to have source and line: %s',
|
||||
logging.get_full_module_name(node), logging.repr_domxml(node))
|
||||
node.source = find_source_node(node)
|
||||
node.line = 0 # need fix docutils to get `node.line`
|
||||
return
|
||||
@ -74,7 +82,6 @@ def apply_source_workaround(node):
|
||||
|
||||
IGNORED_NODES = (
|
||||
nodes.Invisible,
|
||||
nodes.Inline,
|
||||
nodes.literal_block,
|
||||
nodes.doctest_block,
|
||||
addnodes.versionmodified,
|
||||
@ -96,17 +103,30 @@ def is_translatable(node):
|
||||
if isinstance(node, addnodes.translatable):
|
||||
return True
|
||||
|
||||
if isinstance(node, nodes.Inline) and 'translatable' not in node:
|
||||
# inline node must not be translated if 'translatable' is not set
|
||||
return False
|
||||
|
||||
if isinstance(node, nodes.TextElement):
|
||||
if not node.source:
|
||||
logger.debug('[i18n] SKIP %r because no node.source: %s',
|
||||
logging.get_full_module_name(node), logging.repr_domxml(node))
|
||||
return False # built-in message
|
||||
if isinstance(node, IGNORED_NODES) and 'translatable' not in node:
|
||||
logger.debug("[i18n] SKIP %r because node is in IGNORED_NODES "
|
||||
"and no node['translatable']: %s",
|
||||
logging.get_full_module_name(node), logging.repr_domxml(node))
|
||||
return False
|
||||
if not node.get('translatable', True):
|
||||
# not(node['translatable'] == True or node['translatable'] is None)
|
||||
logger.debug("[i18n] SKIP %r because not node['translatable']: %s",
|
||||
logging.get_full_module_name(node), logging.repr_domxml(node))
|
||||
return False
|
||||
# <field_name>orphan</field_name>
|
||||
# XXX ignore all metadata (== docinfo)
|
||||
if isinstance(node, nodes.field_name) and node.children[0] == 'orphan':
|
||||
logger.debug('[i18n] SKIP %r because orphan node: %s',
|
||||
logging.get_full_module_name(node), logging.repr_domxml(node))
|
||||
return False
|
||||
return True
|
||||
|
||||
|
@ -1,54 +1,3 @@
|
||||
from sphinx.config import string_classes, ENUM
|
||||
|
||||
value1 = 123 # wrong type
|
||||
value2 = 123 # lambda with wrong type
|
||||
value3 = [] # lambda with correct type
|
||||
value4 = True # child type
|
||||
value5 = 3 # parent type
|
||||
value6 = () # other sequence type, also raises
|
||||
value7 = ['foo'] # explicitly permitted
|
||||
|
||||
|
||||
class A(object):
|
||||
pass
|
||||
|
||||
|
||||
class B(A):
|
||||
pass
|
||||
|
||||
|
||||
class C(A):
|
||||
pass
|
||||
|
||||
|
||||
value8 = C() # sibling type
|
||||
|
||||
# both have no default or permissible types
|
||||
value9 = 'foo'
|
||||
value10 = 123
|
||||
value11 = u'bar'
|
||||
value12 = u'bar'
|
||||
value13 = 'bar'
|
||||
value14 = u'bar'
|
||||
value15 = 'bar'
|
||||
value16 = u'bar'
|
||||
|
||||
|
||||
def setup(app):
|
||||
app.add_config_value('value1', 'string', False)
|
||||
app.add_config_value('value2', lambda conf: [], False)
|
||||
app.add_config_value('value3', [], False)
|
||||
app.add_config_value('value4', 100, False)
|
||||
app.add_config_value('value5', False, False)
|
||||
app.add_config_value('value6', [], False)
|
||||
app.add_config_value('value7', 'string', False, [list])
|
||||
app.add_config_value('value8', B(), False)
|
||||
app.add_config_value('value9', None, False)
|
||||
app.add_config_value('value10', None, False)
|
||||
app.add_config_value('value11', None, False, [str])
|
||||
app.add_config_value('value12', 'string', False)
|
||||
app.add_config_value('value13', None, False, string_classes)
|
||||
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'))
|
||||
project = 'Sphinx <Tests>'
|
||||
release = '0.6alpha1'
|
||||
templates_path = ['_templates']
|
||||
|
@ -12,7 +12,7 @@ from sphinx import addnodes
|
||||
sys.path.append(os.path.abspath('.'))
|
||||
|
||||
extensions = ['sphinx.ext.autodoc', 'sphinx.ext.jsmath', 'sphinx.ext.todo',
|
||||
'sphinx.ext.coverage', 'sphinx.ext.extlinks', 'ext']
|
||||
'sphinx.ext.coverage', 'sphinx.ext.extlinks']
|
||||
|
||||
jsmath_path = 'dummy.js'
|
||||
|
||||
@ -65,8 +65,6 @@ man_pages = [
|
||||
'Georg Brandl and someone else', 1),
|
||||
]
|
||||
|
||||
value_from_conf_py = 84
|
||||
|
||||
coverage_c_path = ['special/*.h']
|
||||
coverage_c_regexes = {'function': r'^PyAPI_FUNC\(.*\)\s+([^_][\w_]+)'}
|
||||
|
||||
@ -104,7 +102,6 @@ class ClassDirective(Directive):
|
||||
def setup(app):
|
||||
import parsermod
|
||||
|
||||
app.add_config_value('value_from_conf_py', 42, False)
|
||||
app.add_directive('clsdir', ClassDirective)
|
||||
app.add_object_type('userdesc', 'userdescrole', '%s (userdesc)',
|
||||
userdesc_parse, objname='user desc')
|
||||
|
@ -1,5 +0,0 @@
|
||||
# Test extension module
|
||||
|
||||
|
||||
def setup(app):
|
||||
app.add_config_value('value_from_ext', [], False)
|
@ -11,7 +11,7 @@
|
||||
import pytest
|
||||
from docutils import nodes
|
||||
|
||||
from sphinx.application import ExtensionError
|
||||
from sphinx.errors import ExtensionError
|
||||
from sphinx.domains import Domain
|
||||
from sphinx.testing.util import strip_escseq
|
||||
from sphinx.util import logging
|
||||
|
@ -11,15 +11,15 @@
|
||||
"""
|
||||
import mock
|
||||
import pytest
|
||||
from six import PY3, iteritems
|
||||
from six import PY3
|
||||
|
||||
import sphinx
|
||||
from sphinx.config import Config
|
||||
from sphinx.config import Config, ENUM, string_classes, check_confval_types
|
||||
from sphinx.errors import ExtensionError, ConfigError, VersionRequirementError
|
||||
from sphinx.testing.path import path
|
||||
|
||||
|
||||
@pytest.mark.sphinx(confoverrides={
|
||||
@pytest.mark.sphinx(testroot='config', confoverrides={
|
||||
'master_doc': 'master',
|
||||
'nonexisting_value': 'True',
|
||||
'latex_elements.docclass': 'scrartcl',
|
||||
@ -74,36 +74,64 @@ def test_core_config(app, status, warning):
|
||||
assert cfg['project'] == cfg.project == 'Sphinx Tests'
|
||||
|
||||
|
||||
def test_extension_values(app, status, warning):
|
||||
cfg = app.config
|
||||
def test_extension_values():
|
||||
config = Config()
|
||||
|
||||
# default value
|
||||
assert cfg.value_from_ext == []
|
||||
# non-default value
|
||||
assert cfg.value_from_conf_py == 84
|
||||
# check standard settings
|
||||
assert config.master_doc == 'contents'
|
||||
|
||||
# no duplicate values allowed
|
||||
# can't override it by add_config_value()
|
||||
with pytest.raises(ExtensionError) as excinfo:
|
||||
app.add_config_value('html_title', 'x', True)
|
||||
config.add('master_doc', 'index', 'env', None)
|
||||
assert 'already present' in str(excinfo.value)
|
||||
|
||||
# add a new config value
|
||||
config.add('value_from_ext', [], 'env', None)
|
||||
assert config.value_from_ext == []
|
||||
|
||||
# can't override it by add_config_value()
|
||||
with pytest.raises(ExtensionError) as excinfo:
|
||||
app.add_config_value('value_from_ext', 'x', True)
|
||||
config.add('value_from_ext', [], 'env', None)
|
||||
assert 'already present' in str(excinfo.value)
|
||||
|
||||
|
||||
def test_overrides():
|
||||
config = Config({'value1': '1', 'value2': 2, 'value6': {'default': 6}},
|
||||
{'value2': 999, 'value3': '999', 'value5.attr1': 999, 'value6.attr1': 999,
|
||||
'value7': 'abc,def,ghi', 'value8': 'abc,def,ghi'})
|
||||
config.add('value1', None, 'env', ())
|
||||
config.add('value2', None, 'env', ())
|
||||
config.add('value3', 0, 'env', ())
|
||||
config.add('value4', 0, 'env', ())
|
||||
config.add('value5', {'default': 0}, 'env', ())
|
||||
config.add('value6', {'default': 0}, 'env', ())
|
||||
config.add('value7', None, 'env', ())
|
||||
config.add('value8', [], 'env', ())
|
||||
config.init_values()
|
||||
|
||||
assert config.value1 == '1'
|
||||
assert config.value2 == 999
|
||||
assert config.value3 == 999
|
||||
assert config.value4 == 0
|
||||
assert config.value5 == {'attr1': 999}
|
||||
assert config.value6 == {'default': 6, 'attr1': 999}
|
||||
assert config.value7 == 'abc,def,ghi'
|
||||
assert config.value8 == ['abc', 'def', 'ghi']
|
||||
|
||||
|
||||
@mock.patch("sphinx.config.logger")
|
||||
def test_errors_warnings(logger, tempdir):
|
||||
# test the error for syntax errors in the config file
|
||||
(tempdir / 'conf.py').write_text(u'project = \n', encoding='ascii')
|
||||
with pytest.raises(ConfigError) as excinfo:
|
||||
Config(tempdir, 'conf.py', {}, None)
|
||||
Config.read(tempdir, {}, None)
|
||||
assert 'conf.py' in str(excinfo.value)
|
||||
|
||||
# test the automatic conversion of 2.x only code in configs
|
||||
(tempdir / 'conf.py').write_text(
|
||||
u'# -*- coding: utf-8\n\nproject = u"Jägermeister"\n',
|
||||
encoding='utf-8')
|
||||
cfg = Config(tempdir, 'conf.py', {}, None)
|
||||
cfg = Config.read(tempdir, {}, None)
|
||||
cfg.init_values()
|
||||
assert cfg.project == u'Jägermeister'
|
||||
assert logger.called is False
|
||||
@ -115,7 +143,7 @@ def test_errors_warnings(logger, tempdir):
|
||||
return
|
||||
(tempdir / 'conf.py').write_text(
|
||||
u'# -*- coding: latin-1\nproject = "fooä"\n', encoding='latin-1')
|
||||
cfg = Config(tempdir, 'conf.py', {}, None)
|
||||
cfg = Config.read(tempdir, {}, None)
|
||||
|
||||
assert logger.warning.called is False
|
||||
cfg.check_unicode()
|
||||
@ -174,7 +202,7 @@ def test_config_eol(logger, tempdir):
|
||||
configfile = tempdir / 'conf.py'
|
||||
for eol in (b'\n', b'\r\n'):
|
||||
configfile.write_bytes(b'project = "spam"' + eol)
|
||||
cfg = Config(tempdir, 'conf.py', {}, None)
|
||||
cfg = Config.read(tempdir, {}, None)
|
||||
cfg.init_values()
|
||||
assert cfg.project == u'spam'
|
||||
assert logger.called is False
|
||||
@ -195,60 +223,81 @@ def test_builtin_conf(app, status, warning):
|
||||
'warning')
|
||||
|
||||
|
||||
# See roots/test-config/conf.py.
|
||||
TYPECHECK_WARNINGS = {
|
||||
'value1': True,
|
||||
'value2': True,
|
||||
'value3': False,
|
||||
'value4': True,
|
||||
'value5': False,
|
||||
'value6': True,
|
||||
'value7': False,
|
||||
'value8': False,
|
||||
'value9': False,
|
||||
'value10': False,
|
||||
'value11': False if PY3 else True,
|
||||
'value12': False,
|
||||
'value13': False,
|
||||
'value14': False,
|
||||
'value15': False,
|
||||
'value16': False,
|
||||
}
|
||||
# example classes for type checking
|
||||
class A(object):
|
||||
pass
|
||||
|
||||
|
||||
@pytest.mark.parametrize("key,should", iteritems(TYPECHECK_WARNINGS))
|
||||
@pytest.mark.sphinx(testroot='config')
|
||||
def test_check_types(warning, key, should):
|
||||
warn = warning.getvalue()
|
||||
if should:
|
||||
assert key in warn, (
|
||||
'override on "%s" should raise a type warning' % key
|
||||
)
|
||||
else:
|
||||
assert key not in warn, (
|
||||
'override on "%s" should NOT raise a type warning' % key
|
||||
)
|
||||
class B(A):
|
||||
pass
|
||||
|
||||
|
||||
@pytest.mark.sphinx(testroot='config')
|
||||
def test_check_enum(app, status, warning):
|
||||
assert "The config value `value17` has to be a one of ('default', 'one', 'two'), " \
|
||||
not in warning.getvalue()
|
||||
class C(A):
|
||||
pass
|
||||
|
||||
|
||||
@pytest.mark.sphinx(testroot='config', confoverrides={'value17': 'invalid'})
|
||||
def test_check_enum_failed(app, status, warning):
|
||||
assert "The config value `value17` has to be a one of ('default', 'one', 'two'), " \
|
||||
"but `invalid` is given." in warning.getvalue()
|
||||
# name, default, annotation, actual, warned
|
||||
TYPECHECK_WARNINGS = [
|
||||
('value1', 'string', None, 123, True), # wrong type
|
||||
('value2', lambda _: [], None, 123, True), # lambda with wrong type
|
||||
('value3', lambda _: [], None, [], False), # lambda with correct type
|
||||
('value4', 100, None, True, True), # child type
|
||||
('value5', False, None, True, False), # parent type
|
||||
('value6', [], None, (), True), # other sequence type
|
||||
('value7', 'string', [list], ['foo'], False), # explicit type annotation
|
||||
('value8', B(), None, C(), False), # sibling type
|
||||
('value9', None, None, 'foo', False), # no default or no annotations
|
||||
('value10', None, None, 123, False), # no default or no annotations
|
||||
('value11', None, [str], u'bar', False if PY3 else True), # str vs unicode
|
||||
('value12', 'string', None, u'bar', False), # str vs unicode
|
||||
('value13', None, string_classes, 'bar', False), # string_classes
|
||||
('value14', None, string_classes, u'bar', False), # string_classes
|
||||
('value15', u'unicode', None, 'bar', False), # str vs unicode
|
||||
('value16', u'unicode', None, u'bar', False), # str vs unicode
|
||||
]
|
||||
|
||||
|
||||
@pytest.mark.sphinx(testroot='config', confoverrides={'value17': ['one', 'two']})
|
||||
def test_check_enum_for_list(app, status, warning):
|
||||
assert "The config value `value17` has to be a one of ('default', 'one', 'two'), " \
|
||||
not in warning.getvalue()
|
||||
@mock.patch("sphinx.config.logger")
|
||||
@pytest.mark.parametrize("name,default,annotation,actual,warned", TYPECHECK_WARNINGS)
|
||||
def test_check_types(logger, name, default, annotation, actual, warned):
|
||||
config = Config({name: actual})
|
||||
config.add(name, default, 'env', annotation or ())
|
||||
config.init_values()
|
||||
check_confval_types(None, config)
|
||||
assert logger.warning.called == warned
|
||||
|
||||
|
||||
@pytest.mark.sphinx(testroot='config', confoverrides={'value17': ['one', 'two', 'invalid']})
|
||||
def test_check_enum_for_list_failed(app, status, warning):
|
||||
assert "The config value `value17` has to be a one of ('default', 'one', 'two'), " \
|
||||
"but `['one', 'two', 'invalid']` is given." in warning.getvalue()
|
||||
@mock.patch("sphinx.config.logger")
|
||||
def test_check_enum(logger):
|
||||
config = Config()
|
||||
config.add('value', 'default', False, ENUM('default', 'one', 'two'))
|
||||
config.init_values()
|
||||
check_confval_types(None, config)
|
||||
logger.warning.assert_not_called() # not warned
|
||||
|
||||
|
||||
@mock.patch("sphinx.config.logger")
|
||||
def test_check_enum_failed(logger):
|
||||
config = Config({'value': 'invalid'})
|
||||
config.add('value', 'default', False, ENUM('default', 'one', 'two'))
|
||||
config.init_values()
|
||||
check_confval_types(None, config)
|
||||
logger.warning.assert_called()
|
||||
|
||||
|
||||
@mock.patch("sphinx.config.logger")
|
||||
def test_check_enum_for_list(logger):
|
||||
config = Config({'value': ['one', 'two']})
|
||||
config.add('value', 'default', False, ENUM('default', 'one', 'two'))
|
||||
config.init_values()
|
||||
check_confval_types(None, config)
|
||||
logger.warning.assert_not_called() # not warned
|
||||
|
||||
|
||||
@mock.patch("sphinx.config.logger")
|
||||
def test_check_enum_for_list_failed(logger):
|
||||
config = Config({'value': ['one', 'two', 'invalid']})
|
||||
config.add('value', 'default', False, ENUM('default', 'one', 'two'))
|
||||
config.init_values()
|
||||
check_confval_types(None, config)
|
||||
logger.warning.assert_called()
|
||||
|
@ -17,7 +17,7 @@ from sphinx.config import Config
|
||||
from sphinx.directives.code import LiteralIncludeReader
|
||||
from sphinx.testing.util import etree_parse
|
||||
|
||||
DUMMY_CONFIG = Config(None, None, {}, '')
|
||||
DUMMY_CONFIG = Config({}, {})
|
||||
|
||||
|
||||
@pytest.fixture(scope='module')
|
||||
|
@ -15,6 +15,7 @@ import sys
|
||||
import pytest
|
||||
|
||||
from sphinx.testing.path import path
|
||||
from sphinx.util.docutils import patch_docutils
|
||||
|
||||
|
||||
def regex_count(expr, result):
|
||||
@ -23,7 +24,9 @@ def regex_count(expr, result):
|
||||
|
||||
@pytest.mark.sphinx('html', testroot='docutilsconf', freshenv=True, docutilsconf='')
|
||||
def test_html_with_default_docutilsconf(app, status, warning):
|
||||
with patch_docutils(app.confdir):
|
||||
app.builder.build(['contents'])
|
||||
|
||||
result = (app.outdir / 'contents.html').text(encoding='utf-8')
|
||||
|
||||
assert regex_count(r'<th class="field-name">', result) == 1
|
||||
@ -39,7 +42,9 @@ def test_html_with_default_docutilsconf(app, status, warning):
|
||||
'\n')
|
||||
)
|
||||
def test_html_with_docutilsconf(app, status, warning):
|
||||
with patch_docutils(app.confdir):
|
||||
app.builder.build(['contents'])
|
||||
|
||||
result = (app.outdir / 'contents.html').text(encoding='utf-8')
|
||||
|
||||
assert regex_count(r'<th class="field-name">', result) == 0
|
||||
@ -50,24 +55,28 @@ def test_html_with_docutilsconf(app, status, warning):
|
||||
|
||||
@pytest.mark.sphinx('html', testroot='docutilsconf')
|
||||
def test_html(app, status, warning):
|
||||
with patch_docutils(app.confdir):
|
||||
app.builder.build(['contents'])
|
||||
assert warning.getvalue() == ''
|
||||
|
||||
|
||||
@pytest.mark.sphinx('latex', testroot='docutilsconf')
|
||||
def test_latex(app, status, warning):
|
||||
with patch_docutils(app.confdir):
|
||||
app.builder.build(['contents'])
|
||||
assert warning.getvalue() == ''
|
||||
|
||||
|
||||
@pytest.mark.sphinx('man', testroot='docutilsconf')
|
||||
def test_man(app, status, warning):
|
||||
with patch_docutils(app.confdir):
|
||||
app.builder.build(['contents'])
|
||||
assert warning.getvalue() == ''
|
||||
|
||||
|
||||
@pytest.mark.sphinx('texinfo', testroot='docutilsconf')
|
||||
def test_texinfo(app, status, warning):
|
||||
with patch_docutils(app.confdir):
|
||||
app.builder.build(['contents'])
|
||||
|
||||
|
||||
@ -87,4 +96,5 @@ def test_docutils_source_link_with_nonascii_file(app, status, warning):
|
||||
'nonascii filename not supported on this filesystem encoding: '
|
||||
'%s', FILESYSTEMENCODING)
|
||||
|
||||
with patch_docutils(app.confdir):
|
||||
app.builder.build_all()
|
||||
|
@ -8,6 +8,7 @@
|
||||
:copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS.
|
||||
:license: BSD, see LICENSE for details.
|
||||
"""
|
||||
import os
|
||||
import pytest
|
||||
from packaging.specifiers import InvalidSpecifier
|
||||
from packaging.version import InvalidVersion
|
||||
@ -68,7 +69,7 @@ def test_reporting_with_autodoc(app, status, warning, capfd):
|
||||
written = []
|
||||
app.builder._warn_out = written.append
|
||||
app.builder.build_all()
|
||||
lines = '\n'.join(written).split('\n')
|
||||
lines = '\n'.join(written).replace(os.sep, '/').split('\n')
|
||||
failures = [l for l in lines if l.startswith('File')]
|
||||
expected = [
|
||||
'File "dir/inner.rst", line 1, in default',
|
||||
|
@ -22,24 +22,26 @@ def test_graphviz_png_html(app, status, warning):
|
||||
app.builder.build_all()
|
||||
|
||||
content = (app.outdir / 'index.html').text()
|
||||
html = (r'<div class="figure" .*?>\s*<img .*?/>\s*<p class="caption">'
|
||||
html = (r'<div class="figure" .*?>\s*'
|
||||
r'<div class="graphviz"><img .*?/></div>\s*<p class="caption">'
|
||||
r'<span class="caption-text">caption of graph</span>.*</p>\s*</div>')
|
||||
assert re.search(html, content, re.S)
|
||||
|
||||
html = 'Hello <img .*?/>\n graphviz world'
|
||||
html = 'Hello <div class="graphviz"><img .*?/></div>\n graphviz world'
|
||||
assert re.search(html, content, re.S)
|
||||
|
||||
html = '<img src=".*?" alt="digraph {\n bar -> baz\n}" />'
|
||||
assert re.search(html, content, re.M)
|
||||
|
||||
html = (r'<div class="figure align-right" .*?>\s*<img .*?/>\s*<p class="caption">'
|
||||
html = (r'<div class="figure align-right" .*?>\s*'
|
||||
r'<div class="graphviz"><img .*?/></div>\s*<p class="caption">'
|
||||
r'<span class="caption-text">on right</span>.*</p>\s*</div>')
|
||||
assert re.search(html, content, re.S)
|
||||
|
||||
html = (r'<div align=\"center\" class=\"align-center\">'
|
||||
r'<img src=\".*\.png\" alt=\"digraph foo {\n'
|
||||
r'<div class="graphviz"><img src=\".*\.png\" alt=\"digraph foo {\n'
|
||||
r'centered\n'
|
||||
r'}\" />\n</div>')
|
||||
r'}\" /></div>\n</div>')
|
||||
assert re.search(html, content, re.S)
|
||||
|
||||
|
||||
@ -52,34 +54,34 @@ def test_graphviz_svg_html(app, status, warning):
|
||||
content = (app.outdir / 'index.html').text()
|
||||
|
||||
html = (r'<div class=\"figure\" .*?>\n'
|
||||
r'<object data=\".*\.svg\".*>\n'
|
||||
r'\s+<p class=\"warning\">digraph foo {\n'
|
||||
r'<div class="graphviz"><object data=\".*\.svg\".*>\n'
|
||||
r'\s*<p class=\"warning\">digraph foo {\n'
|
||||
r'bar -> baz\n'
|
||||
r'}</p></object>\n'
|
||||
r'}</p></object></div>\n'
|
||||
r'<p class=\"caption\"><span class=\"caption-text\">'
|
||||
r'caption of graph</span>.*</p>\n</div>')
|
||||
assert re.search(html, content, re.S)
|
||||
|
||||
html = (r'Hello <object.*>\n'
|
||||
r'\s+<p class=\"warning\">graph</p></object>\n'
|
||||
html = (r'Hello <div class="graphviz"><object.*>\n'
|
||||
r'\s*<p class=\"warning\">graph</p></object></div>\n'
|
||||
r' graphviz world')
|
||||
assert re.search(html, content, re.S)
|
||||
|
||||
html = (r'<div class=\"figure align-right\" .*\>\n'
|
||||
r'<object data=\".*\.svg\".*>\n'
|
||||
r'\s+<p class=\"warning\">digraph bar {\n'
|
||||
r'<div class="graphviz"><object data=\".*\.svg\".*>\n'
|
||||
r'\s*<p class=\"warning\">digraph bar {\n'
|
||||
r'foo -> bar\n'
|
||||
r'}</p></object>\n'
|
||||
r'}</p></object></div>\n'
|
||||
r'<p class=\"caption\"><span class=\"caption-text\">'
|
||||
r'on right</span>.*</p>\n'
|
||||
r'</div>')
|
||||
assert re.search(html, content, re.S)
|
||||
|
||||
html = (r'<div align=\"center\" class=\"align-center\">'
|
||||
r'<object data=\".*\.svg\".*>\n'
|
||||
r'\s+<p class=\"warning\">digraph foo {\n'
|
||||
r'<div class="graphviz"><object data=\".*\.svg\".*>\n'
|
||||
r'\s*<p class=\"warning\">digraph foo {\n'
|
||||
r'centered\n'
|
||||
r'}</p></object>\n'
|
||||
r'}</p></object></div>\n'
|
||||
r'</div>')
|
||||
assert re.search(html, content, re.S)
|
||||
|
||||
|
@ -19,14 +19,34 @@ from sphinx.ext.inheritance_diagram import InheritanceException, import_classes
|
||||
|
||||
@pytest.mark.sphinx('html', testroot='ext-inheritance_diagram')
|
||||
@pytest.mark.usefixtures('if_graphviz_found')
|
||||
def test_inheritance_diagram_html(app, status, warning):
|
||||
def test_inheritance_diagram_png_html(app, status, warning):
|
||||
app.builder.build_all()
|
||||
|
||||
content = (app.outdir / 'index.html').text()
|
||||
|
||||
pattern = ('<div class="figure" id="id1">\n'
|
||||
'<div class="graphviz">'
|
||||
'<img src="_images/inheritance-\\w+.png" alt="Inheritance diagram of test.Foo" '
|
||||
'class="inheritance"/>\n<p class="caption"><span class="caption-text">'
|
||||
'class="inheritance"/></div>\n<p class="caption"><span class="caption-text">'
|
||||
'Test Foo!</span><a class="headerlink" href="#id1" '
|
||||
'title="Permalink to this image">\xb6</a></p>')
|
||||
assert re.search(pattern, content, re.M)
|
||||
|
||||
|
||||
@pytest.mark.sphinx('html', testroot='ext-inheritance_diagram',
|
||||
confoverrides={'graphviz_output_format': 'svg'})
|
||||
@pytest.mark.usefixtures('if_graphviz_found')
|
||||
def test_inheritance_diagram_svg_html(app, status, warning):
|
||||
app.builder.build_all()
|
||||
|
||||
content = (app.outdir / 'index.html').text()
|
||||
|
||||
pattern = ('<div class="figure" id="id1">\n'
|
||||
'<div class="graphviz">'
|
||||
'<object data="_images/inheritance-\\w+.svg" '
|
||||
'type="image/svg\\+xml" class="inheritance">\n'
|
||||
'<p class=\"warning\">Inheritance diagram of test.Foo</p>'
|
||||
'</object></div>\n<p class="caption"><span class="caption-text">'
|
||||
'Test Foo!</span><a class="headerlink" href="#id1" '
|
||||
'title="Permalink to this image">\xb6</a></p>')
|
||||
assert re.search(pattern, content, re.M)
|
||||
@ -62,8 +82,9 @@ def test_inheritance_diagram_latex_alias(app, status, warning):
|
||||
content = (app.outdir / 'index.html').text()
|
||||
|
||||
pattern = ('<div class="figure" id="id1">\n'
|
||||
'<div class="graphviz">'
|
||||
'<img src="_images/inheritance-\\w+.png" alt="Inheritance diagram of test.Foo" '
|
||||
'class="inheritance"/>\n<p class="caption"><span class="caption-text">'
|
||||
'class="inheritance"/></div>\n<p class="caption"><span class="caption-text">'
|
||||
'Test Foo!</span><a class="headerlink" href="#id1" '
|
||||
'title="Permalink to this image">\xb6</a></p>')
|
||||
assert re.search(pattern, content, re.M)
|
||||
|
Loading…
Reference in New Issue
Block a user