Merge branch 'master' into 4614_keep_going

This commit is contained in:
Takeshi KOMIYA 2018-07-31 01:11:08 +09:00 committed by GitHub
commit 609ec5ef33
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
69 changed files with 7242 additions and 725 deletions

2
.gitignore vendored
View File

@ -29,3 +29,5 @@ doc/locale/
tests/.coverage
tests/build/
utils/regression_test.js
node_modules/

View File

@ -7,6 +7,7 @@ env:
global:
- PYTHONFAULTHANDLER=x
- SKIP_LATEX_BUILD=1
- IS_PYTHON=true
matrix:
include:
@ -24,8 +25,12 @@ matrix:
env:
- TOXENV=py36
- PYTEST_ADDOPTS="--cov ./ --cov-append --cov-config setup.cfg"
- python: 'nightly'
- python: '3.7'
env: TOXENV=py37
dist: xenial
sudo: true
- python: 'nightly'
env: TOXENV=py38
- python: '3.6'
env: TOXENV=docs
- python: '3.6'
@ -33,11 +38,21 @@ matrix:
- python: '3.6'
env: TOXENV=flake8
- language: node_js
node_js:
- 10.7
env: IS_PYTHON=false
before_script:
- export DISPLAY=:99.0
- sh -e /etc/init.d/xvfb start
install:
- pip install -U tox codecov
- if [ $IS_PYTHON = true ]; then pip install -U tox codecov; fi
- if [ $IS_PYTHON = false ]; then npm install; fi
script:
- tox -- -v
- if [ $IS_PYTHON = true ]; then tox -- -v; fi
- if [ $IS_PYTHON = false ]; then npm test; fi
after_success:
- if [[ -e .coverage ]]; then codecov -e $TOXENV; fi

View File

@ -14,6 +14,7 @@ Other co-maintainers:
* Takeshi Komiya <@tk0miya>
* Jean-François Burnol <@jfbu>
* Yoshiki Shibukawa <@shibu_jp>
* Timotheus Kampik - <@TimKam>
Other contributors, listed alphabetically, are:
@ -37,7 +38,6 @@ Other contributors, listed alphabetically, are:
* Zac Hatfield-Dodds -- doctest reporting improvements
* Doug Hellmann -- graphviz improvements
* Tim Hoffmann -- theme improvements
* Timotheus Kampik - JS theme & search enhancements
* Dave Kuhlman -- original LaTeX writer
* Blaise Laflamme -- pyramid theme
* Chris Lamb -- reproducibility fixes

25
CHANGES
View File

@ -49,6 +49,7 @@ Incompatible changes
upgrading Sphinx, please clean latex build repertory of existing project
before new build.
* #5163: html: hlist items are now aligned to top
* ``highlightlang`` directive is processed on resolving phase
Deprecated
----------
@ -58,6 +59,7 @@ Deprecated
based directives.
* ``sphinx.util.docutils.directive_helper()`` is deprecated
* ``sphinx.cmdline`` is deprecated
* ``sphinx.make_mode`` is deprecated
* ``sphinx.locale.l_()`` is deprecated
* #2157: helper function ``warn()`` for HTML themes is deprecated
* ``app.override_domain()`` is deprecated
@ -95,13 +97,30 @@ Deprecated
* ``sphinx.writers.latex.LaTeXTranslator.unrestrict_footnote()`` is deprecated
* ``sphinx.writers.latex.LaTeXTranslator.push_hyperlink_ids()`` is deprecated
* ``sphinx.writers.latex.LaTeXTranslator.pop_hyperlink_ids()`` is deprecated
* ``sphinx.writers.latex.LaTeXTranslator.check_latex_elements()`` is deprecated
* ``sphinx.writers.latex.LaTeXTranslator.bibitems`` is deprecated
* ``sphinx.writers.latex.LaTeXTranslator.hlsettingstack`` is deprecated
* ``sphinx.writers.latex.ExtBabel.get_shorthandoff()`` is deprecated
* ``sphinx.writers.html.HTMLTranslator.highlightlang`` is deprecated
* ``sphinx.writers.html.HTMLTranslator.highlightlang_base`` is deprecated
* ``sphinx.writers.html.HTMLTranslator.highlightlangopts`` is deprecated
* ``sphinx.writers.html.HTMLTranslator.highlightlinenothreshold`` is deprecated
* ``sphinx.writers.html5.HTMLTranslator.highlightlang`` is deprecated
* ``sphinx.writers.html5.HTMLTranslator.highlightlang_base`` is deprecated
* ``sphinx.writers.html5.HTMLTranslator.highlightlangopts`` is deprecated
* ``sphinx.writers.html5.HTMLTranslator.highlightlinenothreshold`` is deprecated
* ``sphinx.ext.mathbase`` extension is deprecated
* ``sphinx.ext.mathbase.math`` node is deprecated
* ``sphinx.ext.mathbase.displaymath`` node is deprecated
* ``sphinx.ext.mathbase.eqref`` node is deprecated
* ``sphinx.ext.mathbase.is_in_section_title()`` is deprecated
* ``sphinx.ext.mathbase.MathDomain`` is deprecated
* ``sphinx.ext.mathbase.setup_math()`` is deprecated
* ``sphinx.highlighting.PygmentsBridge.unhighlight()`` is deprecated
* ``sphinx.ext.mathbase.get_node_equation_number()`` is deprecated
* ``sphinx.ext.mathbase.wrap_displaymath()`` is deprecated
* The ``trim_doctest_flags`` argument of ``sphinx.highlighting.PygmentsBridge``
is deprecated
For more details, see `deprecation APIs list
<http://www.sphinx-doc.org/en/master/extdev/index.html#deprecated-apis>`_
@ -162,6 +181,10 @@ Features added
if :confval:`latex_engine` is ``'xelatex'`` or ``'lualatex'``.
* #4976: ``SphinxLoggerAdapter.info()`` now supports ``location`` parameter
* #5122: setuptools: support nitpicky option
* #2820: autoclass directive supports nested class
* Add ``app.add_html_math_renderer()`` to register a math renderer for HTML
* Apply :confval:`trim_doctest_flags` to all builders (cf. text, manpages)
* #5140: linkcheck: Add better Accept header to HTTP client
* #4614: sphinx-build: Add ``--keep-going`` option to show all warnings
Bugs fixed
@ -175,6 +198,8 @@ Bugs fixed
* #5132: (lualatex) PDF build fails if indexed word starts with Unicode character
* #5133: latex: index headings "Symbols" and "Numbers" not internationalized
* #5114: sphinx-build: Handle errors on scanning documents
* epub: spine has been broken when "self" is listed on toctree (refs: #4611)
* #344: autosummary does not understand docstring of module level attributes
Testing
--------

View File

@ -154,6 +154,12 @@ These are the basic steps needed to start developing on Sphinx.
tox -e docs -- -b html,latexpdf
* To run JavaScript tests with `Karma <https://karma-runner.github.io>`_,
execute the following commands (requires `Node.js <https://nodejs.org>`_)::
npm install
npm run test
You can also test by installing dependencies in your local environment. ::
pip install .[test]
@ -302,8 +308,8 @@ Debugging Tips
in `this repository <https://github.com/shibukawa/snowball-stemmer.jsx>`_.
You can get the resulting JavaScript files using the following command::
$ npm install
$ node_modules/.bin/grunt build # -> dest/*.global.js
npm install
node_modules/.bin/grunt build # -> dest/*.global.js
Branch Model
@ -402,3 +408,6 @@ and other ``test_*.py`` files under ``tests`` directory.
.. versionadded:: 1.6
``sphinx.testing`` as a experimental.
.. versionadded:: 1.8
Sphinx also runs JavaScript tests.

View File

@ -93,6 +93,8 @@ package.
.. automethod:: Sphinx.add_html_theme(name, theme_path)
.. automethod:: Sphinx.add_html_math_renderer(name, inline_renderers, block_renderers)
.. automethod:: Sphinx.add_message_catalog(catalog, locale_dir)
.. automethod:: Sphinx.is_parallel_allowed(typ)

View File

@ -131,16 +131,47 @@ The following is a list of deprecated interface.
- 4.0
- :meth:`~sphinx.application.Sphinx.add_js_file()`
* - ``sphinx.highlighting.PygmentsBridge.unhighlight()``
- 1.8
- 3.0
- N/A
* - ``trim_doctest_flags`` arguments of
``sphinx.highlighting.PygmentsBridge``
- 1.8
- 3.0
- N/A
* - ``sphinx.ext.mathbase``
- 1.8
- 3.0
- N/A
* - ``sphinx.ext.mathbase.MathDomain``
- 1.8
- 3.0
- ``sphinx.domains.math.MathDomain``
* - ``sphinx.ext.mathbase.setup_math()``
- 1.8
- 3.0
- :meth:`~sphinx.application.Sphinx.add_html_math_renderer()`
* - ``sphinx.ext.mathbase.is_in_section_title()``
- 1.8
- 3.0
- N/A
* - ``sphinx.ext.mathbase.get_node_equation_number()``
- 1.8
- 3.0
- ``sphinx.util.math.get_node_equation_number()``
* - ``sphinx.ext.mathbase.wrap_displaymath()``
- 1.8
- 3.0
- ``sphinx.util.math.wrap_displaymath()``
* - ``sphinx.ext.mathbase.math`` (node)
- 1.8
- 3.0
@ -216,11 +247,61 @@ The following is a list of deprecated interface.
- 3.0
- N/A
* - ``sphinx.writers.latex.LaTeXTranslator.hlsettingstack``
- 1.8
- 3.0
- N/A
* - ``sphinx.writers.latex.ExtBabel.get_shorthandoff()``
- 1.8
- 3.0
- N/A
* - ``sphinx.writers.html.HTMLTranslator.highlightlang()``
- 1.8
- 3.0
- N/A
* - ``sphinx.writers.html.HTMLTranslator.highlightlang_base()``
- 1.8
- 3.0
- N/A
* - ``sphinx.writers.html.HTMLTranslator.highlightlangopts()``
- 1.8
- 3.0
- N/A
* - ``sphinx.writers.html.HTMLTranslator.highlightlinenothreshold()``
- 1.8
- 3.0
- N/A
* - ``sphinx.writers.html5.HTMLTranslator.highlightlang()``
- 1.8
- 3.0
- N/A
* - ``sphinx.writers.html5.HTMLTranslator.highlightlang_base()``
- 1.8
- 3.0
- N/A
* - ``sphinx.writers.html5.HTMLTranslator.highlightlangopts()``
- 1.8
- 3.0
- N/A
* - ``sphinx.writers.html5.HTMLTranslator.highlightlinenothreshold()``
- 1.8
- 3.0
- N/A
* - ``sphinx.writers.latex.LaTeXTranslator.check_latex_elements()``
- 1.8
- 3.0
- Nothing
* - ``sphinx.application.CONFIG_FILENAME``
- 1.8
- 3.0
@ -349,6 +430,11 @@ The following is a list of deprecated interface.
- 3.0
- ``sphinx.cmd.build``
* - ``sphinx.make_mode``
- 1.8
- 3.0
- ``sphinx.cmd.make_mode``
* - ``sphinx.locale.l_()``
- 1.8
- 3.0

View File

@ -773,6 +773,35 @@ documentation on :ref:`intl` for details.
Added ``{path}`` and ``{basename}`` tokens.
.. _math-options:
Options for Math
----------------
These options influence Math notations.
.. confval:: math_number_all
Set this option to ``True`` if you want all displayed math to be numbered.
The default is ``False``.
.. confval:: math_eqref_format
A string that are used for format of label of references to equations.
As a special character, ``{number}`` will be replaced to equaition number.
Example: ``'Eq.{number}'`` is rendered as ``Eq.10``
.. confval:: math_numfig
If ``True``, displayed math equations are numbered across pages when
:confval:`numfig` is enabled. The :confval:`numfig_secnum_depth` setting
is respected. The :rst:role:`eq`, not :rst:role:`numref`, role
must be used to reference equation numbers. Default is ``True``.
.. versionadded:: 1.7
.. _html-options:
Options for HTML output
@ -1290,6 +1319,13 @@ that use Sphinx's HTMLWriter class.
.. versionadded:: 1.3
.. confval:: html_math_renderer
The name of math_renderer extension for HTML output. The default is
``'mathjax'``.
.. versionadded:: 1.8
.. confval:: html_experimental_html5_writer
Output is processed with HTML5 writer. This feature needs docutils 0.13 or

View File

@ -2,123 +2,20 @@
.. _math-support:
Math support in Sphinx
======================
Math support for HTML outputs in Sphinx
=======================================
.. module:: sphinx.ext.mathbase
:synopsis: Common math support for imgmath and mathjax / jsmath.
.. versionadded:: 0.5
.. versionchanged:: 1.8
Math support for non-HTML builders is integrated to sphinx-core.
So mathbase extension is no longer needed.
Since mathematical notation isn't natively supported by HTML in any way, Sphinx
supports math in documentation with several extensions.
The basic math support is contained in :mod:`sphinx.ext.mathbase`. Other math
support extensions should, if possible, reuse that support too.
.. note::
:mod:`.mathbase` is not meant to be added to the :confval:`extensions` config
value, instead, use either :mod:`sphinx.ext.imgmath` or
:mod:`sphinx.ext.mathjax` as described below.
The input language for mathematics is LaTeX markup. This is the de-facto
standard for plain-text math notation and has the added advantage that no
further translation is necessary when building LaTeX output.
Keep in mind that when you put math markup in **Python docstrings** read by
:mod:`autodoc <sphinx.ext.autodoc>`, you either have to double all backslashes,
or use Python raw strings (``r"raw"``).
:mod:`.mathbase` provides the following config values:
.. confval:: math_number_all
Set this option to ``True`` if you want all displayed math to be numbered.
The default is ``False``.
.. confval:: math_eqref_format
A string that are used for format of label of references to equations.
As a special character, ``{number}`` will be replaced to equaition number.
Example: ``'Eq.{number}'`` is rendered as ``Eq.10``
.. confval:: math_numfig
If ``True``, displayed math equations are numbered across pages when
:confval:`numfig` is enabled. The :confval:`numfig_secnum_depth` setting
is respected. The :rst:role:`eq`, not :rst:role:`numref`, role
must be used to reference equation numbers. Default is ``True``.
.. versionadded:: 1.7
:mod:`.mathbase` defines these new markup elements:
.. rst:role:: math
Role for inline math. Use like this::
Since Pythagoras, we know that :math:`a^2 + b^2 = c^2`.
.. rst:directive:: math
Directive for displayed math (math that takes the whole line for itself).
The directive supports multiple equations, which should be separated by a
blank line::
.. math::
(a + b)^2 = a^2 + 2ab + b^2
(a - b)^2 = a^2 - 2ab + b^2
In addition, each single equation is set within a ``split`` environment,
which means that you can have multiple aligned lines in an equation,
aligned at ``&`` and separated by ``\\``::
.. math::
(a + b)^2 &= (a + b)(a + b) \\
&= a^2 + 2ab + b^2
For more details, look into the documentation of the `AmSMath LaTeX
package`_.
When the math is only one line of text, it can also be given as a directive
argument::
.. math:: (a + b)^2 = a^2 + 2ab + b^2
Normally, equations are not numbered. If you want your equation to get a
number, use the ``label`` option. When given, it selects an internal label
for the equation, by which it can be cross-referenced, and causes an equation
number to be issued. See :rst:role:`eq` for an example. The numbering
style depends on the output format.
There is also an option ``nowrap`` that prevents any wrapping of the given
math in a math environment. When you give this option, you must make sure
yourself that the math is properly set up. For example::
.. math::
:nowrap:
\begin{eqnarray}
y & = & ax^2 + bx + c \\
f(x) & = & x^2 + 2xy + y^2
\end{eqnarray}
.. rst:role:: eq
Role for cross-referencing equations via their label. Example::
.. math:: e^{i\pi} + 1 = 0
:label: euler
Euler's identity, equation :eq:`euler`, was elected one of the most
beautiful mathematical formulas.
gives a math support to HTML document with several extensions.
:mod:`sphinx.ext.imgmath` -- Render math as images
--------------------------------------------------
@ -299,4 +196,3 @@ package jsMath_. It provides this config value:
.. _MathJax: https://www.mathjax.org/
.. _jsMath: http://www.math.union.edu/~dpvc/jsmath/
.. _preview-latex package: https://www.gnu.org/software/auctex/preview-latex.html
.. _AmSMath LaTeX package: https://www.ams.org/publications/authors/tex/amslatex

View File

@ -1005,9 +1005,63 @@ this reason, the following directive exists:
Math
----
.. todo:: Move this in here.
The input language for mathematics is LaTeX markup. This is the de-facto
standard for plain-text math notation and has the added advantage that no
further translation is necessary when building LaTeX output.
See :ref:`math-support`.
Keep in mind that when you put math markup in **Python docstrings** read by
:mod:`autodoc <sphinx.ext.autodoc>`, you either have to double all backslashes,
or use Python raw strings (``r"raw"``).
.. rst:directive:: math
Directive for displayed math (math that takes the whole line for itself).
The directive supports multiple equations, which should be separated by a
blank line::
.. math::
(a + b)^2 = a^2 + 2ab + b^2
(a - b)^2 = a^2 - 2ab + b^2
In addition, each single equation is set within a ``split`` environment,
which means that you can have multiple aligned lines in an equation,
aligned at ``&`` and separated by ``\\``::
.. math::
(a + b)^2 &= (a + b)(a + b) \\
&= a^2 + 2ab + b^2
For more details, look into the documentation of the `AmSMath LaTeX
package`_.
When the math is only one line of text, it can also be given as a directive
argument::
.. math:: (a + b)^2 = a^2 + 2ab + b^2
Normally, equations are not numbered. If you want your equation to get a
number, use the ``label`` option. When given, it selects an internal label
for the equation, by which it can be cross-referenced, and causes an equation
number to be issued. See :rst:role:`eq` for an example. The numbering
style depends on the output format.
There is also an option ``nowrap`` that prevents any wrapping of the given
math in a math environment. When you give this option, you must make sure
yourself that the math is properly set up. For example::
.. math::
:nowrap:
\begin{eqnarray}
y & = & ax^2 + bx + c \\
f(x) & = & x^2 + 2xy + y^2
\end{eqnarray}
.. _AmSMath LaTeX package: https://www.ams.org/publications/authors/tex/amslatex
Grammar production displays

View File

@ -277,6 +277,26 @@ The following role creates a cross-reference to a term in a
during build.
Math
----
.. rst:role:: math
Role for inline math. Use like this::
Since Pythagoras, we know that :math:`a^2 + b^2 = c^2`.
.. rst:role:: eq
Role for cross-referencing equations via their label. Example::
.. math:: e^{i\pi} + 1 = 0
:label: euler
Euler's identity, equation :eq:`euler`, was elected one of the most
beautiful mathematical formulas.
Other semantic markup
---------------------

72
karma.conf.js Normal file
View File

@ -0,0 +1,72 @@
// Karma configuration
// Generated on Sat Jul 21 2018 22:01:48 GMT+0200 (CEST)
module.exports = function(config) {
config.set({
// base path that will be used to resolve all patterns (eg. files, exclude)
basePath: '',
// frameworks to use
// available frameworks: https://npmjs.org/browse/keyword/karma-adapter
frameworks: ['jasmine'],
// list of files / patterns to load in the browser
files: [
'sphinx/themes/basic/static/underscore.js',
'sphinx/themes/basic/static/jquery.js',
'sphinx/themes/basic/static/doctools.js',
'tests/js/*.js'
],
// list of files / patterns to exclude
exclude: [
],
// preprocess matching files before serving them to the browser
// available preprocessors: https://npmjs.org/browse/keyword/karma-preprocessor
preprocessors: {
},
// test results reporter to use
// possible values: 'dots', 'progress'
// available reporters: https://npmjs.org/browse/keyword/karma-reporter
reporters: ['progress'],
// web server port
port: 9876,
// enable / disable colors in the output (reporters and logs)
colors: true,
// level of logging
// possible values: config.LOG_DISABLE || config.LOG_ERROR || config.LOG_WARN || config.LOG_INFO || config.LOG_DEBUG
logLevel: config.LOG_INFO,
// enable / disable watching file and executing tests whenever any file changes
autoWatch: true,
// start these browsers
// available browser launchers: https://npmjs.org/browse/keyword/karma-launcher
browsers: ['Chrome', 'Firefox'],
// Continuous Integration mode
// if true, Karma captures browsers, runs the tests and exits
singleRun: false,
// Concurrency level
// how many browser should be started simultaneous
concurrency: Infinity
})
}

4456
package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

20
package.json Normal file
View File

@ -0,0 +1,20 @@
{
"name": "sphinx",
"scripts": {
"test": "./node_modules/.bin/karma start --browsers Firefox --single-run"
},
"repository": {
"type": "git",
"url": "git+https://github.com/sphinx-doc/sphinx.git"
},
"bugs": {
"url": "https://github.com/sphinx-doc/sphinx/issues"
},
"devDependencies": {
"jasmine-core": "^3.1.0",
"karma": "^2.0.4",
"karma-chrome-launcher": "^2.2.0",
"karma-firefox-launcher": "^1.1.0",
"karma-jasmine": "^1.1.2"
}
}

View File

@ -96,6 +96,7 @@ builtin_extensions = (
'sphinx.registry',
'sphinx.roles',
'sphinx.transforms.post_transforms',
'sphinx.transforms.post_transforms.code',
'sphinx.transforms.post_transforms.images',
'sphinx.transforms.post_transforms.compat',
'sphinx.util.compat',
@ -1227,6 +1228,20 @@ class Sphinx(object):
logger.debug('[app] adding HTML theme: %r, %r', name, theme_path)
self.html_themes[name] = theme_path
def add_html_math_renderer(self, name, inline_renderers=None, block_renderers=None):
# type: (unicode, Tuple[Callable, Callable], Tuple[Callable, Callable]) -> None
"""Register a math renderer for HTML.
The *name* is a name of the math renderer. Both *inline_renderers* and
*block_renderes* are used as visitor functions for HTML writer.
*inline_renderers* is used for inline math node (``nodes.math`)). The
another is used for block math node (``nodes.math_block``). About
visitor functions, see :meth:`add_node` for more details.
.. versionadded:: 1.8
"""
self.registry.add_html_math_renderer(name, inline_renderers, block_renderers)
def add_message_catalog(self, catalog, locale_dir):
# type: (unicode, unicode) -> None
"""Register a message catalog.

View File

@ -195,7 +195,7 @@ class EpubBuilder(StandaloneHTMLBuilder):
"""Collect section titles, their depth in the toc and the refuri."""
# XXX: is there a better way than checking the attribute
# toctree-l[1-8] on the parent node?
if isinstance(doctree, nodes.reference) and 'refuri' in doctree:
if isinstance(doctree, nodes.reference) and doctree.get('refuri'):
refuri = doctree['refuri']
if refuri.startswith('http://') or refuri.startswith('https://') \
or refuri.startswith('irc:') or refuri.startswith('mailto:'):

View File

@ -36,7 +36,7 @@ from sphinx.deprecation import RemovedInSphinx20Warning, RemovedInSphinx30Warnin
from sphinx.environment.adapters.asset import ImageAdapter
from sphinx.environment.adapters.indexentries import IndexEntries
from sphinx.environment.adapters.toctree import TocTree
from sphinx.errors import ThemeError
from sphinx.errors import ConfigError, ThemeError
from sphinx.highlighting import PygmentsBridge
from sphinx.locale import _, __
from sphinx.search import js_index
@ -386,8 +386,7 @@ class StandaloneHTMLBuilder(Builder):
style = self.theme.get_config('theme', 'pygments_style', 'none')
else:
style = 'sphinx'
self.highlighter = PygmentsBridge('html', style,
self.config.trim_doctest_flags)
self.highlighter = PygmentsBridge('html', style)
def init_css_files(self):
# type: () -> None
@ -438,6 +437,27 @@ class StandaloneHTMLBuilder(Builder):
else:
return HTMLTranslator
@property
def math_renderer_name(self):
# type: () -> unicode
name = self.get_builder_config('math_renderer', 'html')
if name is not None:
# use given name
return name
else:
# not given: choose a math_renderer from registered ones as possible
renderers = list(self.app.registry.html_inline_math_renderers)
if len(renderers) == 1:
# only default math_renderer (mathjax) is registered
return renderers[0]
elif len(renderers) == 2:
# default and another math_renderer are registered; prior the another
renderers.remove('mathjax')
return renderers[0]
else:
# many math_renderers are registered. can't choose automatically!
return None
def get_outdated_docs(self):
# type: () -> Iterator[unicode]
try:
@ -1625,6 +1645,19 @@ def setup_js_tag_helper(app, pagename, templatexname, context, doctree):
context['js_tag'] = js_tag
def validate_math_renderer(app):
# type: (Sphinx) -> None
if app.builder.format != 'html':
return
name = app.builder.math_renderer_name # type: ignore
if name is None:
raise ConfigError(__('Many math_renderers are registered. '
'But no math_renderer is selected.'))
elif name not in app.registry.html_inline_math_renderers:
raise ConfigError(__('Unknown math_renderer %r is given.') % name)
def setup(app):
# type: (Sphinx) -> Dict[unicode, Any]
# builders
@ -1674,12 +1707,17 @@ def setup(app):
app.add_config_value('html_scaled_image_link', True, 'html')
app.add_config_value('html_experimental_html5_writer', None, 'html')
app.add_config_value('html_baseurl', '', 'html')
app.add_config_value('html_math_renderer', None, 'env')
# event handlers
app.connect('config-inited', convert_html_css_files)
app.connect('config-inited', convert_html_js_files)
app.connect('builder-inited', validate_math_renderer)
app.connect('html-page-context', setup_js_tag_helper)
# load default math renderer
app.setup_extension('sphinx.ext.mathjax')
return {
'version': 'builtin',
'parallel_read_safe': True,

View File

@ -34,7 +34,7 @@ from sphinx.util.docutils import SphinxFileOutput, new_document
from sphinx.util.fileutil import copy_asset_file
from sphinx.util.nodes import inline_all_toctrees
from sphinx.util.osutil import SEP, make_filename
from sphinx.writers.latex import LaTeXWriter, LaTeXTranslator
from sphinx.writers.latex import DEFAULT_SETTINGS, LaTeXWriter, LaTeXTranslator
if False:
# For type annotation
@ -169,8 +169,7 @@ class LaTeXBuilder(Builder):
def write_stylesheet(self):
# type: () -> None
highlighter = highlighting.PygmentsBridge(
'latex', self.config.pygments_style, self.config.trim_doctest_flags)
highlighter = highlighting.PygmentsBridge('latex', self.config.pygments_style)
stylesheet = path.join(self.outdir, 'sphinxhighlight.sty')
with open(stylesheet, 'w') as f:
f.write('\\NeedsTeXFormat{LaTeX2e}[1995/12/01]\n')
@ -374,6 +373,12 @@ def validate_config_values(app, config):
'Please use u"..." notation instead): %r') % (document,)
)
for key in list(config.latex_elements):
if key not in DEFAULT_SETTINGS:
msg = __("Unknown configure key: latex_elements[%r]. ignored.")
logger.warning(msg % key)
config.latex_elements.pop(key)
def default_latex_engine(config):
# type: (Config) -> unicode

View File

@ -120,12 +120,15 @@ class CheckExternalLinksBuilder(Builder):
def check_thread(self):
# type: () -> None
kwargs = {}
kwargs = {
'allow_redirects': True,
'headers': {
'Accept': 'text/html,application/xhtml+xml;q=0.9,*/*;q=0.8'
},
}
if self.app.config.linkcheck_timeout:
kwargs['timeout'] = self.app.config.linkcheck_timeout
kwargs['allow_redirects'] = True
def check_uri():
# type: () -> Tuple[unicode, unicode, int]
# split off anchor

View File

@ -202,7 +202,7 @@ files can be built by specifying individual filenames.
def make_main(argv=sys.argv[1:]): # type: ignore
# type: (List[unicode]) -> int
"""Sphinx build "make mode" entry."""
from sphinx import make_mode
from sphinx.cmd import make_mode
return make_mode.run_make_mode(argv[1:])

165
sphinx/cmd/make_mode.py Normal file
View File

@ -0,0 +1,165 @@
# -*- coding: utf-8 -*-
"""
sphinx.cmd.make_mode
~~~~~~~~~~~~~~~~~~~~
sphinx-build -M command-line handling.
This replaces the old, platform-dependent and once-generated content
of Makefile / make.bat.
This is in its own module so that importing it is fast. It should not
import the main Sphinx modules (like sphinx.applications, sphinx.builders).
:copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS.
:license: BSD, see LICENSE for details.
"""
from __future__ import print_function
import os
import subprocess
import sys
from os import path
import sphinx
from sphinx.cmd.build import build_main
from sphinx.util.console import color_terminal, nocolor, bold, blue # type: ignore
from sphinx.util.osutil import cd, rmtree
if False:
# For type annotation
from typing import List # NOQA
BUILDERS = [
("", "html", "to make standalone HTML files"),
("", "dirhtml", "to make HTML files named index.html in directories"),
("", "singlehtml", "to make a single large HTML file"),
("", "pickle", "to make pickle files"),
("", "json", "to make JSON files"),
("", "htmlhelp", "to make HTML files and an HTML help project"),
("", "qthelp", "to make HTML files and a qthelp project"),
("", "devhelp", "to make HTML files and a Devhelp project"),
("", "epub", "to make an epub"),
("", "latex", "to make LaTeX files, you can set PAPER=a4 or PAPER=letter"),
("posix", "latexpdf", "to make LaTeX and PDF files (default pdflatex)"),
("posix", "latexpdfja", "to make LaTeX files and run them through platex/dvipdfmx"),
("", "text", "to make text files"),
("", "man", "to make manual pages"),
("", "texinfo", "to make Texinfo files"),
("posix", "info", "to make Texinfo files and run them through makeinfo"),
("", "gettext", "to make PO message catalogs"),
("", "changes", "to make an overview of all changed/added/deprecated items"),
("", "xml", "to make Docutils-native XML files"),
("", "pseudoxml", "to make pseudoxml-XML files for display purposes"),
("", "linkcheck", "to check all external links for integrity"),
("", "doctest", "to run all doctests embedded in the documentation "
"(if enabled)"),
("", "coverage", "to run coverage check of the documentation (if enabled)"),
]
class Make(object):
def __init__(self, srcdir, builddir, opts):
# type: (unicode, unicode, List[unicode]) -> None
self.srcdir = srcdir
self.builddir = builddir
self.opts = opts
self.makecmd = os.environ.get('MAKE', 'make') # refer $MAKE to determine make command
def builddir_join(self, *comps):
# type: (unicode) -> unicode
return path.join(self.builddir, *comps)
def build_clean(self):
# type: () -> int
if not path.exists(self.builddir):
return 0
elif not path.isdir(self.builddir):
print("Error: %r is not a directory!" % self.builddir)
return 1
print("Removing everything under %r..." % self.builddir)
for item in os.listdir(self.builddir):
rmtree(self.builddir_join(item))
return 0
def build_help(self):
# type: () -> None
if not color_terminal():
nocolor()
print(bold("Sphinx v%s" % sphinx.__display_version__))
print("Please use `make %s' where %s is one of" % ((blue('target'),) * 2)) # type: ignore # NOQA
for osname, bname, description in BUILDERS:
if not osname or os.name == osname:
print(' %s %s' % (blue(bname.ljust(10)), description))
def build_latexpdf(self):
# type: () -> int
if self.run_generic_build('latex') > 0:
return 1
try:
with cd(self.builddir_join('latex')):
return subprocess.call([self.makecmd, 'all-pdf'])
except OSError:
print('Error: Failed to run: %s' % self.makecmd)
return 1
def build_latexpdfja(self):
# type: () -> int
if self.run_generic_build('latex') > 0:
return 1
try:
with cd(self.builddir_join('latex')):
return subprocess.call([self.makecmd, 'all-pdf-ja'])
except OSError:
print('Error: Failed to run: %s' % self.makecmd)
return 1
def build_info(self):
# type: () -> int
if self.run_generic_build('texinfo') > 0:
return 1
try:
with cd(self.builddir_join('texinfo')):
return subprocess.call([self.makecmd, 'info'])
except OSError:
print('Error: Failed to run: %s' % self.makecmd)
return 1
def build_gettext(self):
# type: () -> int
dtdir = self.builddir_join('gettext', '.doctrees')
if self.run_generic_build('gettext', doctreedir=dtdir) > 0:
return 1
return 0
def run_generic_build(self, builder, doctreedir=None):
# type: (unicode, unicode) -> int
# compatibility with old Makefile
papersize = os.getenv('PAPER', '')
opts = self.opts
if papersize in ('a4', 'letter'):
opts.extend(['-D', 'latex_elements.papersize=' + papersize])
if doctreedir is None:
doctreedir = self.builddir_join('doctrees')
args = ['-b', builder,
'-d', doctreedir,
self.srcdir,
self.builddir_join(builder)]
return build_main(args + opts)
def run_make_mode(args):
# type: (List[unicode]) -> int
if len(args) < 3:
print('Error: at least 3 arguments (builder, source '
'dir, build dir) are required.', file=sys.stderr)
return 1
make = Make(args[1], args[2], args[3:])
run_method = 'build_' + args[0]
if hasattr(make, run_method):
return getattr(make, run_method)()
return make.run_generic_build(args[0])

View File

@ -1265,6 +1265,11 @@ class DataDocumenter(ModuleLevelDocumenter):
# type: (bool) -> None
pass
def get_real_modname(self):
# type: () -> str
return self.get_attr(self.parent or self.object, '__module__', None) \
or self.modname
class MethodDocumenter(DocstringSignatureMixin, ClassLevelDocumenter): # type: ignore
"""

View File

@ -167,8 +167,21 @@ def import_object(modname, objpath, objtype='', attrgetter=safe_getattr, warning
logger.debug('[autodoc] import %s', modname)
try:
module = import_module(modname, warningiserror=warningiserror)
logger.debug('[autodoc] => %r', module)
module = None
objpath = list(objpath)
while module is None:
try:
module = import_module(modname, warningiserror=warningiserror)
logger.debug('[autodoc] import %s => %r', modname, module)
except ImportError:
logger.debug('[autodoc] import %s => failed', modname)
if '.' in modname:
# retry with parent module
modname, name = modname.rsplit('.', 1)
objpath.insert(0, name)
else:
raise
obj = module
parent = None
object_name = None

View File

@ -22,11 +22,10 @@ from docutils import nodes
from six import text_type
import sphinx
from sphinx.errors import SphinxError, ExtensionError
from sphinx.ext.mathbase import get_node_equation_number
from sphinx.ext.mathbase import setup_math as mathbase_setup, wrap_displaymath
from sphinx.errors import SphinxError
from sphinx.locale import _, __
from sphinx.util import logging
from sphinx.util.math import get_node_equation_number, wrap_displaymath
from sphinx.util.osutil import ensuredir, ENOENT, cd
from sphinx.util.png import read_png_depth, write_png_depth
from sphinx.util.pycompat import sys_encoding
@ -34,10 +33,10 @@ from sphinx.util.pycompat import sys_encoding
if False:
# For type annotation
from typing import Any, Dict, List, Tuple # NOQA
from sphinx.addnodes import displaymath # NOQA
from sphinx.application import Sphinx # NOQA
from sphinx.builders import Builder # NOQA
from sphinx.config import Config # NOQA
from sphinx.ext.mathbase import displaymath # NOQA
logger = logging.getLogger(__name__)
@ -315,7 +314,7 @@ def html_visit_math(self, node):
def html_visit_displaymath(self, node):
# type: (nodes.NodeVisitor, displaymath) -> None
# type: (nodes.NodeVisitor, nodes.math_block) -> None
if node['nowrap']:
latex = node.astext()
else:
@ -349,10 +348,9 @@ def html_visit_displaymath(self, node):
def setup(app):
# type: (Sphinx) -> Dict[unicode, Any]
try:
mathbase_setup(app, (html_visit_math, None), (html_visit_displaymath, None))
except ExtensionError:
raise ExtensionError('sphinx.ext.imgmath: other math package is already loaded')
app.add_html_math_renderer('imgmath',
(html_visit_math, None),
(html_visit_displaymath, None))
app.add_config_value('imgmath_image_format', 'png', 'html')
app.add_config_value('imgmath_dvipng', 'dvipng', 'html')

View File

@ -14,9 +14,8 @@ from docutils import nodes
import sphinx
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 _
from sphinx.util.math import get_node_equation_number
if False:
# For type annotation
@ -61,7 +60,9 @@ def html_visit_displaymath(self, node):
def builder_inited(app):
# type: (Sphinx) -> None
if not app.config.jsmath_path:
if app.builder.format != 'html' or app.builder.math_renderer_name != 'jsmath': # type: ignore # NOQA
pass
elif not app.config.jsmath_path:
raise ExtensionError('jsmath_path config value must be set for the '
'jsmath extension to work')
if app.builder.format == 'html':
@ -70,10 +71,9 @@ def builder_inited(app):
def setup(app):
# type: (Sphinx) -> Dict[unicode, Any]
try:
mathbase_setup(app, (html_visit_math, None), (html_visit_displaymath, None))
except ExtensionError:
raise ExtensionError('sphinx.ext.jsmath: other math package is already loaded')
app.add_html_math_renderer('jsmath',
(html_visit_math, None),
(html_visit_displaymath, None))
app.add_config_value('jsmath_path', '', False)
app.connect('builder-inited', builder_inited)

View File

@ -13,7 +13,7 @@ import warnings
from docutils import nodes
from sphinx.addnodes import math, math_block as displaymath
from sphinx.addnodes import math, math_block as displaymath # NOQA # to keep compatibility
from sphinx.builders.latex.nodes import math_reference as eqref # NOQA # to keep compatibility
from sphinx.deprecation import RemovedInSphinx30Warning
from sphinx.domains.math import MathDomain # NOQA # to keep compatibility
@ -28,57 +28,20 @@ if False:
def get_node_equation_number(writer, node):
# type: (Writer, nodes.Node) -> unicode
if writer.builder.config.math_numfig and writer.builder.config.numfig:
figtype = 'displaymath'
if writer.builder.name == 'singlehtml':
key = u"%s/%s" % (writer.docnames[-1], figtype)
else:
key = figtype
id = node['ids'][0]
number = writer.builder.fignumbers.get(key, {}).get(id, ())
number = '.'.join(map(str, number))
else:
number = node['number']
return number
warnings.warn('sphinx.ext.mathbase.get_node_equation_number() is moved to '
'sphinx.util.math package.',
RemovedInSphinx30Warning)
from sphinx.util.math import get_node_equation_number
return get_node_equation_number(writer, node)
def wrap_displaymath(math, label, numbering):
def wrap_displaymath(text, label, numbering):
# type: (unicode, unicode, bool) -> unicode
def is_equation(part):
# type: (unicode) -> unicode
return part.strip()
if label is None:
labeldef = ''
else:
labeldef = r'\label{%s}' % label
numbering = True
parts = list(filter(is_equation, math.split('\n\n')))
equations = []
if len(parts) == 0:
return ''
elif len(parts) == 1:
if numbering:
begin = r'\begin{equation}' + labeldef
end = r'\end{equation}'
else:
begin = r'\begin{equation*}' + labeldef
end = r'\end{equation*}'
equations.append('\\begin{split}%s\\end{split}\n' % parts[0])
else:
if numbering:
begin = r'\begin{align}%s\!\begin{aligned}' % labeldef
end = r'\end{aligned}\end{align}'
else:
begin = r'\begin{align*}%s\!\begin{aligned}' % labeldef
end = r'\end{aligned}\end{align*}'
for part in parts:
equations.append('%s\\\\\n' % part.strip())
return '%s\n%s%s' % (begin, ''.join(equations), end)
warnings.warn('sphinx.ext.mathbase.wrap_displaymath() is moved to '
'sphinx.util.math package.',
RemovedInSphinx30Warning)
from sphinx.util.math import wrap_displaymath
return wrap_displaymath(text, label, numbering)
def is_in_section_title(node):
@ -97,8 +60,9 @@ def is_in_section_title(node):
def setup_math(app, htmlinlinevisitors, htmldisplayvisitors):
# type: (Sphinx, Tuple[Callable, Any], Tuple[Callable, Any]) -> None
app.add_node(math, override=True,
html=htmlinlinevisitors)
app.add_node(displaymath, override=True,
html=htmldisplayvisitors)
# type: (Sphinx, Tuple[Callable, Callable], Tuple[Callable, Callable]) -> None
warnings.warn('setup_math() is deprecated. '
'Please use app.add_html_math_renderer() instead.',
RemovedInSphinx30Warning)
app.add_html_math_renderer('unknown', htmlinlinevisitors, htmldisplayvisitors)

View File

@ -15,9 +15,8 @@ from docutils import nodes
import sphinx
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 _
from sphinx.util.math import get_node_equation_number
if False:
# For type annotation
@ -69,7 +68,9 @@ def html_visit_displaymath(self, node):
def builder_inited(app):
# type: (Sphinx) -> None
if not app.config.mathjax_path:
if app.builder.format != 'html' or app.builder.math_renderer_name != 'mathjax': # type: ignore # NOQA
pass
elif not app.config.mathjax_path:
raise ExtensionError('mathjax_path config value must be set for the '
'mathjax extension to work')
if app.builder.format == 'html':
@ -81,10 +82,9 @@ def builder_inited(app):
def setup(app):
# type: (Sphinx) -> Dict[unicode, Any]
try:
mathbase_setup(app, (html_visit_math, None), (html_visit_displaymath, None))
except ExtensionError:
raise ExtensionError('sphinx.ext.mathjax: other math package is already loaded')
app.add_html_math_renderer('mathjax',
(html_visit_math, None),
(html_visit_displaymath, None))
# more information for mathjax secure url is here:
# https://docs.mathjax.org/en/latest/start.html#secure-access-to-the-cdn

View File

@ -9,6 +9,8 @@
:license: BSD, see LICENSE for details.
"""
import warnings
from pygments import highlight
from pygments.filters import ErrorToken
from pygments.formatters import HtmlFormatter, LatexFormatter
@ -20,6 +22,7 @@ from pygments.styles import get_style_by_name
from pygments.util import ClassNotFound
from six import text_type
from sphinx.deprecation import RemovedInSphinx30Warning
from sphinx.ext import doctest
from sphinx.locale import __
from sphinx.pygments_styles import SphinxStyle, NoneStyle
@ -65,7 +68,7 @@ class PygmentsBridge(object):
html_formatter = HtmlFormatter
latex_formatter = LatexFormatter
def __init__(self, dest='html', stylename='sphinx', trim_doctest_flags=False):
def __init__(self, dest='html', stylename='sphinx', trim_doctest_flags=None):
# type: (unicode, unicode, bool) -> None
self.dest = dest
if stylename is None or stylename == 'sphinx':
@ -78,7 +81,6 @@ class PygmentsBridge(object):
stylename)
else:
style = get_style_by_name(stylename)
self.trim_doctest_flags = trim_doctest_flags
self.formatter_args = {'style': style} # type: Dict[unicode, Any]
if dest == 'html':
self.formatter = self.html_formatter
@ -86,6 +88,11 @@ class PygmentsBridge(object):
self.formatter = self.latex_formatter
self.formatter_args['commandprefix'] = 'PYG'
self.trim_doctest_flags = trim_doctest_flags
if trim_doctest_flags is not None:
warnings.warn('trim_doctest_flags option for PygmentsBridge is now deprecated.',
RemovedInSphinx30Warning)
def get_formatter(self, **kwargs):
# type: (Any) -> Formatter
kwargs.update(self.formatter_args) # type: ignore
@ -93,6 +100,8 @@ class PygmentsBridge(object):
def unhighlighted(self, source):
# type: (unicode) -> unicode
warnings.warn('PygmentsBridge.unhighlighted() is now deprecated.',
RemovedInSphinx30Warning)
if self.dest == 'html':
return '<pre>' + htmlescape(source) + '</pre>\n'
else:
@ -161,8 +170,6 @@ class PygmentsBridge(object):
if self.dest == 'html':
return hlsource
else:
if not isinstance(hlsource, text_type): # Py2 / Pygments < 1.6
hlsource = hlsource.decode()
return hlsource.translate(tex_hl_escape_map_new)
def get_stylesheet(self):

View File

@ -14,152 +14,26 @@
:copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS.
:license: BSD, see LICENSE for details.
"""
from __future__ import print_function
import os
import subprocess
import sys
from os import path
import warnings
import sphinx
from sphinx.cmd.build import build_main
from sphinx.util.console import color_terminal, nocolor, bold, blue # type: ignore
from sphinx.util.osutil import cd, rmtree
if False:
# For type annotation
from typing import List # NOQA
from sphinx.cmd import make_mode
from sphinx.deprecation import RemovedInSphinx30Warning
BUILDERS = [
("", "html", "to make standalone HTML files"),
("", "dirhtml", "to make HTML files named index.html in directories"),
("", "singlehtml", "to make a single large HTML file"),
("", "pickle", "to make pickle files"),
("", "json", "to make JSON files"),
("", "htmlhelp", "to make HTML files and an HTML help project"),
("", "qthelp", "to make HTML files and a qthelp project"),
("", "devhelp", "to make HTML files and a Devhelp project"),
("", "epub", "to make an epub"),
("", "latex", "to make LaTeX files, you can set PAPER=a4 or PAPER=letter"),
("posix", "latexpdf", "to make LaTeX and PDF files (default pdflatex)"),
("posix", "latexpdfja", "to make LaTeX files and run them through platex/dvipdfmx"),
("", "text", "to make text files"),
("", "man", "to make manual pages"),
("", "texinfo", "to make Texinfo files"),
("posix", "info", "to make Texinfo files and run them through makeinfo"),
("", "gettext", "to make PO message catalogs"),
("", "changes", "to make an overview of all changed/added/deprecated items"),
("", "xml", "to make Docutils-native XML files"),
("", "pseudoxml", "to make pseudoxml-XML files for display purposes"),
("", "linkcheck", "to check all external links for integrity"),
("", "doctest", "to run all doctests embedded in the documentation "
"(if enabled)"),
("", "coverage", "to run coverage check of the documentation (if enabled)"),
]
BUILDERS = make_mode.BUILDERS
class Make(object):
def __init__(self, srcdir, builddir, opts):
# type: (unicode, unicode, List[unicode]) -> None
self.srcdir = srcdir
self.builddir = builddir
self.opts = opts
self.makecmd = os.environ.get('MAKE', 'make') # refer $MAKE to determine make command
def builddir_join(self, *comps):
# type: (unicode) -> unicode
return path.join(self.builddir, *comps)
def build_clean(self):
# type: () -> int
if not path.exists(self.builddir):
return 0
elif not path.isdir(self.builddir):
print("Error: %r is not a directory!" % self.builddir)
return 1
print("Removing everything under %r..." % self.builddir)
for item in os.listdir(self.builddir):
rmtree(self.builddir_join(item))
return 0
def build_help(self):
# type: () -> None
if not color_terminal():
nocolor()
print(bold("Sphinx v%s" % sphinx.__display_version__))
print("Please use `make %s' where %s is one of" % ((blue('target'),) * 2)) # type: ignore # NOQA
for osname, bname, description in BUILDERS:
if not osname or os.name == osname:
print(' %s %s' % (blue(bname.ljust(10)), description))
def build_latexpdf(self):
# type: () -> int
if self.run_generic_build('latex') > 0:
return 1
try:
with cd(self.builddir_join('latex')):
return subprocess.call([self.makecmd, 'all-pdf'])
except OSError:
print('Error: Failed to run: %s' % self.makecmd)
return 1
def build_latexpdfja(self):
# type: () -> int
if self.run_generic_build('latex') > 0:
return 1
try:
with cd(self.builddir_join('latex')):
return subprocess.call([self.makecmd, 'all-pdf-ja'])
except OSError:
print('Error: Failed to run: %s' % self.makecmd)
return 1
def build_info(self):
# type: () -> int
if self.run_generic_build('texinfo') > 0:
return 1
try:
with cd(self.builddir_join('texinfo')):
return subprocess.call([self.makecmd, 'info'])
except OSError:
print('Error: Failed to run: %s' % self.makecmd)
return 1
def build_gettext(self):
# type: () -> int
dtdir = self.builddir_join('gettext', '.doctrees')
if self.run_generic_build('gettext', doctreedir=dtdir) > 0:
return 1
return 0
def run_generic_build(self, builder, doctreedir=None):
# type: (unicode, unicode) -> int
# compatibility with old Makefile
papersize = os.getenv('PAPER', '')
opts = self.opts
if papersize in ('a4', 'letter'):
opts.extend(['-D', 'latex_elements.papersize=' + papersize])
if doctreedir is None:
doctreedir = self.builddir_join('doctrees')
args = ['-b', builder,
'-d', doctreedir,
self.srcdir,
self.builddir_join(builder)]
return build_main(args + opts)
class Make(make_mode.Make):
def __init__(self, *args):
warnings.warn('sphinx.make_mode.Make is deprecated. '
'Please use sphinx.cmd.make_mode.Make instead.',
RemovedInSphinx30Warning)
super(Make, self).__init__(*args)
def run_make_mode(args):
# type: (List[unicode]) -> int
if len(args) < 3:
print('Error: at least 3 arguments (builder, source '
'dir, build dir) are required.', file=sys.stderr)
return 1
make = Make(args[1], args[2], args[3:])
run_method = 'build_' + args[0]
if hasattr(make, run_method):
return getattr(make, run_method)()
return make.run_generic_build(args[0])
warnings.warn('sphinx.make_mode.run_make_mode() is deprecated. '
'Please use sphinx.cmd.make_mode.run_make_mode() instead.',
RemovedInSphinx30Warning)
return make_mode.run_make_mode(args)

View File

@ -92,6 +92,11 @@ class SphinxComponentRegistry(object):
#: a dict of node class -> tuple of figtype and title_getter function
self.enumerable_nodes = {} # type: Dict[nodes.Node, Tuple[unicode, TitleGetter]]
#: HTML inline and block math renderers
#: a dict of name -> tuple of visit function and depart function
self.html_inline_math_renderers = {} # type: Dict[unicode, Tuple[Callable, Callable]] # NOQA
self.html_block_math_renderers = {} # type: Dict[unicode, Tuple[Callable, Callable]] # NOQA
#: js_files; list of JS paths or URLs
self.js_files = [] # type: List[Tuple[unicode, Dict[unicode, unicode]]]
@ -439,6 +444,16 @@ class SphinxComponentRegistry(object):
raise ExtensionError(__('enumerable_node %r already registered') % node)
self.enumerable_nodes[node] = (figtype, title_getter)
def add_html_math_renderer(self, name, inline_renderers, block_renderers):
# type: (unicode, Tuple[Callable, Callable], Tuple[Callable, Callable]) -> None
logger.debug('[app] adding html_math_renderer: %s, %r, %r',
name, inline_renderers, block_renderers)
if name in self.html_inline_math_renderers:
raise ExtensionError(__('math renderer %s is already registred') % name)
self.html_inline_math_renderers[name] = inline_renderers
self.html_block_math_renderers[name] = block_renderers
def load_extension(self, app, extname):
# type: (Sphinx, unicode) -> None
"""Load a Sphinx extension."""

View File

@ -21,7 +21,7 @@ from distutils.errors import DistutilsOptionError, DistutilsExecError
from six import StringIO, string_types
from sphinx.application import Sphinx
from sphinx.cmdline import handle_exception
from sphinx.cmd.build import handle_exception
from sphinx.util.console import nocolor, color_terminal
from sphinx.util.docutils import docutils_namespace, patch_docutils
from sphinx.util.osutil import abspath

View File

@ -1,6 +1,6 @@
;; -*- coding: utf-8; mode: Lisp; -*-
;; style file for xindy
;; filename: cyrLICRutf8.xdy
;; filename: LICRcyr2utf8.xdy
;; description: style file for xindy which maps back LaTeX Internal
;; Character Representation of Cyrillic to utf-8
;; usage: for use with pdflatex produced .idx files.

View File

@ -0,0 +1,236 @@
;; style file for xindy
;; filename: LICRlatin2utf8.xdy
;; description: style file for xindy which maps back LaTeX Internal
;; Character Representation of letters (as arising in .idx index
;; file) to UTF-8 encoding for correct sorting by xindy.
;; usage: for use with the pdflatex engine,
;; *not* for use with xelatex or lualatex.
;;
;; This is based upon xindy's distributed file tex/inputenc/utf8.xdy.
;; The modifications include:
;;
;; - Updates for compatibility with current LaTeX macro encoding.
;;
;; - Systematic usage of the \IeC {...} mark-up, because mark-up in
;; tex/inputenc/utf8.xdy was using it on seemingly random basis, and
;; Sphinx coercing of xindy usability for both Latin and Cyrillic scripts
;; with pdflatex requires its systematic presence here.
;;
;; - Support for some extra letters: Ÿ, Ŋ, ŋ, Œ, œ, IJ, ij, ȷ and ẞ.
;;
;; Indeed Sphinx needs to support for pdflatex engine all Unicode letters
;; available in TeX T1 font encoding. The above letters are found in
;; that encoding but not in the Latin1, 2, 3 charsets which are those
;; covered by original tex/inputenc/utf8.xdy.
;;
;; - There is a problem that ȷ is not supported out-of-the box by LaTeX
;; with inputenc, one must add explicitely
;; \DeclareUnicodeCharacter{0237}{\j}
;; to preamble of LaTeX document. However this character is not supported
;; by the TeX "times" font used by default by Sphinx for pdflatex engine.
;;
;; - ẞ needs \DeclareUnicodeCharacter{1E9E}{\SS} (but ß needs no extra set-up).
;;
;; - U+02DB (˛) and U+02D9 (˙) are also not supported by inputenc
;; out of the box and require
;; \DeclareUnicodeCharacter{02DB}{\k{}}
;; \DeclareUnicodeCharacter{02D9}{\.{}}
;; to be added to preamble.
;;
;; - U+0127 ħ and U+0126 Ħ are absent from TeX T1+TS1 font encodings.
;;
;; - Characters Ŋ and ŋ are not supported by TeX font "times" used by
;; default by Sphinx for pdflatex engine but they are supported by
;; some TeX fonts, in particular by the default LaTeX font for T1
;; encoding.
;;
;; - " and ~ must be escaped as ~" and resp. ~~ in xindy merge rules.
;;
;; Contributed by the Sphinx team, July 2018.
;;
;; See sphinx.xdy for superior figures, as they are escaped by LaTeX writer.
(merge-rule "\IeC {\textonesuperior }" "¹" :string)
(merge-rule "\IeC {\texttwosuperior }" "²" :string)
(merge-rule "\IeC {\textthreesuperior }" "³" :string)
(merge-rule "\IeC {\'a}" "á" :string)
(merge-rule "\IeC {\'A}" "Á" :string)
(merge-rule "\IeC {\`a}" "à" :string)
(merge-rule "\IeC {\`A}" "À" :string)
(merge-rule "\IeC {\^a}" "â" :string)
(merge-rule "\IeC {\^A}" "Â" :string)
(merge-rule "\IeC {\~"a}" "ä" :string)
(merge-rule "\IeC {\~"A}" "Ä" :string)
(merge-rule "\IeC {\~~a}" "ã" :string)
(merge-rule "\IeC {\~~A}" "Ã" :string)
(merge-rule "\IeC {\c c}" "ç" :string)
(merge-rule "\IeC {\c C}" "Ç" :string)
(merge-rule "\IeC {\'c}" "ć" :string)
(merge-rule "\IeC {\'C}" "Ć" :string)
(merge-rule "\IeC {\^c}" "ĉ" :string)
(merge-rule "\IeC {\^C}" "Ĉ" :string)
(merge-rule "\IeC {\.c}" "ċ" :string)
(merge-rule "\IeC {\.C}" "Ċ" :string)
(merge-rule "\IeC {\c s}" "ş" :string)
(merge-rule "\IeC {\c S}" "Ş" :string)
(merge-rule "\IeC {\c t}" "ţ" :string)
(merge-rule "\IeC {\c T}" "Ţ" :string)
(merge-rule "\IeC {\-}" "­" :string); soft hyphen
(merge-rule "\IeC {\textdiv }" "÷" :string)
(merge-rule "\IeC {\'e}" "é" :string)
(merge-rule "\IeC {\'E}" "É" :string)
(merge-rule "\IeC {\`e}" "è" :string)
(merge-rule "\IeC {\`E}" "È" :string)
(merge-rule "\IeC {\^e}" "ê" :string)
(merge-rule "\IeC {\^E}" "Ê" :string)
(merge-rule "\IeC {\~"e}" "ë" :string)
(merge-rule "\IeC {\~"E}" "Ë" :string)
(merge-rule "\IeC {\^g}" "ĝ" :string)
(merge-rule "\IeC {\^G}" "Ĝ" :string)
(merge-rule "\IeC {\.g}" "ġ" :string)
(merge-rule "\IeC {\.G}" "Ġ" :string)
(merge-rule "\IeC {\^h}" "ĥ" :string)
(merge-rule "\IeC {\^H}" "Ĥ" :string)
(merge-rule "\IeC {\H o}" "ő" :string)
(merge-rule "\IeC {\H O}" "Ő" :string)
(merge-rule "\IeC {\textacutedbl }" "˝" :string)
(merge-rule "\IeC {\H u}" "ű" :string)
(merge-rule "\IeC {\H U}" "Ű" :string)
(merge-rule "\IeC {\ae }" "æ" :string)
(merge-rule "\IeC {\AE }" "Æ" :string)
(merge-rule "\IeC {\textcopyright }" "©" :string)
(merge-rule "\IeC {\c \ }" "¸" :string)
(merge-rule "\IeC {\dh }" "ð" :string)
(merge-rule "\IeC {\DH }" "Ð" :string)
(merge-rule "\IeC {\dj }" "đ" :string)
(merge-rule "\IeC {\DJ }" "Đ" :string)
(merge-rule "\IeC {\guillemotleft }" "«" :string)
(merge-rule "\IeC {\guillemotright }" "»" :string)
(merge-rule "\IeC {\'\i }" "í" :string)
(merge-rule "\IeC {\`\i }" "ì" :string)
(merge-rule "\IeC {\^\i }" "î" :string)
(merge-rule "\IeC {\~"\i }" "ï" :string)
(merge-rule "\IeC {\i }" "ı" :string)
(merge-rule "\IeC {\^\j }" "ĵ" :string)
(merge-rule "\IeC {\k {}}" "˛" :string)
(merge-rule "\IeC {\l }" "ł" :string)
(merge-rule "\IeC {\L }" "Ł" :string)
(merge-rule "\IeC {\nobreakspace }" " " :string)
(merge-rule "\IeC {\o }" "ø" :string)
(merge-rule "\IeC {\O }" "Ø" :string)
(merge-rule "\IeC {\textsterling }" "£" :string)
(merge-rule "\IeC {\textparagraph }" "¶" :string)
(merge-rule "\IeC {\ss }" "ß" :string)
(merge-rule "\IeC {\textsection }" "§" :string)
(merge-rule "\IeC {\textbrokenbar }" "¦" :string)
(merge-rule "\IeC {\textcent }" "¢" :string)
(merge-rule "\IeC {\textcurrency }" "¤" :string)
(merge-rule "\IeC {\textdegree }" "°" :string)
(merge-rule "\IeC {\textexclamdown }" "¡" :string)
(merge-rule "\IeC {\texthbar }" "ħ" :string)
(merge-rule "\IeC {\textHbar }" "Ħ" :string)
(merge-rule "\IeC {\textonehalf }" "½" :string)
(merge-rule "\IeC {\textonequarter }" "¼" :string)
(merge-rule "\IeC {\textordfeminine }" "ª" :string)
(merge-rule "\IeC {\textordmasculine }" "º" :string)
(merge-rule "\IeC {\textperiodcentered }" "·" :string)
(merge-rule "\IeC {\textquestiondown }" "¿" :string)
(merge-rule "\IeC {\textregistered }" "®" :string)
(merge-rule "\IeC {\textthreequarters }" "¾" :string)
(merge-rule "\IeC {\textyen }" "¥" :string)
(merge-rule "\IeC {\th }" "þ" :string)
(merge-rule "\IeC {\TH }" "Þ" :string)
(merge-rule "\IeC {\'I}" "Í" :string)
(merge-rule "\IeC {\`I}" "Ì" :string)
(merge-rule "\IeC {\^I}" "Î" :string)
(merge-rule "\IeC {\~"I}" "Ï" :string)
(merge-rule "\IeC {\.I}" "İ" :string)
(merge-rule "\IeC {\^J}" "Ĵ" :string)
(merge-rule "\IeC {\k a}" "ą" :string)
(merge-rule "\IeC {\k A}" "Ą" :string)
(merge-rule "\IeC {\k e}" "ę" :string)
(merge-rule "\IeC {\k E}" "Ę" :string)
(merge-rule "\IeC {\'l}" "ĺ" :string)
(merge-rule "\IeC {\'L}" "Ĺ" :string)
(merge-rule "\IeC {\textlnot }" "¬" :string)
(merge-rule "\IeC {\textmu }" "µ" :string)
(merge-rule "\IeC {\'n}" "ń" :string)
(merge-rule "\IeC {\'N}" "Ń" :string)
(merge-rule "\IeC {\~~n}" "ñ" :string)
(merge-rule "\IeC {\~~N}" "Ñ" :string)
(merge-rule "\IeC {\'o}" "ó" :string)
(merge-rule "\IeC {\'O}" "Ó" :string)
(merge-rule "\IeC {\`o}" "ò" :string)
(merge-rule "\IeC {\`O}" "Ò" :string)
(merge-rule "\IeC {\^o}" "ô" :string)
(merge-rule "\IeC {\^O}" "Ô" :string)
(merge-rule "\IeC {\~"o}" "ö" :string)
(merge-rule "\IeC {\~"O}" "Ö" :string)
(merge-rule "\IeC {\~~o}" "õ" :string)
(merge-rule "\IeC {\~~O}" "Õ" :string)
(merge-rule "\IeC {\textpm }" "±" :string)
(merge-rule "\IeC {\r a}" "å" :string)
(merge-rule "\IeC {\r A}" "Å" :string)
(merge-rule "\IeC {\'r}" "ŕ" :string)
(merge-rule "\IeC {\'R}" "Ŕ" :string)
(merge-rule "\IeC {\r u}" "ů" :string)
(merge-rule "\IeC {\r U}" "Ů" :string)
(merge-rule "\IeC {\'s}" "ś" :string)
(merge-rule "\IeC {\'S}" "Ś" :string)
(merge-rule "\IeC {\^s}" "ŝ" :string)
(merge-rule "\IeC {\^S}" "Ŝ" :string)
(merge-rule "\IeC {\textasciidieresis }" "¨" :string)
(merge-rule "\IeC {\textasciimacron }" "¯" :string)
(merge-rule "\IeC {\.{}}" "˙" :string)
(merge-rule "\IeC {\textasciiacute }" "´" :string)
(merge-rule "\IeC {\texttimes }" "×" :string)
(merge-rule "\IeC {\u a}" "ă" :string)
(merge-rule "\IeC {\u A}" "Ă" :string)
(merge-rule "\IeC {\u g}" "ğ" :string)
(merge-rule "\IeC {\u G}" "Ğ" :string)
(merge-rule "\IeC {\textasciibreve }" "˘" :string)
(merge-rule "\IeC {\'u}" "ú" :string)
(merge-rule "\IeC {\'U}" "Ú" :string)
(merge-rule "\IeC {\`u}" "ù" :string)
(merge-rule "\IeC {\`U}" "Ù" :string)
(merge-rule "\IeC {\^u}" "û" :string)
(merge-rule "\IeC {\^U}" "Û" :string)
(merge-rule "\IeC {\~"u}" "ü" :string)
(merge-rule "\IeC {\~"U}" "Ü" :string)
(merge-rule "\IeC {\u u}" "ŭ" :string)
(merge-rule "\IeC {\u U}" "Ŭ" :string)
(merge-rule "\IeC {\v c}" "č" :string)
(merge-rule "\IeC {\v C}" "Č" :string)
(merge-rule "\IeC {\v d}" "ď" :string)
(merge-rule "\IeC {\v D}" "Ď" :string)
(merge-rule "\IeC {\v e}" "ě" :string)
(merge-rule "\IeC {\v E}" "Ě" :string)
(merge-rule "\IeC {\v l}" "ľ" :string)
(merge-rule "\IeC {\v L}" "Ľ" :string)
(merge-rule "\IeC {\v n}" "ň" :string)
(merge-rule "\IeC {\v N}" "Ň" :string)
(merge-rule "\IeC {\v r}" "ř" :string)
(merge-rule "\IeC {\v R}" "Ř" :string)
(merge-rule "\IeC {\v s}" "š" :string)
(merge-rule "\IeC {\v S}" "Š" :string)
(merge-rule "\IeC {\textasciicaron }" "ˇ" :string)
(merge-rule "\IeC {\v t}" "ť" :string)
(merge-rule "\IeC {\v T}" "Ť" :string)
(merge-rule "\IeC {\v z}" "ž" :string)
(merge-rule "\IeC {\v Z}" "Ž" :string)
(merge-rule "\IeC {\'y}" "ý" :string)
(merge-rule "\IeC {\'Y}" "Ý" :string)
(merge-rule "\IeC {\~"y}" "ÿ" :string)
(merge-rule "\IeC {\'z}" "ź" :string)
(merge-rule "\IeC {\'Z}" "Ź" :string)
(merge-rule "\IeC {\.z}" "ż" :string)
(merge-rule "\IeC {\.Z}" "Ż" :string)
;; letters not in Latin1, 2, 3 but available in TeX T1 font encoding
(merge-rule "\IeC {\~"Y}" "Ÿ" :string)
(merge-rule "\IeC {\NG }" "Ŋ" :string)
(merge-rule "\IeC {\ng }" "ŋ" :string)
(merge-rule "\IeC {\OE }" "Œ" :string)
(merge-rule "\IeC {\oe }" "œ" :string)
(merge-rule "\IeC {\IJ }" "IJ" :string)
(merge-rule "\IeC {\ij }" "ij" :string)
(merge-rule "\IeC {\j }" "ȷ" :string)
(merge-rule "\IeC {\SS }" "ẞ" :string)

View File

@ -0,0 +1,607 @@
;; style file for xindy
;; filename: LatinRules.xdy
;;
;; It is based upon xindy's files lang/general/utf8.xdy and
;; lang/general/utf8-lang.xdy which implement
;; "a general sorting order for Western European languages"
;;
;; The aim for Sphinx is to be able to index in a Cyrillic document
;; also terms using the Latin alphabets, inclusive of letters
;; with diacritics. To this effect the xindy rules from lang/general
;; got manually re-coded to avoid collisions with the encoding
;; done by xindy for sorting words in Cyrillic languages, which was
;; observed not to use bytes with octal encoding 0o266 or higher.
;;
;; So here we use only 0o266 or higher bytes.
;; (Ŋ, ŋ, IJ, and ij are absent from
;; lang/general/utf8.xdy and not included here)
;; Contributed by the Sphinx team, 2018.
(define-letter-group "A" :prefixes ("¶"))
(define-letter-group "B" :after "A" :prefixes ("·"))
(define-letter-group "C" :after "B" :prefixes ("¸"))
(define-letter-group "D" :after "C" :prefixes ("¹"))
(define-letter-group "E" :after "D" :prefixes ("º"))
(define-letter-group "F" :after "E" :prefixes ("»"))
(define-letter-group "G" :after "F" :prefixes ("¼"))
(define-letter-group "H" :after "G" :prefixes ("½"))
(define-letter-group "I" :after "H" :prefixes ("¾"))
(define-letter-group "J" :after "I" :prefixes ("¿"))
(define-letter-group "K" :after "J" :prefixes ("À"))
(define-letter-group "L" :after "K" :prefixes ("Á"))
(define-letter-group "M" :after "L" :prefixes ("Â"))
(define-letter-group "N" :after "M" :prefixes ("Ã"))
(define-letter-group "O" :after "N" :prefixes ("Ä"))
(define-letter-group "P" :after "O" :prefixes ("È"))
(define-letter-group "Q" :after "P" :prefixes ("Ê"))
(define-letter-group "R" :after "Q" :prefixes ("Ë"))
(define-letter-group "S" :after "R" :prefixes ("Ð"))
(define-letter-group "T" :after "S" :prefixes ("Ú"))
(define-letter-group "U" :after "T" :prefixes ("à"))
(define-letter-group "V" :after "U" :prefixes ("å"))
(define-letter-group "W" :after "V" :prefixes ("æ"))
(define-letter-group "X" :after "W" :prefixes ("ë"))
(define-letter-group "Y" :after "X" :prefixes ("í"))
(define-letter-group "Z" :after "Y" :prefixes ("ð"))
(define-rule-set "sphinx-xy-alphabetize"
:rules (("À" "¶" :string)
("Ä‚" "¶" :string)
("â" "¶" :string)
("Ä" "¶" :string)
("à" "¶" :string)
("Ã…" "¶" :string)
("Ã" "¶" :string)
("Ã<>" "¶" :string)
("á" "¶" :string)
("ã" "¶" :string)
("Â" "¶" :string)
("ă" "¶" :string)
("Ã¥" "¶" :string)
("Ä…" "¶" :string)
("ä" "¶" :string)
("Ä„" "¶" :string)
("æ" "¶º" :string)
("Æ" "¶º" :string)
("ć" "¸" :string)
("ĉ" "¸" :string)
("ç" "¸" :string)
("ÄŒ" "¸" :string)
("Ä<>" "¸" :string)
("Ĉ" "¸" :string)
("Ç" "¸" :string)
("Ć" "¸" :string)
("Ä<>" "¹" :string)
("Ä<>" "¹" :string)
("ÄŽ" "¹" :string)
("Ä‘" "¹" :string)
("ê" "º" :string)
("Ę" "º" :string)
("Äš" "º" :string)
("ë" "º" :string)
("Ä›" "º" :string)
("é" "º" :string)
("È" "º" :string)
("Ë" "º" :string)
("É" "º" :string)
("è" "º" :string)
("Ê" "º" :string)
("Ä™" "º" :string)
("Ä<>" "¼" :string)
("ÄŸ" "¼" :string)
("Äž" "¼" :string)
("Äœ" "¼" :string)
("Ä¥" "½" :string)
("Ĥ" "½" :string)
("Ã<>" "¾" :string)
("Ã<>" "¾" :string)
("ï" "¾" :string)
("ÃŽ" "¾" :string)
("î" "¾" :string)
("ı" "¾" :string)
("İ" "¾" :string)
("í" "¾" :string)
("ÃŒ" "¾" :string)
("ì" "¾" :string)
("Ä´" "¿" :string)
("ĵ" "¿" :string)
("Å‚" "Á" :string)
("Å<>" "Á" :string)
("ľ" "Á" :string)
("Ľ" "Á" :string)
("Å„" "Ã" :string)
("Ń" "Ã" :string)
("ñ" "Ã" :string)
("ň" "Ã" :string)
("Ñ" "Ã" :string)
("Ň" "Ã" :string)
("Õ" "Ä" :string)
("Å<>" "Ä" :string)
("ó" "Ä" :string)
("ö" "Ä" :string)
("ô" "Ä" :string)
("Å‘" "Ä" :string)
("Ø" "Ä" :string)
("Ö" "Ä" :string)
("õ" "Ä" :string)
("Ô" "Ä" :string)
("ø" "Ä" :string)
("Ó" "Ä" :string)
("Ã’" "Ä" :string)
("ò" "Ä" :string)
("œ" "ĺ" :string)
("Œ" "ĺ" :string)
("Ř" "Ë" :string)
("Å™" "Ë" :string)
("Å”" "Ë" :string)
("Å•" "Ë" :string)
("Å<>" "Ð" :string)
("Åš" "Ð" :string)
("È™" "Ð" :string)
("ÅŸ" "Ð" :string)
("Åœ" "Ð" :string)
("Å›" "Ð" :string)
("Ș" "Ð" :string)
("Å¡" "Ð" :string)
("Åž" "Ð" :string)
("Å " "Ð" :string)
("ß" "ÐÐ" :string)
("Èš" "Ú" :string)
("Ť" "Ú" :string)
("È›" "Ú" :string)
("Å¥" "Ú" :string)
("û" "à" :string)
("Å­" "à" :string)
("ů" "à" :string)
("ű" "à" :string)
("ù" "à" :string)
("Ŭ" "à" :string)
("Ù" "à" :string)
("Ű" "à" :string)
("Ü" "à" :string)
("Å®" "à" :string)
("ú" "à" :string)
("Ú" "à" :string)
("Û" "à" :string)
("ü" "à" :string)
("ÿ" "í" :string)
("Ã<>" "í" :string)
("Ÿ" "í" :string)
("ý" "í" :string)
("Å»" "ð" :string)
("Ž" "ð" :string)
("Ź" "ð" :string)
("ž" "ð" :string)
("ż" "ð" :string)
("ź" "ð" :string)
("a" "¶" :string)
("A" "¶" :string)
("b" "·" :string)
("B" "·" :string)
("c" "¸" :string)
("C" "¸" :string)
("d" "¹" :string)
("D" "¹" :string)
("e" "º" :string)
("E" "º" :string)
("F" "»" :string)
("f" "»" :string)
("G" "¼" :string)
("g" "¼" :string)
("H" "½" :string)
("h" "½" :string)
("i" "¾" :string)
("I" "¾" :string)
("J" "¿" :string)
("j" "¿" :string)
("K" "À" :string)
("k" "À" :string)
("L" "Á" :string)
("l" "Á" :string)
("M" "Â" :string)
("m" "Â" :string)
("n" "Ã" :string)
("N" "Ã" :string)
("O" "Ä" :string)
("o" "Ä" :string)
("p" "È" :string)
("P" "È" :string)
("Q" "Ê" :string)
("q" "Ê" :string)
("r" "Ë" :string)
("R" "Ë" :string)
("S" "Ð" :string)
("s" "Ð" :string)
("t" "Ú" :string)
("T" "Ú" :string)
("u" "à" :string)
("U" "à" :string)
("v" "å" :string)
("V" "å" :string)
("W" "æ" :string)
("w" "æ" :string)
("x" "ë" :string)
("X" "ë" :string)
("Y" "í" :string)
("y" "í" :string)
("z" "ð" :string)
("Z" "ð" :string)
))
(define-rule-set "sphinx-xy-resolve-diacritics"
:rules (("Ĥ" "£" :string)
("ó" "£" :string)
("ľ" "£" :string)
("Ř" "£" :string)
("Ä<>" "£" :string)
("Ä<>" "£" :string)
("Äš" "£" :string)
("Ä¥" "£" :string)
("ÄŒ" "£" :string)
("Ä´" "£" :string)
("Ä›" "£" :string)
("ž" "£" :string)
("ÄŽ" "£" :string)
("Å™" "£" :string)
("Ž" "£" :string)
("ı" "£" :string)
("Ť" "£" :string)
("á" "£" :string)
("Ä<>" "£" :string)
("Ã<>" "£" :string)
("ň" "£" :string)
("Å " "£" :string)
("Ň" "£" :string)
("ĵ" "£" :string)
("Å¥" "£" :string)
("Ó" "£" :string)
("ý" "£" :string)
("Äœ" "£" :string)
("Ú" "£" :string)
("Ľ" "£" :string)
("Å¡" "£" :string)
("Ã<>" "£" :string)
("ú" "£" :string)
("Åš" "¤" :string)
("ć" "¤" :string)
("Å<>" "¤" :string)
("Å‚" "¤" :string)
("Å„" "¤" :string)
("À" "¤" :string)
("Ź" "¤" :string)
("à" "¤" :string)
("Ń" "¤" :string)
("Ä<>" "¤" :string)
("ÿ" "¤" :string)
("Å›" "¤" :string)
("Äž" "¤" :string)
("ÄŸ" "¤" :string)
("Ù" "¤" :string)
("İ" "¤" :string)
("Ä‘" "¤" :string)
("ù" "¤" :string)
("Èš" "¤" :string)
("é" "¤" :string)
("Å•" "¤" :string)
("Ć" "¤" :string)
("È›" "¤" :string)
("ò" "¤" :string)
("ź" "¤" :string)
("Ã’" "¤" :string)
("Ÿ" "¤" :string)
("Å”" "¤" :string)
("É" "¤" :string)
("ĉ" "¥" :string)
("ô" "¥" :string)
("Ã<>" "¥" :string)
("Å<>" "¥" :string)
("Å»" "¥" :string)
("Ä‚" "¥" :string)
("Åœ" "¥" :string)
("ñ" "¥" :string)
("Å­" "¥" :string)
("í" "¥" :string)
("È" "¥" :string)
("Ô" "¥" :string)
("Ŭ" "¥" :string)
("ż" "¥" :string)
("Ñ" "¥" :string)
("è" "¥" :string)
("Ĉ" "¥" :string)
("ă" "¥" :string)
("â" "¦" :string)
("û" "¦" :string)
("ê" "¦" :string)
("Õ" "¦" :string)
("õ" "¦" :string)
("È™" "¦" :string)
("ç" "¦" :string)
("Â" "¦" :string)
("Ê" "¦" :string)
("Û" "¦" :string)
("Ç" "¦" :string)
("ì" "¦" :string)
("ÃŒ" "¦" :string)
("Ș" "¦" :string)
("ö" "§" :string)
("Ö" "§" :string)
("ÅŸ" "§" :string)
("ů" "§" :string)
("ë" "§" :string)
("ã" "§" :string)
("î" "§" :string)
("ÃŽ" "§" :string)
("Ã" "§" :string)
("Åž" "§" :string)
("Å®" "§" :string)
("Ë" "§" :string)
("ï" "¨" :string)
("Å<>" "¨" :string)
("Ã<>" "¨" :string)
("Ę" "¨" :string)
("Å‘" "¨" :string)
("Ü" "¨" :string)
("Ã…" "¨" :string)
("ü" "¨" :string)
("Ä™" "¨" :string)
("Ã¥" "¨" :string)
("Ä" "©" :string)
("ű" "©" :string)
("Ø" "©" :string)
("ø" "©" :string)
("Ű" "©" :string)
("ä" "©" :string)
("Ä„" "ª" :string)
("Ä…" "ª" :string)
("Å“" "ÿ" :string)
("ß" "ÿ" :string)
("Æ" "ÿ" :string)
("Å’" "ÿ" :string)
("æ" "ÿ" :string)
("e" "¢" :string)
("t" "¢" :string)
("L" "¢" :string)
("Y" "¢" :string)
("J" "¢" :string)
("a" "¢" :string)
("p" "¢" :string)
("u" "¢" :string)
("j" "¢" :string)
("b" "¢" :string)
("G" "¢" :string)
("U" "¢" :string)
("F" "¢" :string)
("H" "¢" :string)
("i" "¢" :string)
("z" "¢" :string)
("c" "¢" :string)
("l" "¢" :string)
("A" "¢" :string)
("Q" "¢" :string)
("w" "¢" :string)
("D" "¢" :string)
("R" "¢" :string)
("d" "¢" :string)
("s" "¢" :string)
("r" "¢" :string)
("k" "¢" :string)
("v" "¢" :string)
("m" "¢" :string)
("P" "¢" :string)
("y" "¢" :string)
("K" "¢" :string)
("q" "¢" :string)
("S" "¢" :string)
("I" "¢" :string)
("C" "¢" :string)
("M" "¢" :string)
("Z" "¢" :string)
("T" "¢" :string)
("W" "¢" :string)
("B" "¢" :string)
("h" "¢" :string)
("x" "¢" :string)
("X" "¢" :string)
("f" "¢" :string)
("E" "¢" :string)
("V" "¢" :string)
("N" "¢" :string)
("O" "¢" :string)
("o" "¢" :string)
("g" "¢" :string)
("n" "¢" :string)
))
(define-rule-set "sphinx-xy-resolve-case"
:rules (("Ú" "8" :string)
("Ÿ" "8" :string)
("Ç" "8" :string)
("Ĉ" "8" :string)
("Å”" "8" :string)
("Ľ" "8" :string)
("Å®" "8" :string)
("Ã<>" "8" :string)
("É" "8" :string)
("Ë" "8" :string)
("Ș" "8" :string)
("Ì" "8" :string)
("Ê" "8" :string)
("Ň" "8" :string)
("Ä„" "8" :string)
("Å " "8" :string)
("Û" "8" :string)
("Åž" "8" :string)
("Ć" "8" :string)
("Ã’" "8" :string)
("Ĝ" "8" :string)
("Ñ" "8" :string)
("Ó" "8" :string)
("ÃŽ" "8" :string)
("Ã<>" "8" :string)
("Ã" "8" :string)
("Èš" "8" :string)
("Ã…" "8" :string)
("Äž" "8" :string)
("Ü" "8" :string)
("È" "8" :string)
("Ô" "8" :string)
("İ" "8" :string)
("Ű" "8" :string)
("Ù" "8" :string)
("Ŭ" "8" :string)
("Â" "8" :string)
("Ť" "8" :string)
("Ń" "8" :string)
("ÄŽ" "8" :string)
("Ź" "8" :string)
("Ž" "8" :string)
("Ä<>" "8" :string)
("Ŝ" "8" :string)
("Č" "8" :string)
("Ä´" "8" :string)
("Ö" "8" :string)
("Ø" "8" :string)
("Å»" "8" :string)
("Å<>" "8" :string)
("Ä‚" "8" :string)
("Äš" "8" :string)
("Å<>" "8" :string)
("Õ" "8" :string)
("Ę" "8" :string)
("Ã<>" "8" :string)
("À" "8" :string)
("Ĥ" "8" :string)
("Ä" "8" :string)
("Åš" "8" :string)
("Ř" "8" :string)
("Ã<>" "8" :string)
("Å’" "89" :string)
("Æ" "89" :string)
("ì" "9" :string)
("è" "9" :string)
("Ä…" "9" :string)
("Å¡" "9" :string)
("ú" "9" :string)
("Ã¥" "9" :string)
("ă" "9" :string)
("Ä™" "9" :string)
("ü" "9" :string)
("ź" "9" :string)
("ò" "9" :string)
("Å¥" "9" :string)
("È›" "9" :string)
("ĵ" "9" :string)
("Å•" "9" :string)
("ż" "9" :string)
("ä" "9" :string)
("ý" "9" :string)
("ù" "9" :string)
("á" "9" :string)
("é" "9" :string)
("Ä<>" "9" :string)
("ň" "9" :string)
("Å›" "9" :string)
("ø" "9" :string)
("í" "9" :string)
("Ä‘" "9" :string)
("ı" "9" :string)
("ÄŸ" "9" :string)
("î" "9" :string)
("ã" "9" :string)
("à" "9" :string)
("Å™" "9" :string)
("Å‘" "9" :string)
("ů" "9" :string)
("È™" "9" :string)
("ÿ" "9" :string)
("ë" "9" :string)
("Å­" "9" :string)
("ç" "9" :string)
("ű" "9" :string)
("ñ" "9" :string)
("õ" "9" :string)
("Ä›" "9" :string)
("ÅŸ" "9" :string)
("ž" "9" :string)
("Ä<>" "9" :string)
("Å<>" "9" :string)
("Å„" "9" :string)
("û" "9" :string)
("Å‚" "9" :string)
("Ä<>" "9" :string)
("Ä¥" "9" :string)
("ê" "9" :string)
("ô" "9" :string)
("ĉ" "9" :string)
("â" "9" :string)
("ć" "9" :string)
("ï" "9" :string)
("ö" "9" :string)
("ľ" "9" :string)
("ó" "9" :string)
("æ" "99" :string)
("ß" "99" :string)
("Å“" "99" :string)
("N" "8" :string)
("V" "8" :string)
("O" "8" :string)
("X" "8" :string)
("E" "8" :string)
("P" "8" :string)
("K" "8" :string)
("T" "8" :string)
("Z" "8" :string)
("M" "8" :string)
("C" "8" :string)
("I" "8" :string)
("S" "8" :string)
("B" "8" :string)
("W" "8" :string)
("D" "8" :string)
("R" "8" :string)
("H" "8" :string)
("F" "8" :string)
("Q" "8" :string)
("A" "8" :string)
("G" "8" :string)
("U" "8" :string)
("J" "8" :string)
("Y" "8" :string)
("L" "8" :string)
("o" "9" :string)
("n" "9" :string)
("g" "9" :string)
("x" "9" :string)
("f" "9" :string)
("y" "9" :string)
("q" "9" :string)
("h" "9" :string)
("w" "9" :string)
("s" "9" :string)
("d" "9" :string)
("v" "9" :string)
("k" "9" :string)
("r" "9" :string)
("m" "9" :string)
("z" "9" :string)
("c" "9" :string)
("i" "9" :string)
("l" "9" :string)
("b" "9" :string)
("j" "9" :string)
("a" "9" :string)
("p" "9" :string)
("u" "9" :string)
("t" "9" :string)
("e" "9" :string)
))
(use-rule-set :run 0
:rule-set ("sphinx-xy-alphabetize"))
(use-rule-set :run 1
:rule-set ("sphinx-xy-resolve-diacritics"))
(use-rule-set :run 2
:rule-set ("sphinx-xy-resolve-case"))

View File

@ -24,13 +24,18 @@ export LATEXOPTS =
LATEXMKOPTS =
{% if xindy_use -%}
export XINDYOPTS = {{ xindy_lang_option }} -M sphinx.xdy
{% if latex_engine == 'pdflatex' and xindy_cyrillic -%}
XINDYOPTS += -M cyrLICRutf8.xdy
{% if latex_engine == 'pdflatex' -%}
XINDYOPTS += -M LICRlatin2utf8.xdy
{% if xindy_cyrillic -%}
XINDYOPTS += -M LICRcyr2utf8.xdy
{% endif -%}
{% if latex_engine == 'xelatex' or latex_engine == 'lualatex' -%}
{% endif -%}
{% if xindy_cyrillic -%}
XINDYOPTS += -M LatinRules.xdy
{% endif -%}
# also with pdflatex as LICRlatin2utf8.xdy replaces xindy's /tex/inputenc/utf8.xdy
XINDYOPTS += -I xelatex
{% endif -%}
{% endif -%}
# format: pdf or dvi (used only by archive targets)
FMT = pdf

View File

@ -26,7 +26,7 @@
;; man page says to use rather xelatex or lualatex in case of Cyrillic
;; scripts.
;; Sphinx contributes cyrLICRutf8.xdy to provide support for Cyrillic
;; Sphinx contributes LICRcyr2utf8.xdy to provide support for Cyrillic
;; scripts for the pdflatex engine.
;; Another issue caused by xindy ignoring all TeX macros except those
@ -42,6 +42,14 @@
;; Rather it incorporates some suitable extracts from latex.xdy and
;; tex.xdy with additional Sphinx contributed rules.
;; But, this means for pdflatex and Latin scripts that the xindy file
;; tex/inputenc/uf8.xdy is not usable because it refers to the macro
;; \IeC only sporadically, and as tex.xdy is not loaded, a rule such as
;; (merge-rule "\'e" "é" :string)
;; does not work, it must be
;; (merge-rule "\IeC {\'e}" "é" :string)
;; So Sphinx contributes LICRlatin2utf8.xdy to mitigate that problem.
;;;;;;;; extracts from tex.xdy (discarding most original comments):
;;;
@ -84,12 +92,10 @@
;;;;;;;; end of extracts from latex.xdy
;; Sphinx additions, cf sphinx.util.texescape for rationale
;;
;; The LaTeX \index command turns \ into normal character so the TeX macros
;; written to .idx files are not followed by a blank. This is different
;; from non-ascii letters which end up (with pdflatex) as \IeC macros in .idx
;; file, with a blank.
;; file, with a blank space after \IeC
;; Details of the syntax are explained at
;; http://xindy.sourceforge.net/doc/manual-3.html
@ -98,6 +104,8 @@
;; guess, for example "\\_" is not detected as RE but "\\P\{\}" is, so for
;; being sure we apply the :string switch everywhere and do not use \\ etc...
;; Go back from sphinx.util.texescape TeX macros to UTF-8
(merge-rule "\sphinxleftcurlybrace{}" "{" :string)
(merge-rule "\sphinxrightcurlybrace{}" "}" :string)
(merge-rule "\_" "_" :string)
@ -118,12 +126,66 @@
(merge-rule "\(\checkmark\)" "✓" :string)
(merge-rule "\textendash{}" "" :string)
(merge-rule "\textbar{}" "|" :string)
(merge-rule "\(\sp{\text{0}}\)" "⁰" :string)
(merge-rule "\(\sp{\text{1}}\)" "¹" :string)
(merge-rule "\(\sp{\text{2}}\)" "²" :string)
(merge-rule "\(\sp{\text{3}}\)" "³" :string)
(merge-rule "\(\sp{\text{4}}\)" "⁴" :string)
(merge-rule "\(\sp{\text{5}}\)" "⁵" :string)
(merge-rule "\(\sp{\text{6}}\)" "⁶" :string)
(merge-rule "\(\sp{\text{7}}\)" "⁷" :string)
(merge-rule "\(\sp{\text{8}}\)" "⁸" :string)
(merge-rule "\(\sp{\text{9}}\)" "⁹" :string)
(merge-rule "\(\sb{\text{0}}\)" "₀" :string)
(merge-rule "\(\sb{\text{1}}\)" "₁" :string)
(merge-rule "\(\sb{\text{2}}\)" "₂" :string)
(merge-rule "\(\sb{\text{3}}\)" "₃" :string)
(merge-rule "\(\sb{\text{4}}\)" "₄" :string)
(merge-rule "\(\sb{\text{5}}\)" "₅" :string)
(merge-rule "\(\sb{\text{6}}\)" "₆" :string)
(merge-rule "\(\sb{\text{7}}\)" "₇" :string)
(merge-rule "\(\sb{\text{8}}\)" "₈" :string)
(merge-rule "\(\sb{\text{9}}\)" "₉" :string)
(merge-rule "\(\alpha\)" "α" :string)
(merge-rule "\(\beta\)" "β" :string)
(merge-rule "\(\gamma\)" "γ" :string)
(merge-rule "\(\delta\)" "δ" :string)
(merge-rule "\(\epsilon\)" "ε" :string)
(merge-rule "\(\zeta\)" "ζ" :string)
(merge-rule "\(\eta\)" "η" :string)
(merge-rule "\(\theta\)" "θ" :string)
(merge-rule "\(\iota\)" "ι" :string)
(merge-rule "\(\kappa\)" "κ" :string)
(merge-rule "\(\lambda\)" "λ" :string)
(merge-rule "\(\mu\)" "μ" :string)
(merge-rule "\(\nu\)" "ν" :string)
(merge-rule "\(\xi\)" "ξ" :string)
(merge-rule "\(\pi\)" "π" :string)
(merge-rule "\(\rho\)" "ρ" :string)
(merge-rule "\(\sigma\)" "σ" :string)
(merge-rule "\(\tau\)" "τ" :string)
(merge-rule "\(\upsilon\)" "υ" :string)
(merge-rule "\(\phi\)" "φ" :string)
(merge-rule "\(\chi\)" "χ" :string)
(merge-rule "\(\psi\)" "ψ" :string)
(merge-rule "\(\omega\)" "ω" :string)
(merge-rule "\(\Gamma\)" "Γ" :string)
(merge-rule "\(\Delta\)" "Δ" :string)
(merge-rule "\(\Theta\)" "Θ" :string)
(merge-rule "\(\Lambda\)" "Λ" :string)
(merge-rule "\(\Xi\)" "Ξ" :string)
(merge-rule "\(\Pi\)" "Π" :string)
(merge-rule "\(\Sigma\)" "Σ" :string)
(merge-rule "\(\Upsilon\)" "Υ" :string)
(merge-rule "\(\Phi\)" "Φ" :string)
(merge-rule "\(\Psi\)" "Ψ" :string)
(merge-rule "\(\Omega\)" "Ω" :string)
;; This xindy module provides some basic support for "see"
(require "makeindex.xdy")
;; This creates one-letter headings and works fine with utf-8 letters.
;; For Cyrillic and pdflatex necessitates cyrLICRutf8.xdy to be loaded too.
;; For Cyrillic with pdflatex works thanks to LICRcyr2utf8.xdy
(require "latin-lettergroups.xdy")
;; currently we don't (know how to easily) separate "Numbers" from

View File

@ -150,9 +150,9 @@ var Documentation = {
this.fixFirefoxAnchorBug();
this.highlightSearchWords();
this.initIndexTable();
{% if theme_navigation_with_keys|tobool %}
this.initOnKeyListeners();
{% endif %}
if (DOCUMENTATION_OPTIONS.NAVIGATION_WITH_KEYS) {
this.initOnKeyListeners();
}
},
/**

View File

@ -5,5 +5,20 @@ var DOCUMENTATION_OPTIONS = {
COLLAPSE_INDEX: false,
FILE_SUFFIX: '{{ '' if no_search_suffix else file_suffix }}',
HAS_SOURCE: {{ has_source|lower }},
SOURCELINK_SUFFIX: '{{ sourcelink_suffix }}'
SOURCELINK_SUFFIX: '{{ sourcelink_suffix }}',
NAVIGATION_WITH_KEYS: {{ 'true' if theme_navigation_with_keys|tobool else 'false'}},
SEARCH_LANGUAGE_STOP_WORDS: {{ search_language_stop_words }}
};
{% if search_language_stemming_code %}
/* Non-minified version JS is _stemmer.js if file is provided */ {% endif -%}
{{ search_language_stemming_code|safe }}
{% if search_scorer_tool %}
{{ search_scorer_tool|safe }}
{% endif -%}
{% if search_word_splitter_code %}
{{ search_word_splitter_code }}
{% endif -%}

View File

@ -1,5 +1,5 @@
/*
* searchtools.js_t
* searchtools.js
* ~~~~~~~~~~~~~~~~
*
* Sphinx JavaScript utilities for the full-text search.
@ -9,51 +9,43 @@
*
*/
{% if search_language_stemming_code %}
/* Non-minified version JS is _stemmer.js if file is provided */ {% endif -%}
{{ search_language_stemming_code|safe }}
if (!Scorer) {
/**
* Simple result scoring code.
*/
var Scorer = {
// Implement the following function to further tweak the score for each result
// The function takes a result array [filename, title, anchor, descr, score]
// and returns the new score.
/*
score: function(result) {
return result[4];
},
*/
{% if search_scorer_tool %}
{{ search_scorer_tool|safe }}
{% else %}
/**
* Simple result scoring code.
*/
var Scorer = {
// Implement the following function to further tweak the score for each result
// The function takes a result array [filename, title, anchor, descr, score]
// and returns the new score.
/*
score: function(result) {
return result[4];
},
*/
// query matches the full name of an object
objNameMatch: 11,
// or matches in the last dotted part of the object name
objPartialMatch: 6,
// Additive scores depending on the priority of the object
objPrio: {0: 15, // used to be importantResults
1: 5, // used to be objectResults
2: -5}, // used to be unimportantResults
// Used when the priority is not in the mapping.
objPrioDefault: 0,
// query matches the full name of an object
objNameMatch: 11,
// or matches in the last dotted part of the object name
objPartialMatch: 6,
// Additive scores depending on the priority of the object
objPrio: {0: 15, // used to be importantResults
1: 5, // used to be objectResults
2: -5}, // used to be unimportantResults
// Used when the priority is not in the mapping.
objPrioDefault: 0,
// query found in title
title: 15,
// query found in terms
term: 5
};
{% endif %}
{% if search_word_splitter_code %}
{{ search_word_splitter_code }}
{% else %}
function splitQuery(query) {
return query.split(/\s+/);
// query found in title
title: 15,
// query found in terms
term: 5
};
}
if (!splitQuery) {
function splitQuery(query) {
return query.split(/\s+/);
}
}
{% endif %}
/**
* Search Module
@ -146,7 +138,7 @@ var Search = {
*/
query : function(query) {
var i;
var stopwords = {{ search_language_stop_words }};
var stopwords = DOCUMENTATION_OPTIONS.SEARCH_LANGUAGE_STOP_WORDS;
// stem the searchterms and add them to the correct list
var stemmer = new Stemmer();

View File

@ -9,9 +9,9 @@
#}
{%- extends "basic/layout.html" %}
{% if theme_collapsiblesidebar|tobool %}
{%- block scripts %}
{{ super() }}
{% if theme_collapsiblesidebar|tobool %}
<script type="text/javascript" src="{{ pathto('_static/sidebar.js', 1) }}"></script>
{% endif %}
{%- endblock %}
{% endif %}

View File

@ -0,0 +1,150 @@
# -*- coding: utf-8 -*-
"""
sphinx.transforms.post_transforms.code
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
transforms for code-blocks.
:copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS.
:license: BSD, see LICENSE for details.
"""
import sys
from typing import NamedTuple
from docutils import nodes
from pygments.lexers import PythonConsoleLexer, guess_lexer
from six import text_type
from sphinx import addnodes
from sphinx.ext import doctest
from sphinx.transforms import SphinxTransform
if False:
# For type annotation
from typing import Any, Dict, List # NOQA
from sphinx.application import Sphinx # NOQA
HighlightSetting = NamedTuple('HighlightSetting', [('language', text_type),
('lineno_threshold', int)])
class HighlightLanguageTransform(SphinxTransform):
"""
Apply highlight_language to all literal_block nodes.
This refers both :confval:`highlight_language` setting and
:rst:dir:`highlightlang` directive. After processing, this transform
removes ``highlightlang`` node from doctree.
"""
default_priority = 400
def apply(self):
visitor = HighlightLanguageVisitor(self.document,
self.config.highlight_language)
self.document.walkabout(visitor)
for node in self.document.traverse(addnodes.highlightlang):
node.parent.remove(node)
class HighlightLanguageVisitor(nodes.NodeVisitor):
def __init__(self, document, default_language):
# type: (nodes.document, unicode) -> None
self.default_setting = HighlightSetting(default_language, sys.maxsize)
self.settings = [] # type: List[HighlightSetting]
nodes.NodeVisitor.__init__(self, document)
def unknown_visit(self, node):
# type: (nodes.Node) -> None
pass
def unknown_departure(self, node):
# type: (nodes.Node) -> None
pass
def visit_document(self, node):
# type: (nodes.Node) -> None
self.settings.append(self.default_setting)
def depart_document(self, node):
# type: (nodes.Node) -> None
self.settings.pop()
def visit_start_of_file(self, node):
# type: (nodes.Node) -> None
self.settings.append(self.default_setting)
def depart_start_of_file(self, node):
# type: (nodes.Node) -> None
self.settings.pop()
def visit_highlightlang(self, node):
# type: (addnodes.highlightlang) -> None
self.settings[-1] = HighlightSetting(node['lang'], node['linenothreshold'])
def visit_literal_block(self, node):
# type: (nodes.literal_block) -> None
setting = self.settings[-1]
if 'language' not in node:
node['language'] = setting.language
node['force_highlighting'] = False
else:
node['force_highlighting'] = True
if 'linenos' not in node:
lines = node.astext().count('\n')
node['linenos'] = (lines >= setting.lineno_threshold - 1)
class TrimDoctestFlagsTransform(SphinxTransform):
"""
Trim doctest flags like ``# doctest: +FLAG`` from python code-blocks.
see :confval:`trim_doctest_flags` for more information.
"""
default_priority = HighlightLanguageTransform.default_priority + 1
def apply(self):
if not self.config.trim_doctest_flags:
return
for node in self.document.traverse(nodes.literal_block):
if self.is_pyconsole(node):
source = node.rawsource
source = doctest.blankline_re.sub('', source)
source = doctest.doctestopt_re.sub('', source)
node.rawsource = source
node[:] = [nodes.Text(source)]
@staticmethod
def is_pyconsole(node):
# type: (nodes.literal_block) -> bool
if node.rawsource != node.astext():
return False # skip parsed-literal node
language = node.get('language')
if language in ('pycon', 'pycon3'):
return True
elif language in ('py', 'py3', 'python', 'python3', 'default'):
return node.rawsource.startswith('>>>')
elif language == 'guess':
try:
lexer = guess_lexer(node.rawsource)
return isinstance(lexer, PythonConsoleLexer)
except Exception:
pass
return False
def setup(app):
# type: (Sphinx) -> Dict[unicode, Any]
app.add_post_transform(HighlightLanguageTransform)
app.add_post_transform(TrimDoctestFlagsTransform)
return {
'version': 'builtin',
'parallel_read_safe': True,
'parallel_write_safe': True,
}

71
sphinx/util/math.py Normal file
View File

@ -0,0 +1,71 @@
# -*- coding: utf-8 -*-
"""
sphinx.util.math
~~~~~~~~~~~~~~~~
Utility functions for math.
:copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS.
:license: BSD, see LICENSE for details.
"""
if False:
# For type annotation
from docutils import nodes # NOQA
from docutils.writers.html4css1 import Writer # NOQA
def get_node_equation_number(writer, node):
# type: (Writer, nodes.Node) -> unicode
if writer.builder.config.math_numfig and writer.builder.config.numfig:
figtype = 'displaymath'
if writer.builder.name == 'singlehtml':
key = u"%s/%s" % (writer.docnames[-1], figtype)
else:
key = figtype
id = node['ids'][0]
number = writer.builder.fignumbers.get(key, {}).get(id, ())
number = '.'.join(map(str, number))
else:
number = node['number']
return number
def wrap_displaymath(text, label, numbering):
# type: (unicode, unicode, bool) -> unicode
def is_equation(part):
# type: (unicode) -> unicode
return part.strip()
if label is None:
labeldef = ''
else:
labeldef = r'\label{%s}' % label
numbering = True
parts = list(filter(is_equation, text.split('\n\n')))
equations = []
if len(parts) == 0:
return ''
elif len(parts) == 1:
if numbering:
begin = r'\begin{equation}' + labeldef
end = r'\end{equation}'
else:
begin = r'\begin{equation*}' + labeldef
end = r'\end{equation*}'
equations.append('\\begin{split}%s\\end{split}\n' % parts[0])
else:
if numbering:
begin = r'\begin{align}%s\!\begin{aligned}' % labeldef
end = r'\end{aligned}\end{align}'
else:
begin = r'\begin{align*}%s\!\begin{aligned}' % labeldef
end = r'\end{aligned}\end{align*}'
for part in parts:
equations.append('%s\\\\\n' % part.strip())
return '%s\n%s%s' % (begin, ''.join(equations), end)

View File

@ -56,7 +56,10 @@ def repr_domxml(node, length=80):
returns full of DOM XML representation.
:return: DOM XML representation
"""
text = node.asdom().toxml()
try:
text = node.asdom().toxml()
except Exception:
text = text_type(node)
if length and len(text) > length:
text = text[:length] + '...'
return text

View File

@ -8,6 +8,7 @@
:copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS.
:license: BSD, see LICENSE for details.
"""
from __future__ import absolute_import
import os
import time

View File

@ -13,12 +13,14 @@ import copy
import os
import posixpath
import sys
import warnings
from docutils import nodes
from docutils.writers.html4css1 import Writer, HTMLTranslator as BaseTranslator
from six import string_types
from sphinx import addnodes
from sphinx.deprecation import RemovedInSphinx30Warning
from sphinx.locale import admonitionlabels, _, __
from sphinx.util import logging
from sphinx.util.images import get_image_size
@ -74,10 +76,6 @@ class HTMLTranslator(BaseTranslator):
BaseTranslator.__init__(self, *args, **kwds)
self.highlighter = builder.highlighter
self.builder = builder
self.highlightlang = self.highlightlang_base = \
builder.config.highlight_language
self.highlightopts = builder.config.highlight_options
self.highlightlinenothreshold = sys.maxsize
self.docnames = [builder.current_docname] # for singlehtml builder
self.manpages_url = builder.config.manpages_url
self.protect_literal_text = 0
@ -423,19 +421,14 @@ class HTMLTranslator(BaseTranslator):
if node.rawsource != node.astext():
# most probably a parsed-literal block -- don't highlight
return BaseTranslator.visit_literal_block(self, node)
lang = self.highlightlang
linenos = node.rawsource.count('\n') >= \
self.highlightlinenothreshold - 1
lang = node.get('language', 'default')
linenos = node.get('linenos', False)
highlight_args = node.get('highlight_args', {})
if 'language' in node:
# code-block directives
lang = node['language']
highlight_args['force'] = True
if 'linenos' in node:
linenos = node['linenos']
if lang is self.highlightlang_base:
highlight_args['force'] = node.get('force_highlighting', False)
if lang is self.builder.config.highlight_language:
# only pass highlighter options for original language
opts = self.highlightopts
opts = self.builder.config.highlight_options
else:
opts = {}
@ -569,15 +562,6 @@ class HTMLTranslator(BaseTranslator):
# type: (nodes.Node) -> None
pass
def visit_highlightlang(self, node):
# type: (nodes.Node) -> None
self.highlightlang = node['lang']
self.highlightlinenothreshold = node['linenothreshold']
def depart_highlightlang(self, node):
# type: (nodes.Node) -> None
pass
def visit_download_reference(self, node):
# type: (nodes.Node) -> None
if self.builder.download_support and node.hasattr('filename'):
@ -874,12 +858,60 @@ class HTMLTranslator(BaseTranslator):
def visit_math(self, node, math_env=''):
# type: (nodes.Node, unicode) -> None
logger.warning(__('using "math" markup without a Sphinx math extension '
'active, please use one of the math extensions '
'described at http://sphinx-doc.org/en/master/ext/math.html'),
location=(self.builder.current_docname, node.line))
raise nodes.SkipNode
name = self.builder.math_renderer_name
visit, _ = self.builder.app.registry.html_inline_math_renderers[name]
visit(self, node)
def depart_math(self, node, math_env=''):
# type: (nodes.Node, unicode) -> None
name = self.builder.math_renderer_name
_, depart = self.builder.app.registry.html_inline_math_renderers[name]
if depart:
depart(self, node)
def visit_math_block(self, node, math_env=''):
# type: (nodes.Node, unicode) -> None
name = self.builder.math_renderer_name
visit, _ = self.builder.app.registry.html_block_math_renderers[name]
visit(self, node)
def depart_math_block(self, node, math_env=''):
# type: (nodes.Node, unicode) -> None
name = self.builder.math_renderer_name
_, depart = self.builder.app.registry.html_block_math_renderers[name]
if depart:
depart(self, node)
def unknown_visit(self, node):
# type: (nodes.Node) -> None
raise NotImplementedError('Unknown node: ' + node.__class__.__name__)
# --------- METHODS FOR COMPATIBILITY --------------------------------------
@property
def highlightlang(self):
# type: () -> unicode
warnings.warn('HTMLTranslator.highlightlang is deprecated.',
RemovedInSphinx30Warning)
return self.builder.config.highlight_language
@property
def highlightlang_base(self):
# type: () -> unicode
warnings.warn('HTMLTranslator.highlightlang_base is deprecated.',
RemovedInSphinx30Warning)
return self.builder.config.highlight_language
@property
def highlightopts(self):
# type: () -> unicode
warnings.warn('HTMLTranslator.highlightopts is deprecated.',
RemovedInSphinx30Warning)
return self.builder.config.highlight_options
@property
def highlightlinenothreshold(self):
# type: () -> int
warnings.warn('HTMLTranslator.highlightlinenothreshold is deprecated.',
RemovedInSphinx30Warning)
return sys.maxsize

View File

@ -12,12 +12,14 @@
import os
import posixpath
import sys
import warnings
from docutils import nodes
from docutils.writers.html5_polyglot import HTMLTranslator as BaseTranslator
from six import string_types
from sphinx import addnodes
from sphinx.deprecation import RemovedInSphinx30Warning
from sphinx.locale import admonitionlabels, _, __
from sphinx.util import logging
from sphinx.util.images import get_image_size
@ -44,10 +46,6 @@ class HTML5Translator(BaseTranslator):
BaseTranslator.__init__(self, *args, **kwds)
self.highlighter = builder.highlighter
self.builder = builder
self.highlightlang = self.highlightlang_base = \
builder.config.highlight_language
self.highlightopts = builder.config.highlight_options
self.highlightlinenothreshold = sys.maxsize
self.docnames = [builder.current_docname] # for singlehtml builder
self.manpages_url = builder.config.manpages_url
self.protect_literal_text = 0
@ -369,19 +367,14 @@ class HTML5Translator(BaseTranslator):
if node.rawsource != node.astext():
# most probably a parsed-literal block -- don't highlight
return BaseTranslator.visit_literal_block(self, node)
lang = self.highlightlang
linenos = node.rawsource.count('\n') >= \
self.highlightlinenothreshold - 1
lang = node.get('language', 'default')
linenos = node.get('linenos', False)
highlight_args = node.get('highlight_args', {})
if 'language' in node:
# code-block directives
lang = node['language']
highlight_args['force'] = True
if 'linenos' in node:
linenos = node['linenos']
if lang is self.highlightlang_base:
highlight_args['force'] = node.get('force_highlighting', False)
if lang is self.builder.config.highlight_language:
# only pass highlighter options for original language
opts = self.highlightopts
opts = self.builder.config.highlight_options
else:
opts = {}
@ -515,15 +508,6 @@ class HTML5Translator(BaseTranslator):
# type: (nodes.Node) -> None
pass
def visit_highlightlang(self, node):
# type: (nodes.Node) -> None
self.highlightlang = node['lang']
self.highlightlinenothreshold = node['linenothreshold']
def depart_highlightlang(self, node):
# type: (nodes.Node) -> None
pass
def visit_download_reference(self, node):
# type: (nodes.Node) -> None
if self.builder.download_support and node.hasattr('filename'):
@ -825,12 +809,60 @@ class HTML5Translator(BaseTranslator):
def visit_math(self, node, math_env=''):
# type: (nodes.Node, unicode) -> None
logger.warning(__('using "math" markup without a Sphinx math extension '
'active, please use one of the math extensions '
'described at http://sphinx-doc.org/en/master/ext/math.html'),
location=(self.builder.current_docname, node.line))
raise nodes.SkipNode
name = self.builder.math_renderer_name
visit, _ = self.builder.app.registry.html_inline_math_renderers[name]
visit(self, node)
def depart_math(self, node, math_env=''):
# type: (nodes.Node, unicode) -> None
name = self.builder.math_renderer_name
_, depart = self.builder.app.registry.html_inline_math_renderers[name]
if depart:
depart(self, node)
def visit_math_block(self, node, math_env=''):
# type: (nodes.Node, unicode) -> None
name = self.builder.math_renderer_name
visit, _ = self.builder.app.registry.html_block_math_renderers[name]
visit(self, node)
def depart_math_block(self, node, math_env=''):
# type: (nodes.Node, unicode) -> None
name = self.builder.math_renderer_name
_, depart = self.builder.app.registry.html_block_math_renderers[name]
if depart:
depart(self, node)
def unknown_visit(self, node):
# type: (nodes.Node) -> None
raise NotImplementedError('Unknown node: ' + node.__class__.__name__)
# --------- METHODS FOR COMPATIBILITY --------------------------------------
@property
def highlightlang(self):
# type: () -> unicode
warnings.warn('HTMLTranslator.highlightlang is deprecated.',
RemovedInSphinx30Warning)
return self.builder.config.highlight_language
@property
def highlightlang_base(self):
# type: () -> unicode
warnings.warn('HTMLTranslator.highlightlang_base is deprecated.',
RemovedInSphinx30Warning)
return self.builder.config.highlight_language
@property
def highlightopts(self):
# type: () -> unicode
warnings.warn('HTMLTranslator.highlightopts is deprecated.',
RemovedInSphinx30Warning)
return self.builder.config.highlight_options
@property
def highlightlinenothreshold(self):
# type: () -> int
warnings.warn('HTMLTranslator.highlightlinenothreshold is deprecated.',
RemovedInSphinx30Warning)
return sys.maxsize

View File

@ -494,7 +494,6 @@ class LaTeXTranslator(nodes.NodeVisitor):
'babel': '\\usepackage{babel}',
})
# allow the user to override them all
self.check_latex_elements()
self.elements.update(builder.config.latex_elements)
# but some have other interface in config file
@ -697,19 +696,11 @@ class LaTeXTranslator(nodes.NodeVisitor):
self.babel_defmacro('\\pageautorefname', self.encode(_('page')))
self.elements['numfig_format'] = self.generate_numfig_format(builder)
self.highlighter = highlighting.PygmentsBridge(
'latex',
builder.config.pygments_style, builder.config.trim_doctest_flags)
self.highlighter = highlighting.PygmentsBridge('latex', builder.config.pygments_style)
self.context = [] # type: List[Any]
self.descstack = [] # type: List[unicode]
self.table = None # type: Table
self.next_table_colspec = None # type: unicode
# stack of [language, linenothreshold] settings per file
# the first item here is the default and must not be changed
# the second item is the default for the master file and can be changed
# by .. highlight:: directive in the master file
self.hlsettingstack = 2 * [[builder.config.highlight_language,
sys.maxsize]]
self.bodystack = [] # type: List[List[unicode]]
self.footnote_restricted = False
self.pending_footnotes = [] # type: List[nodes.footnote_reference]
@ -727,13 +718,6 @@ class LaTeXTranslator(nodes.NodeVisitor):
self.body = self.bodystack.pop()
return body
def check_latex_elements(self):
# type: () -> None
for key in self.builder.config.latex_elements:
if key not in self.elements:
msg = __("Unknown configure key: latex_elements[%r] is ignored.")
logger.warning(msg % key)
def restrict_footnote(self, node):
# type: (nodes.Node) -> None
warnings.warn('LaTeXWriter.restrict_footnote() is deprecated.',
@ -945,8 +929,6 @@ class LaTeXTranslator(nodes.NodeVisitor):
def visit_start_of_file(self, node):
# type: (nodes.Node) -> None
self.curfilestack.append(node['docname'])
# use default highlight settings for new file
self.hlsettingstack.append(self.hlsettingstack[0])
def collect_footnotes(self, node):
# type: (nodes.Node) -> Dict[unicode, List[Union[collected_footnote, bool]]]
@ -971,12 +953,6 @@ class LaTeXTranslator(nodes.NodeVisitor):
def depart_start_of_file(self, node):
# type: (nodes.Node) -> None
self.curfilestack.pop()
self.hlsettingstack.pop()
def visit_highlightlang(self, node):
# type: (nodes.Node) -> None
self.hlsettingstack[-1] = [node['lang'], node['linenothreshold']]
raise nodes.SkipNode
def visit_section(self, node):
# type: (nodes.Node) -> None
@ -2246,26 +2222,18 @@ class LaTeXTranslator(nodes.NodeVisitor):
if labels and not self.in_footnote:
self.body.append('\n\\def\\sphinxLiteralBlockLabel{' + labels + '}')
code = node.astext()
lang = self.hlsettingstack[-1][0]
linenos = code.count('\n') >= self.hlsettingstack[-1][1] - 1
lang = node.get('language', 'default')
linenos = node.get('linenos', False)
highlight_args = node.get('highlight_args', {})
hllines = '\\fvset{hllines={, %s,}}%%' %\
str(highlight_args.get('hl_lines', []))[1:-1]
if 'language' in node:
# code-block directives
lang = node['language']
highlight_args['force'] = True
if 'linenos' in node:
linenos = node['linenos']
if lang is self.hlsettingstack[0][0]:
highlight_args['force'] = node.get('force_highlighting', False)
if lang is self.builder.config.highlight_language:
# only pass highlighter options for original language
opts = self.builder.config.highlight_options
else:
opts = {}
hlcode = self.highlighter.highlight_block(
code, lang, opts=opts, linenos=linenos,
node.rawsource, lang, opts=opts, linenos=linenos,
location=(self.curfilestack[-1], node.line), **highlight_args
)
# workaround for Unicode issue
@ -2290,6 +2258,9 @@ class LaTeXTranslator(nodes.NodeVisitor):
hlcode += '\\end{sphinxVerbatimintable}'
else:
hlcode += '\\end{sphinxVerbatim}'
hllines = '\\fvset{hllines={, %s,}}%%' %\
str(highlight_args.get('hl_lines', []))[1:-1]
self.body.append('\n' + hllines + '\n' + hlcode + '\n')
raise nodes.SkipNode
@ -2565,11 +2536,7 @@ class LaTeXTranslator(nodes.NodeVisitor):
self.body.append(r'\label{%s}' % label)
self.body.append(node.astext())
else:
def is_equation(part):
# type: (unicode) -> unicode
return part.strip()
from sphinx.ext.mathbase import wrap_displaymath
from sphinx.util.math import wrap_displaymath
self.body.append(wrap_displaymath(node.astext(), label,
self.builder.config.math_number_all))
raise nodes.SkipNode
@ -2639,6 +2606,23 @@ class LaTeXTranslator(nodes.NodeVisitor):
RemovedInSphinx30Warning)
return set()
@property
def hlsettingstack(self):
# type: () -> List[List[Union[unicode, int]]]
warnings.warn('LaTeXTranslator.hlsettingstack is deprecated.',
RemovedInSphinx30Warning)
return [[self.builder.config.highlight_language, sys.maxsize]]
def check_latex_elements(self):
# type: () -> None
warnings.warn('check_latex_elements() is deprecated.',
RemovedInSphinx30Warning)
for key in self.builder.config.latex_elements:
if key not in self.elements:
msg = __("Unknown configure key: latex_elements[%r] is ignored.")
logger.warning(msg % key)
# Import old modules here for compatibility
# They should be imported after `LaTeXTranslator` to avoid recursive import.

View File

@ -378,14 +378,6 @@ class ManualPageTranslator(BaseTranslator):
# type: (nodes.Node) -> None
pass
def visit_highlightlang(self, node):
# type: (nodes.Node) -> None
pass
def depart_highlightlang(self, node):
# type: (nodes.Node) -> None
pass
def visit_download_reference(self, node):
# type: (nodes.Node) -> None
pass

View File

@ -1533,14 +1533,6 @@ class TexinfoTranslator(nodes.NodeVisitor):
self.body.append('\n\n')
raise nodes.SkipNode
def visit_highlightlang(self, node):
# type: (nodes.Node) -> None
pass
def depart_highlightlang(self, node):
# type: (nodes.Node) -> None
pass
# -- Desc
def visit_desc(self, node):

View File

@ -251,10 +251,6 @@ class TextTranslator(nodes.NodeVisitor):
for line in lines)
# XXX header/footer?
def visit_highlightlang(self, node):
# type: (nodes.Node) -> None
raise nodes.SkipNode
def visit_section(self, node):
# type: (nodes.Node) -> None
self._title_char = self.sectionchars[self.sectionlevel]

32
tests/js/doctools.js Normal file
View File

@ -0,0 +1,32 @@
var DOCUMENTATION_OPTIONS = {};
describe('urldecode', function() {
it('should correctly decode URLs and replace `+`s with a spaces', function() {
var test_encoded_string =
'%D1%88%D0%B5%D0%BB%D0%BB%D1%8B+%D1%88%D0%B5%D0%BB%D0%BB%D1%8B';
var test_decoded_string = 'шеллы шеллы';
expect(jQuery.urldecode(test_encoded_string)).toEqual(test_decoded_string);
});
});
describe('getQueryParameters', function() {
var paramString = '?q=test+this&check_keywords=yes&area=default';
var queryParamObject = {
area: ['default'],
check_keywords: ['yes'],
q: ['test this']
};
it('should correctly create query parameter object from string', function() {
expect(jQuery.getQueryParameters(paramString)).toEqual(queryParamObject);
});
it('should correctly create query param object from URL params', function() {
history.pushState({}, '_', window.location + paramString);
expect(jQuery.getQueryParameters()).toEqual(queryParamObject);
});
});

View File

@ -1,8 +1,5 @@
# -*- coding: utf-8 -*-
import os
import sys
extensions = ['sphinx.ext.viewcode']
master_doc = 'index'
exclude_patterns = ['_build']

View File

@ -3,6 +3,7 @@ submodule
"""
raise RuntimeError('This module should not get imported')
def decorator(f):
return f

View File

@ -1,4 +1,4 @@
"""
r"""
Test with a class diagram like this::

View File

@ -2,4 +2,3 @@
master_doc = 'equations'
extensions = ['sphinx.ext.imgmath']

View File

@ -0,0 +1,9 @@
# -*- coding: utf-8 -*-
master_doc = 'index'
extensions = ['sphinx.ext.doctest']
latex_documents = [
(master_doc, 'test.tex', 'The basic Sphinx documentation for testing', 'Sphinx', 'report')
]

View File

@ -0,0 +1,23 @@
test-trim_doctest_flags
=======================
.. code-block:: pycon
>>> datetime.date.now() # doctest: +FOO
datetime.date(2008, 1, 1)
.. code-block:: none
>>> datetime.date.now() # doctest: +BAR
datetime.date(2008, 1, 1)
.. code-block:: guess
# vim: set filetype=pycon
>>> datetime.date.now() # doctest: +BAZ
datetime.date(2008, 1, 1)
.. testcode::
>>> datetime.date.now() # doctest: +QUX
datetime.date(2008, 1, 1)

View File

@ -12,7 +12,6 @@ import pytest
from docutils import nodes
from sphinx.errors import ExtensionError
from sphinx.domains import Domain
from sphinx.testing.util import strip_escseq
from sphinx.util import logging

View File

@ -10,6 +10,7 @@
:license: BSD, see LICENSE for details.
"""
import re
import sys
from warnings import catch_warnings
@ -20,12 +21,24 @@ from six import PY3
from sphinx.ext.autodoc import (
AutoDirective, ModuleLevelDocumenter, FunctionDocumenter, cut_lines, between, ALL
)
from sphinx.ext.autodoc.directive import DocumenterBridge, process_documenter_options
from sphinx.testing.util import SphinxTestApp, Struct # NOQA
from sphinx.util import logging
from sphinx.util.docutils import LoggingReporter
app = None
def do_autodoc(app, objtype, name, options={}):
doccls = app.registry.documenters[objtype]
docoptions = process_documenter_options(doccls, app.config, options)
bridge = DocumenterBridge(app.env, LoggingReporter(''), docoptions, 1)
documenter = doccls(bridge, name)
documenter.generate()
return bridge.result
@pytest.fixture(scope='module', autouse=True)
def setup_module(rootdir, sphinx_test_tempdir):
try:
@ -756,175 +769,549 @@ def test_generate():
assert_result_contains('.. py:class:: Class(arg)', 'module', 'target')
assert_result_contains('.. py:exception:: CustomEx', 'module', 'target')
# test noindex flag
options.members = []
options.noindex = True
assert_result_contains(' :noindex:', 'module', 'target')
assert_result_contains(' :noindex:', 'class', 'Base')
# okay, now let's get serious about mixing Python and C signature stuff
assert_result_contains('.. py:class:: CustomDict', 'class', 'CustomDict',
all_members=True)
@pytest.mark.sphinx('html', testroot='ext-autodoc')
def test_autodoc_noindex(app):
options = {"noindex": True}
actual = do_autodoc(app, 'module', 'target', options)
assert list(actual) == [
'',
'.. py:module:: target',
' :noindex:',
''
]
# test inner class handling
assert_processes([('class', 'target.Outer'),
('class', 'target.Outer.Inner'),
('method', 'target.Outer.Inner.meth')],
'class', 'Outer', all_members=True)
# TODO: :noindex: should be propagated to children of target item.
# test descriptor docstrings
assert_result_contains(' Descriptor instance docstring.',
'attribute', 'target.Class.descr')
actual = do_autodoc(app, 'class', 'target.Base', options)
assert list(actual) == [
'',
'.. py:class:: Base',
' :noindex:',
' :module: target',
''
]
# test generation for C modules (which have no source file)
directive.env.ref_context['py:module'] = 'time'
assert_processes([('function', 'time.asctime')], 'function', 'asctime')
assert_processes([('function', 'time.asctime')], 'function', 'asctime')
# test autodoc_member_order == 'source'
directive.env.ref_context['py:module'] = 'target'
options.private_members = True
@pytest.mark.sphinx('html', testroot='ext-autodoc')
def test_autodoc_subclass_of_builtin_class(app):
options = {"members": None}
actual = do_autodoc(app, 'class', 'target.CustomDict', options)
assert list(actual) == [
'',
'.. py:class:: CustomDict',
' :module: target',
'',
' Docstring.',
' '
]
@pytest.mark.sphinx('html', testroot='ext-autodoc')
def test_autodoc_inner_class(app):
if PY3:
roger_line = ' .. py:classmethod:: Class.roger(a, *, b=2, c=3, d=4, e=5, f=6)'
builtins = ' alias of :class:`builtins.dict`'
else:
roger_line = ' .. py:classmethod:: Class.roger(a, e=5, f=6)'
assert_order(['.. py:class:: Class(arg)',
' .. py:attribute:: Class.descr',
' .. py:method:: Class.meth()',
' .. py:method:: Class.undocmeth()',
' .. py:attribute:: Class.attr',
' .. py:attribute:: Class.prop',
' .. py:attribute:: Class.docattr',
' .. py:attribute:: Class.udocattr',
' .. py:attribute:: Class.mdocattr',
roger_line,
' .. py:classmethod:: Class.moore(a, e, f) -> happiness',
' .. py:attribute:: Class.inst_attr_comment',
' .. py:attribute:: Class.inst_attr_string',
' .. py:attribute:: Class._private_inst_attr',
' .. py:classmethod:: Class.inheritedclassmeth()',
' .. py:method:: Class.inheritedmeth()',
' .. py:staticmethod:: Class.inheritedstaticmeth(cls)',
],
'class', 'Class', member_order='bysource', all_members=True)
del directive.env.ref_context['py:module']
builtins = ' alias of :class:`__builtin__.dict`'
# test attribute initialized to class instance from other module
directive.env.temp_data['autodoc:class'] = 'target.Class'
assert_result_contains(u' should be documented as well - s\xfc\xdf',
'attribute', 'mdocattr')
del directive.env.temp_data['autodoc:class']
options = {"members": None}
actual = do_autodoc(app, 'class', 'target.Outer', options)
assert list(actual) == [
'',
'.. py:class:: Outer',
' :module: target',
'',
' Foo',
' ',
' ',
' .. py:class:: Outer.Inner',
' :module: target',
' ',
' Foo',
' ',
' ',
' .. py:method:: Outer.Inner.meth()',
' :module: target',
' ',
' Foo',
' ',
' ',
' .. py:attribute:: Outer.factory',
' :module: target',
' ',
builtins
]
# test autodoc_docstring_signature
assert_result_contains(
'.. py:method:: DocstringSig.meth(FOO, BAR=1) -> BAZ', 'method',
'target.DocstringSig.meth')
assert_result_contains(
' rest of docstring', 'method', 'target.DocstringSig.meth')
assert_result_contains(
'.. py:method:: DocstringSig.meth2()', 'method',
'target.DocstringSig.meth2')
assert_result_contains(
' indented line', 'method',
'target.DocstringSig.meth2')
assert_result_contains(
'.. py:classmethod:: Class.moore(a, e, f) -> happiness', 'method',
'target.Class.moore')
actual = do_autodoc(app, 'class', 'target.Outer.Inner', options)
assert list(actual) == [
'',
'.. py:class:: Inner',
' :module: target.Outer',
'',
' Foo',
' ',
' ',
' .. py:method:: Inner.meth()',
' :module: target.Outer',
' ',
' Foo',
' ',
]
# test new attribute documenter behavior
directive.env.ref_context['py:module'] = 'target'
options.undoc_members = True
assert_processes([('class', 'target.AttCls'),
('attribute', 'target.AttCls.a1'),
('attribute', 'target.AttCls.a2'),
], 'class', 'AttCls')
assert_result_contains(
' :annotation: = hello world', 'attribute', 'AttCls.a1')
assert_result_contains(
' :annotation: = None', 'attribute', 'AttCls.a2')
# test explicit members with instance attributes
del directive.env.temp_data['autodoc:class']
del directive.env.temp_data['autodoc:module']
directive.env.ref_context['py:module'] = 'target'
options.inherited_members = False
options.undoc_members = False
options.members = ALL
assert_processes([
('class', 'target.InstAttCls'),
('attribute', 'target.InstAttCls.ca1'),
('attribute', 'target.InstAttCls.ca2'),
('attribute', 'target.InstAttCls.ca3'),
('attribute', 'target.InstAttCls.ia1'),
('attribute', 'target.InstAttCls.ia2'),
], 'class', 'InstAttCls')
del directive.env.temp_data['autodoc:class']
del directive.env.temp_data['autodoc:module']
options.members = ['ca1', 'ia1']
assert_processes([
('class', 'target.InstAttCls'),
('attribute', 'target.InstAttCls.ca1'),
('attribute', 'target.InstAttCls.ia1'),
], 'class', 'InstAttCls')
del directive.env.temp_data['autodoc:class']
del directive.env.temp_data['autodoc:module']
del directive.env.ref_context['py:module']
@pytest.mark.sphinx('html', testroot='ext-autodoc')
def test_autodoc_descriptor(app):
actual = do_autodoc(app, 'attribute', 'target.Class.descr')
assert list(actual) == [
'',
'.. py:attribute:: Class.descr',
' :module: target',
'',
' Descriptor instance docstring.',
' '
]
# test members with enum attributes
directive.env.ref_context['py:module'] = 'target'
options.inherited_members = False
options.undoc_members = True
options.members = ALL
assert_processes([
('class', 'target.EnumCls'),
('attribute', 'target.EnumCls.val1'),
('attribute', 'target.EnumCls.val2'),
('attribute', 'target.EnumCls.val3'),
('attribute', 'target.EnumCls.val4'),
], 'class', 'EnumCls')
assert_result_contains(
' :annotation: = 12', 'attribute', 'EnumCls.val1')
assert_result_contains(
' :annotation: = 23', 'attribute', 'EnumCls.val2')
assert_result_contains(
' :annotation: = 34', 'attribute', 'EnumCls.val3')
del directive.env.temp_data['autodoc:class']
del directive.env.temp_data['autodoc:module']
# test descriptor class documentation
options.members = ['CustomDataDescriptor', 'CustomDataDescriptor2']
assert_result_contains('.. py:class:: CustomDataDescriptor(doc)',
'module', 'target')
assert_result_contains(' .. py:method:: CustomDataDescriptor.meth()',
'module', 'target')
assert_result_contains('.. py:class:: CustomDataDescriptor2(doc)',
'module', 'target')
@pytest.mark.sphinx('html', testroot='ext-autodoc')
def test_autodoc_c_module(app):
actual = do_autodoc(app, 'function', 'time.asctime')
assert list(actual) == [
'',
'.. py:function:: asctime([tuple]) -> string',
' :module: time',
'',
" Convert a time tuple to a string, e.g. 'Sat Jun 06 16:26:11 1998'.",
' When the time tuple is not present, current time as returned by localtime()',
' is used.',
' '
]
# test mocked module imports
options.members = ['TestAutodoc']
options.undoc_members = False
assert_result_contains('.. py:class:: TestAutodoc',
'module', 'autodoc_missing_imports')
assert_result_contains(' .. py:method:: TestAutodoc.decoratedMethod()',
'module', 'autodoc_missing_imports')
options.members = ['decoratedFunction']
assert_result_contains('.. py:function:: decoratedFunction()',
'module', 'autodoc_missing_imports')
@pytest.mark.sphinx('html', testroot='ext-autodoc')
def test_autodoc_member_order(app):
if PY3:
roger_method = ' .. py:classmethod:: Class.roger(a, *, b=2, c=3, d=4, e=5, f=6)'
else:
roger_method = ' .. py:classmethod:: Class.roger(a, e=5, f=6)'
# case member-order='bysource'
options = {"members": None,
'member-order': 'bysource',
"undoc-members": True,
'private-members': True}
actual = do_autodoc(app, 'class', 'target.Class', options)
assert list(filter(lambda l: '::' in l, actual)) == [
'.. py:class:: Class(arg)',
' .. py:attribute:: Class.descr',
' .. py:method:: Class.meth()',
' .. py:method:: Class.undocmeth()',
' .. py:method:: Class.skipmeth()',
' .. py:method:: Class.excludemeth()',
' .. py:attribute:: Class.skipattr',
' .. py:attribute:: Class.attr',
' .. py:attribute:: Class.prop',
' .. py:attribute:: Class.docattr',
' .. py:attribute:: Class.udocattr',
' .. py:attribute:: Class.mdocattr',
roger_method,
' .. py:classmethod:: Class.moore(a, e, f) -> happiness',
' .. py:attribute:: Class.inst_attr_inline',
' .. py:attribute:: Class.inst_attr_comment',
' .. py:attribute:: Class.inst_attr_string',
' .. py:attribute:: Class._private_inst_attr'
]
# case member-order='groupwise'
options = {"members": None,
'member-order': 'groupwise',
"undoc-members": True,
'private-members': True}
actual = do_autodoc(app, 'class', 'target.Class', options)
assert list(filter(lambda l: '::' in l, actual)) == [
'.. py:class:: Class(arg)',
' .. py:method:: Class.excludemeth()',
' .. py:method:: Class.meth()',
' .. py:classmethod:: Class.moore(a, e, f) -> happiness',
roger_method,
' .. py:method:: Class.skipmeth()',
' .. py:method:: Class.undocmeth()',
' .. py:attribute:: Class._private_inst_attr',
' .. py:attribute:: Class.attr',
' .. py:attribute:: Class.descr',
' .. py:attribute:: Class.docattr',
' .. py:attribute:: Class.inst_attr_comment',
' .. py:attribute:: Class.inst_attr_inline',
' .. py:attribute:: Class.inst_attr_string',
' .. py:attribute:: Class.mdocattr',
' .. py:attribute:: Class.prop',
' .. py:attribute:: Class.skipattr',
' .. py:attribute:: Class.udocattr'
]
# case member-order=None
options = {"members": None,
"undoc-members": True,
'private-members': True}
actual = do_autodoc(app, 'class', 'target.Class', options)
assert list(filter(lambda l: '::' in l, actual)) == [
'.. py:class:: Class(arg)',
' .. py:attribute:: Class._private_inst_attr',
' .. py:attribute:: Class.attr',
' .. py:attribute:: Class.descr',
' .. py:attribute:: Class.docattr',
' .. py:method:: Class.excludemeth()',
' .. py:attribute:: Class.inst_attr_comment',
' .. py:attribute:: Class.inst_attr_inline',
' .. py:attribute:: Class.inst_attr_string',
' .. py:attribute:: Class.mdocattr',
' .. py:method:: Class.meth()',
' .. py:classmethod:: Class.moore(a, e, f) -> happiness',
' .. py:attribute:: Class.prop',
roger_method,
' .. py:attribute:: Class.skipattr',
' .. py:method:: Class.skipmeth()',
' .. py:attribute:: Class.udocattr',
' .. py:method:: Class.undocmeth()'
]
@pytest.mark.sphinx('html', testroot='ext-autodoc')
def test_autodoc_module_scope(app):
def convert(s):
return re.sub('<.*>', '<FILTERED>', s) # for py2/py3
app.env.temp_data['autodoc:module'] = 'target'
actual = do_autodoc(app, 'attribute', 'Class.mdocattr')
assert list(map(convert, actual)) == [
u'',
u'.. py:attribute:: Class.mdocattr',
u' :module: target',
u' :annotation: = <FILTERED>',
u'',
u' should be documented as well - süß',
u' '
]
@pytest.mark.sphinx('html', testroot='ext-autodoc')
def test_autodoc_class_scope(app):
def convert(s):
return re.sub('<.*>', '<FILTERED>', s) # for py2/py3
app.env.temp_data['autodoc:module'] = 'target'
app.env.temp_data['autodoc:class'] = 'Class'
actual = do_autodoc(app, 'attribute', 'mdocattr')
assert list(map(convert, actual)) == [
u'',
u'.. py:attribute:: Class.mdocattr',
u' :module: target',
u' :annotation: = <FILTERED>',
u'',
u' should be documented as well - süß',
u' '
]
@pytest.mark.sphinx('html', testroot='ext-autodoc')
def test_autodoc_docstring_signature(app):
options = {"members": None}
actual = do_autodoc(app, 'class', 'target.DocstringSig', options)
assert list(actual) == [
'',
'.. py:class:: DocstringSig',
' :module: target',
'',
' ',
' .. py:method:: DocstringSig.meth(FOO, BAR=1) -> BAZ',
' :module: target',
' ',
' First line of docstring',
' ',
' rest of docstring',
' ',
' ',
' .. py:method:: DocstringSig.meth2()',
' :module: target',
' ',
' First line, no signature',
' Second line followed by indentation::',
' ',
' indented line',
' ',
' ',
' .. py:attribute:: DocstringSig.prop1',
' :module: target',
' ',
' First line of docstring',
' ',
' ',
' .. py:attribute:: DocstringSig.prop2',
' :module: target',
' ',
' First line of docstring',
' Second line of docstring',
' '
]
# disable autodoc_docstring_signature
app.config.autodoc_docstring_signature = False
actual = do_autodoc(app, 'class', 'target.DocstringSig', options)
assert list(actual) == [
u'',
u'.. py:class:: DocstringSig',
u' :module: target',
u'',
u' ',
u' .. py:method:: DocstringSig.meth()',
u' :module: target',
u' ',
u' meth(FOO, BAR=1) -> BAZ',
u' First line of docstring',
u' ',
u' rest of docstring',
u' ',
u' ',
u' ',
u' .. py:method:: DocstringSig.meth2()',
u' :module: target',
u' ',
u' First line, no signature',
u' Second line followed by indentation::',
u' ',
u' indented line',
u' ',
u' ',
u' .. py:attribute:: DocstringSig.prop1',
u' :module: target',
u' ',
u' DocstringSig.prop1(self)',
u' First line of docstring',
u' ',
u' ',
u' .. py:attribute:: DocstringSig.prop2',
u' :module: target',
u' ',
u' First line of docstring',
u' Second line of docstring',
u' '
]
@pytest.mark.sphinx('html', testroot='ext-autodoc')
def test_class_attributes(app):
options = {"members": None,
"undoc-members": True}
actual = do_autodoc(app, 'class', 'target.AttCls', options)
assert list(actual) == [
'',
'.. py:class:: AttCls',
' :module: target',
'',
' ',
' .. py:attribute:: AttCls.a1',
' :module: target',
' :annotation: = hello world',
' ',
' ',
' .. py:attribute:: AttCls.a2',
' :module: target',
' :annotation: = None',
' '
]
@pytest.mark.sphinx('html', testroot='ext-autodoc')
def test_instance_attributes(app):
options = {"members": None}
actual = do_autodoc(app, 'class', 'target.InstAttCls', options)
assert list(actual) == [
'',
'.. py:class:: InstAttCls()',
' :module: target',
'',
' Class with documented class and instance attributes.',
' ',
' ',
' .. py:attribute:: InstAttCls.ca1',
' :module: target',
" :annotation: = 'a'",
' ',
' Doc comment for class attribute InstAttCls.ca1.',
' It can have multiple lines.',
' ',
' ',
' .. py:attribute:: InstAttCls.ca2',
' :module: target',
" :annotation: = 'b'",
' ',
' Doc comment for InstAttCls.ca2. One line only.',
' ',
' ',
' .. py:attribute:: InstAttCls.ca3',
' :module: target',
" :annotation: = 'c'",
' ',
' Docstring for class attribute InstAttCls.ca3.',
' ',
' ',
' .. py:attribute:: InstAttCls.ia1',
' :module: target',
' :annotation: = None',
' ',
' Doc comment for instance attribute InstAttCls.ia1',
' ',
' ',
' .. py:attribute:: InstAttCls.ia2',
' :module: target',
' :annotation: = None',
' ',
' Docstring for instance attribute InstAttCls.ia2.',
' '
]
# pick up arbitrary attributes
options = {"members": 'ca1,ia1'}
actual = do_autodoc(app, 'class', 'target.InstAttCls', options)
assert list(actual) == [
'',
'.. py:class:: InstAttCls()',
' :module: target',
'',
' Class with documented class and instance attributes.',
' ',
' ',
' .. py:attribute:: InstAttCls.ca1',
' :module: target',
" :annotation: = 'a'",
' ',
' Doc comment for class attribute InstAttCls.ca1.',
' It can have multiple lines.',
' ',
' ',
' .. py:attribute:: InstAttCls.ia1',
' :module: target',
' :annotation: = None',
' ',
' Doc comment for instance attribute InstAttCls.ia1',
' '
]
@pytest.mark.sphinx('html', testroot='ext-autodoc')
def test_enum_class(app):
options = {"members": None,
"undoc-members": True}
actual = do_autodoc(app, 'class', 'target.EnumCls', options)
assert list(actual) == [
'',
'.. py:class:: EnumCls',
' :module: target',
'',
' this is enum class',
' ',
' ',
' .. py:attribute:: EnumCls.val1',
' :module: target',
' :annotation: = 12',
' ',
' doc for val1',
' ',
' ',
' .. py:attribute:: EnumCls.val2',
' :module: target',
' :annotation: = 23',
' ',
' doc for val2',
' ',
' ',
' .. py:attribute:: EnumCls.val3',
' :module: target',
' :annotation: = 34',
' ',
' doc for val3',
' ',
' ',
' .. py:attribute:: EnumCls.val4',
' :module: target',
' :annotation: = 34',
' '
]
# checks for an attribute of EnumClass
actual = do_autodoc(app, 'attribute', 'target.EnumCls.val1')
assert list(actual) == [
'',
'.. py:attribute:: EnumCls.val1',
' :module: target',
' :annotation: = 12',
'',
' doc for val1',
' '
]
@pytest.mark.sphinx('html', testroot='ext-autodoc')
def test_descriptor_class(app):
options = {"members": 'CustomDataDescriptor,CustomDataDescriptor2'}
actual = do_autodoc(app, 'module', 'target', options)
assert list(actual) == [
'',
'.. py:module:: target',
'',
'',
'.. py:class:: CustomDataDescriptor(doc)',
' :module: target',
'',
' Descriptor class docstring.',
' ',
' ',
' .. py:method:: CustomDataDescriptor.meth()',
' :module: target',
' ',
' Function.',
' ',
'',
'.. py:class:: CustomDataDescriptor2(doc)',
' :module: target',
'',
' Descriptor class with custom metaclass docstring.',
' '
]
@pytest.mark.sphinx('html', testroot='root')
def test_mocked_module_imports(app):
options = {"members": 'TestAutodoc,decoratedFunction'}
actual = do_autodoc(app, 'module', 'autodoc_missing_imports', options)
assert list(actual) == [
'',
'.. py:module:: autodoc_missing_imports',
'',
'',
'.. py:class:: TestAutodoc',
' :module: autodoc_missing_imports',
'',
' TestAutodoc docstring.',
' ',
' ',
' .. py:method:: TestAutodoc.decoratedMethod()',
' :module: autodoc_missing_imports',
' ',
' TestAutodoc::decoratedMethod docstring',
' ',
'',
'.. py:function:: decoratedFunction()',
' :module: autodoc_missing_imports',
'',
' decoratedFunction docstring',
' '
]
@pytest.mark.skipif(sys.version_info < (3, 4),
reason='functools.partialmethod is available on py34 or above')
@pytest.mark.usefixtures('setup_test')
def test_partialmethod():
def call_autodoc(objtype, name):
inst = app.registry.documenters[objtype](directive, name)
inst.generate()
result = list(directive.result)
del directive.result[:]
return result
options.inherited_members = True
options.undoc_members = True
@pytest.mark.sphinx('html', testroot='ext-autodoc')
def test_partialmethod(app):
expected = [
'',
'.. py:class:: Cell',
@ -959,4 +1346,27 @@ def test_partialmethod():
# TODO: this condition should be updated after 3.7-final release.
expected = '\n'.join(expected).replace(' -> None', '').split('\n')
assert call_autodoc('class', 'target.partialmethod.Cell') == expected
options = {"members": None}
actual = do_autodoc(app, 'class', 'target.partialmethod.Cell', options)
assert list(actual) == expected
@pytest.mark.sphinx('html', testroot='ext-autodoc')
def test_autodoc_default_flags(app):
# no settings
actual = do_autodoc(app, 'class', 'target.EnumCls')
assert ' .. py:attribute:: EnumCls.val1' not in actual
assert ' .. py:attribute:: EnumCls.val4' not in actual
# with :members:
app.config.autodoc_default_flags = ['members']
actual = do_autodoc(app, 'class', 'target.EnumCls')
assert ' .. py:attribute:: EnumCls.val1' in actual
assert ' .. py:attribute:: EnumCls.val4' not in actual
# with :members: and :undoc-members:
app.config.autodoc_default_flags = ['members',
'undoc-members']
actual = do_autodoc(app, 'class', 'target.EnumCls')
assert ' .. py:attribute:: EnumCls.val1' in actual
assert ' .. py:attribute:: EnumCls.val4' in actual

View File

@ -175,8 +175,8 @@ def test_gettext_template_msgid_order_in_sphinxpot(app):
result = (app.outdir / 'sphinx.pot').text(encoding='utf-8')
assert re.search(
('msgid "Template 1".*'
'msgid "This is Template 1\.".*'
'msgid "This is Template 1\\.".*'
'msgid "Template 2".*'
'msgid "This is Template 2\.".*'),
'msgid "This is Template 2\\.".*'),
result,
flags=re.S)

View File

@ -18,6 +18,7 @@ import pytest
from html5lib import getTreeBuilder, HTMLParser
from six import PY3
from sphinx.errors import ConfigError
from sphinx.testing.util import remove_unicode_literals, strip_escseq
from sphinx.util.inventory import InventoryFile
@ -1327,3 +1328,62 @@ def test_html_baseurl_and_html_file_suffix(app, status, warning):
result = (app.outdir / 'qux' / 'index.htm').text(encoding='utf8')
assert '<link rel="canonical" href="https://example.com/subdir/qux/index.htm" />' in result
@pytest.mark.sphinx('html', testroot='basic')
def test_default_html_math_renderer(app, status, warning):
assert app.builder.math_renderer_name == 'mathjax'
@pytest.mark.sphinx('html', testroot='basic',
confoverrides={'extensions': ['sphinx.ext.mathjax']})
def test_html_math_renderer_is_mathjax(app, status, warning):
assert app.builder.math_renderer_name == 'mathjax'
@pytest.mark.sphinx('html', testroot='basic',
confoverrides={'extensions': ['sphinx.ext.imgmath']})
def test_html_math_renderer_is_imgmath(app, status, warning):
assert app.builder.math_renderer_name == 'imgmath'
@pytest.mark.sphinx('html', testroot='basic',
confoverrides={'extensions': ['sphinx.ext.jsmath',
'sphinx.ext.imgmath']})
def test_html_math_renderer_is_duplicated(make_app, app_params):
try:
args, kwargs = app_params
make_app(*args, **kwargs)
assert False
except ConfigError as exc:
assert str(exc) == ('Many math_renderers are registered. '
'But no math_renderer is selected.')
@pytest.mark.sphinx('html', testroot='basic',
confoverrides={'extensions': ['sphinx.ext.imgmath',
'sphinx.ext.mathjax']})
def test_html_math_renderer_is_duplicated2(app, status, warning):
# case of both mathjax and another math_renderer is loaded
assert app.builder.math_renderer_name == 'imgmath' # The another one is chosen
@pytest.mark.sphinx('html', testroot='basic',
confoverrides={'extensions': ['sphinx.ext.jsmath',
'sphinx.ext.imgmath'],
'html_math_renderer': 'imgmath'})
def test_html_math_renderer_is_chosen(app, status, warning):
assert app.builder.math_renderer_name == 'imgmath'
@pytest.mark.sphinx('html', testroot='basic',
confoverrides={'extensions': ['sphinx.ext.jsmath',
'sphinx.ext.mathjax'],
'html_math_renderer': 'imgmath'})
def test_html_math_renderer_is_mismatched(make_app, app_params):
try:
args, kwargs = app_params
make_app(*args, **kwargs)
assert False
except ConfigError as exc:
assert str(exc) == "Unknown math_renderer 'imgmath' is given."

View File

@ -22,7 +22,7 @@ from sphinx.testing.path import path
@pytest.mark.sphinx(testroot='config', confoverrides={
'master_doc': 'master',
'nonexisting_value': 'True',
'latex_elements.docclass': 'scrartcl',
'latex_elements.maketitle': 'blah blah blah',
'modindex_common_prefix': 'path1,path2'})
def test_core_config(app, status, warning):
cfg = app.config
@ -34,7 +34,7 @@ def test_core_config(app, status, warning):
# overrides
assert cfg.master_doc == 'master'
assert cfg.latex_elements['docclass'] == 'scrartcl'
assert cfg.latex_elements['maketitle'] == 'blah blah blah'
assert cfg.modindex_common_prefix == ['path1', 'path2']
# simple default values
@ -172,20 +172,20 @@ def make_app_with_empty_project(make_app, tempdir):
def test_needs_sphinx(make_app_with_empty_project):
make_app = make_app_with_empty_project
# micro version
app = make_app(confoverrides={'needs_sphinx': '1.3.3'}) # OK: less
app = make_app(confoverrides={'needs_sphinx': '1.3.4'}) # OK: equals
make_app(confoverrides={'needs_sphinx': '1.3.3'}) # OK: less
make_app(confoverrides={'needs_sphinx': '1.3.4'}) # OK: equals
with pytest.raises(VersionRequirementError):
make_app(confoverrides={'needs_sphinx': '1.3.5'}) # NG: greater
# minor version
app = make_app(confoverrides={'needs_sphinx': '1.2'}) # OK: less
app = make_app(confoverrides={'needs_sphinx': '1.3'}) # OK: equals
make_app(confoverrides={'needs_sphinx': '1.2'}) # OK: less
make_app(confoverrides={'needs_sphinx': '1.3'}) # OK: equals
with pytest.raises(VersionRequirementError):
make_app(confoverrides={'needs_sphinx': '1.4'}) # NG: greater
# major version
app = make_app(confoverrides={'needs_sphinx': '0'}) # OK: less
app = make_app(confoverrides={'needs_sphinx': '1'}) # OK: equals
make_app(confoverrides={'needs_sphinx': '0'}) # OK: less
make_app(confoverrides={'needs_sphinx': '1'}) # OK: equals
with pytest.raises(VersionRequirementError):
make_app(confoverrides={'needs_sphinx': '2'}) # NG: greater

View File

@ -760,9 +760,9 @@ def test_xref_consistency(app, status, warning):
def classes(role, tag):
pattern = (r'{role}-role:.*?'
'<(?P<tag>{tag}) .*?class=["\'](?P<classes>.*?)["\'].*?>'
'.*'
'</(?P=tag)>').format(role=role, tag=tag)
r'<(?P<tag>{tag}) .*?class=["\'](?P<classes>.*?)["\'].*?>'
r'.*'
r'</(?P=tag)>').format(role=role, tag=tag)
result = re.search(pattern, output)
expect = '''\
Pattern for role `{role}` with tag `{tag}`
@ -783,17 +783,17 @@ not found in `{test}`
self.content_classes[tag] = classes(role, tag)
# not actually used as a reference point
#code_role = RoleClasses('code', 'code', [])
# code_role = RoleClasses('code', 'code', [])
any_role = RoleClasses('any', 'a', ['code'])
cpp_any_role = RoleClasses('cpp-any', 'a', ['code'])
# NYI: consistent looks
#texpr_role = RoleClasses('cpp-texpr', 'span', ['a', 'code'])
# texpr_role = RoleClasses('cpp-texpr', 'span', ['a', 'code'])
expr_role = RoleClasses('cpp-expr', 'code', ['a'])
texpr_role = RoleClasses('cpp-texpr', 'span', ['a', 'span'])
# XRefRole-style classes
## any and cpp:any do not put these classes at the root
# any and cpp:any do not put these classes at the root
# n.b. the generic any machinery finds the specific 'cpp-class' object type
expect = 'any uses XRefRole classes'

View File

@ -113,7 +113,8 @@ def test_glob(app):
maxdepth=-1, numbered=0, includefiles=includefiles,
entries=[(None, 'foo'), (None, 'bar/index'), (None, 'bar/bar_1'),
(None, 'bar/bar_2'), (None, 'bar/bar_3'), (None, 'baz'),
(None, 'qux/index'), ('hyperref', 'https://sphinx-doc.org/?q=sphinx')])
(None, 'qux/index'),
('hyperref', 'https://sphinx-doc.org/?q=sphinx')])
assert_node(toctree[0][1][1],
[list_item, ([compact_paragraph, reference, "reversed order"],
[bullet_list, addnodes.toctree])]) # [0][1][1][1][0]

View File

@ -387,8 +387,6 @@ def extract_toc(path):
coderoot='test-apidoc-subpackage-in-toc',
options=['--separate']
)
def test_subpackage_in_toc(make_app, apidoc):
"""Make sure that empty subpackages with non-empty subpackages in them
are not skipped (issue #4520)

View File

@ -9,6 +9,7 @@
:license: BSD, see LICENSE for details.
"""
import os
import pytest
from packaging.specifiers import InvalidSpecifier
from packaging.version import InvalidVersion

View File

@ -76,16 +76,6 @@ def test_set_formatter():
PygmentsBridge.html_formatter = HtmlFormatter
def test_trim_doctest_flags():
PygmentsBridge.html_formatter = MyFormatter
try:
bridge = PygmentsBridge('html', trim_doctest_flags=True)
ret = bridge.highlight_block('>>> 1+2 # doctest: SKIP\n3\n', 'pycon')
assert ret == '>>> 1+2 \n3\n'
finally:
PygmentsBridge.html_formatter = HtmlFormatter
@mock.patch('sphinx.highlighting.logger')
def test_default_highlight(logger):
bridge = PygmentsBridge('html')

View File

@ -0,0 +1,32 @@
# -*- coding: utf-8 -*-
"""
test_transforms_post_transforms_code
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
:copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS.
:license: BSD, see LICENSE for details.
"""
import pytest
@pytest.mark.sphinx('html', testroot='trim_doctest_flags')
def test_trim_doctest_flags_html(app, status, warning):
app.build()
result = (app.outdir / 'index.html').text(encoding='utf8')
assert 'FOO' not in result
assert 'BAR' in result
assert 'BAZ' not in result
assert 'QUX' not in result
@pytest.mark.sphinx('latex', testroot='trim_doctest_flags')
def test_trim_doctest_flags_latex(app, status, warning):
app.build()
result = (app.outdir / 'test.tex').text(encoding='utf8')
assert 'FOO' not in result
assert 'BAR' in result
assert 'BAZ' not in result
assert 'QUX' not in result

View File

@ -1,13 +1,13 @@
[tox]
minversion = 2.0
envlist = docs,flake8,mypy,coverage,py{27,34,35,36,py},du{11,12,13,14}
envlist = docs,flake8,mypy,coverage,py{27,34,35,36,37,38,py},du{11,12,13,14}
[testenv]
usedevelop = True
passenv =
https_proxy http_proxy no_proxy PERL PERL5LIB PYTEST_ADDOPTS EPUBCHECK_PATH
description =
py{27,34,35,36,py}: Run unit tests against {envname}.
py{27,34,35,36,37,38,py}: Run unit tests against {envname}.
du{11,12,13,14}: Run unit tests with the given version of docutils.
# TODO(stephenfin) Replace this with the 'extras' config option when tox 2.4 is