mirror of
https://github.com/sphinx-doc/sphinx.git
synced 2025-02-25 18:55:22 -06:00
Merge branch 'master' into simplify_conf.py
This commit is contained in:
@@ -13,13 +13,14 @@ matrix:
|
|||||||
include:
|
include:
|
||||||
- python: '3.5'
|
- python: '3.5'
|
||||||
env:
|
env:
|
||||||
- TOXENV=du13
|
- TOXENV=du12
|
||||||
- python: '3.6'
|
- python: '3.6'
|
||||||
env:
|
env:
|
||||||
- TOXENV=py36
|
- TOXENV=du13
|
||||||
- PYTEST_ADDOPTS="--cov ./ --cov-append --cov-config setup.cfg"
|
|
||||||
- python: '3.7'
|
- python: '3.7'
|
||||||
env: TOXENV=py37
|
env:
|
||||||
|
- TOXENV=py37
|
||||||
|
- PYTEST_ADDOPTS="--cov ./ --cov-append --cov-config setup.cfg"
|
||||||
- python: 'nightly'
|
- python: 'nightly'
|
||||||
env: TOXENV=py38
|
env: TOXENV=py38
|
||||||
- python: '3.6'
|
- python: '3.6'
|
||||||
|
|||||||
29
CHANGES
29
CHANGES
@@ -23,6 +23,7 @@ Dependencies
|
|||||||
|
|
||||||
- sphinxcontrib.applehelp
|
- sphinxcontrib.applehelp
|
||||||
- sphinxcontrib.devhelp
|
- sphinxcontrib.devhelp
|
||||||
|
- sphinxcontrib.htmlhelp
|
||||||
- sphinxcontrib.jsmath
|
- sphinxcontrib.jsmath
|
||||||
- sphinxcontrib.qthelp
|
- sphinxcontrib.qthelp
|
||||||
|
|
||||||
@@ -66,6 +67,8 @@ Incompatible changes
|
|||||||
the text width and height, even if width and/or height option were used.
|
the text width and height, even if width and/or height option were used.
|
||||||
(refs: #5956)
|
(refs: #5956)
|
||||||
* epub: ``epub_title`` defaults to the :confval:`project` option
|
* epub: ``epub_title`` defaults to the :confval:`project` option
|
||||||
|
* #4550: All tables and figures without ``align`` option are displayed to center
|
||||||
|
* #4587: html: Output HTML5 by default
|
||||||
|
|
||||||
Deprecated
|
Deprecated
|
||||||
----------
|
----------
|
||||||
@@ -76,6 +79,10 @@ Deprecated
|
|||||||
``EpubBuilder.build_container()``, ``EpubBuilder.bulid_content()``,
|
``EpubBuilder.build_container()``, ``EpubBuilder.bulid_content()``,
|
||||||
``EpubBuilder.build_toc()`` and ``EpubBuilder.build_epub()``
|
``EpubBuilder.build_toc()`` and ``EpubBuilder.build_epub()``
|
||||||
* The arguments of ``Epub3Builder.build_navigation_doc()``
|
* The arguments of ``Epub3Builder.build_navigation_doc()``
|
||||||
|
* The config variables
|
||||||
|
|
||||||
|
- :confval:`html_experimental_html5_writer`
|
||||||
|
|
||||||
* The ``encoding`` argument of ``autodoc.Documenter.get_doc()``,
|
* The ``encoding`` argument of ``autodoc.Documenter.get_doc()``,
|
||||||
``autodoc.DocstringSignatureMixin.get_doc()``,
|
``autodoc.DocstringSignatureMixin.get_doc()``,
|
||||||
``autodoc.DocstringSignatureMixin._find_signature()``, and
|
``autodoc.DocstringSignatureMixin._find_signature()``, and
|
||||||
@@ -109,6 +116,11 @@ Deprecated
|
|||||||
* ``sphinx.io.SphinxFileInput.supported``
|
* ``sphinx.io.SphinxFileInput.supported``
|
||||||
* ``sphinx.io.SphinxRSTFileInput``
|
* ``sphinx.io.SphinxRSTFileInput``
|
||||||
* ``sphinx.registry.SphinxComponentRegistry.add_source_input()``
|
* ``sphinx.registry.SphinxComponentRegistry.add_source_input()``
|
||||||
|
* ``sphinx.roles.abbr_role()``
|
||||||
|
* ``sphinx.roles.emph_literal_role()``
|
||||||
|
* ``sphinx.roles.menusel_role()``
|
||||||
|
* ``sphinx.roles.index_role()``
|
||||||
|
* ``sphinx.roles.indexmarkup_role()``
|
||||||
* ``sphinx.testing.util.remove_unicode_literal()``
|
* ``sphinx.testing.util.remove_unicode_literal()``
|
||||||
* ``sphinx.util.attrdict``
|
* ``sphinx.util.attrdict``
|
||||||
* ``sphinx.util.force_decode()``
|
* ``sphinx.util.force_decode()``
|
||||||
@@ -120,10 +132,13 @@ Deprecated
|
|||||||
* ``sphinx.util.osutil.EPIPE``
|
* ``sphinx.util.osutil.EPIPE``
|
||||||
* ``sphinx.util.osutil.walk()``
|
* ``sphinx.util.osutil.walk()``
|
||||||
* ``sphinx.util.PeekableIterator``
|
* ``sphinx.util.PeekableIterator``
|
||||||
|
* ``sphinx.util.pycompat.NoneType``
|
||||||
* ``sphinx.util.pycompat.TextIOWrapper``
|
* ``sphinx.util.pycompat.TextIOWrapper``
|
||||||
* ``sphinx.util.pycompat.UnicodeMixin``
|
* ``sphinx.util.pycompat.UnicodeMixin``
|
||||||
* ``sphinx.util.pycompat.htmlescape``
|
* ``sphinx.util.pycompat.htmlescape``
|
||||||
* ``sphinx.util.pycompat.indent``
|
* ``sphinx.util.pycompat.indent``
|
||||||
|
* ``sphinx.util.pycompat.sys_encoding``
|
||||||
|
* ``sphinx.util.pycompat.terminal_safe()``
|
||||||
* ``sphinx.util.pycompat.u``
|
* ``sphinx.util.pycompat.u``
|
||||||
* ``sphinx.writers.latex.ExtBabel``
|
* ``sphinx.writers.latex.ExtBabel``
|
||||||
* ``sphinx.writers.latex.LaTeXTranslator._make_visit_admonition()``
|
* ``sphinx.writers.latex.LaTeXTranslator._make_visit_admonition()``
|
||||||
@@ -155,6 +170,10 @@ Features added
|
|||||||
|
|
||||||
* #4182: autodoc: Support :confval:`suppress_warnings`
|
* #4182: autodoc: Support :confval:`suppress_warnings`
|
||||||
* #5533: autodoc: :confval:`autodoc_default_options` supports ``member-order``
|
* #5533: autodoc: :confval:`autodoc_default_options` supports ``member-order``
|
||||||
|
* #5394: autodoc: Display readable names in type annotations for mocked objects
|
||||||
|
* #5459: autodoc: :confval:`autodoc_default_options` accepts ``True`` as a value
|
||||||
|
* #5635: autosummary: Add :confval:`autosummary_mock_imports` to mock external
|
||||||
|
libraries on importing targets
|
||||||
* #4018: htmlhelp: Add :confval:`htmlhelp_file_suffix` and
|
* #4018: htmlhelp: Add :confval:`htmlhelp_file_suffix` and
|
||||||
:confval:`htmlhelp_link_suffix`
|
:confval:`htmlhelp_link_suffix`
|
||||||
* #5559: text: Support complex tables (colspan and rowspan)
|
* #5559: text: Support complex tables (colspan and rowspan)
|
||||||
@@ -174,10 +193,17 @@ Features added
|
|||||||
* #4611: epub: Show warning for duplicated ToC entries
|
* #4611: epub: Show warning for duplicated ToC entries
|
||||||
* #1851: Allow to omit an argument for :rst:dir:`code-block` directive. If
|
* #1851: Allow to omit an argument for :rst:dir:`code-block` directive. If
|
||||||
omitted, it follows :rst:dir:`highlight` or :confval:`highlight_language`
|
omitted, it follows :rst:dir:`highlight` or :confval:`highlight_language`
|
||||||
|
* #4587: html: Add :confval:`html4_writer` to use old HTML4 writer
|
||||||
* #6016: HTML search: A placeholder for the search summary prevents search
|
* #6016: HTML search: A placeholder for the search summary prevents search
|
||||||
result links from changing their position when the search terminates. This
|
result links from changing their position when the search terminates. This
|
||||||
makes navigating search results easier.
|
makes navigating search results easier.
|
||||||
|
* #5196: linkcheck also checks remote images exist
|
||||||
|
* #5924: githubpages: create CNAME file for custom domains when
|
||||||
|
:confval:`html_baseurl` set
|
||||||
|
* #4261: autosectionlabel: restrict the labeled sections by new config value;
|
||||||
|
:confval:`autosectionlabel_maxdepth`
|
||||||
|
|
||||||
|
|
||||||
Bugs fixed
|
Bugs fixed
|
||||||
----------
|
----------
|
||||||
|
|
||||||
@@ -226,6 +252,7 @@ Bugs fixed
|
|||||||
----------
|
----------
|
||||||
|
|
||||||
* LaTeX: Remove extraneous space after author names on PDF title page (refs: #6004)
|
* LaTeX: Remove extraneous space after author names on PDF title page (refs: #6004)
|
||||||
|
* #6046: LaTeX: ``TypeError`` is raised when invalid latex_elements given
|
||||||
|
|
||||||
Testing
|
Testing
|
||||||
--------
|
--------
|
||||||
|
|||||||
23
doc/_themes/sphinx13/static/sphinx13.css
vendored
23
doc/_themes/sphinx13/static/sphinx13.css
vendored
@@ -337,7 +337,7 @@ a tt:hover {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pre {
|
pre {
|
||||||
font-family: 'Consolas', 'DejaVu Sans Mono',
|
font-family: 'Consolas', 'Courier New', 'DejaVu Sans Mono',
|
||||||
'Bitstream Vera Sans Mono', monospace;
|
'Bitstream Vera Sans Mono', monospace;
|
||||||
font-size: 13px;
|
font-size: 13px;
|
||||||
letter-spacing: 0.015em;
|
letter-spacing: 0.015em;
|
||||||
@@ -388,32 +388,29 @@ div.admonition, div.warning {
|
|||||||
padding: 0;
|
padding: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
div.admonition p, div.warning p {
|
div.admonition > p, div.warning > p {
|
||||||
margin: 0.5em 1em 0.5em 1em;
|
margin: 0.5em 1em 0.5em 1em;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
div.admonition pre, div.warning pre {
|
div.admonition > pre, div.warning > pre {
|
||||||
margin: 0.4em 1em 0.4em 1em;
|
margin: 0.4em 1em 0.4em 1em;
|
||||||
}
|
}
|
||||||
|
|
||||||
div.admonition p.admonition-title,
|
div.admonition > p.admonition-title,
|
||||||
div.warning p.admonition-title {
|
div.warning > p.admonition-title {
|
||||||
margin-top: 1em;
|
margin-top: 0.5em;
|
||||||
padding-top: 0.5em;
|
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
}
|
}
|
||||||
|
|
||||||
div.warning {
|
div.warning {
|
||||||
border: 1px solid #940000;
|
border: 1px solid #940000;
|
||||||
/* background-color: #FFCCCF;*/
|
|
||||||
}
|
}
|
||||||
|
|
||||||
div.warning p.admonition-title {
|
div.admonition > ul,
|
||||||
}
|
div.admonition > ol,
|
||||||
|
div.warning > ul,
|
||||||
div.admonition ul, div.admonition ol,
|
div.warning > ol {
|
||||||
div.warning ul, div.warning ol {
|
|
||||||
margin: 0.1em 0.5em 0.5em 3em;
|
margin: 0.1em 0.5em 0.5em 3em;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -295,6 +295,11 @@ The following is a list of deprecated interfaces.
|
|||||||
- 4.0
|
- 4.0
|
||||||
- ``sphinx.builders.singlehtml.SingleFileHTMLBuilder``
|
- ``sphinx.builders.singlehtml.SingleFileHTMLBuilder``
|
||||||
|
|
||||||
|
* - ``sphinx.builders.htmlhelp``
|
||||||
|
- 2.0
|
||||||
|
- 4.0
|
||||||
|
- ``sphinxcontrib.htmlhelp``
|
||||||
|
|
||||||
* - ``sphinx.builders.htmlhelp.HTMLHelpBuilder.open_file()``
|
* - ``sphinx.builders.htmlhelp.HTMLHelpBuilder.open_file()``
|
||||||
- 2.0
|
- 2.0
|
||||||
- 4.0
|
- 4.0
|
||||||
@@ -370,6 +375,31 @@ The following is a list of deprecated interfaces.
|
|||||||
- 4.0
|
- 4.0
|
||||||
- ``sphinxcontrib.jsmath``
|
- ``sphinxcontrib.jsmath``
|
||||||
|
|
||||||
|
* - ``sphinx.roles.abbr_role()``
|
||||||
|
- 2.0
|
||||||
|
- 4.0
|
||||||
|
- ``sphinx.roles.Abbreviation``
|
||||||
|
|
||||||
|
* - ``sphinx.roles.emph_literal_role()``
|
||||||
|
- 2.0
|
||||||
|
- 4.0
|
||||||
|
- ``sphinx.roles.EmphasizedLiteral``
|
||||||
|
|
||||||
|
* - ``sphinx.roles.menusel_role()``
|
||||||
|
- 2.0
|
||||||
|
- 4.0
|
||||||
|
- ``sphinx.roles.GUILabel`` or ``sphinx.roles.MenuSelection``
|
||||||
|
|
||||||
|
* - ``sphinx.roles.index_role()``
|
||||||
|
- 2.0
|
||||||
|
- 4.0
|
||||||
|
- ``sphinx.roles.Index``
|
||||||
|
|
||||||
|
* - ``sphinx.roles.indexmarkup_role()``
|
||||||
|
- 2.0
|
||||||
|
- 4.0
|
||||||
|
- ``sphinx.roles.PEP`` or ``sphinx.roles.RFC``
|
||||||
|
|
||||||
* - ``sphinx.testing.util.remove_unicode_literal()``
|
* - ``sphinx.testing.util.remove_unicode_literal()``
|
||||||
- 2.0
|
- 2.0
|
||||||
- 4.0
|
- 4.0
|
||||||
@@ -420,6 +450,11 @@ The following is a list of deprecated interfaces.
|
|||||||
- 4.0
|
- 4.0
|
||||||
- ``os.walk()``
|
- ``os.walk()``
|
||||||
|
|
||||||
|
* - ``sphinx.util.pycompat.NoneType``
|
||||||
|
- 2.0
|
||||||
|
- 4.0
|
||||||
|
- ``sphinx.util.typing.NoneType``
|
||||||
|
|
||||||
* - ``sphinx.util.pycompat.TextIOWrapper``
|
* - ``sphinx.util.pycompat.TextIOWrapper``
|
||||||
- 2.0
|
- 2.0
|
||||||
- 4.0
|
- 4.0
|
||||||
@@ -440,6 +475,16 @@ The following is a list of deprecated interfaces.
|
|||||||
- 4.0
|
- 4.0
|
||||||
- ``textwrap.indent()``
|
- ``textwrap.indent()``
|
||||||
|
|
||||||
|
* - ``sphinx.util.pycompat.sys_encoding``
|
||||||
|
- 2.0
|
||||||
|
- 4.0
|
||||||
|
- ``sys.getdefaultencoding()``
|
||||||
|
|
||||||
|
* - ``sphinx.util.pycompat.terminal_safe()``
|
||||||
|
- 2.0
|
||||||
|
- 4.0
|
||||||
|
- ``sphinx.util.console.terminal_safe()``
|
||||||
|
|
||||||
* - ``sphinx.util.pycompat.u``
|
* - ``sphinx.util.pycompat.u``
|
||||||
- 2.0
|
- 2.0
|
||||||
- 4.0
|
- 4.0
|
||||||
|
|||||||
@@ -18,5 +18,11 @@ components (e.g. :class:`.Config`, :class:`.BuildEnvironment` and so on) easily.
|
|||||||
.. autoclass:: sphinx.util.docutils.SphinxDirective
|
.. autoclass:: sphinx.util.docutils.SphinxDirective
|
||||||
:members:
|
:members:
|
||||||
|
|
||||||
|
.. autoclass:: sphinx.util.docutils.SphinxRole
|
||||||
|
:members:
|
||||||
|
|
||||||
|
.. autoclass:: sphinx.util.docutils.ReferenceRole
|
||||||
|
:members:
|
||||||
|
|
||||||
.. autoclass:: sphinx.transforms.post_transforms.images.ImageConverter
|
.. autoclass:: sphinx.transforms.post_transforms.images.ImageConverter
|
||||||
:members:
|
:members:
|
||||||
|
|||||||
@@ -28,6 +28,7 @@ The builder's "name" must be given to the **-b** command-line option of
|
|||||||
|
|
||||||
.. autoattribute:: supported_image_types
|
.. autoattribute:: supported_image_types
|
||||||
|
|
||||||
|
.. module:: sphinx.builders.dirhtml
|
||||||
.. class:: DirectoryHTMLBuilder
|
.. class:: DirectoryHTMLBuilder
|
||||||
|
|
||||||
This is a subclass of the standard HTML builder. Its output is a directory
|
This is a subclass of the standard HTML builder. Its output is a directory
|
||||||
@@ -45,6 +46,7 @@ The builder's "name" must be given to the **-b** command-line option of
|
|||||||
|
|
||||||
.. versionadded:: 0.6
|
.. versionadded:: 0.6
|
||||||
|
|
||||||
|
.. module:: sphinx.builders.singlehtml
|
||||||
.. class:: SingleFileHTMLBuilder
|
.. class:: SingleFileHTMLBuilder
|
||||||
|
|
||||||
This is an HTML builder that combines the whole project in one output file.
|
This is an HTML builder that combines the whole project in one output file.
|
||||||
|
|||||||
@@ -1331,6 +1331,12 @@ that use Sphinx's HTMLWriter class.
|
|||||||
|
|
||||||
.. versionadded:: 1.6
|
.. versionadded:: 1.6
|
||||||
|
|
||||||
|
.. deprecated:: 2.0
|
||||||
|
|
||||||
|
.. confval:: html4_writer
|
||||||
|
|
||||||
|
Output is processed with HTML4 writer. Default is ``False``.
|
||||||
|
|
||||||
Options for Single HTML output
|
Options for Single HTML output
|
||||||
-------------------------------
|
-------------------------------
|
||||||
|
|
||||||
|
|||||||
@@ -376,12 +376,12 @@ There are also new config values that you can set:
|
|||||||
'members': 'var1, var2',
|
'members': 'var1, var2',
|
||||||
'member-order': 'bysource',
|
'member-order': 'bysource',
|
||||||
'special-members': '__init__',
|
'special-members': '__init__',
|
||||||
'undoc-members': None,
|
'undoc-members': True,
|
||||||
'exclude-members': '__weakref__'
|
'exclude-members': '__weakref__'
|
||||||
}
|
}
|
||||||
|
|
||||||
Setting ``None`` is equivalent to giving the option name in the list format
|
Setting ``None`` or ``True`` to the value is equivalent to giving only the
|
||||||
(i.e. it means "yes/true/on").
|
option name to the directives.
|
||||||
|
|
||||||
The supported options are ``'members'``, ``'member-order'``,
|
The supported options are ``'members'``, ``'member-order'``,
|
||||||
``'undoc-members'``, ``'private-members'``, ``'special-members'``,
|
``'undoc-members'``, ``'private-members'``, ``'special-members'``,
|
||||||
@@ -390,6 +390,9 @@ There are also new config values that you can set:
|
|||||||
|
|
||||||
.. versionadded:: 1.8
|
.. versionadded:: 1.8
|
||||||
|
|
||||||
|
.. versionchanged:: 2.0
|
||||||
|
Accepts ``True`` as a value.
|
||||||
|
|
||||||
.. confval:: autodoc_docstring_signature
|
.. confval:: autodoc_docstring_signature
|
||||||
|
|
||||||
Functions imported from C modules cannot be introspected, and therefore the
|
Functions imported from C modules cannot be introspected, and therefore the
|
||||||
|
|||||||
@@ -38,3 +38,10 @@ Configuration
|
|||||||
called ``Introduction`` that appears in document ``index.rst``. Useful for
|
called ``Introduction`` that appears in document ``index.rst``. Useful for
|
||||||
avoiding ambiguity when the same section heading appears in different
|
avoiding ambiguity when the same section heading appears in different
|
||||||
documents.
|
documents.
|
||||||
|
|
||||||
|
.. confval:: autosectionlabel_maxdepth
|
||||||
|
|
||||||
|
If set, autosectionlabel chooses the sections for labeling by its depth. For
|
||||||
|
example, when set 1 to ``autosectionlabel_maxdepth``, labels are generated
|
||||||
|
only for top level sections, and deeper sections are not labeled. It
|
||||||
|
defaults to ``None`` (disabled).
|
||||||
|
|||||||
@@ -143,6 +143,11 @@ also use this new config value:
|
|||||||
The new files will be placed in the directories specified in the
|
The new files will be placed in the directories specified in the
|
||||||
``:toctree:`` options of the directives.
|
``:toctree:`` options of the directives.
|
||||||
|
|
||||||
|
.. confval:: autosummary_mock_imports
|
||||||
|
|
||||||
|
This value contains a list of modules to be mocked up. See
|
||||||
|
:confval:`autodoc_mock_imports` for more details. It defaults to
|
||||||
|
:confval:`autodoc_mock_imports`.
|
||||||
|
|
||||||
Customizing templates
|
Customizing templates
|
||||||
---------------------
|
---------------------
|
||||||
|
|||||||
@@ -6,5 +6,11 @@
|
|||||||
|
|
||||||
.. versionadded:: 1.4
|
.. versionadded:: 1.4
|
||||||
|
|
||||||
|
.. versionchanged:: 2.0
|
||||||
|
Support ``CNAME`` file
|
||||||
|
|
||||||
This extension creates ``.nojekyll`` file on generated HTML directory to publish
|
This extension creates ``.nojekyll`` file on generated HTML directory to publish
|
||||||
the document on GitHub Pages.
|
the document on GitHub Pages.
|
||||||
|
|
||||||
|
It also creates a ``CNAME`` file for custom domains when :confval:`html_baseurl`
|
||||||
|
set.
|
||||||
|
|||||||
1
setup.py
1
setup.py
@@ -18,6 +18,7 @@ install_requires = [
|
|||||||
'sphinxcontrib-applehelp',
|
'sphinxcontrib-applehelp',
|
||||||
'sphinxcontrib-devhelp',
|
'sphinxcontrib-devhelp',
|
||||||
'sphinxcontrib-jsmath',
|
'sphinxcontrib-jsmath',
|
||||||
|
'sphinxcontrib-htmlhelp',
|
||||||
'sphinxcontrib-qthelp',
|
'sphinxcontrib-qthelp',
|
||||||
'Jinja2>=2.3',
|
'Jinja2>=2.3',
|
||||||
'Pygments>=2.0',
|
'Pygments>=2.0',
|
||||||
|
|||||||
@@ -37,7 +37,6 @@ from sphinx.registry import SphinxComponentRegistry
|
|||||||
from sphinx.util import docutils
|
from sphinx.util import docutils
|
||||||
from sphinx.util import import_object, progress_message
|
from sphinx.util import import_object, progress_message
|
||||||
from sphinx.util import logging
|
from sphinx.util import logging
|
||||||
from sphinx.util import pycompat # noqa: F401
|
|
||||||
from sphinx.util.build_phase import BuildPhase
|
from sphinx.util.build_phase import BuildPhase
|
||||||
from sphinx.util.console import bold # type: ignore
|
from sphinx.util.console import bold # type: ignore
|
||||||
from sphinx.util.docutils import directive_helper
|
from sphinx.util.docutils import directive_helper
|
||||||
@@ -68,7 +67,6 @@ builtin_extensions = (
|
|||||||
'sphinx.builders.dummy',
|
'sphinx.builders.dummy',
|
||||||
'sphinx.builders.gettext',
|
'sphinx.builders.gettext',
|
||||||
'sphinx.builders.html',
|
'sphinx.builders.html',
|
||||||
'sphinx.builders.htmlhelp',
|
|
||||||
'sphinx.builders.latex',
|
'sphinx.builders.latex',
|
||||||
'sphinx.builders.linkcheck',
|
'sphinx.builders.linkcheck',
|
||||||
'sphinx.builders.manpage',
|
'sphinx.builders.manpage',
|
||||||
@@ -108,6 +106,7 @@ builtin_extensions = (
|
|||||||
# 1st party extensions
|
# 1st party extensions
|
||||||
'sphinxcontrib.applehelp',
|
'sphinxcontrib.applehelp',
|
||||||
'sphinxcontrib.devhelp',
|
'sphinxcontrib.devhelp',
|
||||||
|
'sphinxcontrib.htmlhelp',
|
||||||
'sphinxcontrib.qthelp',
|
'sphinxcontrib.qthelp',
|
||||||
# Strictly, alabaster theme is not a builtin extension,
|
# Strictly, alabaster theme is not a builtin extension,
|
||||||
# but it is loaded automatically to use it as default theme.
|
# but it is loaded automatically to use it as default theme.
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ from sphinx.environment.adapters.asset import ImageAdapter
|
|||||||
from sphinx.errors import SphinxError
|
from sphinx.errors import SphinxError
|
||||||
from sphinx.io import read_doc
|
from sphinx.io import read_doc
|
||||||
from sphinx.locale import __
|
from sphinx.locale import __
|
||||||
from sphinx.util import i18n, import_object, logging, rst, status_iterator
|
from sphinx.util import i18n, import_object, logging, rst, progress_message, status_iterator
|
||||||
from sphinx.util.build_phase import BuildPhase
|
from sphinx.util.build_phase import BuildPhase
|
||||||
from sphinx.util.console import bold # type: ignore
|
from sphinx.util.console import bold # type: ignore
|
||||||
from sphinx.util.docutils import sphinx_domains
|
from sphinx.util.docutils import sphinx_domains
|
||||||
@@ -351,16 +351,14 @@ class Builder:
|
|||||||
if updated_docnames:
|
if updated_docnames:
|
||||||
# save the environment
|
# save the environment
|
||||||
from sphinx.application import ENV_PICKLE_FILENAME
|
from sphinx.application import ENV_PICKLE_FILENAME
|
||||||
logger.info(bold(__('pickling environment... ')), nonl=True)
|
with progress_message(__('pickling environment')):
|
||||||
with open(path.join(self.doctreedir, ENV_PICKLE_FILENAME), 'wb') as f:
|
with open(path.join(self.doctreedir, ENV_PICKLE_FILENAME), 'wb') as f:
|
||||||
pickle.dump(self.env, f, pickle.HIGHEST_PROTOCOL)
|
pickle.dump(self.env, f, pickle.HIGHEST_PROTOCOL)
|
||||||
logger.info(__('done'))
|
|
||||||
|
|
||||||
# global actions
|
# global actions
|
||||||
self.app.phase = BuildPhase.CONSISTENCY_CHECK
|
self.app.phase = BuildPhase.CONSISTENCY_CHECK
|
||||||
logger.info(bold(__('checking consistency... ')), nonl=True)
|
with progress_message(__('checking consistency')):
|
||||||
self.env.check_consistency()
|
self.env.check_consistency()
|
||||||
logger.info(__('done'))
|
|
||||||
else:
|
else:
|
||||||
if method == 'update' and not docnames:
|
if method == 'update' and not docnames:
|
||||||
logger.info(bold(__('no targets are out of date.')))
|
logger.info(bold(__('no targets are out of date.')))
|
||||||
@@ -559,9 +557,8 @@ class Builder:
|
|||||||
docnames.add(tocdocname)
|
docnames.add(tocdocname)
|
||||||
docnames.add(self.config.master_doc)
|
docnames.add(self.config.master_doc)
|
||||||
|
|
||||||
logger.info(bold(__('preparing documents... ')), nonl=True)
|
with progress_message(__('preparing documents')):
|
||||||
self.prepare_writing(docnames)
|
self.prepare_writing(docnames)
|
||||||
logger.info(__('done'))
|
|
||||||
|
|
||||||
if self.parallel_ok:
|
if self.parallel_ok:
|
||||||
# number of subprocesses is parallel-1 because the main process
|
# number of subprocesses is parallel-1 because the main process
|
||||||
|
|||||||
@@ -134,8 +134,6 @@ class EpubBuilder(StandaloneHTMLBuilder):
|
|||||||
html_scaled_image_link = False
|
html_scaled_image_link = False
|
||||||
# don't generate search index or include search page
|
# don't generate search index or include search page
|
||||||
search = False
|
search = False
|
||||||
# use html5 translator by default
|
|
||||||
default_html5_translator = True
|
|
||||||
|
|
||||||
coverpage_name = COVERPAGE_NAME
|
coverpage_name = COVERPAGE_NAME
|
||||||
toctree_template = TOCTREE_TEMPLATE
|
toctree_template = TOCTREE_TEMPLATE
|
||||||
@@ -655,7 +653,7 @@ class EpubBuilder(StandaloneHTMLBuilder):
|
|||||||
if incr:
|
if incr:
|
||||||
self.playorder += 1
|
self.playorder += 1
|
||||||
self.tocid += 1
|
self.tocid += 1
|
||||||
return NavPoint(self.esc('navPoint%d' % self.tocid), self.playorder,
|
return NavPoint('navPoint%d' % self.tocid, self.playorder,
|
||||||
node['text'], node['refuri'], [])
|
node['text'], node['refuri'], [])
|
||||||
|
|
||||||
def build_navpoints(self, nodes):
|
def build_navpoints(self, nodes):
|
||||||
|
|||||||
@@ -18,7 +18,6 @@ import warnings
|
|||||||
from hashlib import md5
|
from hashlib import md5
|
||||||
from os import path
|
from os import path
|
||||||
|
|
||||||
import docutils
|
|
||||||
from docutils import nodes
|
from docutils import nodes
|
||||||
from docutils.core import publish_parts
|
from docutils.core import publish_parts
|
||||||
from docutils.frontend import OptionParser
|
from docutils.frontend import OptionParser
|
||||||
@@ -58,7 +57,7 @@ if False:
|
|||||||
from sphinx.domains import Domain, Index, IndexEntry # NOQA
|
from sphinx.domains import Domain, Index, IndexEntry # NOQA
|
||||||
from sphinx.util.tags import Tags # NOQA
|
from sphinx.util.tags import Tags # NOQA
|
||||||
|
|
||||||
# Experimental HTML5 Writer
|
# HTML5 Writer is avialable or not
|
||||||
if is_html5_writer_available():
|
if is_html5_writer_available():
|
||||||
from sphinx.writers.html5 import HTML5Translator
|
from sphinx.writers.html5 import HTML5Translator
|
||||||
html5_ready = True
|
html5_ready = True
|
||||||
@@ -242,8 +241,6 @@ class StandaloneHTMLBuilder(Builder):
|
|||||||
search = True # for things like HTML help and Apple help: suppress search
|
search = True # for things like HTML help and Apple help: suppress search
|
||||||
use_index = False
|
use_index = False
|
||||||
download_support = True # enable download role
|
download_support = True # enable download role
|
||||||
# use html5 translator by default
|
|
||||||
default_html5_translator = False
|
|
||||||
|
|
||||||
imgpath = None # type: str
|
imgpath = None # type: str
|
||||||
domain_indices = [] # type: List[Tuple[str, Type[Index], List[Tuple[str, List[IndexEntry]]], bool]] # NOQA
|
domain_indices = [] # type: List[Tuple[str, Type[Index], List[Tuple[str, List[IndexEntry]]], bool]] # NOQA
|
||||||
@@ -285,11 +282,6 @@ class StandaloneHTMLBuilder(Builder):
|
|||||||
|
|
||||||
self.use_index = self.get_builder_config('use_index', 'html')
|
self.use_index = self.get_builder_config('use_index', 'html')
|
||||||
|
|
||||||
if self.config.html_experimental_html5_writer and not html5_ready:
|
|
||||||
logger.warning(__('html_experimental_html5_writer is set, but current version '
|
|
||||||
'is old. Docutils\' version should be 0.13 or newer, but %s.'),
|
|
||||||
docutils.__version__)
|
|
||||||
|
|
||||||
def create_build_info(self):
|
def create_build_info(self):
|
||||||
# type: () -> BuildInfo
|
# type: () -> BuildInfo
|
||||||
return BuildInfo(self.config, self.tags, ['html'])
|
return BuildInfo(self.config, self.tags, ['html'])
|
||||||
@@ -374,14 +366,10 @@ class StandaloneHTMLBuilder(Builder):
|
|||||||
@property
|
@property
|
||||||
def default_translator_class(self): # type: ignore
|
def default_translator_class(self): # type: ignore
|
||||||
# type: () -> Type[nodes.NodeVisitor]
|
# type: () -> Type[nodes.NodeVisitor]
|
||||||
use_html5_writer = self.config.html_experimental_html5_writer
|
if not html5_ready or self.config.html4_writer:
|
||||||
if use_html5_writer is None:
|
|
||||||
use_html5_writer = self.default_html5_translator
|
|
||||||
|
|
||||||
if use_html5_writer and html5_ready:
|
|
||||||
return HTML5Translator
|
|
||||||
else:
|
|
||||||
return HTMLTranslator
|
return HTMLTranslator
|
||||||
|
else:
|
||||||
|
return HTML5Translator
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def math_renderer_name(self):
|
def math_renderer_name(self):
|
||||||
@@ -562,7 +550,7 @@ class StandaloneHTMLBuilder(Builder):
|
|||||||
'parents': [],
|
'parents': [],
|
||||||
'logo': logo,
|
'logo': logo,
|
||||||
'favicon': favicon,
|
'favicon': favicon,
|
||||||
'html5_doctype': self.config.html_experimental_html5_writer and html5_ready,
|
'html5_doctype': html5_ready and not self.config.html4_writer
|
||||||
}
|
}
|
||||||
if self.theme:
|
if self.theme:
|
||||||
self.globalcontext.update(
|
self.globalcontext.update(
|
||||||
@@ -1440,9 +1428,9 @@ def setup(app):
|
|||||||
app.add_config_value('html_search_options', {}, 'html')
|
app.add_config_value('html_search_options', {}, 'html')
|
||||||
app.add_config_value('html_search_scorer', '', None)
|
app.add_config_value('html_search_scorer', '', None)
|
||||||
app.add_config_value('html_scaled_image_link', True, 'html')
|
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_baseurl', '', 'html')
|
||||||
app.add_config_value('html_math_renderer', None, 'env')
|
app.add_config_value('html_math_renderer', None, 'env')
|
||||||
|
app.add_config_value('html4_writer', False, 'html')
|
||||||
|
|
||||||
# event handlers
|
# event handlers
|
||||||
app.connect('config-inited', convert_html_css_files)
|
app.connect('config-inited', convert_html_css_files)
|
||||||
|
|||||||
@@ -9,364 +9,36 @@
|
|||||||
:license: BSD, see LICENSE for details.
|
:license: BSD, see LICENSE for details.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
import html
|
|
||||||
import os
|
|
||||||
import warnings
|
import warnings
|
||||||
from os import path
|
|
||||||
|
|
||||||
from docutils import nodes
|
from sphinxcontrib.htmlhelp import (
|
||||||
|
chm_locales, chm_htmlescape, HTMLHelpBuilder, default_htmlhelp_basename
|
||||||
|
)
|
||||||
|
|
||||||
|
from sphinx.deprecation import RemovedInSphinx40Warning, deprecated_alias
|
||||||
|
|
||||||
from sphinx import addnodes
|
|
||||||
from sphinx.builders.html import StandaloneHTMLBuilder
|
|
||||||
from sphinx.deprecation import RemovedInSphinx40Warning
|
|
||||||
from sphinx.environment.adapters.indexentries import IndexEntries
|
|
||||||
from sphinx.locale import __
|
|
||||||
from sphinx.util import logging
|
|
||||||
from sphinx.util.nodes import NodeMatcher
|
|
||||||
from sphinx.util.osutil import make_filename_from_project
|
|
||||||
|
|
||||||
if False:
|
if False:
|
||||||
# For type annotation
|
# For type annotation
|
||||||
from typing import Any, Dict, IO, List, Match, Tuple # NOQA
|
from typing import Any, Dict # NOQA
|
||||||
from sphinx.application import Sphinx # NOQA
|
from sphinx.application import Sphinx # NOQA
|
||||||
from sphinx.config import Config # NOQA
|
|
||||||
|
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
deprecated_alias('sphinx.builders.devhelp',
|
||||||
|
{
|
||||||
|
'chm_locales': chm_locales,
|
||||||
# Project file (*.hhp) template. 'outname' is the file basename (like
|
'chm_htmlescape': chm_htmlescape,
|
||||||
# the pythlp in pythlp.hhp); 'version' is the doc version number (like
|
'HTMLHelpBuilder': HTMLHelpBuilder,
|
||||||
# the 2.2 in Python 2.2).
|
'default_htmlhelp_basename': default_htmlhelp_basename,
|
||||||
# The magical numbers in the long line under [WINDOWS] set most of the
|
},
|
||||||
# user-visible features (visible buttons, tabs, etc).
|
RemovedInSphinx40Warning)
|
||||||
# About 0x10384e: This defines the buttons in the help viewer. The
|
|
||||||
# following defns are taken from htmlhelp.h. Not all possibilities
|
|
||||||
# actually work, and not all those that work are available from the Help
|
|
||||||
# Workshop GUI. In particular, the Zoom/Font button works and is not
|
|
||||||
# available from the GUI. The ones we're using are marked with 'x':
|
|
||||||
#
|
|
||||||
# 0x000002 Hide/Show x
|
|
||||||
# 0x000004 Back x
|
|
||||||
# 0x000008 Forward x
|
|
||||||
# 0x000010 Stop
|
|
||||||
# 0x000020 Refresh
|
|
||||||
# 0x000040 Home x
|
|
||||||
# 0x000080 Forward
|
|
||||||
# 0x000100 Back
|
|
||||||
# 0x000200 Notes
|
|
||||||
# 0x000400 Contents
|
|
||||||
# 0x000800 Locate x
|
|
||||||
# 0x001000 Options x
|
|
||||||
# 0x002000 Print x
|
|
||||||
# 0x004000 Index
|
|
||||||
# 0x008000 Search
|
|
||||||
# 0x010000 History
|
|
||||||
# 0x020000 Favorites
|
|
||||||
# 0x040000 Jump 1
|
|
||||||
# 0x080000 Jump 2
|
|
||||||
# 0x100000 Zoom/Font x
|
|
||||||
# 0x200000 TOC Next
|
|
||||||
# 0x400000 TOC Prev
|
|
||||||
|
|
||||||
project_template = '''\
|
|
||||||
[OPTIONS]
|
|
||||||
Binary TOC=No
|
|
||||||
Binary Index=No
|
|
||||||
Compiled file=%(outname)s.chm
|
|
||||||
Contents file=%(outname)s.hhc
|
|
||||||
Default Window=%(outname)s
|
|
||||||
Default topic=%(master_doc)s
|
|
||||||
Display compile progress=No
|
|
||||||
Full text search stop list file=%(outname)s.stp
|
|
||||||
Full-text search=Yes
|
|
||||||
Index file=%(outname)s.hhk
|
|
||||||
Language=%(lcid)#x
|
|
||||||
Title=%(title)s
|
|
||||||
|
|
||||||
[WINDOWS]
|
|
||||||
%(outname)s="%(title)s","%(outname)s.hhc","%(outname)s.hhk",\
|
|
||||||
"%(master_doc)s","%(master_doc)s",,,,,0x63520,220,0x10384e,[0,0,1024,768],,,,,,,0
|
|
||||||
|
|
||||||
[FILES]
|
|
||||||
'''
|
|
||||||
|
|
||||||
contents_header = '''\
|
|
||||||
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
|
|
||||||
<HTML>
|
|
||||||
<HEAD>
|
|
||||||
<meta name="GENERATOR" content="Microsoft® HTML Help Workshop 4.1">
|
|
||||||
<!-- Sitemap 1.0 -->
|
|
||||||
</HEAD><BODY>
|
|
||||||
<OBJECT type="text/site properties">
|
|
||||||
<param name="Window Styles" value="0x801227">
|
|
||||||
<param name="ImageType" value="Folder">
|
|
||||||
</OBJECT>
|
|
||||||
<UL>
|
|
||||||
'''
|
|
||||||
|
|
||||||
contents_footer = '''\
|
|
||||||
</UL></BODY></HTML>
|
|
||||||
'''
|
|
||||||
|
|
||||||
object_sitemap = '''\
|
|
||||||
<OBJECT type="text/sitemap">
|
|
||||||
<param name="Name" value="%s">
|
|
||||||
<param name="Local" value="%s">
|
|
||||||
</OBJECT>
|
|
||||||
'''
|
|
||||||
|
|
||||||
# List of words the full text search facility shouldn't index. This
|
|
||||||
# becomes file outname.stp. Note that this list must be pretty small!
|
|
||||||
# Different versions of the MS docs claim the file has a maximum size of
|
|
||||||
# 256 or 512 bytes (including \r\n at the end of each line).
|
|
||||||
# Note that "and", "or", "not" and "near" are operators in the search
|
|
||||||
# language, so no point indexing them even if we wanted to.
|
|
||||||
stopwords = """
|
|
||||||
a and are as at
|
|
||||||
be but by
|
|
||||||
for
|
|
||||||
if in into is it
|
|
||||||
near no not
|
|
||||||
of on or
|
|
||||||
such
|
|
||||||
that the their then there these they this to
|
|
||||||
was will with
|
|
||||||
""".split()
|
|
||||||
|
|
||||||
# The following list includes only languages supported by Sphinx. See
|
|
||||||
# https://docs.microsoft.com/en-us/previous-versions/windows/embedded/ms930130(v=msdn.10)
|
|
||||||
# for more.
|
|
||||||
chm_locales = {
|
|
||||||
# lang: LCID, encoding
|
|
||||||
'ca': (0x403, 'cp1252'),
|
|
||||||
'cs': (0x405, 'cp1250'),
|
|
||||||
'da': (0x406, 'cp1252'),
|
|
||||||
'de': (0x407, 'cp1252'),
|
|
||||||
'en': (0x409, 'cp1252'),
|
|
||||||
'es': (0x40a, 'cp1252'),
|
|
||||||
'et': (0x425, 'cp1257'),
|
|
||||||
'fa': (0x429, 'cp1256'),
|
|
||||||
'fi': (0x40b, 'cp1252'),
|
|
||||||
'fr': (0x40c, 'cp1252'),
|
|
||||||
'hr': (0x41a, 'cp1250'),
|
|
||||||
'hu': (0x40e, 'cp1250'),
|
|
||||||
'it': (0x410, 'cp1252'),
|
|
||||||
'ja': (0x411, 'cp932'),
|
|
||||||
'ko': (0x412, 'cp949'),
|
|
||||||
'lt': (0x427, 'cp1257'),
|
|
||||||
'lv': (0x426, 'cp1257'),
|
|
||||||
'nl': (0x413, 'cp1252'),
|
|
||||||
'no_NB': (0x414, 'cp1252'),
|
|
||||||
'pl': (0x415, 'cp1250'),
|
|
||||||
'pt_BR': (0x416, 'cp1252'),
|
|
||||||
'ru': (0x419, 'cp1251'),
|
|
||||||
'sk': (0x41b, 'cp1250'),
|
|
||||||
'sl': (0x424, 'cp1250'),
|
|
||||||
'sv': (0x41d, 'cp1252'),
|
|
||||||
'tr': (0x41f, 'cp1254'),
|
|
||||||
'uk_UA': (0x422, 'cp1251'),
|
|
||||||
'zh_CN': (0x804, 'cp936'),
|
|
||||||
'zh_TW': (0x404, 'cp950'),
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
def chm_htmlescape(s, quote=True):
|
|
||||||
# type: (str, bool) -> str
|
|
||||||
"""
|
|
||||||
chm_htmlescape() is a wrapper of html.escape().
|
|
||||||
.hhc/.hhk files don't recognize hex escaping, we need convert
|
|
||||||
hex escaping to decimal escaping. for example: ``'`` -> ``'``
|
|
||||||
html.escape() may generates a hex escaping ``'`` for single
|
|
||||||
quote ``'``, this wrapper fixes this.
|
|
||||||
"""
|
|
||||||
s = html.escape(s, quote)
|
|
||||||
s = s.replace(''', ''') # re-escape as decimal
|
|
||||||
return s
|
|
||||||
|
|
||||||
|
|
||||||
class HTMLHelpBuilder(StandaloneHTMLBuilder):
|
|
||||||
"""
|
|
||||||
Builder that also outputs Windows HTML help project, contents and
|
|
||||||
index files. Adapted from the original Doc/tools/prechm.py.
|
|
||||||
"""
|
|
||||||
name = 'htmlhelp'
|
|
||||||
epilog = __('You can now run HTML Help Workshop with the .htp file in '
|
|
||||||
'%(outdir)s.')
|
|
||||||
|
|
||||||
# don't copy the reST source
|
|
||||||
copysource = False
|
|
||||||
supported_image_types = ['image/png', 'image/gif', 'image/jpeg']
|
|
||||||
|
|
||||||
# don't add links
|
|
||||||
add_permalinks = False
|
|
||||||
# don't add sidebar etc.
|
|
||||||
embedded = True
|
|
||||||
|
|
||||||
# don't generate search index or include search page
|
|
||||||
search = False
|
|
||||||
|
|
||||||
lcid = 0x409
|
|
||||||
encoding = 'cp1252'
|
|
||||||
|
|
||||||
def init(self):
|
|
||||||
# type: () -> None
|
|
||||||
# the output files for HTML help is .html by default
|
|
||||||
self.out_suffix = '.html'
|
|
||||||
self.link_suffix = '.html'
|
|
||||||
super().init()
|
|
||||||
# determine the correct locale setting
|
|
||||||
locale = chm_locales.get(self.config.language)
|
|
||||||
if locale is not None:
|
|
||||||
self.lcid, self.encoding = locale
|
|
||||||
|
|
||||||
def open_file(self, outdir, basename, mode='w'):
|
|
||||||
# type: (str, str, str) -> IO
|
|
||||||
# open a file with the correct encoding for the selected language
|
|
||||||
warnings.warn('HTMLHelpBuilder.open_file() is deprecated.',
|
|
||||||
RemovedInSphinx40Warning)
|
|
||||||
return open(path.join(outdir, basename), mode, encoding=self.encoding,
|
|
||||||
errors='xmlcharrefreplace')
|
|
||||||
|
|
||||||
def update_page_context(self, pagename, templatename, ctx, event_arg):
|
|
||||||
# type: (str, str, Dict, str) -> None
|
|
||||||
ctx['encoding'] = self.encoding
|
|
||||||
|
|
||||||
def handle_finish(self):
|
|
||||||
# type: () -> None
|
|
||||||
self.build_hhx(self.outdir, self.config.htmlhelp_basename)
|
|
||||||
|
|
||||||
def write_doc(self, docname, doctree):
|
|
||||||
# type: (str, nodes.document) -> None
|
|
||||||
for node in doctree.traverse(nodes.reference):
|
|
||||||
# add ``target=_blank`` attributes to external links
|
|
||||||
if node.get('internal') is None and 'refuri' in node:
|
|
||||||
node['target'] = '_blank'
|
|
||||||
|
|
||||||
super().write_doc(docname, doctree)
|
|
||||||
|
|
||||||
def build_hhx(self, outdir, outname):
|
|
||||||
# type: (str, str) -> None
|
|
||||||
logger.info(__('dumping stopword list...'))
|
|
||||||
filename = path.join(outdir, outname + '.stp')
|
|
||||||
with open(filename, 'w', encoding=self.encoding, errors='xmlcharrefreplace') as f:
|
|
||||||
for word in sorted(stopwords):
|
|
||||||
print(word, file=f)
|
|
||||||
|
|
||||||
logger.info(__('writing project file...'))
|
|
||||||
filename = path.join(outdir, outname + '.hhp')
|
|
||||||
with open(filename, 'w', encoding=self.encoding, errors='xmlcharrefreplace') as f:
|
|
||||||
f.write(project_template % {
|
|
||||||
'outname': outname,
|
|
||||||
'title': self.config.html_title,
|
|
||||||
'version': self.config.version,
|
|
||||||
'project': self.config.project,
|
|
||||||
'lcid': self.lcid,
|
|
||||||
'master_doc': self.config.master_doc + self.out_suffix
|
|
||||||
})
|
|
||||||
if not outdir.endswith(os.sep):
|
|
||||||
outdir += os.sep
|
|
||||||
olen = len(outdir)
|
|
||||||
for root, dirs, files in os.walk(outdir):
|
|
||||||
dirs.sort()
|
|
||||||
files.sort()
|
|
||||||
staticdir = root.startswith(path.join(outdir, '_static'))
|
|
||||||
for fn in sorted(files):
|
|
||||||
if (staticdir and not fn.endswith('.js')) or \
|
|
||||||
fn.endswith('.html'):
|
|
||||||
print(path.join(root, fn)[olen:].replace(os.sep, '\\'),
|
|
||||||
file=f)
|
|
||||||
|
|
||||||
logger.info(__('writing TOC file...'))
|
|
||||||
filename = path.join(outdir, outname + '.hhc')
|
|
||||||
with open(filename, 'w', encoding=self.encoding, errors='xmlcharrefreplace') as f:
|
|
||||||
f.write(contents_header)
|
|
||||||
# special books
|
|
||||||
f.write('<LI> ' + object_sitemap % (self.config.html_short_title,
|
|
||||||
self.config.master_doc + self.out_suffix))
|
|
||||||
for indexname, indexcls, content, collapse in self.domain_indices:
|
|
||||||
f.write('<LI> ' + object_sitemap % (indexcls.localname,
|
|
||||||
'%s.html' % indexname))
|
|
||||||
# the TOC
|
|
||||||
tocdoc = self.env.get_and_resolve_doctree(
|
|
||||||
self.config.master_doc, self, prune_toctrees=False)
|
|
||||||
|
|
||||||
def write_toc(node, ullevel=0):
|
|
||||||
# type: (nodes.Node, int) -> None
|
|
||||||
if isinstance(node, nodes.list_item):
|
|
||||||
f.write('<LI> ')
|
|
||||||
for subnode in node:
|
|
||||||
write_toc(subnode, ullevel)
|
|
||||||
elif isinstance(node, nodes.reference):
|
|
||||||
link = node['refuri']
|
|
||||||
title = chm_htmlescape(node.astext(), True)
|
|
||||||
f.write(object_sitemap % (title, link))
|
|
||||||
elif isinstance(node, nodes.bullet_list):
|
|
||||||
if ullevel != 0:
|
|
||||||
f.write('<UL>\n')
|
|
||||||
for subnode in node:
|
|
||||||
write_toc(subnode, ullevel + 1)
|
|
||||||
if ullevel != 0:
|
|
||||||
f.write('</UL>\n')
|
|
||||||
elif isinstance(node, addnodes.compact_paragraph):
|
|
||||||
for subnode in node:
|
|
||||||
write_toc(subnode, ullevel)
|
|
||||||
|
|
||||||
matcher = NodeMatcher(addnodes.compact_paragraph, toctree=True)
|
|
||||||
for node in tocdoc.traverse(matcher): # type: addnodes.compact_paragraph
|
|
||||||
write_toc(node)
|
|
||||||
f.write(contents_footer)
|
|
||||||
|
|
||||||
logger.info(__('writing index file...'))
|
|
||||||
index = IndexEntries(self.env).create_index(self)
|
|
||||||
filename = path.join(outdir, outname + '.hhk')
|
|
||||||
with open(filename, 'w', encoding=self.encoding, errors='xmlcharrefreplace') as f:
|
|
||||||
f.write('<UL>\n')
|
|
||||||
|
|
||||||
def write_index(title, refs, subitems):
|
|
||||||
# type: (str, List[Tuple[str, str]], List[Tuple[str, List[Tuple[str, str]]]]) -> None # NOQA
|
|
||||||
def write_param(name, value):
|
|
||||||
# type: (str, str) -> None
|
|
||||||
item = ' <param name="%s" value="%s">\n' % (name, value)
|
|
||||||
f.write(item)
|
|
||||||
title = chm_htmlescape(title, True)
|
|
||||||
f.write('<LI> <OBJECT type="text/sitemap">\n')
|
|
||||||
write_param('Keyword', title)
|
|
||||||
if len(refs) == 0:
|
|
||||||
write_param('See Also', title)
|
|
||||||
elif len(refs) == 1:
|
|
||||||
write_param('Local', refs[0][1])
|
|
||||||
else:
|
|
||||||
for i, ref in enumerate(refs):
|
|
||||||
# XXX: better title?
|
|
||||||
write_param('Name', '[%d] %s' % (i, ref[1]))
|
|
||||||
write_param('Local', ref[1])
|
|
||||||
f.write('</OBJECT>\n')
|
|
||||||
if subitems:
|
|
||||||
f.write('<UL> ')
|
|
||||||
for subitem in subitems:
|
|
||||||
write_index(subitem[0], subitem[1], [])
|
|
||||||
f.write('</UL>')
|
|
||||||
for (key, group) in index:
|
|
||||||
for title, (refs, subitems, key_) in group:
|
|
||||||
write_index(title, refs, subitems)
|
|
||||||
f.write('</UL>\n')
|
|
||||||
|
|
||||||
|
|
||||||
def default_htmlhelp_basename(config):
|
|
||||||
# type: (Config) -> str
|
|
||||||
"""Better default htmlhelp_basename setting."""
|
|
||||||
return make_filename_from_project(config.project) + 'doc'
|
|
||||||
|
|
||||||
|
|
||||||
def setup(app):
|
def setup(app):
|
||||||
# type: (Sphinx) -> Dict[str, Any]
|
# type: (Sphinx) -> Dict[str, Any]
|
||||||
app.setup_extension('sphinx.builders.html')
|
warnings.warn('sphinx.builders.htmlhelp has been moved to sphinxcontrib-htmlhelp.',
|
||||||
app.add_builder(HTMLHelpBuilder)
|
RemovedInSphinx40Warning)
|
||||||
|
app.setup_extension('sphinxcontrib.htmlhelp')
|
||||||
app.add_config_value('htmlhelp_basename', default_htmlhelp_basename, None)
|
|
||||||
app.add_config_value('htmlhelp_file_suffix', None, 'html', [str])
|
|
||||||
app.add_config_value('htmlhelp_link_suffix', None, 'html', [str])
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
'version': 'builtin',
|
'version': 'builtin',
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ from sphinx.environment.adapters.asset import ImageAdapter
|
|||||||
from sphinx.errors import SphinxError
|
from sphinx.errors import SphinxError
|
||||||
from sphinx.locale import _, __
|
from sphinx.locale import _, __
|
||||||
from sphinx.transforms import SphinxTransformer
|
from sphinx.transforms import SphinxTransformer
|
||||||
from sphinx.util import texescape, logging, status_iterator
|
from sphinx.util import texescape, logging, progress_message, status_iterator
|
||||||
from sphinx.util.console import bold, darkgreen # type: ignore
|
from sphinx.util.console import bold, darkgreen # type: ignore
|
||||||
from sphinx.util.docutils import SphinxFileOutput, new_document
|
from sphinx.util.docutils import SphinxFileOutput, new_document
|
||||||
from sphinx.util.fileutil import copy_asset_file
|
from sphinx.util.fileutil import copy_asset_file
|
||||||
@@ -250,33 +250,32 @@ class LaTeXBuilder(Builder):
|
|||||||
toctree_only = entry[5]
|
toctree_only = entry[5]
|
||||||
destination = SphinxFileOutput(destination_path=path.join(self.outdir, targetname),
|
destination = SphinxFileOutput(destination_path=path.join(self.outdir, targetname),
|
||||||
encoding='utf-8', overwrite_if_changed=True)
|
encoding='utf-8', overwrite_if_changed=True)
|
||||||
logger.info(__("processing %s..."), targetname, nonl=True)
|
with progress_message(__("processing %s") % targetname):
|
||||||
toctrees = self.env.get_doctree(docname).traverse(addnodes.toctree)
|
toctrees = self.env.get_doctree(docname).traverse(addnodes.toctree)
|
||||||
if toctrees:
|
if toctrees:
|
||||||
if toctrees[0].get('maxdepth') > 0:
|
if toctrees[0].get('maxdepth') > 0:
|
||||||
tocdepth = toctrees[0].get('maxdepth')
|
tocdepth = toctrees[0].get('maxdepth')
|
||||||
|
else:
|
||||||
|
tocdepth = None
|
||||||
else:
|
else:
|
||||||
tocdepth = None
|
tocdepth = None
|
||||||
else:
|
doctree = self.assemble_doctree(
|
||||||
tocdepth = None
|
docname, toctree_only,
|
||||||
doctree = self.assemble_doctree(
|
appendices=((docclass != 'howto') and self.config.latex_appendices or []))
|
||||||
docname, toctree_only,
|
doctree['tocdepth'] = tocdepth
|
||||||
appendices=((docclass != 'howto') and self.config.latex_appendices or []))
|
self.apply_transforms(doctree)
|
||||||
doctree['tocdepth'] = tocdepth
|
self.post_process_images(doctree)
|
||||||
self.apply_transforms(doctree)
|
self.update_doc_context(title, author)
|
||||||
self.post_process_images(doctree)
|
|
||||||
self.update_doc_context(title, author)
|
|
||||||
|
|
||||||
logger.info(__("writing... "), nonl=True)
|
with progress_message(__("writing")):
|
||||||
docsettings.author = author
|
docsettings.author = author
|
||||||
docsettings.title = title
|
docsettings.title = title
|
||||||
docsettings.contentsname = self.get_contentsname(docname)
|
docsettings.contentsname = self.get_contentsname(docname)
|
||||||
docsettings.docname = docname
|
docsettings.docname = docname
|
||||||
docsettings.docclass = docclass
|
docsettings.docclass = docclass
|
||||||
|
|
||||||
doctree.settings = docsettings
|
doctree.settings = docsettings
|
||||||
docwriter.write(doctree, destination)
|
docwriter.write(doctree, destination)
|
||||||
logger.info(__("done"))
|
|
||||||
|
|
||||||
def get_contentsname(self, indexfile):
|
def get_contentsname(self, indexfile):
|
||||||
# type: (str) -> str
|
# type: (str) -> str
|
||||||
@@ -354,8 +353,15 @@ class LaTeXBuilder(Builder):
|
|||||||
# type: () -> None
|
# type: () -> None
|
||||||
self.copy_image_files()
|
self.copy_image_files()
|
||||||
self.write_message_catalog()
|
self.write_message_catalog()
|
||||||
|
self.copy_support_files()
|
||||||
|
|
||||||
# copy TeX support files from texinputs
|
if self.config.latex_additional_files:
|
||||||
|
self.copy_latex_additional_files()
|
||||||
|
|
||||||
|
@progress_message(__('copying TeX support files'))
|
||||||
|
def copy_support_files(self):
|
||||||
|
# type: () -> None
|
||||||
|
"""copy TeX support files from texinputs."""
|
||||||
# configure usage of xindy (impacts Makefile and latexmkrc)
|
# configure usage of xindy (impacts Makefile and latexmkrc)
|
||||||
# FIXME: convert this rather to a confval with suitable default
|
# FIXME: convert this rather to a confval with suitable default
|
||||||
# according to language ? but would require extra documentation
|
# according to language ? but would require extra documentation
|
||||||
@@ -386,21 +392,19 @@ class LaTeXBuilder(Builder):
|
|||||||
copy_asset_file(path.join(staticdirname, 'Makefile_t'),
|
copy_asset_file(path.join(staticdirname, 'Makefile_t'),
|
||||||
self.outdir, context=context)
|
self.outdir, context=context)
|
||||||
|
|
||||||
# copy additional files
|
|
||||||
if self.config.latex_additional_files:
|
|
||||||
logger.info(bold(__('copying additional files...')), nonl=True)
|
|
||||||
for filename in self.config.latex_additional_files:
|
|
||||||
logger.info(' ' + filename, nonl=True)
|
|
||||||
copy_asset_file(path.join(self.confdir, filename), self.outdir)
|
|
||||||
logger.info('')
|
|
||||||
|
|
||||||
# the logo is handled differently
|
# the logo is handled differently
|
||||||
if self.config.latex_logo:
|
if self.config.latex_logo:
|
||||||
if not path.isfile(path.join(self.confdir, self.config.latex_logo)):
|
if not path.isfile(path.join(self.confdir, self.config.latex_logo)):
|
||||||
raise SphinxError(__('logo file %r does not exist') % self.config.latex_logo)
|
raise SphinxError(__('logo file %r does not exist') % self.config.latex_logo)
|
||||||
else:
|
else:
|
||||||
copy_asset_file(path.join(self.confdir, self.config.latex_logo), self.outdir)
|
copy_asset_file(path.join(self.confdir, self.config.latex_logo), self.outdir)
|
||||||
logger.info(__('done'))
|
|
||||||
|
@progress_message(__('copying additional files'))
|
||||||
|
def copy_latex_additional_files(self):
|
||||||
|
# type: () -> None
|
||||||
|
for filename in self.config.latex_additional_files:
|
||||||
|
logger.info(' ' + filename, nonl=True)
|
||||||
|
copy_asset_file(path.join(self.confdir, filename), self.outdir)
|
||||||
|
|
||||||
def copy_image_files(self):
|
def copy_image_files(self):
|
||||||
# type: () -> None
|
# type: () -> None
|
||||||
@@ -439,7 +443,7 @@ def validate_config_values(app, config):
|
|||||||
for key in list(config.latex_elements):
|
for key in list(config.latex_elements):
|
||||||
if key not in DEFAULT_SETTINGS:
|
if key not in DEFAULT_SETTINGS:
|
||||||
msg = __("Unknown configure key: latex_elements[%r]. ignored.")
|
msg = __("Unknown configure key: latex_elements[%r]. ignored.")
|
||||||
logger.warning(msg % key)
|
logger.warning(msg % (key,))
|
||||||
config.latex_elements.pop(key)
|
config.latex_elements.pop(key)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ from sphinx.util import encode_uri, requests, logging
|
|||||||
from sphinx.util.console import ( # type: ignore
|
from sphinx.util.console import ( # type: ignore
|
||||||
purple, red, darkgreen, darkgray, darkred, turquoise
|
purple, red, darkgreen, darkgray, darkred, turquoise
|
||||||
)
|
)
|
||||||
from sphinx.util.nodes import traverse_parent
|
from sphinx.util.nodes import get_node_line
|
||||||
from sphinx.util.requests import is_ssl_error
|
from sphinx.util.requests import is_ssl_error
|
||||||
|
|
||||||
if False:
|
if False:
|
||||||
@@ -271,17 +271,24 @@ class CheckExternalLinksBuilder(Builder):
|
|||||||
# type: (str, nodes.Node) -> None
|
# type: (str, nodes.Node) -> None
|
||||||
logger.info('')
|
logger.info('')
|
||||||
n = 0
|
n = 0
|
||||||
for node in doctree.traverse(nodes.reference):
|
|
||||||
if 'refuri' not in node:
|
# reference nodes
|
||||||
|
for refnode in doctree.traverse(nodes.reference):
|
||||||
|
if 'refuri' not in refnode:
|
||||||
continue
|
continue
|
||||||
uri = node['refuri']
|
uri = refnode['refuri']
|
||||||
lineno = None
|
lineno = get_node_line(refnode)
|
||||||
for parent in traverse_parent(node):
|
|
||||||
if parent.line:
|
|
||||||
lineno = parent.line
|
|
||||||
break
|
|
||||||
self.wqueue.put((uri, docname, lineno), False)
|
self.wqueue.put((uri, docname, lineno), False)
|
||||||
n += 1
|
n += 1
|
||||||
|
|
||||||
|
# image nodes
|
||||||
|
for imgnode in doctree.traverse(nodes.image):
|
||||||
|
uri = imgnode['candidates'].get('?')
|
||||||
|
if uri and '://' in uri:
|
||||||
|
lineno = get_node_line(imgnode)
|
||||||
|
self.wqueue.put((uri, docname, lineno), False)
|
||||||
|
n += 1
|
||||||
|
|
||||||
done = 0
|
done = 0
|
||||||
while done < n:
|
while done < n:
|
||||||
self.process_result(self.rqueue.get())
|
self.process_result(self.rqueue.get())
|
||||||
|
|||||||
@@ -18,7 +18,8 @@ from sphinx.builders import Builder
|
|||||||
from sphinx.environment import NoUri
|
from sphinx.environment import NoUri
|
||||||
from sphinx.locale import __
|
from sphinx.locale import __
|
||||||
from sphinx.util import logging
|
from sphinx.util import logging
|
||||||
from sphinx.util.console import bold, darkgreen # type: ignore
|
from sphinx.util import progress_message
|
||||||
|
from sphinx.util.console import darkgreen # type: ignore
|
||||||
from sphinx.util.nodes import inline_all_toctrees
|
from sphinx.util.nodes import inline_all_toctrees
|
||||||
from sphinx.util.osutil import make_filename_from_project
|
from sphinx.util.osutil import make_filename_from_project
|
||||||
from sphinx.writers.manpage import ManualPageWriter, ManualPageTranslator
|
from sphinx.writers.manpage import ManualPageWriter, ManualPageTranslator
|
||||||
@@ -60,6 +61,7 @@ class ManualPageBuilder(Builder):
|
|||||||
return ''
|
return ''
|
||||||
raise NoUri
|
raise NoUri
|
||||||
|
|
||||||
|
@progress_message(__('writing'))
|
||||||
def write(self, *ignored):
|
def write(self, *ignored):
|
||||||
# type: (Any) -> None
|
# type: (Any) -> None
|
||||||
docwriter = ManualPageWriter(self)
|
docwriter = ManualPageWriter(self)
|
||||||
@@ -68,8 +70,6 @@ class ManualPageBuilder(Builder):
|
|||||||
components=(docwriter,),
|
components=(docwriter,),
|
||||||
read_config_files=True).get_default_values() # type: Any
|
read_config_files=True).get_default_values() # type: Any
|
||||||
|
|
||||||
logger.info(bold(__('writing... ')), nonl=True)
|
|
||||||
|
|
||||||
for info in self.config.man_pages:
|
for info in self.config.man_pages:
|
||||||
docname, name, description, authors, section = info
|
docname, name, description, authors, section = info
|
||||||
if docname not in self.env.all_docs:
|
if docname not in self.env.all_docs:
|
||||||
@@ -105,7 +105,6 @@ class ManualPageBuilder(Builder):
|
|||||||
pendingnode.replace_self(pendingnode.children)
|
pendingnode.replace_self(pendingnode.children)
|
||||||
|
|
||||||
docwriter.write(largetree, destination)
|
docwriter.write(largetree, destination)
|
||||||
logger.info('')
|
|
||||||
|
|
||||||
def finish(self):
|
def finish(self):
|
||||||
# type: () -> None
|
# type: () -> None
|
||||||
|
|||||||
@@ -16,7 +16,8 @@ from sphinx.builders.html import StandaloneHTMLBuilder
|
|||||||
from sphinx.environment.adapters.toctree import TocTree
|
from sphinx.environment.adapters.toctree import TocTree
|
||||||
from sphinx.locale import __
|
from sphinx.locale import __
|
||||||
from sphinx.util import logging
|
from sphinx.util import logging
|
||||||
from sphinx.util.console import bold, darkgreen # type: ignore
|
from sphinx.util import progress_message
|
||||||
|
from sphinx.util.console import darkgreen # type: ignore
|
||||||
from sphinx.util.nodes import inline_all_toctrees
|
from sphinx.util.nodes import inline_all_toctrees
|
||||||
|
|
||||||
if False:
|
if False:
|
||||||
@@ -162,24 +163,32 @@ class SingleFileHTMLBuilder(StandaloneHTMLBuilder):
|
|||||||
# type: (Any) -> None
|
# type: (Any) -> None
|
||||||
docnames = self.env.all_docs
|
docnames = self.env.all_docs
|
||||||
|
|
||||||
logger.info(bold(__('preparing documents... ')), nonl=True)
|
with progress_message(__('preparing documents')):
|
||||||
self.prepare_writing(docnames) # type: ignore
|
self.prepare_writing(docnames) # type: ignore
|
||||||
logger.info(__('done'))
|
|
||||||
|
|
||||||
logger.info(bold(__('assembling single document... ')), nonl=True)
|
with progress_message(__('assembling single document')):
|
||||||
doctree = self.assemble_doctree()
|
doctree = self.assemble_doctree()
|
||||||
self.env.toc_secnumbers = self.assemble_toc_secnumbers()
|
self.env.toc_secnumbers = self.assemble_toc_secnumbers()
|
||||||
self.env.toc_fignumbers = self.assemble_toc_fignumbers()
|
self.env.toc_fignumbers = self.assemble_toc_fignumbers()
|
||||||
logger.info('')
|
|
||||||
logger.info(bold(__('writing... ')), nonl=True)
|
with progress_message(__('writing')):
|
||||||
self.write_doc_serialized(self.config.master_doc, doctree)
|
self.write_doc_serialized(self.config.master_doc, doctree)
|
||||||
self.write_doc(self.config.master_doc, doctree)
|
self.write_doc(self.config.master_doc, doctree)
|
||||||
logger.info(__('done'))
|
|
||||||
|
|
||||||
def finish(self):
|
def finish(self):
|
||||||
|
# type: () -> None
|
||||||
|
self.write_additional_files()
|
||||||
|
self.copy_image_files()
|
||||||
|
self.copy_download_files()
|
||||||
|
self.copy_static_files()
|
||||||
|
self.copy_extra_files()
|
||||||
|
self.write_buildinfo()
|
||||||
|
self.dump_inventory()
|
||||||
|
|
||||||
|
@progress_message(__('writing additional files'))
|
||||||
|
def write_additional_files(self):
|
||||||
# type: () -> None
|
# type: () -> None
|
||||||
# no indices or search pages are supported
|
# no indices or search pages are supported
|
||||||
logger.info(bold(__('writing additional files...')), nonl=True)
|
|
||||||
|
|
||||||
# additional pages from conf.py
|
# additional pages from conf.py
|
||||||
for pagename, template in self.config.html_additional_pages.items():
|
for pagename, template in self.config.html_additional_pages.items():
|
||||||
@@ -191,15 +200,6 @@ class SingleFileHTMLBuilder(StandaloneHTMLBuilder):
|
|||||||
fn = path.join(self.outdir, '_static', 'opensearch.xml')
|
fn = path.join(self.outdir, '_static', 'opensearch.xml')
|
||||||
self.handle_page('opensearch', {}, 'opensearch.xml', outfilename=fn)
|
self.handle_page('opensearch', {}, 'opensearch.xml', outfilename=fn)
|
||||||
|
|
||||||
logger.info('')
|
|
||||||
|
|
||||||
self.copy_image_files()
|
|
||||||
self.copy_download_files()
|
|
||||||
self.copy_static_files()
|
|
||||||
self.copy_extra_files()
|
|
||||||
self.write_buildinfo()
|
|
||||||
self.dump_inventory()
|
|
||||||
|
|
||||||
|
|
||||||
def setup(app):
|
def setup(app):
|
||||||
# type: (Sphinx) -> Dict[str, Any]
|
# type: (Sphinx) -> Dict[str, Any]
|
||||||
|
|||||||
@@ -22,8 +22,8 @@ from sphinx.environment import NoUri
|
|||||||
from sphinx.environment.adapters.asset import ImageAdapter
|
from sphinx.environment.adapters.asset import ImageAdapter
|
||||||
from sphinx.locale import _, __
|
from sphinx.locale import _, __
|
||||||
from sphinx.util import logging
|
from sphinx.util import logging
|
||||||
from sphinx.util import status_iterator
|
from sphinx.util import progress_message, status_iterator
|
||||||
from sphinx.util.console import bold, darkgreen # type: ignore
|
from sphinx.util.console import darkgreen # type: ignore
|
||||||
from sphinx.util.docutils import new_document
|
from sphinx.util.docutils import new_document
|
||||||
from sphinx.util.fileutil import copy_asset_file
|
from sphinx.util.fileutil import copy_asset_file
|
||||||
from sphinx.util.nodes import inline_all_toctrees
|
from sphinx.util.nodes import inline_all_toctrees
|
||||||
@@ -113,28 +113,27 @@ class TexinfoBuilder(Builder):
|
|||||||
destination = FileOutput(
|
destination = FileOutput(
|
||||||
destination_path=path.join(self.outdir, targetname),
|
destination_path=path.join(self.outdir, targetname),
|
||||||
encoding='utf-8')
|
encoding='utf-8')
|
||||||
logger.info(__("processing %s..."), targetname, nonl=True)
|
with progress_message(__("processing %s") % targetname):
|
||||||
doctree = self.assemble_doctree(
|
appendices = self.config.texinfo_appendices or []
|
||||||
docname, toctree_only,
|
doctree = self.assemble_doctree(docname, toctree_only, appendices=appendices)
|
||||||
appendices=(self.config.texinfo_appendices or []))
|
|
||||||
logger.info(__("writing... "), nonl=True)
|
with progress_message(__("writing")):
|
||||||
self.post_process_images(doctree)
|
self.post_process_images(doctree)
|
||||||
docwriter = TexinfoWriter(self)
|
docwriter = TexinfoWriter(self)
|
||||||
settings = OptionParser(
|
settings = OptionParser(
|
||||||
defaults=self.env.settings,
|
defaults=self.env.settings,
|
||||||
components=(docwriter,),
|
components=(docwriter,),
|
||||||
read_config_files=True).get_default_values() # type: Any
|
read_config_files=True).get_default_values() # type: Any
|
||||||
settings.author = author
|
settings.author = author
|
||||||
settings.title = title
|
settings.title = title
|
||||||
settings.texinfo_filename = targetname[:-5] + '.info'
|
settings.texinfo_filename = targetname[:-5] + '.info'
|
||||||
settings.texinfo_elements = self.config.texinfo_elements
|
settings.texinfo_elements = self.config.texinfo_elements
|
||||||
settings.texinfo_dir_entry = direntry or ''
|
settings.texinfo_dir_entry = direntry or ''
|
||||||
settings.texinfo_dir_category = category or ''
|
settings.texinfo_dir_category = category or ''
|
||||||
settings.texinfo_dir_description = description or ''
|
settings.texinfo_dir_description = description or ''
|
||||||
settings.docname = docname
|
settings.docname = docname
|
||||||
doctree.settings = settings
|
doctree.settings = settings
|
||||||
docwriter.write(doctree, destination)
|
docwriter.write(doctree, destination)
|
||||||
logger.info(__("done"))
|
|
||||||
|
|
||||||
def assemble_doctree(self, indexfile, toctree_only, appendices):
|
def assemble_doctree(self, indexfile, toctree_only, appendices):
|
||||||
# type: (str, bool, List[str]) -> nodes.document
|
# type: (str, bool, List[str]) -> nodes.document
|
||||||
@@ -182,16 +181,7 @@ class TexinfoBuilder(Builder):
|
|||||||
def finish(self):
|
def finish(self):
|
||||||
# type: () -> None
|
# type: () -> None
|
||||||
self.copy_image_files()
|
self.copy_image_files()
|
||||||
|
self.copy_support_files()
|
||||||
logger.info(bold(__('copying Texinfo support files... ')), nonl=True)
|
|
||||||
# copy Makefile
|
|
||||||
fn = path.join(self.outdir, 'Makefile')
|
|
||||||
logger.info(fn, nonl=True)
|
|
||||||
try:
|
|
||||||
copy_asset_file(os.path.join(template_dir, 'Makefile'), fn)
|
|
||||||
except OSError as err:
|
|
||||||
logger.warning(__("error writing file %s: %s"), fn, err)
|
|
||||||
logger.info(__(' done'))
|
|
||||||
|
|
||||||
def copy_image_files(self):
|
def copy_image_files(self):
|
||||||
# type: () -> None
|
# type: () -> None
|
||||||
@@ -208,6 +198,15 @@ class TexinfoBuilder(Builder):
|
|||||||
logger.warning(__('cannot copy image file %r: %s'),
|
logger.warning(__('cannot copy image file %r: %s'),
|
||||||
path.join(self.srcdir, src), err)
|
path.join(self.srcdir, src), err)
|
||||||
|
|
||||||
|
def copy_support_files(self):
|
||||||
|
# type: () -> None
|
||||||
|
try:
|
||||||
|
with progress_message(__('copying Texinfo support files')):
|
||||||
|
logger.info('Makefile ', nonl=True)
|
||||||
|
copy_asset_file(os.path.join(template_dir, 'Makefile'), self.outdir)
|
||||||
|
except OSError as err:
|
||||||
|
logger.warning(__("error writing file Makefile: %s"), err)
|
||||||
|
|
||||||
|
|
||||||
def default_texinfo_documents(config):
|
def default_texinfo_documents(config):
|
||||||
# type: (Config) -> List[Tuple[str, str, str, str, str, str, str]]
|
# type: (Config) -> List[Tuple[str, str, str, str, str, str, str]]
|
||||||
|
|||||||
@@ -23,9 +23,8 @@ from sphinx.application import Sphinx
|
|||||||
from sphinx.errors import SphinxError
|
from sphinx.errors import SphinxError
|
||||||
from sphinx.locale import __
|
from sphinx.locale import __
|
||||||
from sphinx.util import Tee, format_exception_cut_frames, save_traceback
|
from sphinx.util import Tee, format_exception_cut_frames, save_traceback
|
||||||
from sphinx.util.console import red, nocolor, color_terminal # type: ignore
|
from sphinx.util.console import red, nocolor, color_terminal, terminal_safe # type: ignore
|
||||||
from sphinx.util.docutils import docutils_namespace, patch_docutils
|
from sphinx.util.docutils import docutils_namespace, patch_docutils
|
||||||
from sphinx.util.pycompat import terminal_safe
|
|
||||||
|
|
||||||
if False:
|
if False:
|
||||||
# For type annotation
|
# For type annotation
|
||||||
|
|||||||
@@ -17,7 +17,6 @@ import time
|
|||||||
import warnings
|
import warnings
|
||||||
from collections import OrderedDict
|
from collections import OrderedDict
|
||||||
from os import path
|
from os import path
|
||||||
from urllib.parse import quote
|
|
||||||
|
|
||||||
# try to import readline, unix specific enhancement
|
# try to import readline, unix specific enhancement
|
||||||
try:
|
try:
|
||||||
@@ -37,11 +36,10 @@ import sphinx.locale
|
|||||||
from sphinx import __display_version__, package_dir
|
from sphinx import __display_version__, package_dir
|
||||||
from sphinx.deprecation import RemovedInSphinx40Warning
|
from sphinx.deprecation import RemovedInSphinx40Warning
|
||||||
from sphinx.locale import __
|
from sphinx.locale import __
|
||||||
from sphinx.util import texescape
|
|
||||||
from sphinx.util.console import ( # type: ignore
|
from sphinx.util.console import ( # type: ignore
|
||||||
colorize, bold, red, turquoise, nocolor, color_terminal
|
colorize, bold, red, turquoise, nocolor, color_terminal
|
||||||
)
|
)
|
||||||
from sphinx.util.osutil import ensuredir, make_filename
|
from sphinx.util.osutil import ensuredir
|
||||||
from sphinx.util.template import SphinxRenderer
|
from sphinx.util.template import SphinxRenderer
|
||||||
|
|
||||||
if False:
|
if False:
|
||||||
@@ -375,25 +373,15 @@ def generate(d, overwrite=True, silent=False, templatedir=None):
|
|||||||
"""Generate project based on values in *d*."""
|
"""Generate project based on values in *d*."""
|
||||||
template = QuickstartRenderer(templatedir=templatedir)
|
template = QuickstartRenderer(templatedir=templatedir)
|
||||||
|
|
||||||
texescape.init()
|
|
||||||
|
|
||||||
if 'mastertoctree' not in d:
|
if 'mastertoctree' not in d:
|
||||||
d['mastertoctree'] = ''
|
d['mastertoctree'] = ''
|
||||||
if 'mastertocmaxdepth' not in d:
|
if 'mastertocmaxdepth' not in d:
|
||||||
d['mastertocmaxdepth'] = 2
|
d['mastertocmaxdepth'] = 2
|
||||||
|
|
||||||
d['PY3'] = True
|
|
||||||
d['project_fn'] = make_filename(d['project'])
|
|
||||||
d['project_url'] = quote(d['project'].encode('idna'))
|
|
||||||
d['project_manpage'] = d['project_fn'].lower()
|
|
||||||
d['now'] = time.asctime()
|
d['now'] = time.asctime()
|
||||||
d['project_underline'] = column_width(d['project']) * '='
|
d['project_underline'] = column_width(d['project']) * '='
|
||||||
d.setdefault('extensions', [])
|
d.setdefault('extensions', [])
|
||||||
d['copyright'] = time.strftime('%Y') + ', ' + d['author']
|
d['copyright'] = time.strftime('%Y') + ', ' + d['author']
|
||||||
d['author_texescaped'] = d['author'].translate(texescape.tex_escape_map)
|
|
||||||
d['project_doc'] = d['project'] + ' Documentation'
|
|
||||||
d['project_doc_texescaped'] = (d['project'] + ' Documentation').\
|
|
||||||
translate(texescape.tex_escape_map)
|
|
||||||
|
|
||||||
ensuredir(d['path'])
|
ensuredir(d['path'])
|
||||||
|
|
||||||
|
|||||||
@@ -22,7 +22,8 @@ from sphinx.locale import _, __
|
|||||||
from sphinx.util import logging
|
from sphinx.util import logging
|
||||||
from sphinx.util.i18n import format_date
|
from sphinx.util.i18n import format_date
|
||||||
from sphinx.util.osutil import cd
|
from sphinx.util.osutil import cd
|
||||||
from sphinx.util.pycompat import execfile_, NoneType
|
from sphinx.util.pycompat import execfile_
|
||||||
|
from sphinx.util.typing import NoneType
|
||||||
|
|
||||||
if False:
|
if False:
|
||||||
# For type annotation
|
# For type annotation
|
||||||
|
|||||||
@@ -48,7 +48,7 @@ class _ModuleWrapper(object):
|
|||||||
def __getattr__(self, name):
|
def __getattr__(self, name):
|
||||||
# type: (str) -> Any
|
# type: (str) -> Any
|
||||||
if name in self._objects:
|
if name in self._objects:
|
||||||
warnings.warn("%s.%s is now deprecated. Please refer CHANGES to grasp"
|
warnings.warn("%s.%s is now deprecated. Please refer CHANGES to grasp "
|
||||||
"the changes of Sphinx API." % (self._modname, name),
|
"the changes of Sphinx API." % (self._modname, name),
|
||||||
self._warning, stacklevel=3)
|
self._warning, stacklevel=3)
|
||||||
return self._objects[name]
|
return self._objects[name]
|
||||||
|
|||||||
@@ -7158,7 +7158,7 @@ class CPPDomain(Domain):
|
|||||||
# the non-identifier refs are cross-references, which should be processed:
|
# the non-identifier refs are cross-references, which should be processed:
|
||||||
# - fix parenthesis due to operator() and add_function_parentheses
|
# - fix parenthesis due to operator() and add_function_parentheses
|
||||||
if typ != "identifier":
|
if typ != "identifier":
|
||||||
title = contnode.pop(0).astext() # type: ignore
|
title = contnode.pop(0).astext()
|
||||||
# If it's operator(), we need to add '()' if explicit function parens
|
# If it's operator(), we need to add '()' if explicit function parens
|
||||||
# are requested. Then the Sphinx machinery will add another pair.
|
# are requested. Then the Sphinx machinery will add another pair.
|
||||||
# Also, if it's an 'any' ref that resolves to a function, we need to add
|
# Also, if it's an 'any' ref that resolves to a function, we need to add
|
||||||
|
|||||||
@@ -151,7 +151,7 @@ class PyXrefMixin:
|
|||||||
delims_re = re.compile(delims)
|
delims_re = re.compile(delims)
|
||||||
sub_targets = re.split(delims, target)
|
sub_targets = re.split(delims, target)
|
||||||
|
|
||||||
split_contnode = bool(contnode and contnode.astext() == target) # type: ignore
|
split_contnode = bool(contnode and contnode.astext() == target)
|
||||||
|
|
||||||
results = []
|
results = []
|
||||||
for sub_target in filter(None, sub_targets):
|
for sub_target in filter(None, sub_targets):
|
||||||
|
|||||||
@@ -72,7 +72,7 @@ INSTANCEATTR = object()
|
|||||||
def members_option(arg):
|
def members_option(arg):
|
||||||
# type: (Any) -> Union[object, List[str]]
|
# type: (Any) -> Union[object, List[str]]
|
||||||
"""Used to convert the :members: option to auto directives."""
|
"""Used to convert the :members: option to auto directives."""
|
||||||
if arg is None:
|
if arg is None or arg is True:
|
||||||
return ALL
|
return ALL
|
||||||
return [x.strip() for x in arg.split(',')]
|
return [x.strip() for x in arg.split(',')]
|
||||||
|
|
||||||
|
|||||||
@@ -32,13 +32,18 @@ logger = logging.getLogger(__name__)
|
|||||||
class _MockObject:
|
class _MockObject:
|
||||||
"""Used by autodoc_mock_imports."""
|
"""Used by autodoc_mock_imports."""
|
||||||
|
|
||||||
|
__display_name__ = '_MockObject'
|
||||||
|
|
||||||
def __new__(cls, *args, **kwargs):
|
def __new__(cls, *args, **kwargs):
|
||||||
# type: (Any, Any) -> Any
|
# type: (Any, Any) -> Any
|
||||||
if len(args) == 3 and isinstance(args[1], tuple) and args[1][-1].__class__ is cls:
|
if len(args) == 3 and isinstance(args[1], tuple):
|
||||||
# subclassing MockObject
|
superclass = args[1][-1].__class__
|
||||||
return type(args[0], (_MockObject,), args[2], **kwargs) # type: ignore
|
if superclass is cls:
|
||||||
else:
|
# subclassing MockObject
|
||||||
return super(_MockObject, cls).__new__(cls)
|
return _make_subclass(args[0], superclass.__display_name__,
|
||||||
|
superclass=superclass, attributes=args[2])
|
||||||
|
|
||||||
|
return super(_MockObject, cls).__new__(cls)
|
||||||
|
|
||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
# type: (Any, Any) -> None
|
# type: (Any, Any) -> None
|
||||||
@@ -62,11 +67,11 @@ class _MockObject:
|
|||||||
|
|
||||||
def __getitem__(self, key):
|
def __getitem__(self, key):
|
||||||
# type: (str) -> _MockObject
|
# type: (str) -> _MockObject
|
||||||
return self
|
return _make_subclass(key, self.__display_name__, self.__class__)()
|
||||||
|
|
||||||
def __getattr__(self, key):
|
def __getattr__(self, key):
|
||||||
# type: (str) -> _MockObject
|
# type: (str) -> _MockObject
|
||||||
return self
|
return _make_subclass(key, self.__display_name__, self.__class__)()
|
||||||
|
|
||||||
def __call__(self, *args, **kw):
|
def __call__(self, *args, **kw):
|
||||||
# type: (Any, Any) -> Any
|
# type: (Any, Any) -> Any
|
||||||
@@ -75,6 +80,18 @@ class _MockObject:
|
|||||||
return args[0]
|
return args[0]
|
||||||
return self
|
return self
|
||||||
|
|
||||||
|
def __repr__(self):
|
||||||
|
# type: () -> str
|
||||||
|
return self.__display_name__
|
||||||
|
|
||||||
|
|
||||||
|
def _make_subclass(name, module, superclass=_MockObject, attributes=None):
|
||||||
|
# type: (str, str, Any, dict) -> Any
|
||||||
|
attrs = {'__module__': module, '__display_name__': module + '.' + name}
|
||||||
|
attrs.update(attributes or {})
|
||||||
|
|
||||||
|
return type(name, (superclass,), attrs)
|
||||||
|
|
||||||
|
|
||||||
class _MockModule(ModuleType):
|
class _MockModule(ModuleType):
|
||||||
"""Used by autodoc_mock_imports."""
|
"""Used by autodoc_mock_imports."""
|
||||||
@@ -92,9 +109,11 @@ class _MockModule(ModuleType):
|
|||||||
|
|
||||||
def __getattr__(self, name):
|
def __getattr__(self, name):
|
||||||
# type: (str) -> _MockObject
|
# type: (str) -> _MockObject
|
||||||
o = _MockObject()
|
return _make_subclass(name, self.__name__)()
|
||||||
o.__module__ = self.__name__
|
|
||||||
return o
|
def __repr__(self):
|
||||||
|
# type: () -> str
|
||||||
|
return self.__name__
|
||||||
|
|
||||||
|
|
||||||
class _MockImporter(MetaPathFinder):
|
class _MockImporter(MetaPathFinder):
|
||||||
|
|||||||
@@ -30,11 +30,23 @@ if False:
|
|||||||
from sphinx.application import Sphinx # NOQA
|
from sphinx.application import Sphinx # NOQA
|
||||||
|
|
||||||
|
|
||||||
|
def get_node_depth(node):
|
||||||
|
i = 0
|
||||||
|
cur_node = node
|
||||||
|
while cur_node.parent != node.document:
|
||||||
|
cur_node = cur_node.parent
|
||||||
|
i += 1
|
||||||
|
return i
|
||||||
|
|
||||||
|
|
||||||
def register_sections_as_label(app, document):
|
def register_sections_as_label(app, document):
|
||||||
# type: (Sphinx, nodes.Node) -> None
|
# type: (Sphinx, nodes.Node) -> None
|
||||||
labels = app.env.domaindata['std']['labels']
|
labels = app.env.domaindata['std']['labels']
|
||||||
anonlabels = app.env.domaindata['std']['anonlabels']
|
anonlabels = app.env.domaindata['std']['anonlabels']
|
||||||
for node in document.traverse(nodes.section):
|
for node in document.traverse(nodes.section):
|
||||||
|
if (app.config.autosectionlabel_maxdepth and
|
||||||
|
get_node_depth(node) >= app.config.autosectionlabel_maxdepth):
|
||||||
|
continue
|
||||||
labelid = node['ids'][0]
|
labelid = node['ids'][0]
|
||||||
docname = app.env.docname
|
docname = app.env.docname
|
||||||
title = cast(nodes.title, node[0])
|
title = cast(nodes.title, node[0])
|
||||||
@@ -57,6 +69,7 @@ def register_sections_as_label(app, document):
|
|||||||
def setup(app):
|
def setup(app):
|
||||||
# type: (Sphinx) -> Dict[str, Any]
|
# type: (Sphinx) -> Dict[str, Any]
|
||||||
app.add_config_value('autosectionlabel_prefix_document', False, 'env')
|
app.add_config_value('autosectionlabel_prefix_document', False, 'env')
|
||||||
|
app.add_config_value('autosectionlabel_maxdepth', None, 'env')
|
||||||
app.connect('doctree-read', register_sections_as_label)
|
app.connect('doctree-read', register_sections_as_label)
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
|||||||
@@ -72,7 +72,7 @@ from sphinx.deprecation import RemovedInSphinx40Warning
|
|||||||
from sphinx.environment.adapters.toctree import TocTree
|
from sphinx.environment.adapters.toctree import TocTree
|
||||||
from sphinx.ext.autodoc import get_documenters
|
from sphinx.ext.autodoc import get_documenters
|
||||||
from sphinx.ext.autodoc.directive import DocumenterBridge, Options
|
from sphinx.ext.autodoc.directive import DocumenterBridge, Options
|
||||||
from sphinx.ext.autodoc.importer import import_module
|
from sphinx.ext.autodoc.importer import import_module, mock
|
||||||
from sphinx.locale import __
|
from sphinx.locale import __
|
||||||
from sphinx.pycode import ModuleAnalyzer, PycodeError
|
from sphinx.pycode import ModuleAnalyzer, PycodeError
|
||||||
from sphinx.util import import_object, rst, logging
|
from sphinx.util import import_object, rst, logging
|
||||||
@@ -286,7 +286,8 @@ class Autosummary(SphinxDirective):
|
|||||||
display_name = name.split('.')[-1]
|
display_name = name.split('.')[-1]
|
||||||
|
|
||||||
try:
|
try:
|
||||||
real_name, obj, parent, modname = import_by_name(name, prefixes=prefixes)
|
with mock(self.config.autosummary_mock_imports):
|
||||||
|
real_name, obj, parent, modname = import_by_name(name, prefixes=prefixes)
|
||||||
except ImportError:
|
except ImportError:
|
||||||
logger.warning(__('failed to import %s'), name)
|
logger.warning(__('failed to import %s'), name)
|
||||||
items.append((name, '', '', name))
|
items.append((name, '', '', name))
|
||||||
@@ -702,10 +703,11 @@ def process_generate_options(app):
|
|||||||
'But your source_suffix does not contain .rst. Skipped.'))
|
'But your source_suffix does not contain .rst. Skipped.'))
|
||||||
return
|
return
|
||||||
|
|
||||||
generate_autosummary_docs(genfiles, builder=app.builder,
|
with mock(app.config.autosummary_mock_imports):
|
||||||
warn=logger.warning, info=logger.info,
|
generate_autosummary_docs(genfiles, builder=app.builder,
|
||||||
suffix=suffix, base_path=app.srcdir,
|
warn=logger.warning, info=logger.info,
|
||||||
app=app)
|
suffix=suffix, base_path=app.srcdir,
|
||||||
|
app=app)
|
||||||
|
|
||||||
|
|
||||||
def setup(app):
|
def setup(app):
|
||||||
@@ -729,4 +731,7 @@ def setup(app):
|
|||||||
app.connect('doctree-read', process_autosummary_toc)
|
app.connect('doctree-read', process_autosummary_toc)
|
||||||
app.connect('builder-inited', process_generate_options)
|
app.connect('builder-inited', process_generate_options)
|
||||||
app.add_config_value('autosummary_generate', [], True, [bool])
|
app.add_config_value('autosummary_generate', [], True, [bool])
|
||||||
|
app.add_config_value('autosummary_mock_imports',
|
||||||
|
lambda config: config.autodoc_mock_imports, 'env')
|
||||||
|
|
||||||
return {'version': sphinx.__display_version__, 'parallel_read_safe': True}
|
return {'version': sphinx.__display_version__, 'parallel_read_safe': True}
|
||||||
|
|||||||
@@ -9,6 +9,7 @@
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
import os
|
import os
|
||||||
|
import urllib
|
||||||
|
|
||||||
import sphinx
|
import sphinx
|
||||||
|
|
||||||
@@ -19,14 +20,22 @@ if False:
|
|||||||
from sphinx.environment import BuildEnvironment # NOQA
|
from sphinx.environment import BuildEnvironment # NOQA
|
||||||
|
|
||||||
|
|
||||||
def create_nojekyll(app, env):
|
def create_nojekyll_and_cname(app, env):
|
||||||
# type: (Sphinx, BuildEnvironment) -> None
|
# type: (Sphinx, BuildEnvironment) -> None
|
||||||
if app.builder.format == 'html':
|
if app.builder.format == 'html':
|
||||||
path = os.path.join(app.builder.outdir, '.nojekyll')
|
open(os.path.join(app.builder.outdir, '.nojekyll'), 'wt').close()
|
||||||
open(path, 'wt').close()
|
|
||||||
|
html_baseurl = app.config.html_baseurl
|
||||||
|
if html_baseurl:
|
||||||
|
domain = urllib.parse.urlparse(html_baseurl).hostname
|
||||||
|
if domain and not domain.endswith(".github.io"):
|
||||||
|
with open(os.path.join(app.builder.outdir, 'CNAME'), 'wt') as f:
|
||||||
|
# NOTE: don't write a trailing newline. The `CNAME` file that's
|
||||||
|
# auto-generated by the Github UI doesn't have one.
|
||||||
|
f.write(domain)
|
||||||
|
|
||||||
|
|
||||||
def setup(app):
|
def setup(app):
|
||||||
# type: (Sphinx) -> Dict[str, Any]
|
# type: (Sphinx) -> Dict[str, Any]
|
||||||
app.connect('env-updated', create_nojekyll)
|
app.connect('env-updated', create_nojekyll_and_cname)
|
||||||
return {'version': sphinx.__display_version__, 'parallel_read_safe': True}
|
return {'version': sphinx.__display_version__, 'parallel_read_safe': True}
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ import posixpath
|
|||||||
import re
|
import re
|
||||||
import shutil
|
import shutil
|
||||||
import subprocess
|
import subprocess
|
||||||
|
import sys
|
||||||
import tempfile
|
import tempfile
|
||||||
from hashlib import sha1
|
from hashlib import sha1
|
||||||
from os import path
|
from os import path
|
||||||
@@ -26,7 +27,6 @@ from sphinx.util import logging
|
|||||||
from sphinx.util.math import get_node_equation_number, wrap_displaymath
|
from sphinx.util.math import get_node_equation_number, wrap_displaymath
|
||||||
from sphinx.util.osutil import ensuredir
|
from sphinx.util.osutil import ensuredir
|
||||||
from sphinx.util.png import read_png_depth, write_png_depth
|
from sphinx.util.png import read_png_depth, write_png_depth
|
||||||
from sphinx.util.pycompat import sys_encoding
|
|
||||||
|
|
||||||
if False:
|
if False:
|
||||||
# For type annotation
|
# For type annotation
|
||||||
@@ -46,9 +46,9 @@ class MathExtError(SphinxError):
|
|||||||
def __init__(self, msg, stderr=None, stdout=None):
|
def __init__(self, msg, stderr=None, stdout=None):
|
||||||
# type: (str, bytes, bytes) -> None
|
# type: (str, bytes, bytes) -> None
|
||||||
if stderr:
|
if stderr:
|
||||||
msg += '\n[stderr]\n' + stderr.decode(sys_encoding, 'replace')
|
msg += '\n[stderr]\n' + stderr.decode(sys.getdefaultencoding(), 'replace')
|
||||||
if stdout:
|
if stdout:
|
||||||
msg += '\n[stdout]\n' + stdout.decode(sys_encoding, 'replace')
|
msg += '\n[stdout]\n' + stdout.decode(sys.getdefaultencoding(), 'replace')
|
||||||
super().__init__(msg)
|
super().__init__(msg)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ from typing import Any, Union # NOQA
|
|||||||
from sphinx.deprecation import RemovedInSphinx30Warning
|
from sphinx.deprecation import RemovedInSphinx30Warning
|
||||||
from sphinx.transforms import (
|
from sphinx.transforms import (
|
||||||
ApplySourceWorkaround, ExtraTranslatableNodes, CitationReferences,
|
ApplySourceWorkaround, ExtraTranslatableNodes, CitationReferences,
|
||||||
DefaultSubstitutions, MoveModuleTargets, HandleCodeBlocks, SortIds,
|
DefaultSubstitutions, MoveModuleTargets, HandleCodeBlocks, SortIds, FigureAligner,
|
||||||
AutoNumbering, AutoIndexUpgrader, FilterSystemMessages,
|
AutoNumbering, AutoIndexUpgrader, FilterSystemMessages,
|
||||||
UnreferencedFootnotesDetector, SphinxSmartQuotes, DoctreeReadEvent, ManpageLink
|
UnreferencedFootnotesDetector, SphinxSmartQuotes, DoctreeReadEvent, ManpageLink
|
||||||
)
|
)
|
||||||
@@ -96,7 +96,7 @@ class SphinxStandaloneReader(SphinxBaseReader):
|
|||||||
"""
|
"""
|
||||||
transforms = [ApplySourceWorkaround, ExtraTranslatableNodes, PreserveTranslatableMessages,
|
transforms = [ApplySourceWorkaround, ExtraTranslatableNodes, PreserveTranslatableMessages,
|
||||||
Locale, CitationReferences, DefaultSubstitutions, MoveModuleTargets,
|
Locale, CitationReferences, DefaultSubstitutions, MoveModuleTargets,
|
||||||
HandleCodeBlocks, AutoNumbering, AutoIndexUpgrader, SortIds,
|
HandleCodeBlocks, AutoNumbering, AutoIndexUpgrader, SortIds, FigureAligner,
|
||||||
RemoveTranslatableInline, FilterSystemMessages, RefOnlyBulletListTransform,
|
RemoveTranslatableInline, FilterSystemMessages, RefOnlyBulletListTransform,
|
||||||
UnreferencedFootnotesDetector, SphinxSmartQuotes, ManpageLink,
|
UnreferencedFootnotesDetector, SphinxSmartQuotes, ManpageLink,
|
||||||
SphinxDomains, SubstitutionDefinitionsRemover, DoctreeReadEvent,
|
SphinxDomains, SubstitutionDefinitionsRemover, DoctreeReadEvent,
|
||||||
|
|||||||
221
sphinx/roles.py
221
sphinx/roles.py
@@ -9,13 +9,16 @@
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
import re
|
import re
|
||||||
|
import warnings
|
||||||
|
|
||||||
from docutils import nodes, utils
|
from docutils import nodes, utils
|
||||||
|
|
||||||
from sphinx import addnodes
|
from sphinx import addnodes
|
||||||
|
from sphinx.deprecation import RemovedInSphinx40Warning
|
||||||
from sphinx.errors import SphinxError
|
from sphinx.errors import SphinxError
|
||||||
from sphinx.locale import _
|
from sphinx.locale import _
|
||||||
from sphinx.util import ws_re
|
from sphinx.util import ws_re
|
||||||
|
from sphinx.util.docutils import ReferenceRole, SphinxRole
|
||||||
from sphinx.util.nodes import split_explicit_title, process_index_entry, \
|
from sphinx.util.nodes import split_explicit_title, process_index_entry, \
|
||||||
set_role_source_info
|
set_role_source_info
|
||||||
|
|
||||||
@@ -179,6 +182,8 @@ class AnyXRefRole(XRefRole):
|
|||||||
def indexmarkup_role(typ, rawtext, text, lineno, inliner, options={}, content=[]):
|
def indexmarkup_role(typ, rawtext, text, lineno, inliner, options={}, content=[]):
|
||||||
# type: (str, str, str, int, Inliner, Dict, List[str]) -> Tuple[List[nodes.Node], List[nodes.system_message]] # NOQA
|
# type: (str, str, str, int, Inliner, Dict, List[str]) -> Tuple[List[nodes.Node], List[nodes.system_message]] # NOQA
|
||||||
"""Role for PEP/RFC references that generate an index entry."""
|
"""Role for PEP/RFC references that generate an index entry."""
|
||||||
|
warnings.warn('indexmarkup_role() is deprecated. Please use PEP or RFC class instead.',
|
||||||
|
RemovedInSphinx40Warning, stacklevel=2)
|
||||||
env = inliner.document.settings.env
|
env = inliner.document.settings.env
|
||||||
if not typ:
|
if not typ:
|
||||||
assert env.temp_data['default_role']
|
assert env.temp_data['default_role']
|
||||||
@@ -242,11 +247,87 @@ def indexmarkup_role(typ, rawtext, text, lineno, inliner, options={}, content=[]
|
|||||||
raise ValueError('unknown role type: %s' % typ)
|
raise ValueError('unknown role type: %s' % typ)
|
||||||
|
|
||||||
|
|
||||||
|
class PEP(ReferenceRole):
|
||||||
|
def run(self):
|
||||||
|
# type: () -> Tuple[List[nodes.Node], List[nodes.system_message]]
|
||||||
|
target_id = 'index-%s' % self.env.new_serialno('index')
|
||||||
|
entries = [('single', _('Python Enhancement Proposals; PEP %s') % self.target,
|
||||||
|
target_id, '', None)]
|
||||||
|
|
||||||
|
index = addnodes.index(entries=entries)
|
||||||
|
target = nodes.target('', '', ids=[target_id])
|
||||||
|
self.inliner.document.note_explicit_target(target)
|
||||||
|
|
||||||
|
try:
|
||||||
|
refuri = self.build_uri()
|
||||||
|
reference = nodes.reference('', '', internal=False, refuri=refuri, classes=['pep'])
|
||||||
|
if self.has_explicit_title:
|
||||||
|
reference += nodes.strong(self.title, self.title)
|
||||||
|
else:
|
||||||
|
title = "PEP " + self.title
|
||||||
|
reference += nodes.strong(title, title)
|
||||||
|
except ValueError:
|
||||||
|
msg = self.inliner.reporter.error('invalid PEP number %s' % self.target,
|
||||||
|
line=self.lineno)
|
||||||
|
prb = self.inliner.problematic(self.rawtext, self.rawtext, msg)
|
||||||
|
return [prb], [msg]
|
||||||
|
|
||||||
|
return [index, target, reference], []
|
||||||
|
|
||||||
|
def build_uri(self):
|
||||||
|
# type: () -> str
|
||||||
|
base_url = self.inliner.document.settings.pep_base_url
|
||||||
|
ret = self.target.split('#', 1)
|
||||||
|
if len(ret) == 2:
|
||||||
|
return base_url + 'pep-%04d#%s' % (int(ret[0]), ret[1])
|
||||||
|
else:
|
||||||
|
return base_url + 'pep-%04d' % int(ret[0])
|
||||||
|
|
||||||
|
|
||||||
|
class RFC(ReferenceRole):
|
||||||
|
def run(self):
|
||||||
|
# type: () -> Tuple[List[nodes.Node], List[nodes.system_message]] # NOQA
|
||||||
|
target_id = 'index-%s' % self.env.new_serialno('index')
|
||||||
|
entries = [('single', 'RFC; RFC %s' % self.target, target_id, '', None)]
|
||||||
|
|
||||||
|
index = addnodes.index(entries=entries)
|
||||||
|
target = nodes.target('', '', ids=[target_id])
|
||||||
|
self.inliner.document.note_explicit_target(target)
|
||||||
|
|
||||||
|
try:
|
||||||
|
refuri = self.build_uri()
|
||||||
|
reference = nodes.reference('', '', internal=False, refuri=refuri, classes=['rfc'])
|
||||||
|
if self.has_explicit_title:
|
||||||
|
reference += nodes.strong(self.title, self.title)
|
||||||
|
else:
|
||||||
|
title = "RFC " + self.title
|
||||||
|
reference += nodes.strong(title, title)
|
||||||
|
except ValueError:
|
||||||
|
msg = self.inliner.reporter.error('invalid RFC number %s' % self.target,
|
||||||
|
line=self.lineno)
|
||||||
|
prb = self.inliner.problematic(self.rawtext, self.rawtext, msg)
|
||||||
|
return [prb], [msg]
|
||||||
|
|
||||||
|
return [index, target, reference], []
|
||||||
|
|
||||||
|
def build_uri(self):
|
||||||
|
# type: () -> str
|
||||||
|
base_url = self.inliner.document.settings.rfc_base_url
|
||||||
|
ret = self.target.split('#', 1)
|
||||||
|
if len(ret) == 2:
|
||||||
|
return base_url + self.inliner.rfc_url % int(ret[0]) + '#' + ret[1]
|
||||||
|
else:
|
||||||
|
return base_url + self.inliner.rfc_url % int(ret[0])
|
||||||
|
|
||||||
|
|
||||||
_amp_re = re.compile(r'(?<!&)&(?![&\s])')
|
_amp_re = re.compile(r'(?<!&)&(?![&\s])')
|
||||||
|
|
||||||
|
|
||||||
def menusel_role(typ, rawtext, text, lineno, inliner, options={}, content=[]):
|
def menusel_role(typ, rawtext, text, lineno, inliner, options={}, content=[]):
|
||||||
# type: (str, str, str, int, Inliner, Dict, List[str]) -> Tuple[List[nodes.Node], List[nodes.system_message]] # NOQA
|
# type: (str, str, str, int, Inliner, Dict, List[str]) -> Tuple[List[nodes.Node], List[nodes.system_message]] # NOQA
|
||||||
|
warnings.warn('menusel_role() is deprecated. '
|
||||||
|
'Please use MenuSelection or GUILabel class instead.',
|
||||||
|
RemovedInSphinx40Warning, stacklevel=2)
|
||||||
env = inliner.document.settings.env
|
env = inliner.document.settings.env
|
||||||
if not typ:
|
if not typ:
|
||||||
assert env.temp_data['default_role']
|
assert env.temp_data['default_role']
|
||||||
@@ -279,6 +360,32 @@ def menusel_role(typ, rawtext, text, lineno, inliner, options={}, content=[]):
|
|||||||
return [node], []
|
return [node], []
|
||||||
|
|
||||||
|
|
||||||
|
class GUILabel(SphinxRole):
|
||||||
|
amp_re = re.compile(r'(?<!&)&(?![&\s])')
|
||||||
|
|
||||||
|
def run(self):
|
||||||
|
# type: () -> Tuple[List[nodes.Node], List[nodes.system_message]]
|
||||||
|
node = nodes.inline(rawtext=self.rawtext, classes=[self.name])
|
||||||
|
spans = self.amp_re.split(self.text)
|
||||||
|
node += nodes.Text(spans.pop(0))
|
||||||
|
for span in spans:
|
||||||
|
span = span.replace('&&', '&')
|
||||||
|
|
||||||
|
letter = nodes.Text(span[0])
|
||||||
|
accelerator = nodes.inline('', '', letter, classes=['accelerator'])
|
||||||
|
node += accelerator
|
||||||
|
node += nodes.Text(span[1:])
|
||||||
|
|
||||||
|
return [node], []
|
||||||
|
|
||||||
|
|
||||||
|
class MenuSelection(GUILabel):
|
||||||
|
def run(self):
|
||||||
|
# type: () -> Tuple[List[nodes.Node], List[nodes.system_message]]
|
||||||
|
self.text = self.text.replace('-->', '\N{TRIANGULAR BULLET}') # type: ignore
|
||||||
|
return super().run()
|
||||||
|
|
||||||
|
|
||||||
_litvar_re = re.compile('{([^}]+)}')
|
_litvar_re = re.compile('{([^}]+)}')
|
||||||
parens_re = re.compile(r'(\\*{|\\*})')
|
parens_re = re.compile(r'(\\*{|\\*})')
|
||||||
|
|
||||||
@@ -286,6 +393,9 @@ parens_re = re.compile(r'(\\*{|\\*})')
|
|||||||
def emph_literal_role(typ, rawtext, text, lineno, inliner,
|
def emph_literal_role(typ, rawtext, text, lineno, inliner,
|
||||||
options={}, content=[]):
|
options={}, content=[]):
|
||||||
# type: (str, str, str, int, Inliner, Dict, List[str]) -> Tuple[List[nodes.Node], List[nodes.system_message]] # NOQA
|
# type: (str, str, str, int, Inliner, Dict, List[str]) -> Tuple[List[nodes.Node], List[nodes.system_message]] # NOQA
|
||||||
|
warnings.warn('emph_literal_role() is deprecated. '
|
||||||
|
'Please use EmphasizedLiteral class instead.',
|
||||||
|
RemovedInSphinx40Warning, stacklevel=2)
|
||||||
env = inliner.document.settings.env
|
env = inliner.document.settings.env
|
||||||
if not typ:
|
if not typ:
|
||||||
assert env.temp_data['default_role']
|
assert env.temp_data['default_role']
|
||||||
@@ -333,11 +443,65 @@ def emph_literal_role(typ, rawtext, text, lineno, inliner,
|
|||||||
return [retnode], []
|
return [retnode], []
|
||||||
|
|
||||||
|
|
||||||
|
class EmphasizedLiteral(SphinxRole):
|
||||||
|
parens_re = re.compile(r'(\\\\|\\{|\\}|{|})')
|
||||||
|
|
||||||
|
def run(self):
|
||||||
|
# type: () -> Tuple[List[nodes.Node], List[nodes.system_message]]
|
||||||
|
children = self.parse(self.text)
|
||||||
|
node = nodes.literal(self.rawtext, '', *children,
|
||||||
|
role=self.name.lower(), classes=[self.name])
|
||||||
|
|
||||||
|
return [node], []
|
||||||
|
|
||||||
|
def parse(self, text):
|
||||||
|
# type: (str) -> List[nodes.Node]
|
||||||
|
result = [] # type: List[nodes.Node]
|
||||||
|
|
||||||
|
stack = ['']
|
||||||
|
for part in self.parens_re.split(text):
|
||||||
|
if part == '\\\\': # escaped backslash
|
||||||
|
stack[-1] += '\\'
|
||||||
|
elif part == '{':
|
||||||
|
if len(stack) >= 2 and stack[-2] == "{": # nested
|
||||||
|
stack[-1] += "{"
|
||||||
|
else:
|
||||||
|
# start emphasis
|
||||||
|
stack.append('{')
|
||||||
|
stack.append('')
|
||||||
|
elif part == '}':
|
||||||
|
if len(stack) == 3 and stack[1] == "{" and len(stack[2]) > 0:
|
||||||
|
# emphasized word found
|
||||||
|
if stack[0]:
|
||||||
|
result.append(nodes.Text(stack[0], stack[0]))
|
||||||
|
result.append(nodes.emphasis(stack[2], stack[2]))
|
||||||
|
stack = ['']
|
||||||
|
else:
|
||||||
|
# emphasized word not found; the rparen is not a special symbol
|
||||||
|
stack.append('}')
|
||||||
|
stack = [''.join(stack)]
|
||||||
|
elif part == '\\{': # escaped left-brace
|
||||||
|
stack[-1] += '{'
|
||||||
|
elif part == '\\}': # escaped right-brace
|
||||||
|
stack[-1] += '}'
|
||||||
|
else: # others (containing escaped braces)
|
||||||
|
stack[-1] += part
|
||||||
|
|
||||||
|
if ''.join(stack):
|
||||||
|
# remaining is treated as Text
|
||||||
|
text = ''.join(stack)
|
||||||
|
result.append(nodes.Text(text, text))
|
||||||
|
|
||||||
|
return result
|
||||||
|
|
||||||
|
|
||||||
_abbr_re = re.compile(r'\((.*)\)$', re.S)
|
_abbr_re = re.compile(r'\((.*)\)$', re.S)
|
||||||
|
|
||||||
|
|
||||||
def abbr_role(typ, rawtext, text, lineno, inliner, options={}, content=[]):
|
def abbr_role(typ, rawtext, text, lineno, inliner, options={}, content=[]):
|
||||||
# type: (str, str, str, int, Inliner, Dict, List[str]) -> Tuple[List[nodes.Node], List[nodes.system_message]] # NOQA
|
# type: (str, str, str, int, Inliner, Dict, List[str]) -> Tuple[List[nodes.Node], List[nodes.system_message]] # NOQA
|
||||||
|
warnings.warn('abbr_role() is deprecated. Please use Abbrevation class instead.',
|
||||||
|
RemovedInSphinx40Warning, stacklevel=2)
|
||||||
text = utils.unescape(text)
|
text = utils.unescape(text)
|
||||||
m = _abbr_re.search(text)
|
m = _abbr_re.search(text)
|
||||||
if m is None:
|
if m is None:
|
||||||
@@ -349,8 +513,25 @@ def abbr_role(typ, rawtext, text, lineno, inliner, options={}, content=[]):
|
|||||||
return [nodes.abbreviation(abbr, abbr, **options)], []
|
return [nodes.abbreviation(abbr, abbr, **options)], []
|
||||||
|
|
||||||
|
|
||||||
|
class Abbreviation(SphinxRole):
|
||||||
|
abbr_re = re.compile(r'\((.*)\)$', re.S)
|
||||||
|
|
||||||
|
def run(self):
|
||||||
|
# type: () -> Tuple[List[nodes.Node], List[nodes.system_message]]
|
||||||
|
matched = self.abbr_re.search(self.text)
|
||||||
|
if matched:
|
||||||
|
text = self.text[:matched.start()].strip()
|
||||||
|
self.options['explanation'] = matched.group(1)
|
||||||
|
else:
|
||||||
|
text = self.text
|
||||||
|
|
||||||
|
return [nodes.abbreviation(self.rawtext, text, **self.options)], []
|
||||||
|
|
||||||
|
|
||||||
def index_role(typ, rawtext, text, lineno, inliner, options={}, content=[]):
|
def index_role(typ, rawtext, text, lineno, inliner, options={}, content=[]):
|
||||||
# type: (str, str, str, int, Inliner, Dict, List[str]) -> Tuple[List[nodes.Node], List[nodes.system_message]] # NOQA
|
# type: (str, str, str, int, Inliner, Dict, List[str]) -> Tuple[List[nodes.Node], List[nodes.system_message]] # NOQA
|
||||||
|
warnings.warn('index_role() is deprecated. Please use Index class instead.',
|
||||||
|
RemovedInSphinx40Warning, stacklevel=2)
|
||||||
# create new reference target
|
# create new reference target
|
||||||
env = inliner.document.settings.env
|
env = inliner.document.settings.env
|
||||||
targetid = 'index-%s' % env.new_serialno('index')
|
targetid = 'index-%s' % env.new_serialno('index')
|
||||||
@@ -378,20 +559,44 @@ def index_role(typ, rawtext, text, lineno, inliner, options={}, content=[]):
|
|||||||
return [indexnode, targetnode, textnode], []
|
return [indexnode, targetnode, textnode], []
|
||||||
|
|
||||||
|
|
||||||
|
class Index(ReferenceRole):
|
||||||
|
def run(self):
|
||||||
|
# type: () -> Tuple[List[nodes.Node], List[nodes.system_message]]
|
||||||
|
target_id = 'index-%s' % self.env.new_serialno('index')
|
||||||
|
if self.has_explicit_title:
|
||||||
|
# if an explicit target is given, process it as a full entry
|
||||||
|
title = self.title
|
||||||
|
entries = process_index_entry(self.target, target_id)
|
||||||
|
else:
|
||||||
|
# otherwise we just create a single entry
|
||||||
|
if self.target.startswith('!'):
|
||||||
|
title = self.title[1:]
|
||||||
|
entries = [('single', self.target[1:], target_id, 'main', None)]
|
||||||
|
else:
|
||||||
|
title = self.title
|
||||||
|
entries = [('single', self.target, target_id, '', None)]
|
||||||
|
|
||||||
|
index = addnodes.index(entries=entries)
|
||||||
|
target = nodes.target('', '', ids=[target_id])
|
||||||
|
text = nodes.Text(title, title)
|
||||||
|
self.set_source_info(index)
|
||||||
|
return [index, target, text], []
|
||||||
|
|
||||||
|
|
||||||
specific_docroles = {
|
specific_docroles = {
|
||||||
# links to download references
|
# links to download references
|
||||||
'download': XRefRole(nodeclass=addnodes.download_reference),
|
'download': XRefRole(nodeclass=addnodes.download_reference),
|
||||||
# links to anything
|
# links to anything
|
||||||
'any': AnyXRefRole(warn_dangling=True),
|
'any': AnyXRefRole(warn_dangling=True),
|
||||||
|
|
||||||
'pep': indexmarkup_role,
|
'pep': PEP(),
|
||||||
'rfc': indexmarkup_role,
|
'rfc': RFC(),
|
||||||
'guilabel': menusel_role,
|
'guilabel': GUILabel(),
|
||||||
'menuselection': menusel_role,
|
'menuselection': MenuSelection(),
|
||||||
'file': emph_literal_role,
|
'file': EmphasizedLiteral(),
|
||||||
'samp': emph_literal_role,
|
'samp': EmphasizedLiteral(),
|
||||||
'abbr': abbr_role,
|
'abbr': Abbreviation(),
|
||||||
'index': index_role,
|
'index': Index(),
|
||||||
} # type: Dict[str, RoleFunction]
|
} # type: Dict[str, RoleFunction]
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -18,8 +18,8 @@ from docutils import nodes
|
|||||||
from sphinx import addnodes
|
from sphinx import addnodes
|
||||||
from sphinx import package_dir
|
from sphinx import package_dir
|
||||||
from sphinx.deprecation import RemovedInSphinx40Warning
|
from sphinx.deprecation import RemovedInSphinx40Warning
|
||||||
from sphinx.util import jsdump, rpartition
|
|
||||||
from sphinx.search.jssplitter import splitter_code
|
from sphinx.search.jssplitter import splitter_code
|
||||||
|
from sphinx.util import jsdump, rpartition
|
||||||
|
|
||||||
if False:
|
if False:
|
||||||
# For type annotation
|
# For type annotation
|
||||||
|
|||||||
31
sphinx/templates/htmlhelp/project.hhc
Normal file
31
sphinx/templates/htmlhelp/project.hhc
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
{%- macro sitemap(name, docname) -%}
|
||||||
|
<OBJECT type="text/sitemap">
|
||||||
|
<PARAM name="Name" value="{{ name|e }}" />
|
||||||
|
<PARAM name="Local" value="{{ docname|e }}{{ suffix }}" />
|
||||||
|
</OBJECT>
|
||||||
|
{%- endmacro -%}
|
||||||
|
|
||||||
|
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
|
||||||
|
<HTML>
|
||||||
|
<HEAD>
|
||||||
|
<META name="GENERATOR" content="Microsoft® HTML Help Workshop 4.1" />
|
||||||
|
<!-- Sitemap 1.0 -->
|
||||||
|
</HEAD>
|
||||||
|
<BODY>
|
||||||
|
<OBJECT type="text/site properties">
|
||||||
|
<PARAM name="Window Styles" value="0x801227" />
|
||||||
|
<PARAM name="ImageType" value="Folder" />
|
||||||
|
</OBJECT>
|
||||||
|
<UL>
|
||||||
|
<LI>
|
||||||
|
{{ sitemap(short_title, master_doc)|indent(8) }}
|
||||||
|
</LI>
|
||||||
|
{%- for indexname, indexcls, content, collapse in domain_indices %}
|
||||||
|
<LI>
|
||||||
|
{{ sitemap(indexcls.localname, indexname)|indent(8) }}
|
||||||
|
</LI>
|
||||||
|
{%- endfor %}
|
||||||
|
{{ body|indent(6) }}
|
||||||
|
</UL>
|
||||||
|
</BODY>
|
||||||
|
</HTML>
|
||||||
21
sphinx/templates/htmlhelp/project.hhp
Normal file
21
sphinx/templates/htmlhelp/project.hhp
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
[OPTIONS]
|
||||||
|
Binary TOC=No
|
||||||
|
Binary Index=No
|
||||||
|
Compiled file={{ outname }}.chm
|
||||||
|
Contents file={{ outname }}.hhc
|
||||||
|
Default Window={{ outname }}
|
||||||
|
Default topic={{ master_doc }}
|
||||||
|
Display compile progress=No
|
||||||
|
Full text search stop list file={{ outname }}.stp
|
||||||
|
Full-text search=Yes
|
||||||
|
Index file={{ outname }}.hhk
|
||||||
|
Language={{ "%#x"|format(lcid) }}
|
||||||
|
Title={{ title }}
|
||||||
|
|
||||||
|
[WINDOWS]
|
||||||
|
{{ outname }}="{{ title }}","{{ outname }}.hhc","{{ outname }}.hhk","{{ master_doc }}","{{ master_doc }}",,,,,0x63520,220,0x10384e,[0,0,1024,768],,,,,,,0
|
||||||
|
|
||||||
|
[FILES]
|
||||||
|
{%- for filename in files %}
|
||||||
|
{{ filename }}
|
||||||
|
{%- endfor %}
|
||||||
33
sphinx/templates/htmlhelp/project.stp
Normal file
33
sphinx/templates/htmlhelp/project.stp
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
a
|
||||||
|
and
|
||||||
|
are
|
||||||
|
as
|
||||||
|
at
|
||||||
|
be
|
||||||
|
but
|
||||||
|
by
|
||||||
|
for
|
||||||
|
if
|
||||||
|
in
|
||||||
|
into
|
||||||
|
is
|
||||||
|
it
|
||||||
|
near
|
||||||
|
no
|
||||||
|
not
|
||||||
|
of
|
||||||
|
on
|
||||||
|
or
|
||||||
|
such
|
||||||
|
that
|
||||||
|
the
|
||||||
|
their
|
||||||
|
then
|
||||||
|
there
|
||||||
|
these
|
||||||
|
they
|
||||||
|
this
|
||||||
|
to
|
||||||
|
was
|
||||||
|
will
|
||||||
|
with
|
||||||
@@ -231,6 +231,16 @@ a.headerlink {
|
|||||||
visibility: hidden;
|
visibility: hidden;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
a.brackets:before,
|
||||||
|
span.brackets > a:before{
|
||||||
|
content: "[";
|
||||||
|
}
|
||||||
|
|
||||||
|
a.brackets:after,
|
||||||
|
span.brackets > a:after {
|
||||||
|
content: "]";
|
||||||
|
}
|
||||||
|
|
||||||
h1:hover > a.headerlink,
|
h1:hover > a.headerlink,
|
||||||
h2:hover > a.headerlink,
|
h2:hover > a.headerlink,
|
||||||
h3:hover > a.headerlink,
|
h3:hover > a.headerlink,
|
||||||
@@ -391,6 +401,14 @@ table.citation td {
|
|||||||
border-bottom: none;
|
border-bottom: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
td > p:first-child {
|
||||||
|
margin-top: 0px;
|
||||||
|
}
|
||||||
|
|
||||||
|
td > p:only-child {
|
||||||
|
margin-bottom: 0px;
|
||||||
|
}
|
||||||
|
|
||||||
/* -- figures --------------------------------------------------------------- */
|
/* -- figures --------------------------------------------------------------- */
|
||||||
|
|
||||||
div.figure {
|
div.figure {
|
||||||
@@ -460,11 +478,57 @@ ol.upperroman {
|
|||||||
list-style: upper-roman;
|
list-style: upper-roman;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
li > p:first-child {
|
||||||
|
margin-top: 0px;
|
||||||
|
}
|
||||||
|
|
||||||
|
li > p:only-child {
|
||||||
|
margin-bottom: 0px;
|
||||||
|
}
|
||||||
|
|
||||||
|
dl.footnote > dt,
|
||||||
|
dl.citation > dt {
|
||||||
|
float: left;
|
||||||
|
}
|
||||||
|
|
||||||
|
dl.footnote > dd,
|
||||||
|
dl.citation > dd {
|
||||||
|
margin-bottom: 0em;
|
||||||
|
}
|
||||||
|
|
||||||
|
dl.footnote > dd:after,
|
||||||
|
dl.citation > dd:after {
|
||||||
|
content: "";
|
||||||
|
clear: both;
|
||||||
|
}
|
||||||
|
|
||||||
|
dl.field-list {
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
dl.field-list > dt {
|
||||||
|
flex-basis: 20%;
|
||||||
|
font-weight: bold;
|
||||||
|
word-break: break-word;
|
||||||
|
}
|
||||||
|
|
||||||
|
dl.field-list > dt:after {
|
||||||
|
content: ":";
|
||||||
|
}
|
||||||
|
|
||||||
|
dl.field-list > dd {
|
||||||
|
flex-basis: 70%;
|
||||||
|
padding-left: 1em;
|
||||||
|
margin-left: 0em;
|
||||||
|
margin-bottom: 0em;
|
||||||
|
}
|
||||||
|
|
||||||
dl {
|
dl {
|
||||||
margin-bottom: 15px;
|
margin-bottom: 15px;
|
||||||
}
|
}
|
||||||
|
|
||||||
dd p {
|
dd > p:first-child {
|
||||||
margin-top: 0px;
|
margin-top: 0px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ from sphinx.locale import _, __
|
|||||||
from sphinx.util import logging
|
from sphinx.util import logging
|
||||||
from sphinx.util.docutils import new_document
|
from sphinx.util.docutils import new_document
|
||||||
from sphinx.util.i18n import format_date
|
from sphinx.util.i18n import format_date
|
||||||
from sphinx.util.nodes import apply_source_workaround, is_smartquotable
|
from sphinx.util.nodes import NodeMatcher, apply_source_workaround, is_smartquotable
|
||||||
|
|
||||||
if False:
|
if False:
|
||||||
# For type annotation
|
# For type annotation
|
||||||
@@ -309,6 +309,19 @@ class UnreferencedFootnotesDetector(SphinxTransform):
|
|||||||
location=node)
|
location=node)
|
||||||
|
|
||||||
|
|
||||||
|
class FigureAligner(SphinxTransform):
|
||||||
|
"""
|
||||||
|
Align figures to center by default.
|
||||||
|
"""
|
||||||
|
default_priority = 700
|
||||||
|
|
||||||
|
def apply(self, **kwargs):
|
||||||
|
# type: (Any) -> None
|
||||||
|
matcher = NodeMatcher(nodes.table, nodes.figure)
|
||||||
|
for node in self.document.traverse(matcher): # type: nodes.Element
|
||||||
|
node.setdefault('align', 'center')
|
||||||
|
|
||||||
|
|
||||||
class FilterSystemMessages(SphinxTransform):
|
class FilterSystemMessages(SphinxTransform):
|
||||||
"""Filter system messages from a doctree."""
|
"""Filter system messages from a doctree."""
|
||||||
default_priority = 999
|
default_priority = 999
|
||||||
|
|||||||
@@ -27,6 +27,12 @@ _ansi_re = re.compile('\x1b\\[(\\d\\d;){0,2}\\d\\dm')
|
|||||||
codes = {} # type: Dict[str, str]
|
codes = {} # type: Dict[str, str]
|
||||||
|
|
||||||
|
|
||||||
|
def terminal_safe(s):
|
||||||
|
# type: (str) -> str
|
||||||
|
"""safely encode a string for printing to the terminal."""
|
||||||
|
return s.encode('ascii', 'backslashreplace').decode('ascii')
|
||||||
|
|
||||||
|
|
||||||
def get_terminal_width():
|
def get_terminal_width():
|
||||||
# type: () -> int
|
# type: () -> int
|
||||||
"""Borrowed from the py lib."""
|
"""Borrowed from the py lib."""
|
||||||
|
|||||||
@@ -23,10 +23,10 @@ from docutils import nodes
|
|||||||
from docutils.io import FileOutput
|
from docutils.io import FileOutput
|
||||||
from docutils.parsers.rst import Directive, directives, roles, convert_directive_function
|
from docutils.parsers.rst import Directive, directives, roles, convert_directive_function
|
||||||
from docutils.statemachine import StateMachine
|
from docutils.statemachine import StateMachine
|
||||||
from docutils.utils import Reporter
|
from docutils.utils import Reporter, unescape
|
||||||
|
|
||||||
from sphinx.deprecation import RemovedInSphinx30Warning
|
from sphinx.deprecation import RemovedInSphinx30Warning
|
||||||
from sphinx.errors import ExtensionError
|
from sphinx.errors import ExtensionError, SphinxError
|
||||||
from sphinx.locale import __
|
from sphinx.locale import __
|
||||||
from sphinx.util import logging
|
from sphinx.util import logging
|
||||||
|
|
||||||
@@ -36,7 +36,8 @@ report_re = re.compile('^(.+?:(?:\\d+)?): \\((DEBUG|INFO|WARNING|ERROR|SEVERE)/(
|
|||||||
if False:
|
if False:
|
||||||
# For type annotation
|
# For type annotation
|
||||||
from types import ModuleType # NOQA
|
from types import ModuleType # NOQA
|
||||||
from typing import Any, Callable, Generator, List, Set, Tuple, Type # NOQA
|
from typing import Any, Callable, Dict, Generator, List, Set, Tuple, Type # NOQA
|
||||||
|
from docutils.parsers.rst.states import Inliner # NOQA
|
||||||
from docutils.statemachine import State, StringList # NOQA
|
from docutils.statemachine import State, StringList # NOQA
|
||||||
from sphinx.builders import Builder # NOQA
|
from sphinx.builders import Builder # NOQA
|
||||||
from sphinx.config import Config # NOQA
|
from sphinx.config import Config # NOQA
|
||||||
@@ -383,6 +384,99 @@ class SphinxDirective(Directive):
|
|||||||
return self.env.config
|
return self.env.config
|
||||||
|
|
||||||
|
|
||||||
|
class SphinxRole:
|
||||||
|
"""A base class for Sphinx roles.
|
||||||
|
|
||||||
|
This class provides helper methods for Sphinx roles.
|
||||||
|
|
||||||
|
.. note:: The subclasses of this class might not work with docutils.
|
||||||
|
This class is strongly coupled with Sphinx.
|
||||||
|
"""
|
||||||
|
name = None #: The role name actually used in the document.
|
||||||
|
rawtext = None #: A string containing the entire interpreted text input.
|
||||||
|
text = None #: The interpreted text content.
|
||||||
|
lineno = None #: The line number where the interpreted text begins.
|
||||||
|
inliner = None #: The ``docutils.parsers.rst.states.Inliner`` object.
|
||||||
|
options = None #: A dictionary of directive options for customization
|
||||||
|
#: (from the "role" directive).
|
||||||
|
content = None #: A list of strings, the directive content for customization
|
||||||
|
#: (from the "role" directive).
|
||||||
|
|
||||||
|
def __call__(self, name, rawtext, text, lineno, inliner, options={}, content=[]):
|
||||||
|
# type: (str, str, str, int, Inliner, Dict, List[str]) -> Tuple[List[nodes.Node], List[nodes.system_message]] # NOQA
|
||||||
|
self.rawtext = rawtext
|
||||||
|
self.text = unescape(text)
|
||||||
|
self.lineno = lineno
|
||||||
|
self.inliner = inliner
|
||||||
|
self.options = options
|
||||||
|
self.content = content
|
||||||
|
|
||||||
|
# guess role type
|
||||||
|
if name:
|
||||||
|
self.name = name.lower()
|
||||||
|
else:
|
||||||
|
self.name = self.env.temp_data.get('default_role')
|
||||||
|
if not self.name:
|
||||||
|
self.name = self.env.config.default_role
|
||||||
|
if not self.name:
|
||||||
|
raise SphinxError('cannot determine default role!')
|
||||||
|
|
||||||
|
return self.run()
|
||||||
|
|
||||||
|
def run(self):
|
||||||
|
# type: () -> Tuple[List[nodes.Node], List[nodes.system_message]]
|
||||||
|
raise NotImplementedError
|
||||||
|
|
||||||
|
@property
|
||||||
|
def env(self):
|
||||||
|
# type: () -> BuildEnvironment
|
||||||
|
"""Reference to the :class:`.BuildEnvironment` object."""
|
||||||
|
return self.inliner.document.settings.env
|
||||||
|
|
||||||
|
@property
|
||||||
|
def config(self):
|
||||||
|
# type: () -> Config
|
||||||
|
"""Reference to the :class:`.Config` object."""
|
||||||
|
return self.env.config
|
||||||
|
|
||||||
|
def set_source_info(self, node, lineno=None):
|
||||||
|
# type: (nodes.Node, int) -> None
|
||||||
|
if lineno is None:
|
||||||
|
lineno = self.lineno
|
||||||
|
|
||||||
|
source_info = self.inliner.reporter.get_source_and_line(lineno) # type: ignore
|
||||||
|
node.source, node.line = source_info
|
||||||
|
|
||||||
|
|
||||||
|
class ReferenceRole(SphinxRole):
|
||||||
|
"""A base class for reference roles.
|
||||||
|
|
||||||
|
The reference roles can accpet ``link title <target>`` style as a text for
|
||||||
|
the role. The parsed result; link title and target will be stored to
|
||||||
|
``self.title`` and ``self.target``.
|
||||||
|
"""
|
||||||
|
has_explicit_title = None #: A boolean indicates the role has explicit title or not.
|
||||||
|
title = None #: The link title for the interpreted text.
|
||||||
|
target = None #: The link target for the interpreted text.
|
||||||
|
|
||||||
|
# \x00 means the "<" was backslash-escaped
|
||||||
|
explicit_title_re = re.compile(r'^(.+?)\s*(?<!\x00)<(.*?)>$', re.DOTALL)
|
||||||
|
|
||||||
|
def __call__(self, name, rawtext, text, lineno, inliner, options={}, content=[]):
|
||||||
|
# type: (str, str, str, int, Inliner, Dict, List[str]) -> Tuple[List[nodes.Node], List[nodes.system_message]] # NOQA
|
||||||
|
matched = self.explicit_title_re.match(text)
|
||||||
|
if matched:
|
||||||
|
self.has_explicit_title = True
|
||||||
|
self.title = unescape(matched.group(1))
|
||||||
|
self.target = unescape(matched.group(2))
|
||||||
|
else:
|
||||||
|
self.has_explicit_title = False
|
||||||
|
self.title = unescape(text)
|
||||||
|
self.target = unescape(text)
|
||||||
|
|
||||||
|
return super().__call__(name, rawtext, text, lineno, inliner, options, content)
|
||||||
|
|
||||||
|
|
||||||
class SphinxTranslator(nodes.NodeVisitor):
|
class SphinxTranslator(nodes.NodeVisitor):
|
||||||
"""A base class for Sphinx translators.
|
"""A base class for Sphinx translators.
|
||||||
|
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ from io import StringIO
|
|||||||
|
|
||||||
from sphinx.deprecation import RemovedInSphinx30Warning
|
from sphinx.deprecation import RemovedInSphinx30Warning
|
||||||
from sphinx.util import logging
|
from sphinx.util import logging
|
||||||
from sphinx.util.pycompat import NoneType
|
from sphinx.util.typing import NoneType
|
||||||
|
|
||||||
if False:
|
if False:
|
||||||
# For type annotation
|
# For type annotation
|
||||||
|
|||||||
@@ -285,6 +285,14 @@ def find_source_node(node):
|
|||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
def get_node_line(node):
|
||||||
|
# type: (nodes.Element) -> int
|
||||||
|
for pnode in traverse_parent(node):
|
||||||
|
if pnode.line:
|
||||||
|
return pnode.line
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
def traverse_parent(node, cls=None):
|
def traverse_parent(node, cls=None):
|
||||||
# type: (nodes.Element, Any) -> Iterable[nodes.Element]
|
# type: (nodes.Element, Any) -> Iterable[nodes.Element]
|
||||||
while node:
|
while node:
|
||||||
|
|||||||
@@ -17,6 +17,8 @@ import warnings
|
|||||||
from sphinx.deprecation import RemovedInSphinx40Warning, deprecated_alias
|
from sphinx.deprecation import RemovedInSphinx40Warning, deprecated_alias
|
||||||
from sphinx.locale import __
|
from sphinx.locale import __
|
||||||
from sphinx.util import logging
|
from sphinx.util import logging
|
||||||
|
from sphinx.util.console import terminal_safe
|
||||||
|
from sphinx.util.typing import NoneType
|
||||||
|
|
||||||
if False:
|
if False:
|
||||||
# For type annotation
|
# For type annotation
|
||||||
@@ -26,22 +28,9 @@ if False:
|
|||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
NoneType = type(None)
|
|
||||||
|
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
# Python 2/3 compatibility
|
# Python 2/3 compatibility
|
||||||
|
|
||||||
# sys_encoding: some kind of default system encoding; should be used with
|
|
||||||
# a lenient error handler
|
|
||||||
sys_encoding = sys.getdefaultencoding()
|
|
||||||
|
|
||||||
|
|
||||||
# terminal_safe(): safely encode a string for printing to the terminal
|
|
||||||
def terminal_safe(s):
|
|
||||||
# type: (str) -> str
|
|
||||||
return s.encode('ascii', 'backslashreplace').decode('ascii')
|
|
||||||
|
|
||||||
|
|
||||||
# convert_with_2to3():
|
# convert_with_2to3():
|
||||||
# support for running 2to3 over config files
|
# support for running 2to3 over config files
|
||||||
def convert_with_2to3(filepath):
|
def convert_with_2to3(filepath):
|
||||||
@@ -99,9 +88,12 @@ def execfile_(filepath, _globals, open=open):
|
|||||||
|
|
||||||
deprecated_alias('sphinx.util.pycompat',
|
deprecated_alias('sphinx.util.pycompat',
|
||||||
{
|
{
|
||||||
|
'NoneType': NoneType, # type: ignore
|
||||||
'TextIOWrapper': io.TextIOWrapper,
|
'TextIOWrapper': io.TextIOWrapper,
|
||||||
'htmlescape': html.escape,
|
'htmlescape': html.escape,
|
||||||
'indent': textwrap.indent,
|
'indent': textwrap.indent,
|
||||||
|
'terminal_safe': terminal_safe,
|
||||||
|
'sys_encoding': sys.getdefaultencoding(),
|
||||||
'u': '',
|
'u': '',
|
||||||
},
|
},
|
||||||
RemovedInSphinx40Warning)
|
RemovedInSphinx40Warning)
|
||||||
|
|||||||
@@ -20,6 +20,9 @@ DirectiveOption = Callable[[str], Any]
|
|||||||
# Text like nodes which are initialized with text and rawsource
|
# Text like nodes which are initialized with text and rawsource
|
||||||
TextlikeNode = Union[nodes.Text, nodes.TextElement]
|
TextlikeNode = Union[nodes.Text, nodes.TextElement]
|
||||||
|
|
||||||
|
# type of None
|
||||||
|
NoneType = type(None)
|
||||||
|
|
||||||
# common role functions
|
# common role functions
|
||||||
RoleFunction = Callable[[str, str, str, int, Inliner, Dict, List[str]],
|
RoleFunction = Callable[[str, str, str, int, Inliner, Dict, List[str]],
|
||||||
Tuple[List[nodes.Node], List[nodes.system_message]]]
|
Tuple[List[nodes.Node], List[nodes.system_message]]]
|
||||||
|
|||||||
@@ -247,7 +247,7 @@ class TexinfoTranslator(SphinxTranslator):
|
|||||||
title = self.settings.title # type: str
|
title = self.settings.title # type: str
|
||||||
if not title:
|
if not title:
|
||||||
title_node = self.document.next_node(nodes.title)
|
title_node = self.document.next_node(nodes.title)
|
||||||
title = (title and title_node.astext()) or '<untitled>'
|
title = (title_node and title_node.astext()) or '<untitled>'
|
||||||
elements['title'] = self.escape_id(title) or '<untitled>'
|
elements['title'] = self.escape_id(title) or '<untitled>'
|
||||||
# filename
|
# filename
|
||||||
if not elements['filename']:
|
if not elements['filename']:
|
||||||
|
|||||||
@@ -1 +0,0 @@
|
|||||||
project = 'test'
|
|
||||||
@@ -1,19 +0,0 @@
|
|||||||
Index markup
|
|
||||||
------------
|
|
||||||
|
|
||||||
.. index::
|
|
||||||
single: entry
|
|
||||||
pair: entry; pair
|
|
||||||
double: entry; double
|
|
||||||
triple: index; entry; triple
|
|
||||||
keyword: with
|
|
||||||
see: from; to
|
|
||||||
seealso: fromalso; toalso
|
|
||||||
|
|
||||||
.. index::
|
|
||||||
!Main, !Other
|
|
||||||
!single: entry; pair
|
|
||||||
|
|
||||||
.. index:: triple-quoted string, Unicode Consortium, raw string
|
|
||||||
single: """; string literal
|
|
||||||
single: '''; string literal
|
|
||||||
@@ -1,64 +0,0 @@
|
|||||||
@echo off
|
|
||||||
setlocal
|
|
||||||
|
|
||||||
pushd %~dp0
|
|
||||||
|
|
||||||
set this=%~n0
|
|
||||||
|
|
||||||
if not defined PYTHON set PYTHON=py
|
|
||||||
|
|
||||||
if not defined SPHINXBUILD (
|
|
||||||
%PYTHON% -c "import sphinx" > nul 2> nul
|
|
||||||
if errorlevel 1 (
|
|
||||||
echo Installing sphinx with %PYTHON%
|
|
||||||
%PYTHON% -m pip install sphinx
|
|
||||||
if errorlevel 1 exit /B
|
|
||||||
)
|
|
||||||
set SPHINXBUILD=%PYTHON% -c "import sphinx.cmd.build, sys; sys.exit(sphinx.cmd.build.main())"
|
|
||||||
)
|
|
||||||
|
|
||||||
rem Search for HHC in likely places
|
|
||||||
set HTMLHELP=
|
|
||||||
where hhc /q && set HTMLHELP=hhc && goto :skiphhcsearch
|
|
||||||
where /R ..\externals hhc > "%TEMP%\hhc.loc" 2> nul && set /P HTMLHELP= < "%TEMP%\hhc.loc" & del "%TEMP%\hhc.loc"
|
|
||||||
if not exist "%HTMLHELP%" where /R "%ProgramFiles(x86)%" hhc > "%TEMP%\hhc.loc" 2> nul && set /P HTMLHELP= < "%TEMP%\hhc.loc" & del "%TEMP%\hhc.loc"
|
|
||||||
if not exist "%HTMLHELP%" where /R "%ProgramFiles%" hhc > "%TEMP%\hhc.loc" 2> nul && set /P HTMLHELP= < "%TEMP%\hhc.loc" & del "%TEMP%\hhc.loc"
|
|
||||||
if not exist "%HTMLHELP%" (
|
|
||||||
echo.
|
|
||||||
echo.The HTML Help Workshop was not found. Set the HTMLHELP variable
|
|
||||||
echo.to the path to hhc.exe or download and install it from
|
|
||||||
echo.http://msdn.microsoft.com/en-us/library/ms669985
|
|
||||||
exit /B 1
|
|
||||||
)
|
|
||||||
echo hhc.exe path: %HTMLHELP%
|
|
||||||
|
|
||||||
if "%BUILDDIR%" EQU "" set BUILDDIR=build
|
|
||||||
|
|
||||||
%SPHINXBUILD% >nul 2> nul
|
|
||||||
if errorlevel 9009 (
|
|
||||||
echo.
|
|
||||||
echo.The 'sphinx-build' command was not found. Make sure you have Sphinx
|
|
||||||
echo.installed, then set the SPHINXBUILD environment variable to point
|
|
||||||
echo.to the full path of the 'sphinx-build' executable. Alternatively you
|
|
||||||
echo.may add the Sphinx directory to PATH.
|
|
||||||
popd
|
|
||||||
exit /B 1
|
|
||||||
)
|
|
||||||
|
|
||||||
set SPHINXOPTS=-D html_theme_options.body_max_width=none %SPHINXOPTS%
|
|
||||||
|
|
||||||
cmd /S /C "%SPHINXBUILD% %SPHINXOPTS% -bhtmlhelp -dbuild\doctrees . "%BUILDDIR%\htmlhelp"
|
|
||||||
|
|
||||||
"%HTMLHELP%" "%BUILDDIR%\htmlhelp\test.hhp"
|
|
||||||
rem hhc.exe seems to always exit with code 1, reset to 0 for less than 2
|
|
||||||
if not errorlevel 2 cmd /C exit /b 0
|
|
||||||
|
|
||||||
echo.
|
|
||||||
if errorlevel 1 (
|
|
||||||
echo.Build failed (exit code %ERRORLEVEL%^), check for error messages
|
|
||||||
echo.above. Any output will be found in %BUILDDIR%\%1
|
|
||||||
) else (
|
|
||||||
echo.Build succeeded. All output should be in %BUILDDIR%\%1
|
|
||||||
)
|
|
||||||
|
|
||||||
popd
|
|
||||||
@@ -1,2 +1 @@
|
|||||||
html_theme = 'classic'
|
|
||||||
exclude_patterns = ['_build']
|
exclude_patterns = ['_build']
|
||||||
|
|||||||
@@ -1,2 +1 @@
|
|||||||
html_theme = 'classic'
|
|
||||||
exclude_patterns = ['_build']
|
exclude_patterns = ['_build']
|
||||||
|
|||||||
@@ -1,2 +1 @@
|
|||||||
html_theme = 'classic'
|
|
||||||
exclude_patterns = ['_build']
|
exclude_patterns = ['_build']
|
||||||
|
|||||||
@@ -15,6 +15,11 @@ def decoratedFunction():
|
|||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
def func(arg: missing_module.Class):
|
||||||
|
"""a function takes mocked object as an argument"""
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
class TestAutodoc(object):
|
class TestAutodoc(object):
|
||||||
"""TestAutodoc docstring."""
|
"""TestAutodoc docstring."""
|
||||||
@missing_name
|
@missing_name
|
||||||
|
|||||||
@@ -15,6 +15,12 @@ For Windows users
|
|||||||
For UNIX users
|
For UNIX users
|
||||||
--------------
|
--------------
|
||||||
|
|
||||||
|
Linux
|
||||||
|
^^^^^
|
||||||
|
|
||||||
|
FreeBSD
|
||||||
|
^^^^^^^
|
||||||
|
|
||||||
This one's got an apostrophe
|
This one's got an apostrophe
|
||||||
----------------------------
|
----------------------------
|
||||||
|
|
||||||
@@ -26,4 +32,6 @@ References
|
|||||||
* :ref:`index:Installation`
|
* :ref:`index:Installation`
|
||||||
* :ref:`index:For Windows users`
|
* :ref:`index:For Windows users`
|
||||||
* :ref:`index:For UNIX users`
|
* :ref:`index:For UNIX users`
|
||||||
|
* :ref:`index:Linux`
|
||||||
|
* :ref:`index:FreeBSD`
|
||||||
* :ref:`index:This one's got an apostrophe`
|
* :ref:`index:This one's got an apostrophe`
|
||||||
|
|||||||
@@ -15,15 +15,23 @@ For Windows users
|
|||||||
For UNIX users
|
For UNIX users
|
||||||
--------------
|
--------------
|
||||||
|
|
||||||
|
Linux
|
||||||
|
^^^^^
|
||||||
|
|
||||||
|
FreeBSD
|
||||||
|
^^^^^^^
|
||||||
|
|
||||||
This one's got an apostrophe
|
This one's got an apostrophe
|
||||||
----------------------------
|
----------------------------
|
||||||
|
|
||||||
|
|
||||||
References
|
References
|
||||||
==========
|
==========
|
||||||
|
|
||||||
|
* :ref:`test-ext-autosectionlabel`
|
||||||
* :ref:`Introduce of Sphinx`
|
* :ref:`Introduce of Sphinx`
|
||||||
* :ref:`Installation`
|
* :ref:`Installation`
|
||||||
* :ref:`For Windows users`
|
* :ref:`For Windows users`
|
||||||
* :ref:`For UNIX users`
|
* :ref:`For UNIX users`
|
||||||
|
* :ref:`Linux`
|
||||||
|
* :ref:`FreeBSD`
|
||||||
* :ref:`This one's got an apostrophe`
|
* :ref:`This one's got an apostrophe`
|
||||||
|
|||||||
7
tests/roots/test-ext-autosummary-mock_imports/conf.py
Normal file
7
tests/roots/test-ext-autosummary-mock_imports/conf.py
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
import os
|
||||||
|
import sys
|
||||||
|
sys.path.insert(0, os.path.abspath('.'))
|
||||||
|
|
||||||
|
extensions = ['sphinx.ext.autosummary']
|
||||||
|
autosummary_generate = True
|
||||||
|
autosummary_mock_imports = ['unknown']
|
||||||
6
tests/roots/test-ext-autosummary-mock_imports/foo.py
Normal file
6
tests/roots/test-ext-autosummary-mock_imports/foo.py
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
import unknown
|
||||||
|
|
||||||
|
|
||||||
|
class Foo(unknown.Class):
|
||||||
|
"""Foo class"""
|
||||||
|
pass
|
||||||
7
tests/roots/test-ext-autosummary-mock_imports/index.rst
Normal file
7
tests/roots/test-ext-autosummary-mock_imports/index.rst
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
test-ext-autosummary-mock_imports
|
||||||
|
=================================
|
||||||
|
|
||||||
|
.. autosummary::
|
||||||
|
:toctree: generated
|
||||||
|
|
||||||
|
foo
|
||||||
@@ -1,2 +1 @@
|
|||||||
html_theme = 'classic'
|
|
||||||
exclude_patterns = ['_build']
|
exclude_patterns = ['_build']
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ Empty cell
|
|||||||
----------
|
----------
|
||||||
|
|
||||||
.. list-table::
|
.. list-table::
|
||||||
:header-rows: 1
|
|
||||||
- * un
|
- * un
|
||||||
*
|
*
|
||||||
* trois
|
* trois
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
\label{\detokenize{longtable:longtable}}
|
\label{\detokenize{longtable:longtable}}
|
||||||
|
|
||||||
\begin{savenotes}\sphinxatlongtablestart\begin{longtable}{|l|l|}
|
\begin{savenotes}\sphinxatlongtablestart\begin{longtable}[c]{|l|l|}
|
||||||
\hline
|
\hline
|
||||||
\sphinxstyletheadfamily
|
\sphinxstyletheadfamily
|
||||||
header1
|
header1
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
\label{\detokenize{longtable:longtable-having-caption}}
|
\label{\detokenize{longtable:longtable-having-caption}}
|
||||||
|
|
||||||
\begin{savenotes}\sphinxatlongtablestart\begin{longtable}{|l|l|}
|
\begin{savenotes}\sphinxatlongtablestart\begin{longtable}[c]{|l|l|}
|
||||||
\sphinxthelongtablecaptionisattop
|
\sphinxthelongtablecaptionisattop
|
||||||
\caption{caption for longtable\strut}\label{\detokenize{longtable:id1}}\\*[\sphinxlongtablecapskipadjust]
|
\caption{caption for longtable\strut}\label{\detokenize{longtable:id1}}\\*[\sphinxlongtablecapskipadjust]
|
||||||
\hline
|
\hline
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
\label{\detokenize{longtable:longtable-having-problematic-cell}}
|
\label{\detokenize{longtable:longtable-having-problematic-cell}}
|
||||||
|
|
||||||
\begin{savenotes}\sphinxatlongtablestart\begin{longtable}{|*{2}{\X{1}{2}|}}
|
\begin{savenotes}\sphinxatlongtablestart\begin{longtable}[c]{|*{2}{\X{1}{2}|}}
|
||||||
\hline
|
\hline
|
||||||
\sphinxstyletheadfamily
|
\sphinxstyletheadfamily
|
||||||
header1
|
header1
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
\label{\detokenize{longtable:longtable-having-both-stub-columns-and-problematic-cell}}
|
\label{\detokenize{longtable:longtable-having-both-stub-columns-and-problematic-cell}}
|
||||||
|
|
||||||
\begin{savenotes}\sphinxatlongtablestart\begin{longtable}{|*{3}{\X{1}{3}|}}
|
\begin{savenotes}\sphinxatlongtablestart\begin{longtable}[c]{|*{3}{\X{1}{3}|}}
|
||||||
\hline
|
\hline
|
||||||
\sphinxstyletheadfamily
|
\sphinxstyletheadfamily
|
||||||
header1
|
header1
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
\label{\detokenize{longtable:longtable-having-verbatim}}
|
\label{\detokenize{longtable:longtable-having-verbatim}}
|
||||||
|
|
||||||
\begin{savenotes}\sphinxatlongtablestart\begin{longtable}{|*{2}{\X{1}{2}|}}
|
\begin{savenotes}\sphinxatlongtablestart\begin{longtable}[c]{|*{2}{\X{1}{2}|}}
|
||||||
\hline
|
\hline
|
||||||
\sphinxstyletheadfamily
|
\sphinxstyletheadfamily
|
||||||
header1
|
header1
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
\label{\detokenize{longtable:longtable-having-widths-option}}
|
\label{\detokenize{longtable:longtable-having-widths-option}}
|
||||||
|
|
||||||
\begin{savenotes}\sphinxatlongtablestart\begin{longtable}{|\X{30}{100}|\X{70}{100}|}
|
\begin{savenotes}\sphinxatlongtablestart\begin{longtable}[c]{|\X{30}{100}|\X{70}{100}|}
|
||||||
\hline\noalign{\phantomsection\label{\detokenize{longtable:namedlongtable}}\label{\detokenize{longtable:mylongtable}}}%
|
\hline\noalign{\phantomsection\label{\detokenize{longtable:namedlongtable}}\label{\detokenize{longtable:mylongtable}}}%
|
||||||
\sphinxstyletheadfamily
|
\sphinxstyletheadfamily
|
||||||
header1
|
header1
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
\label{\detokenize{longtable:longtable-having-both-widths-and-problematic-cell}}
|
\label{\detokenize{longtable:longtable-having-both-widths-and-problematic-cell}}
|
||||||
|
|
||||||
\begin{savenotes}\sphinxatlongtablestart\begin{longtable}{|\X{30}{100}|\X{70}{100}|}
|
\begin{savenotes}\sphinxatlongtablestart\begin{longtable}[c]{|\X{30}{100}|\X{70}{100}|}
|
||||||
\hline
|
\hline
|
||||||
\sphinxstyletheadfamily
|
\sphinxstyletheadfamily
|
||||||
header1
|
header1
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
\label{\detokenize{longtable:longtable-with-tabularcolumn}}
|
\label{\detokenize{longtable:longtable-with-tabularcolumn}}
|
||||||
|
|
||||||
\begin{savenotes}\sphinxatlongtablestart\begin{longtable}{|c|c|}
|
\begin{savenotes}\sphinxatlongtablestart\begin{longtable}[c]{|c|c|}
|
||||||
\hline
|
\hline
|
||||||
\sphinxstyletheadfamily
|
\sphinxstyletheadfamily
|
||||||
header1
|
header1
|
||||||
|
|||||||
@@ -11,3 +11,6 @@ Some additional anchors to exercise ignore code
|
|||||||
* `Example Bar invalid <http://example.com/#top>`_
|
* `Example Bar invalid <http://example.com/#top>`_
|
||||||
* `Example anchor invalid <http://www.sphinx-doc.org/en/1.7/intro.html#does-not-exist>`_
|
* `Example anchor invalid <http://www.sphinx-doc.org/en/1.7/intro.html#does-not-exist>`_
|
||||||
* `Complete nonsense <https://localhost:7777/doesnotexist>`_
|
* `Complete nonsense <https://localhost:7777/doesnotexist>`_
|
||||||
|
|
||||||
|
.. image:: http://example.com/image.png
|
||||||
|
.. figure:: http://example.com/image2.png
|
||||||
|
|||||||
@@ -1,2 +1 @@
|
|||||||
html_theme = 'classic'
|
|
||||||
exclude_patterns = ['_build']
|
exclude_patterns = ['_build']
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
html_theme = 'classic'
|
|
||||||
exclude_patterns = ['_build']
|
exclude_patterns = ['_build']
|
||||||
|
|
||||||
latex_elements = {
|
latex_elements = {
|
||||||
|
|||||||
@@ -1,2 +1 @@
|
|||||||
html_theme = 'classic'
|
|
||||||
exclude_patterns = ['_build']
|
exclude_patterns = ['_build']
|
||||||
|
|||||||
@@ -3,8 +3,6 @@ Autodoc tests
|
|||||||
|
|
||||||
Just testing a few autodoc possibilities...
|
Just testing a few autodoc possibilities...
|
||||||
|
|
||||||
.. automodule:: util
|
|
||||||
|
|
||||||
.. automodule:: autodoc_target
|
.. automodule:: autodoc_target
|
||||||
:members:
|
:members:
|
||||||
|
|
||||||
@@ -28,12 +26,6 @@ Just testing a few autodoc possibilities...
|
|||||||
:members:
|
:members:
|
||||||
|
|
||||||
|
|
||||||
.. automodule:: autodoc_fodder
|
|
||||||
:noindex:
|
|
||||||
|
|
||||||
.. autoclass:: MarkupError
|
|
||||||
|
|
||||||
|
|
||||||
.. currentmodule:: autodoc_target
|
.. currentmodule:: autodoc_target
|
||||||
|
|
||||||
.. autoclass:: InstAttCls
|
.. autoclass:: InstAttCls
|
||||||
|
|||||||
@@ -1,7 +0,0 @@
|
|||||||
|
|
||||||
class MarkupError(object):
|
|
||||||
"""
|
|
||||||
.. note:: This is a docstring with a
|
|
||||||
small markup error which should have
|
|
||||||
correct location information.
|
|
||||||
"""
|
|
||||||
@@ -4,9 +4,6 @@ Sphinx image handling
|
|||||||
.. first, a simple test with direct filename
|
.. first, a simple test with direct filename
|
||||||
.. image:: img.png
|
.. image:: img.png
|
||||||
|
|
||||||
.. a non-existing image with direct filename
|
|
||||||
.. image:: foo.png
|
|
||||||
|
|
||||||
.. an image with path name (relative to this directory!)
|
.. an image with path name (relative to this directory!)
|
||||||
.. image:: subdir/img.png
|
.. image:: subdir/img.png
|
||||||
:height: 100
|
:height: 100
|
||||||
|
|||||||
@@ -3,7 +3,6 @@ Testing downloadable files
|
|||||||
|
|
||||||
Download :download:`img.png` here.
|
Download :download:`img.png` here.
|
||||||
Download :download:`this <subdir/img.png>` there.
|
Download :download:`this <subdir/img.png>` there.
|
||||||
Don't download :download:`this <nonexisting.png>`.
|
|
||||||
|
|
||||||
Test file and literal inclusion
|
Test file and literal inclusion
|
||||||
===============================
|
===============================
|
||||||
|
|||||||
@@ -2,4 +2,4 @@
|
|||||||
|
|
||||||
.. Paths in included files are relative to the file that
|
.. Paths in included files are relative to the file that
|
||||||
includes them
|
includes them
|
||||||
.. image:: ../root/img.png
|
.. image:: subdir/img.png
|
||||||
|
|||||||
@@ -1,3 +1,2 @@
|
|||||||
html_theme = 'classic'
|
|
||||||
exclude_patterns = ['_build']
|
exclude_patterns = ['_build']
|
||||||
templates_path = ['_templates']
|
templates_path = ['_templates']
|
||||||
|
|||||||
@@ -1,2 +1 @@
|
|||||||
html_theme = 'classic'
|
|
||||||
exclude_patterns = ['_build']
|
exclude_patterns = ['_build']
|
||||||
|
|||||||
@@ -1,2 +1 @@
|
|||||||
html_theme = 'classic'
|
|
||||||
exclude_patterns = ['_build']
|
exclude_patterns = ['_build']
|
||||||
|
|||||||
@@ -12,6 +12,8 @@ import sys
|
|||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
|
from sphinx.util import docutils
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture(scope='module', autouse=True)
|
@pytest.fixture(scope='module', autouse=True)
|
||||||
def setup_module(rootdir):
|
def setup_module(rootdir):
|
||||||
@@ -26,7 +28,10 @@ def test_html_translator(app, status, warning):
|
|||||||
# no set_translator()
|
# no set_translator()
|
||||||
translator_class = app.builder.get_translator_class()
|
translator_class = app.builder.get_translator_class()
|
||||||
assert translator_class
|
assert translator_class
|
||||||
assert translator_class.__name__ == 'HTMLTranslator'
|
if docutils.__version_info__ < (0, 13):
|
||||||
|
assert translator_class.__name__ == 'HTMLTranslator'
|
||||||
|
else:
|
||||||
|
assert translator_class.__name__ == 'HTML5Translator'
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.sphinx('html', testroot='api-set-translator')
|
@pytest.mark.sphinx('html', testroot='api-set-translator')
|
||||||
|
|||||||
@@ -1345,7 +1345,7 @@ def test_autofunction_for_callable(app):
|
|||||||
@pytest.mark.sphinx('html', testroot='ext-autodoc')
|
@pytest.mark.sphinx('html', testroot='ext-autodoc')
|
||||||
def test_mocked_module_imports(app, warning):
|
def test_mocked_module_imports(app, warning):
|
||||||
# no autodoc_mock_imports
|
# no autodoc_mock_imports
|
||||||
options = {"members": 'TestAutodoc,decoratedFunction'}
|
options = {"members": 'TestAutodoc,decoratedFunction,func'}
|
||||||
actual = do_autodoc(app, 'module', 'target.need_mocks', options)
|
actual = do_autodoc(app, 'module', 'target.need_mocks', options)
|
||||||
assert list(actual) == []
|
assert list(actual) == []
|
||||||
assert "autodoc: failed to import module 'need_mocks'" in warning.getvalue()
|
assert "autodoc: failed to import module 'need_mocks'" in warning.getvalue()
|
||||||
@@ -1382,6 +1382,12 @@ def test_mocked_module_imports(app, warning):
|
|||||||
' :module: target.need_mocks',
|
' :module: target.need_mocks',
|
||||||
'',
|
'',
|
||||||
' decoratedFunction docstring',
|
' decoratedFunction docstring',
|
||||||
|
' ',
|
||||||
|
'',
|
||||||
|
'.. py:function:: func(arg: missing_module.Class)',
|
||||||
|
' :module: target.need_mocks',
|
||||||
|
'',
|
||||||
|
' a function takes mocked object as an argument',
|
||||||
' '
|
' '
|
||||||
]
|
]
|
||||||
assert warning.getvalue() == ''
|
assert warning.getvalue() == ''
|
||||||
@@ -1511,6 +1517,12 @@ def test_autodoc_default_options(app):
|
|||||||
assert ' .. py:attribute:: EnumCls.val1' in actual
|
assert ' .. py:attribute:: EnumCls.val1' in actual
|
||||||
assert ' .. py:attribute:: EnumCls.val4' not in actual
|
assert ' .. py:attribute:: EnumCls.val4' not in actual
|
||||||
|
|
||||||
|
# with :members: = True
|
||||||
|
app.config.autodoc_default_options = {'members': True}
|
||||||
|
actual = do_autodoc(app, 'class', 'target.enum.EnumCls')
|
||||||
|
assert ' .. py:attribute:: EnumCls.val1' in actual
|
||||||
|
assert ' .. py:attribute:: EnumCls.val4' not in actual
|
||||||
|
|
||||||
# with :members: and :undoc-members:
|
# with :members: and :undoc-members:
|
||||||
app.config.autodoc_default_options = {
|
app.config.autodoc_default_options = {
|
||||||
'members': None,
|
'members': None,
|
||||||
|
|||||||
@@ -60,7 +60,7 @@ def nonascii_srcdir(request, rootdir, sphinx_test_tempdir):
|
|||||||
"buildername",
|
"buildername",
|
||||||
[
|
[
|
||||||
# note: no 'html' - if it's ok with dirhtml it's ok with html
|
# note: no 'html' - if it's ok with dirhtml it's ok with html
|
||||||
'dirhtml', 'singlehtml', 'pickle', 'json', 'text', 'htmlhelp',
|
'dirhtml', 'singlehtml', 'pickle', 'json', 'text',
|
||||||
'changes', 'xml', 'pseudoxml', 'linkcheck',
|
'changes', 'xml', 'pseudoxml', 'linkcheck',
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -15,6 +15,8 @@ from xml.etree import ElementTree
|
|||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
|
from sphinx.util import docutils
|
||||||
|
|
||||||
|
|
||||||
# check given command is runnable
|
# check given command is runnable
|
||||||
def runnable(command):
|
def runnable(command):
|
||||||
@@ -350,6 +352,8 @@ def test_epub_css_files(app):
|
|||||||
'href="https://example.com/custom.css" />' not in content)
|
'href="https://example.com/custom.css" />' not in content)
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.skipif(docutils.__version_info__ < (0, 13),
|
||||||
|
reason='docutils-0.13 or above is required')
|
||||||
@pytest.mark.sphinx('epub', testroot='roles-download')
|
@pytest.mark.sphinx('epub', testroot='roles-download')
|
||||||
def test_html_download_role(app, status, warning):
|
def test_html_download_role(app, status, warning):
|
||||||
app.build()
|
app.build()
|
||||||
|
|||||||
@@ -10,6 +10,7 @@
|
|||||||
|
|
||||||
import os
|
import os
|
||||||
import re
|
import re
|
||||||
|
from hashlib import md5
|
||||||
from itertools import cycle, chain
|
from itertools import cycle, chain
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
@@ -17,6 +18,7 @@ from html5lib import HTMLParser
|
|||||||
|
|
||||||
from sphinx.errors import ConfigError
|
from sphinx.errors import ConfigError
|
||||||
from sphinx.testing.util import strip_escseq
|
from sphinx.testing.util import strip_escseq
|
||||||
|
from sphinx.util import docutils
|
||||||
from sphinx.util.inventory import InventoryFile
|
from sphinx.util.inventory import InventoryFile
|
||||||
|
|
||||||
|
|
||||||
@@ -128,6 +130,11 @@ def test_html_warnings(app, warning):
|
|||||||
'--- Got:\n' + html_warnings
|
'--- Got:\n' + html_warnings
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.sphinx('html', confoverrides={'html4_writer': True})
|
||||||
|
def test_html4_output(app, status, warning):
|
||||||
|
app.build()
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.parametrize("fname,expect", flat_dict({
|
@pytest.mark.parametrize("fname,expect", flat_dict({
|
||||||
'images.html': [
|
'images.html': [
|
||||||
(".//img[@src='_images/img.png']", ''),
|
(".//img[@src='_images/img.png']", ''),
|
||||||
@@ -192,18 +199,18 @@ def test_html_warnings(app, warning):
|
|||||||
# an option list
|
# an option list
|
||||||
(".//span[@class='option']", '--help'),
|
(".//span[@class='option']", '--help'),
|
||||||
# admonitions
|
# admonitions
|
||||||
(".//p[@class='first admonition-title']", 'My Admonition'),
|
(".//p[@class='admonition-title']", 'My Admonition'),
|
||||||
(".//p[@class='last']", 'Note text.'),
|
(".//div[@class='admonition note']/p", 'Note text.'),
|
||||||
(".//p[@class='last']", 'Warning text.'),
|
(".//div[@class='admonition warning']/p", 'Warning text.'),
|
||||||
# inline markup
|
# inline markup
|
||||||
(".//li/strong", r'^command\\n$'),
|
(".//li/p/strong", r'^command\\n$'),
|
||||||
(".//li/strong", r'^program\\n$'),
|
(".//li/p/strong", r'^program\\n$'),
|
||||||
(".//li/em", r'^dfn\\n$'),
|
(".//li/p/em", r'^dfn\\n$'),
|
||||||
(".//li/kbd", r'^kbd\\n$'),
|
(".//li/p/kbd", r'^kbd\\n$'),
|
||||||
(".//li/span", 'File \N{TRIANGULAR BULLET} Close'),
|
(".//li/p/span", 'File \N{TRIANGULAR BULLET} Close'),
|
||||||
(".//li/code/span[@class='pre']", '^a/$'),
|
(".//li/p/code/span[@class='pre']", '^a/$'),
|
||||||
(".//li/code/em/span[@class='pre']", '^varpart$'),
|
(".//li/p/code/em/span[@class='pre']", '^varpart$'),
|
||||||
(".//li/code/em/span[@class='pre']", '^i$'),
|
(".//li/p/code/em/span[@class='pre']", '^i$'),
|
||||||
(".//a[@href='https://www.python.org/dev/peps/pep-0008']"
|
(".//a[@href='https://www.python.org/dev/peps/pep-0008']"
|
||||||
"[@class='pep reference external']/strong", 'PEP 8'),
|
"[@class='pep reference external']/strong", 'PEP 8'),
|
||||||
(".//a[@href='https://www.python.org/dev/peps/pep-0008']"
|
(".//a[@href='https://www.python.org/dev/peps/pep-0008']"
|
||||||
@@ -236,13 +243,13 @@ def test_html_warnings(app, warning):
|
|||||||
(".//div[@class='versionchanged']/p",
|
(".//div[@class='versionchanged']/p",
|
||||||
'Second paragraph of versionchanged'),
|
'Second paragraph of versionchanged'),
|
||||||
# footnote reference
|
# footnote reference
|
||||||
(".//a[@class='footnote-reference']", r'\[1\]'),
|
(".//a[@class='footnote-reference brackets']", r'1'),
|
||||||
# created by reference lookup
|
# created by reference lookup
|
||||||
(".//a[@href='index.html#ref1']", ''),
|
(".//a[@href='index.html#ref1']", ''),
|
||||||
# ``seealso`` directive
|
# ``seealso`` directive
|
||||||
(".//div/p[@class='first admonition-title']", 'See also'),
|
(".//div/p[@class='admonition-title']", 'See also'),
|
||||||
# a ``hlist`` directive
|
# a ``hlist`` directive
|
||||||
(".//table[@class='hlist']/tbody/tr/td/ul/li", '^This$'),
|
(".//table[@class='hlist']/tbody/tr/td/ul/li/p", '^This$'),
|
||||||
# a ``centered`` directive
|
# a ``centered`` directive
|
||||||
(".//p[@class='centered']/strong", 'LICENSE'),
|
(".//p[@class='centered']/strong", 'LICENSE'),
|
||||||
# a glossary
|
# a glossary
|
||||||
@@ -261,10 +268,10 @@ def test_html_warnings(app, warning):
|
|||||||
# tests for numeric labels
|
# tests for numeric labels
|
||||||
(".//a[@href='#id1'][@class='reference internal']/span", 'Testing various markup'),
|
(".//a[@href='#id1'][@class='reference internal']/span", 'Testing various markup'),
|
||||||
# tests for smartypants
|
# tests for smartypants
|
||||||
(".//li", 'Smart “quotes” in English ‘text’.'),
|
(".//li/p", 'Smart “quotes” in English ‘text’.'),
|
||||||
(".//li", 'Smart — long and – short dashes.'),
|
(".//li/p", 'Smart — long and – short dashes.'),
|
||||||
(".//li", 'Ellipsis…'),
|
(".//li/p", 'Ellipsis…'),
|
||||||
(".//li//code//span[@class='pre']", 'foo--"bar"...'),
|
(".//li/p/code/span[@class='pre']", 'foo--"bar"...'),
|
||||||
(".//p", 'Этот «абзац» должен использовать „русские“ кавычки.'),
|
(".//p", 'Этот «абзац» должен использовать „русские“ кавычки.'),
|
||||||
(".//p", 'Il dit : « C’est “super” ! »'),
|
(".//p", 'Il dit : « C’est “super” ! »'),
|
||||||
],
|
],
|
||||||
@@ -294,24 +301,24 @@ def test_html_warnings(app, warning):
|
|||||||
(".//li[@class='toctree-l1']/a[@href='markup.html']",
|
(".//li[@class='toctree-l1']/a[@href='markup.html']",
|
||||||
'Testing various markup'),
|
'Testing various markup'),
|
||||||
# test unknown field names
|
# test unknown field names
|
||||||
(".//th[@class='field-name']", 'Field_name:'),
|
(".//dt[@class='field-odd']", 'Field_name'),
|
||||||
(".//th[@class='field-name']", 'Field_name all lower:'),
|
(".//dt[@class='field-even']", 'Field_name all lower'),
|
||||||
(".//th[@class='field-name']", 'FIELD_NAME:'),
|
(".//dt[@class='field-odd']", 'FIELD_NAME'),
|
||||||
(".//th[@class='field-name']", 'FIELD_NAME ALL CAPS:'),
|
(".//dt[@class='field-even']", 'FIELD_NAME ALL CAPS'),
|
||||||
(".//th[@class='field-name']", 'Field_Name:'),
|
(".//dt[@class='field-odd']", 'Field_Name'),
|
||||||
(".//th[@class='field-name']", 'Field_Name All Word Caps:'),
|
(".//dt[@class='field-even']", 'Field_Name All Word Caps'),
|
||||||
(".//th[@class='field-name']", 'Field_name:'),
|
(".//dt[@class='field-odd']", 'Field_name'),
|
||||||
(".//th[@class='field-name']", 'Field_name First word cap:'),
|
(".//dt[@class='field-even']", 'Field_name First word cap'),
|
||||||
(".//th[@class='field-name']", 'FIELd_name:'),
|
(".//dt[@class='field-odd']", 'FIELd_name'),
|
||||||
(".//th[@class='field-name']", 'FIELd_name PARTial caps:'),
|
(".//dt[@class='field-even']", 'FIELd_name PARTial caps'),
|
||||||
# custom sidebar
|
# custom sidebar
|
||||||
(".//h4", 'Custom sidebar'),
|
(".//h4", 'Custom sidebar'),
|
||||||
# docfields
|
# docfields
|
||||||
(".//td[@class='field-body']/strong", '^moo$'),
|
(".//dd[@class='field-odd']/p/strong", '^moo$'),
|
||||||
(".//td[@class='field-body']/strong", tail_check(r'\(Moo\) .* Moo')),
|
(".//dd[@class='field-odd']/p/strong", tail_check(r'\(Moo\) .* Moo')),
|
||||||
(".//td[@class='field-body']/ul/li/strong", '^hour$'),
|
(".//dd[@class='field-odd']/ul/li/p/strong", '^hour$'),
|
||||||
(".//td[@class='field-body']/ul/li/em", '^DuplicateType$'),
|
(".//dd[@class='field-odd']/ul/li/p/em", '^DuplicateType$'),
|
||||||
(".//td[@class='field-body']/ul/li/em", tail_check(r'.* Some parameter')),
|
(".//dd[@class='field-odd']/ul/li/p/em", tail_check(r'.* Some parameter')),
|
||||||
# others
|
# others
|
||||||
(".//a[@class='reference internal'][@href='#cmdoption-perl-arg-p']/code/span",
|
(".//a[@class='reference internal'][@href='#cmdoption-perl-arg-p']/code/span",
|
||||||
'perl'),
|
'perl'),
|
||||||
@@ -340,17 +347,17 @@ def test_html_warnings(app, warning):
|
|||||||
'index.html': [
|
'index.html': [
|
||||||
(".//meta[@name='hc'][@content='hcval']", ''),
|
(".//meta[@name='hc'][@content='hcval']", ''),
|
||||||
(".//meta[@name='hc_co'][@content='hcval_co']", ''),
|
(".//meta[@name='hc_co'][@content='hcval_co']", ''),
|
||||||
(".//td[@class='label']", r'\[Ref1\]'),
|
(".//dt[@class='label']/span[@class='brackets']", r'Ref1'),
|
||||||
(".//td[@class='label']", ''),
|
(".//dt[@class='label']", ''),
|
||||||
(".//li[@class='toctree-l1']/a", 'Testing various markup'),
|
(".//li[@class='toctree-l1']/a", 'Testing various markup'),
|
||||||
(".//li[@class='toctree-l2']/a", 'Inline markup'),
|
(".//li[@class='toctree-l2']/a", 'Inline markup'),
|
||||||
(".//title", 'Sphinx <Tests>'),
|
(".//title", 'Sphinx <Tests>'),
|
||||||
(".//div[@class='footer']", 'Georg Brandl & Team'),
|
(".//div[@class='footer']", 'Georg Brandl & Team'),
|
||||||
(".//a[@href='http://python.org/']"
|
(".//a[@href='http://python.org/']"
|
||||||
"[@class='reference external']", ''),
|
"[@class='reference external']", ''),
|
||||||
(".//li/a[@href='genindex.html']/span", 'Index'),
|
(".//li/p/a[@href='genindex.html']/span", 'Index'),
|
||||||
(".//li/a[@href='py-modindex.html']/span", 'Module Index'),
|
(".//li/p/a[@href='py-modindex.html']/span", 'Module Index'),
|
||||||
(".//li/a[@href='search.html']/span", 'Search Page'),
|
(".//li/p/a[@href='search.html']/span", 'Search Page'),
|
||||||
# custom sidebar only for contents
|
# custom sidebar only for contents
|
||||||
(".//h4", 'Contents sidebar'),
|
(".//h4", 'Contents sidebar'),
|
||||||
# custom JavaScript
|
# custom JavaScript
|
||||||
@@ -381,37 +388,41 @@ def test_html_warnings(app, warning):
|
|||||||
(".//li/a", "double"),
|
(".//li/a", "double"),
|
||||||
],
|
],
|
||||||
'footnote.html': [
|
'footnote.html': [
|
||||||
(".//a[@class='footnote-reference'][@href='#id9'][@id='id1']", r"\[1\]"),
|
(".//a[@class='footnote-reference brackets'][@href='#id9'][@id='id1']", r"1"),
|
||||||
(".//a[@class='footnote-reference'][@href='#id10'][@id='id2']", r"\[2\]"),
|
(".//a[@class='footnote-reference brackets'][@href='#id10'][@id='id2']", r"2"),
|
||||||
(".//a[@class='footnote-reference'][@href='#foo'][@id='id3']", r"\[3\]"),
|
(".//a[@class='footnote-reference brackets'][@href='#foo'][@id='id3']", r"3"),
|
||||||
(".//a[@class='reference internal'][@href='#bar'][@id='id4']", r"\[bar\]"),
|
(".//a[@class='reference internal'][@href='#bar'][@id='id4']", r"\[bar\]"),
|
||||||
(".//a[@class='reference internal'][@href='#baz-qux'][@id='id5']", r"\[baz_qux\]"),
|
(".//a[@class='reference internal'][@href='#baz-qux'][@id='id5']", r"\[baz_qux\]"),
|
||||||
(".//a[@class='footnote-reference'][@href='#id11'][@id='id6']", r"\[4\]"),
|
(".//a[@class='footnote-reference brackets'][@href='#id11'][@id='id6']", r"4"),
|
||||||
(".//a[@class='footnote-reference'][@href='#id12'][@id='id7']", r"\[5\]"),
|
(".//a[@class='footnote-reference brackets'][@href='#id12'][@id='id7']", r"5"),
|
||||||
(".//a[@class='fn-backref'][@href='#id1']", r"\[1\]"),
|
(".//a[@class='fn-backref'][@href='#id1']", r"1"),
|
||||||
(".//a[@class='fn-backref'][@href='#id2']", r"\[2\]"),
|
(".//a[@class='fn-backref'][@href='#id2']", r"2"),
|
||||||
(".//a[@class='fn-backref'][@href='#id3']", r"\[3\]"),
|
(".//a[@class='fn-backref'][@href='#id3']", r"3"),
|
||||||
(".//a[@class='fn-backref'][@href='#id4']", r"\[bar\]"),
|
(".//a[@class='fn-backref'][@href='#id4']", r"bar"),
|
||||||
(".//a[@class='fn-backref'][@href='#id5']", r"\[baz_qux\]"),
|
(".//a[@class='fn-backref'][@href='#id5']", r"baz_qux"),
|
||||||
(".//a[@class='fn-backref'][@href='#id6']", r"\[4\]"),
|
(".//a[@class='fn-backref'][@href='#id6']", r"4"),
|
||||||
(".//a[@class='fn-backref'][@href='#id7']", r"\[5\]"),
|
(".//a[@class='fn-backref'][@href='#id7']", r"5"),
|
||||||
(".//a[@class='fn-backref'][@href='#id8']", r"\[6\]"),
|
(".//a[@class='fn-backref'][@href='#id8']", r"6"),
|
||||||
],
|
],
|
||||||
'otherext.html': [
|
'otherext.html': [
|
||||||
(".//h1", "Generated section"),
|
(".//h1", "Generated section"),
|
||||||
(".//a[@href='_sources/otherext.foo.txt']", ''),
|
(".//a[@href='_sources/otherext.foo.txt']", ''),
|
||||||
]
|
]
|
||||||
}))
|
}))
|
||||||
@pytest.mark.sphinx('html', tags=['testtag'], confoverrides={
|
@pytest.mark.skipif(docutils.__version_info__ < (0, 13),
|
||||||
'html_context.hckey_co': 'hcval_co'})
|
reason='docutils-0.13 or above is required')
|
||||||
|
@pytest.mark.sphinx('html', tags=['testtag'],
|
||||||
|
confoverrides={'html_context.hckey_co': 'hcval_co'})
|
||||||
@pytest.mark.test_params(shared_result='test_build_html_output')
|
@pytest.mark.test_params(shared_result='test_build_html_output')
|
||||||
def test_html_output(app, cached_etree_parse, fname, expect):
|
def test_html5_output(app, cached_etree_parse, fname, expect):
|
||||||
app.build()
|
app.build()
|
||||||
|
print(app.outdir / fname)
|
||||||
check_xpath(cached_etree_parse(app.outdir / fname), fname, *expect)
|
check_xpath(cached_etree_parse(app.outdir / fname), fname, *expect)
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.sphinx('html', tags=['testtag'], confoverrides={
|
@pytest.mark.skipif(docutils.__version_info__ < (0, 13),
|
||||||
'html_context.hckey_co': 'hcval_co'})
|
reason='docutils-0.13 or above is required')
|
||||||
|
@pytest.mark.sphinx('html')
|
||||||
@pytest.mark.test_params(shared_result='test_build_html_output')
|
@pytest.mark.test_params(shared_result='test_build_html_output')
|
||||||
def test_html_download(app):
|
def test_html_download(app):
|
||||||
app.build()
|
app.build()
|
||||||
@@ -435,6 +446,29 @@ def test_html_download(app):
|
|||||||
assert matched.group(1) == filename
|
assert matched.group(1) == filename
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.skipif(docutils.__version_info__ < (0, 13),
|
||||||
|
reason='docutils-0.13 or above is required')
|
||||||
|
@pytest.mark.sphinx('html', testroot='roles-download')
|
||||||
|
def test_html_download_role(app, status, warning):
|
||||||
|
app.build()
|
||||||
|
digest = md5((app.srcdir / 'dummy.dat').encode()).hexdigest()
|
||||||
|
assert (app.outdir / '_downloads' / digest / 'dummy.dat').exists()
|
||||||
|
|
||||||
|
content = (app.outdir / 'index.html').text()
|
||||||
|
assert (('<li><p><a class="reference download internal" download="" '
|
||||||
|
'href="_downloads/%s/dummy.dat">'
|
||||||
|
'<code class="xref download docutils literal notranslate">'
|
||||||
|
'<span class="pre">dummy.dat</span></code></a></p></li>' % digest)
|
||||||
|
in content)
|
||||||
|
assert ('<li><p><code class="xref download docutils literal notranslate">'
|
||||||
|
'<span class="pre">not_found.dat</span></code></p></li>' in content)
|
||||||
|
assert ('<li><p><a class="reference download external" download="" '
|
||||||
|
'href="http://www.sphinx-doc.org/en/master/_static/sphinxheader.png">'
|
||||||
|
'<code class="xref download docutils literal notranslate">'
|
||||||
|
'<span class="pre">Sphinx</span> <span class="pre">logo</span>'
|
||||||
|
'</code></a></p></li>' in content)
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.sphinx('html', testroot='build-html-translator')
|
@pytest.mark.sphinx('html', testroot='build-html-translator')
|
||||||
def test_html_translator(app):
|
def test_html_translator(app):
|
||||||
app.build()
|
app.build()
|
||||||
@@ -473,6 +507,8 @@ def test_html_translator(app):
|
|||||||
(".//h1", '2.1.1. Baz A', True),
|
(".//h1", '2.1.1. Baz A', True),
|
||||||
],
|
],
|
||||||
}))
|
}))
|
||||||
|
@pytest.mark.skipif(docutils.__version_info__ < (0, 13),
|
||||||
|
reason='docutils-0.13 or above is required')
|
||||||
@pytest.mark.sphinx('html', testroot='tocdepth')
|
@pytest.mark.sphinx('html', testroot='tocdepth')
|
||||||
@pytest.mark.test_params(shared_result='test_build_html_tocdepth')
|
@pytest.mark.test_params(shared_result='test_build_html_tocdepth')
|
||||||
def test_tocdepth(app, cached_etree_parse, fname, expect):
|
def test_tocdepth(app, cached_etree_parse, fname, expect):
|
||||||
@@ -508,6 +544,8 @@ def test_tocdepth(app, cached_etree_parse, fname, expect):
|
|||||||
(".//h4", '2.1.1. Baz A', True),
|
(".//h4", '2.1.1. Baz A', True),
|
||||||
],
|
],
|
||||||
}))
|
}))
|
||||||
|
@pytest.mark.skipif(docutils.__version_info__ < (0, 13),
|
||||||
|
reason='docutils-0.13 or above is required')
|
||||||
@pytest.mark.sphinx('singlehtml', testroot='tocdepth')
|
@pytest.mark.sphinx('singlehtml', testroot='tocdepth')
|
||||||
@pytest.mark.test_params(shared_result='test_build_html_tocdepth')
|
@pytest.mark.test_params(shared_result='test_build_html_tocdepth')
|
||||||
def test_tocdepth_singlehtml(app, cached_etree_parse, fname, expect):
|
def test_tocdepth_singlehtml(app, cached_etree_parse, fname, expect):
|
||||||
@@ -527,44 +565,46 @@ def test_numfig_disabled_warn(app, warning):
|
|||||||
|
|
||||||
@pytest.mark.parametrize("fname,expect", flat_dict({
|
@pytest.mark.parametrize("fname,expect", flat_dict({
|
||||||
'index.html': [
|
'index.html': [
|
||||||
(".//div[@class='figure']/p[@class='caption']/"
|
(".//div[@class='figure align-center']/p[@class='caption']/"
|
||||||
"span[@class='caption-number']", None, True),
|
"span[@class='caption-number']", None, True),
|
||||||
(".//table/caption/span[@class='caption-number']", None, True),
|
(".//table/caption/span[@class='caption-number']", None, True),
|
||||||
(".//div[@class='code-block-caption']/"
|
(".//div[@class='code-block-caption']/"
|
||||||
"span[@class='caption-number']", None, True),
|
"span[@class='caption-number']", None, True),
|
||||||
(".//li/code/span", '^fig1$', True),
|
(".//li/p/code/span", '^fig1$', True),
|
||||||
(".//li/code/span", '^Figure%s$', True),
|
(".//li/p/code/span", '^Figure%s$', True),
|
||||||
(".//li/code/span", '^table-1$', True),
|
(".//li/p/code/span", '^table-1$', True),
|
||||||
(".//li/code/span", '^Table:%s$', True),
|
(".//li/p/code/span", '^Table:%s$', True),
|
||||||
(".//li/code/span", '^CODE_1$', True),
|
(".//li/p/code/span", '^CODE_1$', True),
|
||||||
(".//li/code/span", '^Code-%s$', True),
|
(".//li/p/code/span", '^Code-%s$', True),
|
||||||
(".//li/a/span", '^Section 1$', True),
|
(".//li/p/a/span", '^Section 1$', True),
|
||||||
(".//li/a/span", '^Section 2.1$', True),
|
(".//li/p/a/span", '^Section 2.1$', True),
|
||||||
(".//li/code/span", '^Fig.{number}$', True),
|
(".//li/p/code/span", '^Fig.{number}$', True),
|
||||||
(".//li/a/span", '^Sect.1 Foo$', True),
|
(".//li/p/a/span", '^Sect.1 Foo$', True),
|
||||||
],
|
],
|
||||||
'foo.html': [
|
'foo.html': [
|
||||||
(".//div[@class='figure']/p[@class='caption']/"
|
(".//div[@class='figure align-center']/p[@class='caption']/"
|
||||||
"span[@class='caption-number']", None, True),
|
"span[@class='caption-number']", None, True),
|
||||||
(".//table/caption/span[@class='caption-number']", None, True),
|
(".//table/caption/span[@class='caption-number']", None, True),
|
||||||
(".//div[@class='code-block-caption']/"
|
(".//div[@class='code-block-caption']/"
|
||||||
"span[@class='caption-number']", None, True),
|
"span[@class='caption-number']", None, True),
|
||||||
],
|
],
|
||||||
'bar.html': [
|
'bar.html': [
|
||||||
(".//div[@class='figure']/p[@class='caption']/"
|
(".//div[@class='figure align-center']/p[@class='caption']/"
|
||||||
"span[@class='caption-number']", None, True),
|
"span[@class='caption-number']", None, True),
|
||||||
(".//table/caption/span[@class='caption-number']", None, True),
|
(".//table/caption/span[@class='caption-number']", None, True),
|
||||||
(".//div[@class='code-block-caption']/"
|
(".//div[@class='code-block-caption']/"
|
||||||
"span[@class='caption-number']", None, True),
|
"span[@class='caption-number']", None, True),
|
||||||
],
|
],
|
||||||
'baz.html': [
|
'baz.html': [
|
||||||
(".//div[@class='figure']/p[@class='caption']/"
|
(".//div[@class='figure align-center']/p[@class='caption']/"
|
||||||
"span[@class='caption-number']", None, True),
|
"span[@class='caption-number']", None, True),
|
||||||
(".//table/caption/span[@class='caption-number']", None, True),
|
(".//table/caption/span[@class='caption-number']", None, True),
|
||||||
(".//div[@class='code-block-caption']/"
|
(".//div[@class='code-block-caption']/"
|
||||||
"span[@class='caption-number']", None, True),
|
"span[@class='caption-number']", None, True),
|
||||||
],
|
],
|
||||||
}))
|
}))
|
||||||
|
@pytest.mark.skipif(docutils.__version_info__ < (0, 13),
|
||||||
|
reason='docutils-0.13 or above is required')
|
||||||
@pytest.mark.sphinx('html', testroot='numfig')
|
@pytest.mark.sphinx('html', testroot='numfig')
|
||||||
@pytest.mark.test_params(shared_result='test_build_html_numfig')
|
@pytest.mark.test_params(shared_result='test_build_html_numfig')
|
||||||
def test_numfig_disabled(app, cached_etree_parse, fname, expect):
|
def test_numfig_disabled(app, cached_etree_parse, fname, expect):
|
||||||
@@ -593,9 +633,9 @@ def test_numfig_without_numbered_toctree_warn(app, warning):
|
|||||||
|
|
||||||
@pytest.mark.parametrize("fname,expect", flat_dict({
|
@pytest.mark.parametrize("fname,expect", flat_dict({
|
||||||
'index.html': [
|
'index.html': [
|
||||||
(".//div[@class='figure']/p[@class='caption']/"
|
(".//div[@class='figure align-center']/p[@class='caption']/"
|
||||||
"span[@class='caption-number']", '^Fig. 9 $', True),
|
"span[@class='caption-number']", '^Fig. 9 $', True),
|
||||||
(".//div[@class='figure']/p[@class='caption']/"
|
(".//div[@class='figure align-center']/p[@class='caption']/"
|
||||||
"span[@class='caption-number']", '^Fig. 10 $', True),
|
"span[@class='caption-number']", '^Fig. 10 $', True),
|
||||||
(".//table/caption/span[@class='caption-number']",
|
(".//table/caption/span[@class='caption-number']",
|
||||||
'^Table 9 $', True),
|
'^Table 9 $', True),
|
||||||
@@ -605,25 +645,25 @@ def test_numfig_without_numbered_toctree_warn(app, warning):
|
|||||||
"span[@class='caption-number']", '^Listing 9 $', True),
|
"span[@class='caption-number']", '^Listing 9 $', True),
|
||||||
(".//div[@class='code-block-caption']/"
|
(".//div[@class='code-block-caption']/"
|
||||||
"span[@class='caption-number']", '^Listing 10 $', True),
|
"span[@class='caption-number']", '^Listing 10 $', True),
|
||||||
(".//li/a/span", '^Fig. 9$', True),
|
(".//li/p/a/span", '^Fig. 9$', True),
|
||||||
(".//li/a/span", '^Figure6$', True),
|
(".//li/p/a/span", '^Figure6$', True),
|
||||||
(".//li/a/span", '^Table 9$', True),
|
(".//li/p/a/span", '^Table 9$', True),
|
||||||
(".//li/a/span", '^Table:6$', True),
|
(".//li/p/a/span", '^Table:6$', True),
|
||||||
(".//li/a/span", '^Listing 9$', True),
|
(".//li/p/a/span", '^Listing 9$', True),
|
||||||
(".//li/a/span", '^Code-6$', True),
|
(".//li/p/a/span", '^Code-6$', True),
|
||||||
(".//li/code/span", '^foo$', True),
|
(".//li/p/code/span", '^foo$', True),
|
||||||
(".//li/code/span", '^bar_a$', True),
|
(".//li/p/code/span", '^bar_a$', True),
|
||||||
(".//li/a/span", '^Fig.9 should be Fig.1$', True),
|
(".//li/p/a/span", '^Fig.9 should be Fig.1$', True),
|
||||||
(".//li/code/span", '^Sect.{number}$', True),
|
(".//li/p/code/span", '^Sect.{number}$', True),
|
||||||
],
|
],
|
||||||
'foo.html': [
|
'foo.html': [
|
||||||
(".//div[@class='figure']/p[@class='caption']/"
|
(".//div[@class='figure align-center']/p[@class='caption']/"
|
||||||
"span[@class='caption-number']", '^Fig. 1 $', True),
|
"span[@class='caption-number']", '^Fig. 1 $', True),
|
||||||
(".//div[@class='figure']/p[@class='caption']/"
|
(".//div[@class='figure align-center']/p[@class='caption']/"
|
||||||
"span[@class='caption-number']", '^Fig. 2 $', True),
|
"span[@class='caption-number']", '^Fig. 2 $', True),
|
||||||
(".//div[@class='figure']/p[@class='caption']/"
|
(".//div[@class='figure align-center']/p[@class='caption']/"
|
||||||
"span[@class='caption-number']", '^Fig. 3 $', True),
|
"span[@class='caption-number']", '^Fig. 3 $', True),
|
||||||
(".//div[@class='figure']/p[@class='caption']/"
|
(".//div[@class='figure align-center']/p[@class='caption']/"
|
||||||
"span[@class='caption-number']", '^Fig. 4 $', True),
|
"span[@class='caption-number']", '^Fig. 4 $', True),
|
||||||
(".//table/caption/span[@class='caption-number']",
|
(".//table/caption/span[@class='caption-number']",
|
||||||
'^Table 1 $', True),
|
'^Table 1 $', True),
|
||||||
@@ -643,11 +683,11 @@ def test_numfig_without_numbered_toctree_warn(app, warning):
|
|||||||
"span[@class='caption-number']", '^Listing 4 $', True),
|
"span[@class='caption-number']", '^Listing 4 $', True),
|
||||||
],
|
],
|
||||||
'bar.html': [
|
'bar.html': [
|
||||||
(".//div[@class='figure']/p[@class='caption']/"
|
(".//div[@class='figure align-center']/p[@class='caption']/"
|
||||||
"span[@class='caption-number']", '^Fig. 5 $', True),
|
"span[@class='caption-number']", '^Fig. 5 $', True),
|
||||||
(".//div[@class='figure']/p[@class='caption']/"
|
(".//div[@class='figure align-center']/p[@class='caption']/"
|
||||||
"span[@class='caption-number']", '^Fig. 7 $', True),
|
"span[@class='caption-number']", '^Fig. 7 $', True),
|
||||||
(".//div[@class='figure']/p[@class='caption']/"
|
(".//div[@class='figure align-center']/p[@class='caption']/"
|
||||||
"span[@class='caption-number']", '^Fig. 8 $', True),
|
"span[@class='caption-number']", '^Fig. 8 $', True),
|
||||||
(".//table/caption/span[@class='caption-number']",
|
(".//table/caption/span[@class='caption-number']",
|
||||||
'^Table 5 $', True),
|
'^Table 5 $', True),
|
||||||
@@ -663,7 +703,7 @@ def test_numfig_without_numbered_toctree_warn(app, warning):
|
|||||||
"span[@class='caption-number']", '^Listing 8 $', True),
|
"span[@class='caption-number']", '^Listing 8 $', True),
|
||||||
],
|
],
|
||||||
'baz.html': [
|
'baz.html': [
|
||||||
(".//div[@class='figure']/p[@class='caption']/"
|
(".//div[@class='figure align-center']/p[@class='caption']/"
|
||||||
"span[@class='caption-number']", '^Fig. 6 $', True),
|
"span[@class='caption-number']", '^Fig. 6 $', True),
|
||||||
(".//table/caption/span[@class='caption-number']",
|
(".//table/caption/span[@class='caption-number']",
|
||||||
'^Table 6 $', True),
|
'^Table 6 $', True),
|
||||||
@@ -671,6 +711,8 @@ def test_numfig_without_numbered_toctree_warn(app, warning):
|
|||||||
"span[@class='caption-number']", '^Listing 6 $', True),
|
"span[@class='caption-number']", '^Listing 6 $', True),
|
||||||
],
|
],
|
||||||
}))
|
}))
|
||||||
|
@pytest.mark.skipif(docutils.__version_info__ < (0, 13),
|
||||||
|
reason='docutils-0.13 or above is required')
|
||||||
@pytest.mark.sphinx(
|
@pytest.mark.sphinx(
|
||||||
'html', testroot='numfig',
|
'html', testroot='numfig',
|
||||||
srcdir='test_numfig_without_numbered_toctree',
|
srcdir='test_numfig_without_numbered_toctree',
|
||||||
@@ -699,9 +741,9 @@ def test_numfig_with_numbered_toctree_warn(app, warning):
|
|||||||
|
|
||||||
@pytest.mark.parametrize("fname,expect", flat_dict({
|
@pytest.mark.parametrize("fname,expect", flat_dict({
|
||||||
'index.html': [
|
'index.html': [
|
||||||
(".//div[@class='figure']/p[@class='caption']/"
|
(".//div[@class='figure align-center']/p[@class='caption']/"
|
||||||
"span[@class='caption-number']", '^Fig. 1 $', True),
|
"span[@class='caption-number']", '^Fig. 1 $', True),
|
||||||
(".//div[@class='figure']/p[@class='caption']/"
|
(".//div[@class='figure align-center']/p[@class='caption']/"
|
||||||
"span[@class='caption-number']", '^Fig. 2 $', True),
|
"span[@class='caption-number']", '^Fig. 2 $', True),
|
||||||
(".//table/caption/span[@class='caption-number']",
|
(".//table/caption/span[@class='caption-number']",
|
||||||
'^Table 1 $', True),
|
'^Table 1 $', True),
|
||||||
@@ -711,25 +753,25 @@ def test_numfig_with_numbered_toctree_warn(app, warning):
|
|||||||
"span[@class='caption-number']", '^Listing 1 $', True),
|
"span[@class='caption-number']", '^Listing 1 $', True),
|
||||||
(".//div[@class='code-block-caption']/"
|
(".//div[@class='code-block-caption']/"
|
||||||
"span[@class='caption-number']", '^Listing 2 $', True),
|
"span[@class='caption-number']", '^Listing 2 $', True),
|
||||||
(".//li/a/span", '^Fig. 1$', True),
|
(".//li/p/a/span", '^Fig. 1$', True),
|
||||||
(".//li/a/span", '^Figure2.2$', True),
|
(".//li/p/a/span", '^Figure2.2$', True),
|
||||||
(".//li/a/span", '^Table 1$', True),
|
(".//li/p/a/span", '^Table 1$', True),
|
||||||
(".//li/a/span", '^Table:2.2$', True),
|
(".//li/p/a/span", '^Table:2.2$', True),
|
||||||
(".//li/a/span", '^Listing 1$', True),
|
(".//li/p/a/span", '^Listing 1$', True),
|
||||||
(".//li/a/span", '^Code-2.2$', True),
|
(".//li/p/a/span", '^Code-2.2$', True),
|
||||||
(".//li/a/span", '^Section.1$', True),
|
(".//li/p/a/span", '^Section.1$', True),
|
||||||
(".//li/a/span", '^Section.2.1$', True),
|
(".//li/p/a/span", '^Section.2.1$', True),
|
||||||
(".//li/a/span", '^Fig.1 should be Fig.1$', True),
|
(".//li/p/a/span", '^Fig.1 should be Fig.1$', True),
|
||||||
(".//li/a/span", '^Sect.1 Foo$', True),
|
(".//li/p/a/span", '^Sect.1 Foo$', True),
|
||||||
],
|
],
|
||||||
'foo.html': [
|
'foo.html': [
|
||||||
(".//div[@class='figure']/p[@class='caption']/"
|
(".//div[@class='figure align-center']/p[@class='caption']/"
|
||||||
"span[@class='caption-number']", '^Fig. 1.1 $', True),
|
"span[@class='caption-number']", '^Fig. 1.1 $', True),
|
||||||
(".//div[@class='figure']/p[@class='caption']/"
|
(".//div[@class='figure align-center']/p[@class='caption']/"
|
||||||
"span[@class='caption-number']", '^Fig. 1.2 $', True),
|
"span[@class='caption-number']", '^Fig. 1.2 $', True),
|
||||||
(".//div[@class='figure']/p[@class='caption']/"
|
(".//div[@class='figure align-center']/p[@class='caption']/"
|
||||||
"span[@class='caption-number']", '^Fig. 1.3 $', True),
|
"span[@class='caption-number']", '^Fig. 1.3 $', True),
|
||||||
(".//div[@class='figure']/p[@class='caption']/"
|
(".//div[@class='figure align-center']/p[@class='caption']/"
|
||||||
"span[@class='caption-number']", '^Fig. 1.4 $', True),
|
"span[@class='caption-number']", '^Fig. 1.4 $', True),
|
||||||
(".//table/caption/span[@class='caption-number']",
|
(".//table/caption/span[@class='caption-number']",
|
||||||
'^Table 1.1 $', True),
|
'^Table 1.1 $', True),
|
||||||
@@ -749,11 +791,11 @@ def test_numfig_with_numbered_toctree_warn(app, warning):
|
|||||||
"span[@class='caption-number']", '^Listing 1.4 $', True),
|
"span[@class='caption-number']", '^Listing 1.4 $', True),
|
||||||
],
|
],
|
||||||
'bar.html': [
|
'bar.html': [
|
||||||
(".//div[@class='figure']/p[@class='caption']/"
|
(".//div[@class='figure align-center']/p[@class='caption']/"
|
||||||
"span[@class='caption-number']", '^Fig. 2.1 $', True),
|
"span[@class='caption-number']", '^Fig. 2.1 $', True),
|
||||||
(".//div[@class='figure']/p[@class='caption']/"
|
(".//div[@class='figure align-center']/p[@class='caption']/"
|
||||||
"span[@class='caption-number']", '^Fig. 2.3 $', True),
|
"span[@class='caption-number']", '^Fig. 2.3 $', True),
|
||||||
(".//div[@class='figure']/p[@class='caption']/"
|
(".//div[@class='figure align-center']/p[@class='caption']/"
|
||||||
"span[@class='caption-number']", '^Fig. 2.4 $', True),
|
"span[@class='caption-number']", '^Fig. 2.4 $', True),
|
||||||
(".//table/caption/span[@class='caption-number']",
|
(".//table/caption/span[@class='caption-number']",
|
||||||
'^Table 2.1 $', True),
|
'^Table 2.1 $', True),
|
||||||
@@ -769,7 +811,7 @@ def test_numfig_with_numbered_toctree_warn(app, warning):
|
|||||||
"span[@class='caption-number']", '^Listing 2.4 $', True),
|
"span[@class='caption-number']", '^Listing 2.4 $', True),
|
||||||
],
|
],
|
||||||
'baz.html': [
|
'baz.html': [
|
||||||
(".//div[@class='figure']/p[@class='caption']/"
|
(".//div[@class='figure align-center']/p[@class='caption']/"
|
||||||
"span[@class='caption-number']", '^Fig. 2.2 $', True),
|
"span[@class='caption-number']", '^Fig. 2.2 $', True),
|
||||||
(".//table/caption/span[@class='caption-number']",
|
(".//table/caption/span[@class='caption-number']",
|
||||||
'^Table 2.2 $', True),
|
'^Table 2.2 $', True),
|
||||||
@@ -777,6 +819,8 @@ def test_numfig_with_numbered_toctree_warn(app, warning):
|
|||||||
"span[@class='caption-number']", '^Listing 2.2 $', True),
|
"span[@class='caption-number']", '^Listing 2.2 $', True),
|
||||||
],
|
],
|
||||||
}))
|
}))
|
||||||
|
@pytest.mark.skipif(docutils.__version_info__ < (0, 13),
|
||||||
|
reason='docutils-0.13 or above is required')
|
||||||
@pytest.mark.sphinx('html', testroot='numfig', confoverrides={'numfig': True})
|
@pytest.mark.sphinx('html', testroot='numfig', confoverrides={'numfig': True})
|
||||||
@pytest.mark.test_params(shared_result='test_build_html_numfig_on')
|
@pytest.mark.test_params(shared_result='test_build_html_numfig_on')
|
||||||
def test_numfig_with_numbered_toctree(app, cached_etree_parse, fname, expect):
|
def test_numfig_with_numbered_toctree(app, cached_etree_parse, fname, expect):
|
||||||
@@ -802,9 +846,9 @@ def test_numfig_with_prefix_warn(app, warning):
|
|||||||
|
|
||||||
@pytest.mark.parametrize("fname,expect", flat_dict({
|
@pytest.mark.parametrize("fname,expect", flat_dict({
|
||||||
'index.html': [
|
'index.html': [
|
||||||
(".//div[@class='figure']/p[@class='caption']/"
|
(".//div[@class='figure align-center']/p[@class='caption']/"
|
||||||
"span[@class='caption-number']", '^Figure:1 $', True),
|
"span[@class='caption-number']", '^Figure:1 $', True),
|
||||||
(".//div[@class='figure']/p[@class='caption']/"
|
(".//div[@class='figure align-center']/p[@class='caption']/"
|
||||||
"span[@class='caption-number']", '^Figure:2 $', True),
|
"span[@class='caption-number']", '^Figure:2 $', True),
|
||||||
(".//table/caption/span[@class='caption-number']",
|
(".//table/caption/span[@class='caption-number']",
|
||||||
'^Tab_1 $', True),
|
'^Tab_1 $', True),
|
||||||
@@ -814,25 +858,25 @@ def test_numfig_with_prefix_warn(app, warning):
|
|||||||
"span[@class='caption-number']", '^Code-1 $', True),
|
"span[@class='caption-number']", '^Code-1 $', True),
|
||||||
(".//div[@class='code-block-caption']/"
|
(".//div[@class='code-block-caption']/"
|
||||||
"span[@class='caption-number']", '^Code-2 $', True),
|
"span[@class='caption-number']", '^Code-2 $', True),
|
||||||
(".//li/a/span", '^Figure:1$', True),
|
(".//li/p/a/span", '^Figure:1$', True),
|
||||||
(".//li/a/span", '^Figure2.2$', True),
|
(".//li/p/a/span", '^Figure2.2$', True),
|
||||||
(".//li/a/span", '^Tab_1$', True),
|
(".//li/p/a/span", '^Tab_1$', True),
|
||||||
(".//li/a/span", '^Table:2.2$', True),
|
(".//li/p/a/span", '^Table:2.2$', True),
|
||||||
(".//li/a/span", '^Code-1$', True),
|
(".//li/p/a/span", '^Code-1$', True),
|
||||||
(".//li/a/span", '^Code-2.2$', True),
|
(".//li/p/a/span", '^Code-2.2$', True),
|
||||||
(".//li/a/span", '^SECTION-1$', True),
|
(".//li/p/a/span", '^SECTION-1$', True),
|
||||||
(".//li/a/span", '^SECTION-2.1$', True),
|
(".//li/p/a/span", '^SECTION-2.1$', True),
|
||||||
(".//li/a/span", '^Fig.1 should be Fig.1$', True),
|
(".//li/p/a/span", '^Fig.1 should be Fig.1$', True),
|
||||||
(".//li/a/span", '^Sect.1 Foo$', True),
|
(".//li/p/a/span", '^Sect.1 Foo$', True),
|
||||||
],
|
],
|
||||||
'foo.html': [
|
'foo.html': [
|
||||||
(".//div[@class='figure']/p[@class='caption']/"
|
(".//div[@class='figure align-center']/p[@class='caption']/"
|
||||||
"span[@class='caption-number']", '^Figure:1.1 $', True),
|
"span[@class='caption-number']", '^Figure:1.1 $', True),
|
||||||
(".//div[@class='figure']/p[@class='caption']/"
|
(".//div[@class='figure align-center']/p[@class='caption']/"
|
||||||
"span[@class='caption-number']", '^Figure:1.2 $', True),
|
"span[@class='caption-number']", '^Figure:1.2 $', True),
|
||||||
(".//div[@class='figure']/p[@class='caption']/"
|
(".//div[@class='figure align-center']/p[@class='caption']/"
|
||||||
"span[@class='caption-number']", '^Figure:1.3 $', True),
|
"span[@class='caption-number']", '^Figure:1.3 $', True),
|
||||||
(".//div[@class='figure']/p[@class='caption']/"
|
(".//div[@class='figure align-center']/p[@class='caption']/"
|
||||||
"span[@class='caption-number']", '^Figure:1.4 $', True),
|
"span[@class='caption-number']", '^Figure:1.4 $', True),
|
||||||
(".//table/caption/span[@class='caption-number']",
|
(".//table/caption/span[@class='caption-number']",
|
||||||
'^Tab_1.1 $', True),
|
'^Tab_1.1 $', True),
|
||||||
@@ -852,11 +896,11 @@ def test_numfig_with_prefix_warn(app, warning):
|
|||||||
"span[@class='caption-number']", '^Code-1.4 $', True),
|
"span[@class='caption-number']", '^Code-1.4 $', True),
|
||||||
],
|
],
|
||||||
'bar.html': [
|
'bar.html': [
|
||||||
(".//div[@class='figure']/p[@class='caption']/"
|
(".//div[@class='figure align-center']/p[@class='caption']/"
|
||||||
"span[@class='caption-number']", '^Figure:2.1 $', True),
|
"span[@class='caption-number']", '^Figure:2.1 $', True),
|
||||||
(".//div[@class='figure']/p[@class='caption']/"
|
(".//div[@class='figure align-center']/p[@class='caption']/"
|
||||||
"span[@class='caption-number']", '^Figure:2.3 $', True),
|
"span[@class='caption-number']", '^Figure:2.3 $', True),
|
||||||
(".//div[@class='figure']/p[@class='caption']/"
|
(".//div[@class='figure align-center']/p[@class='caption']/"
|
||||||
"span[@class='caption-number']", '^Figure:2.4 $', True),
|
"span[@class='caption-number']", '^Figure:2.4 $', True),
|
||||||
(".//table/caption/span[@class='caption-number']",
|
(".//table/caption/span[@class='caption-number']",
|
||||||
'^Tab_2.1 $', True),
|
'^Tab_2.1 $', True),
|
||||||
@@ -872,7 +916,7 @@ def test_numfig_with_prefix_warn(app, warning):
|
|||||||
"span[@class='caption-number']", '^Code-2.4 $', True),
|
"span[@class='caption-number']", '^Code-2.4 $', True),
|
||||||
],
|
],
|
||||||
'baz.html': [
|
'baz.html': [
|
||||||
(".//div[@class='figure']/p[@class='caption']/"
|
(".//div[@class='figure align-center']/p[@class='caption']/"
|
||||||
"span[@class='caption-number']", '^Figure:2.2 $', True),
|
"span[@class='caption-number']", '^Figure:2.2 $', True),
|
||||||
(".//table/caption/span[@class='caption-number']",
|
(".//table/caption/span[@class='caption-number']",
|
||||||
'^Tab_2.2 $', True),
|
'^Tab_2.2 $', True),
|
||||||
@@ -880,20 +924,22 @@ def test_numfig_with_prefix_warn(app, warning):
|
|||||||
"span[@class='caption-number']", '^Code-2.2 $', True),
|
"span[@class='caption-number']", '^Code-2.2 $', True),
|
||||||
],
|
],
|
||||||
}))
|
}))
|
||||||
@pytest.mark.sphinx('html', testroot='numfig', confoverrides={
|
@pytest.mark.skipif(docutils.__version_info__ < (0, 13),
|
||||||
'numfig': True,
|
reason='docutils-0.13 or above is required')
|
||||||
'numfig_format': {'figure': 'Figure:%s',
|
@pytest.mark.sphinx('html', testroot='numfig',
|
||||||
'table': 'Tab_%s',
|
confoverrides={'numfig': True,
|
||||||
'code-block': 'Code-%s',
|
'numfig_format': {'figure': 'Figure:%s',
|
||||||
'section': 'SECTION-%s'}})
|
'table': 'Tab_%s',
|
||||||
|
'code-block': 'Code-%s',
|
||||||
|
'section': 'SECTION-%s'}})
|
||||||
@pytest.mark.test_params(shared_result='test_build_html_numfig_format_warn')
|
@pytest.mark.test_params(shared_result='test_build_html_numfig_format_warn')
|
||||||
def test_numfig_with_prefix(app, cached_etree_parse, fname, expect):
|
def test_numfig_with_prefix(app, cached_etree_parse, fname, expect):
|
||||||
app.build()
|
app.build()
|
||||||
check_xpath(cached_etree_parse(app.outdir / fname), fname, *expect)
|
check_xpath(cached_etree_parse(app.outdir / fname), fname, *expect)
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.sphinx('html', testroot='numfig', confoverrides={
|
@pytest.mark.sphinx('html', testroot='numfig',
|
||||||
'numfig': True, 'numfig_secnum_depth': 2})
|
confoverrides={'numfig': True, 'numfig_secnum_depth': 2})
|
||||||
@pytest.mark.test_params(shared_result='test_build_html_numfig_depth_2')
|
@pytest.mark.test_params(shared_result='test_build_html_numfig_depth_2')
|
||||||
def test_numfig_with_secnum_depth_warn(app, warning):
|
def test_numfig_with_secnum_depth_warn(app, warning):
|
||||||
app.build()
|
app.build()
|
||||||
@@ -906,9 +952,9 @@ def test_numfig_with_secnum_depth_warn(app, warning):
|
|||||||
|
|
||||||
@pytest.mark.parametrize("fname,expect", flat_dict({
|
@pytest.mark.parametrize("fname,expect", flat_dict({
|
||||||
'index.html': [
|
'index.html': [
|
||||||
(".//div[@class='figure']/p[@class='caption']/"
|
(".//div[@class='figure align-center']/p[@class='caption']/"
|
||||||
"span[@class='caption-number']", '^Fig. 1 $', True),
|
"span[@class='caption-number']", '^Fig. 1 $', True),
|
||||||
(".//div[@class='figure']/p[@class='caption']/"
|
(".//div[@class='figure align-center']/p[@class='caption']/"
|
||||||
"span[@class='caption-number']", '^Fig. 2 $', True),
|
"span[@class='caption-number']", '^Fig. 2 $', True),
|
||||||
(".//table/caption/span[@class='caption-number']",
|
(".//table/caption/span[@class='caption-number']",
|
||||||
'^Table 1 $', True),
|
'^Table 1 $', True),
|
||||||
@@ -918,25 +964,25 @@ def test_numfig_with_secnum_depth_warn(app, warning):
|
|||||||
"span[@class='caption-number']", '^Listing 1 $', True),
|
"span[@class='caption-number']", '^Listing 1 $', True),
|
||||||
(".//div[@class='code-block-caption']/"
|
(".//div[@class='code-block-caption']/"
|
||||||
"span[@class='caption-number']", '^Listing 2 $', True),
|
"span[@class='caption-number']", '^Listing 2 $', True),
|
||||||
(".//li/a/span", '^Fig. 1$', True),
|
(".//li/p/a/span", '^Fig. 1$', True),
|
||||||
(".//li/a/span", '^Figure2.1.2$', True),
|
(".//li/p/a/span", '^Figure2.1.2$', True),
|
||||||
(".//li/a/span", '^Table 1$', True),
|
(".//li/p/a/span", '^Table 1$', True),
|
||||||
(".//li/a/span", '^Table:2.1.2$', True),
|
(".//li/p/a/span", '^Table:2.1.2$', True),
|
||||||
(".//li/a/span", '^Listing 1$', True),
|
(".//li/p/a/span", '^Listing 1$', True),
|
||||||
(".//li/a/span", '^Code-2.1.2$', True),
|
(".//li/p/a/span", '^Code-2.1.2$', True),
|
||||||
(".//li/a/span", '^Section.1$', True),
|
(".//li/p/a/span", '^Section.1$', True),
|
||||||
(".//li/a/span", '^Section.2.1$', True),
|
(".//li/p/a/span", '^Section.2.1$', True),
|
||||||
(".//li/a/span", '^Fig.1 should be Fig.1$', True),
|
(".//li/p/a/span", '^Fig.1 should be Fig.1$', True),
|
||||||
(".//li/a/span", '^Sect.1 Foo$', True),
|
(".//li/p/a/span", '^Sect.1 Foo$', True),
|
||||||
],
|
],
|
||||||
'foo.html': [
|
'foo.html': [
|
||||||
(".//div[@class='figure']/p[@class='caption']/"
|
(".//div[@class='figure align-center']/p[@class='caption']/"
|
||||||
"span[@class='caption-number']", '^Fig. 1.1 $', True),
|
"span[@class='caption-number']", '^Fig. 1.1 $', True),
|
||||||
(".//div[@class='figure']/p[@class='caption']/"
|
(".//div[@class='figure align-center']/p[@class='caption']/"
|
||||||
"span[@class='caption-number']", '^Fig. 1.1.1 $', True),
|
"span[@class='caption-number']", '^Fig. 1.1.1 $', True),
|
||||||
(".//div[@class='figure']/p[@class='caption']/"
|
(".//div[@class='figure align-center']/p[@class='caption']/"
|
||||||
"span[@class='caption-number']", '^Fig. 1.1.2 $', True),
|
"span[@class='caption-number']", '^Fig. 1.1.2 $', True),
|
||||||
(".//div[@class='figure']/p[@class='caption']/"
|
(".//div[@class='figure align-center']/p[@class='caption']/"
|
||||||
"span[@class='caption-number']", '^Fig. 1.2.1 $', True),
|
"span[@class='caption-number']", '^Fig. 1.2.1 $', True),
|
||||||
(".//table/caption/span[@class='caption-number']",
|
(".//table/caption/span[@class='caption-number']",
|
||||||
'^Table 1.1 $', True),
|
'^Table 1.1 $', True),
|
||||||
@@ -956,11 +1002,11 @@ def test_numfig_with_secnum_depth_warn(app, warning):
|
|||||||
"span[@class='caption-number']", '^Listing 1.2.1 $', True),
|
"span[@class='caption-number']", '^Listing 1.2.1 $', True),
|
||||||
],
|
],
|
||||||
'bar.html': [
|
'bar.html': [
|
||||||
(".//div[@class='figure']/p[@class='caption']/"
|
(".//div[@class='figure align-center']/p[@class='caption']/"
|
||||||
"span[@class='caption-number']", '^Fig. 2.1.1 $', True),
|
"span[@class='caption-number']", '^Fig. 2.1.1 $', True),
|
||||||
(".//div[@class='figure']/p[@class='caption']/"
|
(".//div[@class='figure align-center']/p[@class='caption']/"
|
||||||
"span[@class='caption-number']", '^Fig. 2.1.3 $', True),
|
"span[@class='caption-number']", '^Fig. 2.1.3 $', True),
|
||||||
(".//div[@class='figure']/p[@class='caption']/"
|
(".//div[@class='figure align-center']/p[@class='caption']/"
|
||||||
"span[@class='caption-number']", '^Fig. 2.2.1 $', True),
|
"span[@class='caption-number']", '^Fig. 2.2.1 $', True),
|
||||||
(".//table/caption/span[@class='caption-number']",
|
(".//table/caption/span[@class='caption-number']",
|
||||||
'^Table 2.1.1 $', True),
|
'^Table 2.1.1 $', True),
|
||||||
@@ -976,7 +1022,7 @@ def test_numfig_with_secnum_depth_warn(app, warning):
|
|||||||
"span[@class='caption-number']", '^Listing 2.2.1 $', True),
|
"span[@class='caption-number']", '^Listing 2.2.1 $', True),
|
||||||
],
|
],
|
||||||
'baz.html': [
|
'baz.html': [
|
||||||
(".//div[@class='figure']/p[@class='caption']/"
|
(".//div[@class='figure align-center']/p[@class='caption']/"
|
||||||
"span[@class='caption-number']", '^Fig. 2.1.2 $', True),
|
"span[@class='caption-number']", '^Fig. 2.1.2 $', True),
|
||||||
(".//table/caption/span[@class='caption-number']",
|
(".//table/caption/span[@class='caption-number']",
|
||||||
'^Table 2.1.2 $', True),
|
'^Table 2.1.2 $', True),
|
||||||
@@ -984,8 +1030,11 @@ def test_numfig_with_secnum_depth_warn(app, warning):
|
|||||||
"span[@class='caption-number']", '^Listing 2.1.2 $', True),
|
"span[@class='caption-number']", '^Listing 2.1.2 $', True),
|
||||||
],
|
],
|
||||||
}))
|
}))
|
||||||
@pytest.mark.sphinx('html', testroot='numfig', confoverrides={
|
@pytest.mark.skipif(docutils.__version_info__ < (0, 13),
|
||||||
'numfig': True, 'numfig_secnum_depth': 2})
|
reason='docutils-0.13 or above is required')
|
||||||
|
@pytest.mark.sphinx('html', testroot='numfig',
|
||||||
|
confoverrides={'numfig': True,
|
||||||
|
'numfig_secnum_depth': 2})
|
||||||
@pytest.mark.test_params(shared_result='test_build_html_numfig_depth_2')
|
@pytest.mark.test_params(shared_result='test_build_html_numfig_depth_2')
|
||||||
def test_numfig_with_secnum_depth(app, cached_etree_parse, fname, expect):
|
def test_numfig_with_secnum_depth(app, cached_etree_parse, fname, expect):
|
||||||
app.build()
|
app.build()
|
||||||
@@ -994,9 +1043,9 @@ def test_numfig_with_secnum_depth(app, cached_etree_parse, fname, expect):
|
|||||||
|
|
||||||
@pytest.mark.parametrize("fname,expect", flat_dict({
|
@pytest.mark.parametrize("fname,expect", flat_dict({
|
||||||
'index.html': [
|
'index.html': [
|
||||||
(".//div[@class='figure']/p[@class='caption']/"
|
(".//div[@class='figure align-center']/p[@class='caption']/"
|
||||||
"span[@class='caption-number']", '^Fig. 1 $', True),
|
"span[@class='caption-number']", '^Fig. 1 $', True),
|
||||||
(".//div[@class='figure']/p[@class='caption']/"
|
(".//div[@class='figure align-center']/p[@class='caption']/"
|
||||||
"span[@class='caption-number']", '^Fig. 2 $', True),
|
"span[@class='caption-number']", '^Fig. 2 $', True),
|
||||||
(".//table/caption/span[@class='caption-number']",
|
(".//table/caption/span[@class='caption-number']",
|
||||||
'^Table 1 $', True),
|
'^Table 1 $', True),
|
||||||
@@ -1006,23 +1055,23 @@ def test_numfig_with_secnum_depth(app, cached_etree_parse, fname, expect):
|
|||||||
"span[@class='caption-number']", '^Listing 1 $', True),
|
"span[@class='caption-number']", '^Listing 1 $', True),
|
||||||
(".//div[@class='code-block-caption']/"
|
(".//div[@class='code-block-caption']/"
|
||||||
"span[@class='caption-number']", '^Listing 2 $', True),
|
"span[@class='caption-number']", '^Listing 2 $', True),
|
||||||
(".//li/a/span", '^Fig. 1$', True),
|
(".//li/p/a/span", '^Fig. 1$', True),
|
||||||
(".//li/a/span", '^Figure2.2$', True),
|
(".//li/p/a/span", '^Figure2.2$', True),
|
||||||
(".//li/a/span", '^Table 1$', True),
|
(".//li/p/a/span", '^Table 1$', True),
|
||||||
(".//li/a/span", '^Table:2.2$', True),
|
(".//li/p/a/span", '^Table:2.2$', True),
|
||||||
(".//li/a/span", '^Listing 1$', True),
|
(".//li/p/a/span", '^Listing 1$', True),
|
||||||
(".//li/a/span", '^Code-2.2$', True),
|
(".//li/p/a/span", '^Code-2.2$', True),
|
||||||
(".//li/a/span", '^Section.1$', True),
|
(".//li/p/a/span", '^Section.1$', True),
|
||||||
(".//li/a/span", '^Section.2.1$', True),
|
(".//li/p/a/span", '^Section.2.1$', True),
|
||||||
(".//li/a/span", '^Fig.1 should be Fig.1$', True),
|
(".//li/p/a/span", '^Fig.1 should be Fig.1$', True),
|
||||||
(".//li/a/span", '^Sect.1 Foo$', True),
|
(".//li/p/a/span", '^Sect.1 Foo$', True),
|
||||||
(".//div[@class='figure']/p[@class='caption']/"
|
(".//div[@class='figure align-center']/p[@class='caption']/"
|
||||||
"span[@class='caption-number']", '^Fig. 1.1 $', True),
|
"span[@class='caption-number']", '^Fig. 1.1 $', True),
|
||||||
(".//div[@class='figure']/p[@class='caption']/"
|
(".//div[@class='figure align-center']/p[@class='caption']/"
|
||||||
"span[@class='caption-number']", '^Fig. 1.2 $', True),
|
"span[@class='caption-number']", '^Fig. 1.2 $', True),
|
||||||
(".//div[@class='figure']/p[@class='caption']/"
|
(".//div[@class='figure align-center']/p[@class='caption']/"
|
||||||
"span[@class='caption-number']", '^Fig. 1.3 $', True),
|
"span[@class='caption-number']", '^Fig. 1.3 $', True),
|
||||||
(".//div[@class='figure']/p[@class='caption']/"
|
(".//div[@class='figure align-center']/p[@class='caption']/"
|
||||||
"span[@class='caption-number']", '^Fig. 1.4 $', True),
|
"span[@class='caption-number']", '^Fig. 1.4 $', True),
|
||||||
(".//table/caption/span[@class='caption-number']",
|
(".//table/caption/span[@class='caption-number']",
|
||||||
'^Table 1.1 $', True),
|
'^Table 1.1 $', True),
|
||||||
@@ -1040,11 +1089,11 @@ def test_numfig_with_secnum_depth(app, cached_etree_parse, fname, expect):
|
|||||||
"span[@class='caption-number']", '^Listing 1.3 $', True),
|
"span[@class='caption-number']", '^Listing 1.3 $', True),
|
||||||
(".//div[@class='code-block-caption']/"
|
(".//div[@class='code-block-caption']/"
|
||||||
"span[@class='caption-number']", '^Listing 1.4 $', True),
|
"span[@class='caption-number']", '^Listing 1.4 $', True),
|
||||||
(".//div[@class='figure']/p[@class='caption']/"
|
(".//div[@class='figure align-center']/p[@class='caption']/"
|
||||||
"span[@class='caption-number']", '^Fig. 2.1 $', True),
|
"span[@class='caption-number']", '^Fig. 2.1 $', True),
|
||||||
(".//div[@class='figure']/p[@class='caption']/"
|
(".//div[@class='figure align-center']/p[@class='caption']/"
|
||||||
"span[@class='caption-number']", '^Fig. 2.3 $', True),
|
"span[@class='caption-number']", '^Fig. 2.3 $', True),
|
||||||
(".//div[@class='figure']/p[@class='caption']/"
|
(".//div[@class='figure align-center']/p[@class='caption']/"
|
||||||
"span[@class='caption-number']", '^Fig. 2.4 $', True),
|
"span[@class='caption-number']", '^Fig. 2.4 $', True),
|
||||||
(".//table/caption/span[@class='caption-number']",
|
(".//table/caption/span[@class='caption-number']",
|
||||||
'^Table 2.1 $', True),
|
'^Table 2.1 $', True),
|
||||||
@@ -1058,7 +1107,7 @@ def test_numfig_with_secnum_depth(app, cached_etree_parse, fname, expect):
|
|||||||
"span[@class='caption-number']", '^Listing 2.3 $', True),
|
"span[@class='caption-number']", '^Listing 2.3 $', True),
|
||||||
(".//div[@class='code-block-caption']/"
|
(".//div[@class='code-block-caption']/"
|
||||||
"span[@class='caption-number']", '^Listing 2.4 $', True),
|
"span[@class='caption-number']", '^Listing 2.4 $', True),
|
||||||
(".//div[@class='figure']/p[@class='caption']/"
|
(".//div[@class='figure align-center']/p[@class='caption']/"
|
||||||
"span[@class='caption-number']", '^Fig. 2.2 $', True),
|
"span[@class='caption-number']", '^Fig. 2.2 $', True),
|
||||||
(".//table/caption/span[@class='caption-number']",
|
(".//table/caption/span[@class='caption-number']",
|
||||||
'^Table 2.2 $', True),
|
'^Table 2.2 $', True),
|
||||||
@@ -1066,8 +1115,9 @@ def test_numfig_with_secnum_depth(app, cached_etree_parse, fname, expect):
|
|||||||
"span[@class='caption-number']", '^Listing 2.2 $', True),
|
"span[@class='caption-number']", '^Listing 2.2 $', True),
|
||||||
],
|
],
|
||||||
}))
|
}))
|
||||||
@pytest.mark.sphinx('singlehtml', testroot='numfig', confoverrides={
|
@pytest.mark.skipif(docutils.__version_info__ < (0, 13),
|
||||||
'numfig': True})
|
reason='docutils-0.13 or above is required')
|
||||||
|
@pytest.mark.sphinx('singlehtml', testroot='numfig', confoverrides={'numfig': True})
|
||||||
@pytest.mark.test_params(shared_result='test_build_html_numfig_on')
|
@pytest.mark.test_params(shared_result='test_build_html_numfig_on')
|
||||||
def test_numfig_with_singlehtml(app, cached_etree_parse, fname, expect):
|
def test_numfig_with_singlehtml(app, cached_etree_parse, fname, expect):
|
||||||
app.build()
|
app.build()
|
||||||
@@ -1076,25 +1126,25 @@ def test_numfig_with_singlehtml(app, cached_etree_parse, fname, expect):
|
|||||||
|
|
||||||
@pytest.mark.parametrize("fname,expect", flat_dict({
|
@pytest.mark.parametrize("fname,expect", flat_dict({
|
||||||
'index.html': [
|
'index.html': [
|
||||||
(".//div[@class='figure']/p[@class='caption']/span[@class='caption-number']",
|
(".//div[@class='figure align-center']/p[@class='caption']"
|
||||||
"Fig. 1", True),
|
"/span[@class='caption-number']", "Fig. 1", True),
|
||||||
(".//div[@class='figure']/p[@class='caption']/span[@class='caption-number']",
|
(".//div[@class='figure align-center']/p[@class='caption']"
|
||||||
"Fig. 2", True),
|
"/span[@class='caption-number']", "Fig. 2", True),
|
||||||
(".//div[@class='figure']/p[@class='caption']/span[@class='caption-number']",
|
(".//div[@class='figure align-center']/p[@class='caption']"
|
||||||
"Fig. 3", True),
|
"/span[@class='caption-number']", "Fig. 3", True),
|
||||||
(".//div//span[@class='caption-number']", "No.1 ", True),
|
(".//div//span[@class='caption-number']", "No.1 ", True),
|
||||||
(".//div//span[@class='caption-number']", "No.2 ", True),
|
(".//div//span[@class='caption-number']", "No.2 ", True),
|
||||||
(".//li/a/span", 'Fig. 1', True),
|
(".//li/p/a/span", 'Fig. 1', True),
|
||||||
(".//li/a/span", 'Fig. 2', True),
|
(".//li/p/a/span", 'Fig. 2', True),
|
||||||
(".//li/a/span", 'Fig. 3', True),
|
(".//li/p/a/span", 'Fig. 3', True),
|
||||||
(".//li/a/span", 'No.1', True),
|
(".//li/p/a/span", 'No.1', True),
|
||||||
(".//li/a/span", 'No.2', True),
|
(".//li/p/a/span", 'No.2', True),
|
||||||
],
|
],
|
||||||
}))
|
}))
|
||||||
@pytest.mark.sphinx(
|
@pytest.mark.skipif(docutils.__version_info__ < (0, 13),
|
||||||
'html', testroot='add_enumerable_node',
|
reason='docutils-0.13 or above is required')
|
||||||
srcdir='test_enumerable_node',
|
@pytest.mark.sphinx('html', testroot='add_enumerable_node',
|
||||||
)
|
srcdir='test_enumerable_node')
|
||||||
def test_enumerable_node(app, cached_etree_parse, fname, expect):
|
def test_enumerable_node(app, cached_etree_parse, fname, expect):
|
||||||
app.build()
|
app.build()
|
||||||
check_xpath(cached_etree_parse(app.outdir / fname), fname, *expect)
|
check_xpath(cached_etree_parse(app.outdir / fname), fname, *expect)
|
||||||
|
|||||||
@@ -1,367 +0,0 @@
|
|||||||
"""
|
|
||||||
test_build_html5
|
|
||||||
~~~~~~~~~~~~~~~~
|
|
||||||
|
|
||||||
Test the HTML5 writer and check output against XPath.
|
|
||||||
|
|
||||||
This code is digest to reduce test running time.
|
|
||||||
Complete test code is here:
|
|
||||||
|
|
||||||
https://github.com/sphinx-doc/sphinx/pull/2805/files
|
|
||||||
|
|
||||||
:copyright: Copyright 2007-2019 by the Sphinx team, see AUTHORS.
|
|
||||||
:license: BSD, see LICENSE for details.
|
|
||||||
"""
|
|
||||||
|
|
||||||
import re
|
|
||||||
from hashlib import md5
|
|
||||||
|
|
||||||
import pytest
|
|
||||||
from html5lib import HTMLParser
|
|
||||||
from test_build_html import flat_dict, tail_check, check_xpath
|
|
||||||
|
|
||||||
from sphinx.util.docutils import is_html5_writer_available
|
|
||||||
|
|
||||||
|
|
||||||
etree_cache = {}
|
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.skipif(not is_html5_writer_available(), reason='HTML5 writer is not available')
|
|
||||||
@pytest.fixture(scope='module')
|
|
||||||
def cached_etree_parse():
|
|
||||||
def parse(fname):
|
|
||||||
if fname in etree_cache:
|
|
||||||
return etree_cache[fname]
|
|
||||||
with (fname).open('rb') as fp:
|
|
||||||
etree = HTMLParser(namespaceHTMLElements=False).parse(fp)
|
|
||||||
etree_cache.clear()
|
|
||||||
etree_cache[fname] = etree
|
|
||||||
return etree
|
|
||||||
yield parse
|
|
||||||
etree_cache.clear()
|
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.skipif(not is_html5_writer_available(), reason='HTML5 writer is not available')
|
|
||||||
@pytest.mark.parametrize("fname,expect", flat_dict({
|
|
||||||
'images.html': [
|
|
||||||
(".//img[@src='_images/img.png']", ''),
|
|
||||||
(".//img[@src='_images/img1.png']", ''),
|
|
||||||
(".//img[@src='_images/simg.png']", ''),
|
|
||||||
(".//img[@src='_images/svgimg.svg']", ''),
|
|
||||||
(".//a[@href='_sources/images.txt']", ''),
|
|
||||||
],
|
|
||||||
'subdir/images.html': [
|
|
||||||
(".//img[@src='../_images/img1.png']", ''),
|
|
||||||
(".//img[@src='../_images/rimg.png']", ''),
|
|
||||||
],
|
|
||||||
'subdir/includes.html': [
|
|
||||||
(".//a[@class='reference download internal']", ''),
|
|
||||||
(".//img[@src='../_images/img.png']", ''),
|
|
||||||
(".//p", 'This is an include file.'),
|
|
||||||
(".//pre/span", 'line 1'),
|
|
||||||
(".//pre/span", 'line 2'),
|
|
||||||
],
|
|
||||||
'includes.html': [
|
|
||||||
(".//pre", 'Max Strauß'),
|
|
||||||
(".//a[@class='reference download internal']", ''),
|
|
||||||
(".//pre/span", '"quotes"'),
|
|
||||||
(".//pre/span", "'included'"),
|
|
||||||
(".//pre/span[@class='s2']", 'üöä'),
|
|
||||||
(".//div[@class='inc-pyobj1 highlight-text notranslate']//pre",
|
|
||||||
r'^class Foo:\n pass\n\s*$'),
|
|
||||||
(".//div[@class='inc-pyobj2 highlight-text notranslate']//pre",
|
|
||||||
r'^ def baz\(\):\n pass\n\s*$'),
|
|
||||||
(".//div[@class='inc-lines highlight-text notranslate']//pre",
|
|
||||||
r'^class Foo:\n pass\nclass Bar:\n$'),
|
|
||||||
(".//div[@class='inc-startend highlight-text notranslate']//pre",
|
|
||||||
'^foo = "Including Unicode characters: üöä"\\n$'),
|
|
||||||
(".//div[@class='inc-preappend highlight-text notranslate']//pre",
|
|
||||||
r'(?m)^START CODE$'),
|
|
||||||
(".//div[@class='inc-pyobj-dedent highlight-python notranslate']//span",
|
|
||||||
r'def'),
|
|
||||||
(".//div[@class='inc-tab3 highlight-text notranslate']//pre",
|
|
||||||
r'-| |-'),
|
|
||||||
(".//div[@class='inc-tab8 highlight-python notranslate']//pre/span",
|
|
||||||
r'-| |-'),
|
|
||||||
],
|
|
||||||
'autodoc.html': [
|
|
||||||
(".//dt[@id='autodoc_target.Class']", ''),
|
|
||||||
(".//dt[@id='autodoc_target.function']/em", r'\*\*kwds'),
|
|
||||||
(".//dd/p", r'Return spam\.'),
|
|
||||||
],
|
|
||||||
'extapi.html': [
|
|
||||||
(".//strong", 'from class: Bar'),
|
|
||||||
],
|
|
||||||
'markup.html': [
|
|
||||||
(".//title", 'set by title directive'),
|
|
||||||
(".//p/em", 'Section author: Georg Brandl'),
|
|
||||||
(".//p/em", 'Module author: Georg Brandl'),
|
|
||||||
# created by the meta directive
|
|
||||||
(".//meta[@name='author'][@content='Me']", ''),
|
|
||||||
(".//meta[@name='keywords'][@content='docs, sphinx']", ''),
|
|
||||||
# a label created by ``.. _label:``
|
|
||||||
(".//div[@id='label']", ''),
|
|
||||||
# code with standard code blocks
|
|
||||||
(".//pre", '^some code$'),
|
|
||||||
# an option list
|
|
||||||
(".//span[@class='option']", '--help'),
|
|
||||||
# admonitions
|
|
||||||
(".//p[@class='admonition-title']", 'My Admonition'),
|
|
||||||
(".//div[@class='admonition note']/p", 'Note text.'),
|
|
||||||
(".//div[@class='admonition warning']/p", 'Warning text.'),
|
|
||||||
# inline markup
|
|
||||||
(".//li/p/strong", r'^command\\n$'),
|
|
||||||
(".//li/p/strong", r'^program\\n$'),
|
|
||||||
(".//li/p/em", r'^dfn\\n$'),
|
|
||||||
(".//li/p/kbd", r'^kbd\\n$'),
|
|
||||||
(".//li/p/span", 'File \N{TRIANGULAR BULLET} Close'),
|
|
||||||
(".//li/p/code/span[@class='pre']", '^a/$'),
|
|
||||||
(".//li/p/code/em/span[@class='pre']", '^varpart$'),
|
|
||||||
(".//li/p/code/em/span[@class='pre']", '^i$'),
|
|
||||||
(".//a[@href='https://www.python.org/dev/peps/pep-0008']"
|
|
||||||
"[@class='pep reference external']/strong", 'PEP 8'),
|
|
||||||
(".//a[@href='https://www.python.org/dev/peps/pep-0008']"
|
|
||||||
"[@class='pep reference external']/strong",
|
|
||||||
'Python Enhancement Proposal #8'),
|
|
||||||
(".//a[@href='https://tools.ietf.org/html/rfc1.html']"
|
|
||||||
"[@class='rfc reference external']/strong", 'RFC 1'),
|
|
||||||
(".//a[@href='https://tools.ietf.org/html/rfc1.html']"
|
|
||||||
"[@class='rfc reference external']/strong", 'Request for Comments #1'),
|
|
||||||
(".//a[@href='objects.html#envvar-HOME']"
|
|
||||||
"[@class='reference internal']/code/span[@class='pre']", 'HOME'),
|
|
||||||
(".//a[@href='#with']"
|
|
||||||
"[@class='reference internal']/code/span[@class='pre']", '^with$'),
|
|
||||||
(".//a[@href='#grammar-token-try-stmt']"
|
|
||||||
"[@class='reference internal']/code/span", '^statement$'),
|
|
||||||
(".//a[@href='#some-label'][@class='reference internal']/span", '^here$'),
|
|
||||||
(".//a[@href='#some-label'][@class='reference internal']/span", '^there$'),
|
|
||||||
(".//a[@href='subdir/includes.html']"
|
|
||||||
"[@class='reference internal']/span", 'Including in subdir'),
|
|
||||||
(".//a[@href='objects.html#cmdoption-python-c']"
|
|
||||||
"[@class='reference internal']/code/span[@class='pre']", '-c'),
|
|
||||||
# abbreviations
|
|
||||||
(".//abbr[@title='abbreviation']", '^abbr$'),
|
|
||||||
# version stuff
|
|
||||||
(".//div[@class='versionadded']/p/span", 'New in version 0.6: '),
|
|
||||||
(".//div[@class='versionadded']/p/span",
|
|
||||||
tail_check('First paragraph of versionadded')),
|
|
||||||
(".//div[@class='versionchanged']/p/span",
|
|
||||||
tail_check('First paragraph of versionchanged')),
|
|
||||||
(".//div[@class='versionchanged']/p",
|
|
||||||
'Second paragraph of versionchanged'),
|
|
||||||
# footnote reference
|
|
||||||
(".//a[@class='footnote-reference brackets']", r'1'),
|
|
||||||
# created by reference lookup
|
|
||||||
(".//a[@href='index.html#ref1']", ''),
|
|
||||||
# ``seealso`` directive
|
|
||||||
(".//div/p[@class='admonition-title']", 'See also'),
|
|
||||||
# a ``hlist`` directive
|
|
||||||
(".//table[@class='hlist']/tbody/tr/td/ul/li/p", '^This$'),
|
|
||||||
# a ``centered`` directive
|
|
||||||
(".//p[@class='centered']/strong", 'LICENSE'),
|
|
||||||
# a glossary
|
|
||||||
(".//dl/dt[@id='term-boson']", 'boson'),
|
|
||||||
# a production list
|
|
||||||
(".//pre/strong", 'try_stmt'),
|
|
||||||
(".//pre/a[@href='#grammar-token-try1-stmt']/code/span", 'try1_stmt'),
|
|
||||||
# tests for ``only`` directive
|
|
||||||
(".//p", 'A global substitution.'),
|
|
||||||
(".//p", 'In HTML.'),
|
|
||||||
(".//p", 'In both.'),
|
|
||||||
(".//p", 'Always present'),
|
|
||||||
# tests for ``any`` role
|
|
||||||
(".//a[@href='#with']/span", 'headings'),
|
|
||||||
(".//a[@href='objects.html#func_without_body']/code/span", 'objects'),
|
|
||||||
# tests for numeric labels
|
|
||||||
(".//a[@href='#id1'][@class='reference internal']/span", 'Testing various markup'),
|
|
||||||
],
|
|
||||||
'objects.html': [
|
|
||||||
(".//dt[@id='mod.Cls.meth1']", ''),
|
|
||||||
(".//dt[@id='errmod.Error']", ''),
|
|
||||||
(".//dt/code", r'long\(parameter,\s* list\)'),
|
|
||||||
(".//dt/code", 'another one'),
|
|
||||||
(".//a[@href='#mod.Cls'][@class='reference internal']", ''),
|
|
||||||
(".//dl[@class='userdesc']", ''),
|
|
||||||
(".//dt[@id='userdesc-myobj']", ''),
|
|
||||||
(".//a[@href='#userdesc-myobj'][@class='reference internal']", ''),
|
|
||||||
# docfields
|
|
||||||
(".//a[@class='reference internal'][@href='#TimeInt']/em", 'TimeInt'),
|
|
||||||
(".//a[@class='reference internal'][@href='#Time']", 'Time'),
|
|
||||||
(".//a[@class='reference internal'][@href='#errmod.Error']/strong", 'Error'),
|
|
||||||
# C references
|
|
||||||
(".//span[@class='pre']", 'CFunction()'),
|
|
||||||
(".//a[@href='#c.Sphinx_DoSomething']", ''),
|
|
||||||
(".//a[@href='#c.SphinxStruct.member']", ''),
|
|
||||||
(".//a[@href='#c.SPHINX_USE_PYTHON']", ''),
|
|
||||||
(".//a[@href='#c.SphinxType']", ''),
|
|
||||||
(".//a[@href='#c.sphinx_global']", ''),
|
|
||||||
# test global TOC created by toctree()
|
|
||||||
(".//ul[@class='current']/li[@class='toctree-l1 current']/a[@href='#']",
|
|
||||||
'Testing object descriptions'),
|
|
||||||
(".//li[@class='toctree-l1']/a[@href='markup.html']",
|
|
||||||
'Testing various markup'),
|
|
||||||
# test unknown field names
|
|
||||||
(".//dt[@class='field-odd']", 'Field_name'),
|
|
||||||
(".//dt[@class='field-even']", 'Field_name all lower'),
|
|
||||||
(".//dt[@class='field-odd']", 'FIELD_NAME'),
|
|
||||||
(".//dt[@class='field-even']", 'FIELD_NAME ALL CAPS'),
|
|
||||||
(".//dt[@class='field-odd']", 'Field_Name'),
|
|
||||||
(".//dt[@class='field-even']", 'Field_Name All Word Caps'),
|
|
||||||
(".//dt[@class='field-odd']", 'Field_name'),
|
|
||||||
(".//dt[@class='field-even']", 'Field_name First word cap'),
|
|
||||||
(".//dt[@class='field-odd']", 'FIELd_name'),
|
|
||||||
(".//dt[@class='field-even']", 'FIELd_name PARTial caps'),
|
|
||||||
# custom sidebar
|
|
||||||
(".//h4", 'Custom sidebar'),
|
|
||||||
# docfields
|
|
||||||
(".//dd[@class='field-odd']/p/strong", '^moo$'),
|
|
||||||
(".//dd[@class='field-odd']/p/strong", tail_check(r'\(Moo\) .* Moo')),
|
|
||||||
(".//dd[@class='field-odd']/ul/li/p/strong", '^hour$'),
|
|
||||||
(".//dd[@class='field-odd']/ul/li/p/em", '^DuplicateType$'),
|
|
||||||
(".//dd[@class='field-odd']/ul/li/p/em", tail_check(r'.* Some parameter')),
|
|
||||||
# others
|
|
||||||
(".//a[@class='reference internal'][@href='#cmdoption-perl-arg-p']/code/span",
|
|
||||||
'perl'),
|
|
||||||
(".//a[@class='reference internal'][@href='#cmdoption-perl-arg-p']/code/span",
|
|
||||||
'\\+p'),
|
|
||||||
(".//a[@class='reference internal'][@href='#cmdoption-perl-objc']/code/span",
|
|
||||||
'--ObjC\\+\\+'),
|
|
||||||
(".//a[@class='reference internal'][@href='#cmdoption-perl-plugin-option']/code/span",
|
|
||||||
'--plugin.option'),
|
|
||||||
(".//a[@class='reference internal'][@href='#cmdoption-perl-arg-create-auth-token']"
|
|
||||||
"/code/span",
|
|
||||||
'create-auth-token'),
|
|
||||||
(".//a[@class='reference internal'][@href='#cmdoption-perl-arg-arg']/code/span",
|
|
||||||
'arg'),
|
|
||||||
(".//a[@class='reference internal'][@href='#cmdoption-hg-arg-commit']/code/span",
|
|
||||||
'hg'),
|
|
||||||
(".//a[@class='reference internal'][@href='#cmdoption-hg-arg-commit']/code/span",
|
|
||||||
'commit'),
|
|
||||||
(".//a[@class='reference internal'][@href='#cmdoption-git-commit-p']/code/span",
|
|
||||||
'git'),
|
|
||||||
(".//a[@class='reference internal'][@href='#cmdoption-git-commit-p']/code/span",
|
|
||||||
'commit'),
|
|
||||||
(".//a[@class='reference internal'][@href='#cmdoption-git-commit-p']/code/span",
|
|
||||||
'-p'),
|
|
||||||
],
|
|
||||||
'index.html': [
|
|
||||||
(".//meta[@name='hc'][@content='hcval']", ''),
|
|
||||||
(".//meta[@name='hc_co'][@content='hcval_co']", ''),
|
|
||||||
(".//dt[@class='label']/span[@class='brackets']", r'Ref1'),
|
|
||||||
(".//dt[@class='label']", ''),
|
|
||||||
(".//li[@class='toctree-l1']/a", 'Testing various markup'),
|
|
||||||
(".//li[@class='toctree-l2']/a", 'Inline markup'),
|
|
||||||
(".//title", 'Sphinx <Tests>'),
|
|
||||||
(".//div[@class='footer']", 'Georg Brandl & Team'),
|
|
||||||
(".//a[@href='http://python.org/']"
|
|
||||||
"[@class='reference external']", ''),
|
|
||||||
(".//li/p/a[@href='genindex.html']/span", 'Index'),
|
|
||||||
(".//li/p/a[@href='py-modindex.html']/span", 'Module Index'),
|
|
||||||
(".//li/p/a[@href='search.html']/span", 'Search Page'),
|
|
||||||
# custom sidebar only for contents
|
|
||||||
(".//h4", 'Contents sidebar'),
|
|
||||||
# custom JavaScript
|
|
||||||
(".//script[@src='file://moo.js']", ''),
|
|
||||||
# URL in contents
|
|
||||||
(".//a[@class='reference external'][@href='http://sphinx-doc.org/']",
|
|
||||||
'http://sphinx-doc.org/'),
|
|
||||||
(".//a[@class='reference external'][@href='http://sphinx-doc.org/latest/']",
|
|
||||||
'Latest reference'),
|
|
||||||
# Indirect hyperlink targets across files
|
|
||||||
(".//a[@href='markup.html#some-label'][@class='reference internal']/span",
|
|
||||||
'^indirect hyperref$'),
|
|
||||||
],
|
|
||||||
'bom.html': [
|
|
||||||
(".//title", " File with UTF-8 BOM"),
|
|
||||||
],
|
|
||||||
'extensions.html': [
|
|
||||||
(".//a[@href='http://python.org/dev/']", "http://python.org/dev/"),
|
|
||||||
(".//a[@href='http://bugs.python.org/issue1000']", "issue 1000"),
|
|
||||||
(".//a[@href='http://bugs.python.org/issue1042']", "explicit caption"),
|
|
||||||
],
|
|
||||||
'genindex.html': [
|
|
||||||
# index entries
|
|
||||||
(".//a/strong", "Main"),
|
|
||||||
(".//a/strong", "[1]"),
|
|
||||||
(".//a/strong", "Other"),
|
|
||||||
(".//a", "entry"),
|
|
||||||
(".//li/a", "double"),
|
|
||||||
],
|
|
||||||
'footnote.html': [
|
|
||||||
(".//a[@class='footnote-reference brackets'][@href='#id9'][@id='id1']", r"1"),
|
|
||||||
(".//a[@class='footnote-reference brackets'][@href='#id10'][@id='id2']", r"2"),
|
|
||||||
(".//a[@class='footnote-reference brackets'][@href='#foo'][@id='id3']", r"3"),
|
|
||||||
(".//a[@class='reference internal'][@href='#bar'][@id='id4']", r"\[bar\]"),
|
|
||||||
(".//a[@class='reference internal'][@href='#baz-qux'][@id='id5']", r"\[baz_qux\]"),
|
|
||||||
(".//a[@class='footnote-reference brackets'][@href='#id11'][@id='id6']", r"4"),
|
|
||||||
(".//a[@class='footnote-reference brackets'][@href='#id12'][@id='id7']", r"5"),
|
|
||||||
(".//a[@class='fn-backref'][@href='#id1']", r"1"),
|
|
||||||
(".//a[@class='fn-backref'][@href='#id2']", r"2"),
|
|
||||||
(".//a[@class='fn-backref'][@href='#id3']", r"3"),
|
|
||||||
(".//a[@class='fn-backref'][@href='#id4']", r"bar"),
|
|
||||||
(".//a[@class='fn-backref'][@href='#id5']", r"baz_qux"),
|
|
||||||
(".//a[@class='fn-backref'][@href='#id6']", r"4"),
|
|
||||||
(".//a[@class='fn-backref'][@href='#id7']", r"5"),
|
|
||||||
(".//a[@class='fn-backref'][@href='#id8']", r"6"),
|
|
||||||
],
|
|
||||||
'otherext.html': [
|
|
||||||
(".//h1", "Generated section"),
|
|
||||||
(".//a[@href='_sources/otherext.foo.txt']", ''),
|
|
||||||
]
|
|
||||||
}))
|
|
||||||
@pytest.mark.sphinx('html', tags=['testtag'], confoverrides={
|
|
||||||
'html_context.hckey_co': 'hcval_co',
|
|
||||||
'html_experimental_html5_writer': True})
|
|
||||||
@pytest.mark.test_params(shared_result='test_build_html5_output')
|
|
||||||
def test_html5_output(app, cached_etree_parse, fname, expect):
|
|
||||||
app.build()
|
|
||||||
print(app.outdir / fname)
|
|
||||||
check_xpath(cached_etree_parse(app.outdir / fname), fname, *expect)
|
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.sphinx('html', tags=['testtag'], confoverrides={
|
|
||||||
'html_context.hckey_co': 'hcval_co',
|
|
||||||
'html_experimental_html5_writer': True})
|
|
||||||
@pytest.mark.test_params(shared_result='test_build_html_output')
|
|
||||||
def test_html_download(app):
|
|
||||||
app.build()
|
|
||||||
|
|
||||||
# subdir/includes.html
|
|
||||||
result = (app.outdir / 'subdir' / 'includes.html').text()
|
|
||||||
pattern = ('<a class="reference download internal" download="" '
|
|
||||||
'href="../(_downloads/.*/img.png)">')
|
|
||||||
matched = re.search(pattern, result)
|
|
||||||
assert matched
|
|
||||||
assert (app.outdir / matched.group(1)).exists()
|
|
||||||
filename = matched.group(1)
|
|
||||||
|
|
||||||
# includes.html
|
|
||||||
result = (app.outdir / 'includes.html').text()
|
|
||||||
pattern = ('<a class="reference download internal" download="" '
|
|
||||||
'href="(_downloads/.*/img.png)">')
|
|
||||||
matched = re.search(pattern, result)
|
|
||||||
assert matched
|
|
||||||
assert (app.outdir / matched.group(1)).exists()
|
|
||||||
assert matched.group(1) == filename
|
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.sphinx('html', testroot='roles-download',
|
|
||||||
confoverrides={'html_experimental_html5_writer': True})
|
|
||||||
def test_html_download_role(app, status, warning):
|
|
||||||
app.build()
|
|
||||||
digest = md5((app.srcdir / 'dummy.dat').encode()).hexdigest()
|
|
||||||
assert (app.outdir / '_downloads' / digest / 'dummy.dat').exists()
|
|
||||||
|
|
||||||
content = (app.outdir / 'index.html').text()
|
|
||||||
assert (('<li><p><a class="reference download internal" download="" '
|
|
||||||
'href="_downloads/%s/dummy.dat">'
|
|
||||||
'<code class="xref download docutils literal notranslate">'
|
|
||||||
'<span class="pre">dummy.dat</span></code></a></p></li>' % digest)
|
|
||||||
in content)
|
|
||||||
assert ('<li><p><code class="xref download docutils literal notranslate">'
|
|
||||||
'<span class="pre">not_found.dat</span></code></p></li>' in content)
|
|
||||||
assert ('<li><p><a class="reference download external" download="" '
|
|
||||||
'href="http://www.sphinx-doc.org/en/master/_static/sphinxheader.png">'
|
|
||||||
'<code class="xref download docutils literal notranslate">'
|
|
||||||
'<span class="pre">Sphinx</span> <span class="pre">logo</span>'
|
|
||||||
'</code></a></p></li>' in content)
|
|
||||||
@@ -1,63 +0,0 @@
|
|||||||
"""
|
|
||||||
test_build_htmlhelp
|
|
||||||
~~~~~~~~~~~~~~~~~~~
|
|
||||||
|
|
||||||
Test the HTML Help builder and check output against XPath.
|
|
||||||
|
|
||||||
:copyright: Copyright 2007-2019 by the Sphinx team, see AUTHORS.
|
|
||||||
:license: BSD, see LICENSE for details.
|
|
||||||
"""
|
|
||||||
|
|
||||||
import re
|
|
||||||
|
|
||||||
import pytest
|
|
||||||
|
|
||||||
from sphinx.builders.htmlhelp import chm_htmlescape
|
|
||||||
|
|
||||||
from sphinx.builders.htmlhelp import default_htmlhelp_basename
|
|
||||||
from sphinx.config import Config
|
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.sphinx('htmlhelp', testroot='basic')
|
|
||||||
def test_default_htmlhelp_file_suffix(app, warning):
|
|
||||||
assert app.builder.out_suffix == '.html'
|
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.sphinx('htmlhelp', testroot='basic',
|
|
||||||
confoverrides={'htmlhelp_file_suffix': '.htm'})
|
|
||||||
def test_htmlhelp_file_suffix(app, warning):
|
|
||||||
assert app.builder.out_suffix == '.htm'
|
|
||||||
|
|
||||||
|
|
||||||
def test_default_htmlhelp_basename():
|
|
||||||
config = Config({'project': 'Sphinx Documentation'})
|
|
||||||
config.init_values()
|
|
||||||
assert default_htmlhelp_basename(config) == 'sphinxdoc'
|
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.sphinx('htmlhelp', testroot='build-htmlhelp')
|
|
||||||
def test_chm(app):
|
|
||||||
app.build()
|
|
||||||
|
|
||||||
# check .hhk file
|
|
||||||
outname = app.builder.config.htmlhelp_basename
|
|
||||||
hhk_path = str(app.outdir / outname + '.hhk')
|
|
||||||
|
|
||||||
with open(hhk_path, 'rb') as f:
|
|
||||||
data = f.read()
|
|
||||||
m = re.search(br'&#[xX][0-9a-fA-F]+;', data)
|
|
||||||
assert m is None, 'Hex escaping exists in .hhk file: ' + str(m.group(0))
|
|
||||||
|
|
||||||
|
|
||||||
def test_chm_htmlescape():
|
|
||||||
assert chm_htmlescape('Hello world') == 'Hello world'
|
|
||||||
assert chm_htmlescape(u'Unicode 文字') == u'Unicode 文字'
|
|
||||||
assert chm_htmlescape('E') == '&#x45'
|
|
||||||
|
|
||||||
assert chm_htmlescape('<Hello> "world"') == '<Hello> "world"'
|
|
||||||
assert chm_htmlescape('<Hello> "world"', True) == '<Hello> "world"'
|
|
||||||
assert chm_htmlescape('<Hello> "world"', False) == '<Hello> "world"'
|
|
||||||
|
|
||||||
assert chm_htmlescape("Hello 'world'") == "Hello 'world'"
|
|
||||||
assert chm_htmlescape("Hello 'world'", True) == "Hello 'world'"
|
|
||||||
assert chm_htmlescape("Hello 'world'", False) == "Hello 'world'"
|
|
||||||
@@ -24,7 +24,10 @@ def test_defaults(app, status, warning):
|
|||||||
assert "Anchor 'does-not-exist' not found" in content
|
assert "Anchor 'does-not-exist' not found" in content
|
||||||
# looking for non-existent URL should fail
|
# looking for non-existent URL should fail
|
||||||
assert " Max retries exceeded with url: /doesnotexist" in content
|
assert " Max retries exceeded with url: /doesnotexist" in content
|
||||||
assert len(content.splitlines()) == 3
|
# images should fail
|
||||||
|
assert "Not Found for url: http://example.com/image.png" in content
|
||||||
|
assert "Not Found for url: http://example.com/image2.png" in content
|
||||||
|
assert len(content.splitlines()) == 5
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.sphinx(
|
@pytest.mark.sphinx(
|
||||||
@@ -32,7 +35,9 @@ def test_defaults(app, status, warning):
|
|||||||
confoverrides={'linkcheck_anchors_ignore': ["^!", "^top$"],
|
confoverrides={'linkcheck_anchors_ignore': ["^!", "^top$"],
|
||||||
'linkcheck_ignore': [
|
'linkcheck_ignore': [
|
||||||
'https://localhost:7777/doesnotexist',
|
'https://localhost:7777/doesnotexist',
|
||||||
'http://www.sphinx-doc.org/en/1.7/intro.html#']
|
'http://www.sphinx-doc.org/en/1.7/intro.html#',
|
||||||
|
'http://example.com/image.png',
|
||||||
|
'http://example.com/image2.png']
|
||||||
})
|
})
|
||||||
def test_anchors_ignored(app, status, warning):
|
def test_anchors_ignored(app, status, warning):
|
||||||
app.builder.build_all()
|
app.builder.build_all()
|
||||||
|
|||||||
@@ -10,11 +10,12 @@
|
|||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.sphinx('dummy', srcdir="test_builder")
|
@pytest.mark.sphinx('dummy', srcdir="test_builder", freshenv=True)
|
||||||
def test_incremental_reading(app):
|
def test_incremental_reading(app):
|
||||||
# first reading
|
# first reading
|
||||||
updated = app.builder.read()
|
updated = app.builder.read()
|
||||||
assert set(updated) == app.env.found_docs == set(app.env.all_docs)
|
assert set(updated) == app.env.found_docs == set(app.env.all_docs)
|
||||||
|
assert updated == sorted(updated) # sorted by alphanumeric
|
||||||
|
|
||||||
# test if exclude_patterns works ok
|
# test if exclude_patterns works ok
|
||||||
assert 'subdir/excluded' not in app.env.found_docs
|
assert 'subdir/excluded' not in app.env.found_docs
|
||||||
@@ -27,29 +28,20 @@ def test_incremental_reading(app):
|
|||||||
# second reading
|
# second reading
|
||||||
updated = app.builder.read()
|
updated = app.builder.read()
|
||||||
|
|
||||||
# "includes" and "images" are in there because they contain references
|
assert set(updated) == set(['index', 'new'])
|
||||||
# to nonexisting downloadable or image files, which are given another
|
|
||||||
# chance to exist
|
|
||||||
assert set(updated) == set(['index', 'new', 'includes', 'images'])
|
|
||||||
assert 'autodoc' not in app.env.all_docs
|
assert 'autodoc' not in app.env.all_docs
|
||||||
assert 'autodoc' not in app.env.found_docs
|
assert 'autodoc' not in app.env.found_docs
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.sphinx('dummy')
|
@pytest.mark.sphinx('dummy', testroot='warnings', freshenv=True)
|
||||||
def test_env_read_docs(app):
|
def test_incremental_reading_for_missing_files(app):
|
||||||
"""By default, docnames are read in alphanumeric order"""
|
# first reading
|
||||||
def on_env_read_docs_1(app, env, docnames):
|
updated = app.builder.read()
|
||||||
pass
|
assert set(updated) == app.env.found_docs == set(app.env.all_docs)
|
||||||
|
|
||||||
app.connect('env-before-read-docs', on_env_read_docs_1)
|
# second reading
|
||||||
|
updated = app.builder.read()
|
||||||
|
|
||||||
read_docnames = app.builder.read()
|
# "index" is listed up to updated because it contains references
|
||||||
assert len(read_docnames) > 2 and read_docnames == sorted(read_docnames)
|
# to nonexisting downloadable or image files
|
||||||
|
assert set(updated) == set(['index'])
|
||||||
def on_env_read_docs_2(app, env, docnames):
|
|
||||||
docnames.remove('images')
|
|
||||||
|
|
||||||
app.connect('env-before-read-docs', on_env_read_docs_2)
|
|
||||||
|
|
||||||
read_docnames = app.builder.read()
|
|
||||||
assert len(read_docnames) == 2
|
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ import sphinx.domains.cpp as cppDomain
|
|||||||
from sphinx import addnodes
|
from sphinx import addnodes
|
||||||
from sphinx.domains.cpp import DefinitionParser, DefinitionError, NoOldIdError
|
from sphinx.domains.cpp import DefinitionParser, DefinitionError, NoOldIdError
|
||||||
from sphinx.domains.cpp import Symbol, _max_id, _id_prefix
|
from sphinx.domains.cpp import Symbol, _max_id, _id_prefix
|
||||||
|
from sphinx.util import docutils
|
||||||
|
|
||||||
|
|
||||||
def parse(name, string):
|
def parse(name, string):
|
||||||
@@ -734,12 +735,14 @@ def test_build_domain_cpp_misuse_of_roles(app, status, warning):
|
|||||||
# TODO: properly check for the warnings we expect
|
# TODO: properly check for the warnings we expect
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.skipif(docutils.__version_info__ < (0, 13),
|
||||||
|
reason='docutils-0.13 or above is required')
|
||||||
@pytest.mark.sphinx(testroot='domain-cpp', confoverrides={'add_function_parentheses': True})
|
@pytest.mark.sphinx(testroot='domain-cpp', confoverrides={'add_function_parentheses': True})
|
||||||
def test_build_domain_cpp_with_add_function_parentheses_is_True(app, status, warning):
|
def test_build_domain_cpp_with_add_function_parentheses_is_True(app, status, warning):
|
||||||
app.builder.build_all()
|
app.builder.build_all()
|
||||||
|
|
||||||
def check(spec, text, file):
|
def check(spec, text, file):
|
||||||
pattern = '<li>%s<a .*?><code .*?><span .*?>%s</span></code></a></li>' % spec
|
pattern = '<li><p>%s<a .*?><code .*?><span .*?>%s</span></code></a></p></li>' % spec
|
||||||
res = re.search(pattern, text)
|
res = re.search(pattern, text)
|
||||||
if not res:
|
if not res:
|
||||||
print("Pattern\n\t%s\nnot found in %s" % (pattern, file))
|
print("Pattern\n\t%s\nnot found in %s" % (pattern, file))
|
||||||
@@ -775,13 +778,14 @@ def test_build_domain_cpp_with_add_function_parentheses_is_True(app, status, war
|
|||||||
check(s, t, f)
|
check(s, t, f)
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.sphinx(testroot='domain-cpp', confoverrides={
|
@pytest.mark.skipif(docutils.__version_info__ < (0, 13),
|
||||||
'add_function_parentheses': False})
|
reason='docutils-0.13 or above is required')
|
||||||
|
@pytest.mark.sphinx(testroot='domain-cpp', confoverrides={'add_function_parentheses': False})
|
||||||
def test_build_domain_cpp_with_add_function_parentheses_is_False(app, status, warning):
|
def test_build_domain_cpp_with_add_function_parentheses_is_False(app, status, warning):
|
||||||
app.builder.build_all()
|
app.builder.build_all()
|
||||||
|
|
||||||
def check(spec, text, file):
|
def check(spec, text, file):
|
||||||
pattern = '<li>%s<a .*?><code .*?><span .*?>%s</span></code></a></li>' % spec
|
pattern = '<li><p>%s<a .*?><code .*?><span .*?>%s</span></code></a></p></li>' % spec
|
||||||
res = re.search(pattern, text)
|
res = re.search(pattern, text)
|
||||||
if not res:
|
if not res:
|
||||||
print("Pattern\n\t%s\nnot found in %s" % (pattern, file))
|
print("Pattern\n\t%s\nnot found in %s" % (pattern, file))
|
||||||
|
|||||||
@@ -17,8 +17,6 @@ from sphinx.testing.comparer import PathComparer
|
|||||||
@pytest.mark.sphinx('dummy')
|
@pytest.mark.sphinx('dummy')
|
||||||
def test_images(app):
|
def test_images(app):
|
||||||
app.build()
|
app.build()
|
||||||
assert ('image file not readable: foo.png'
|
|
||||||
in app._warning.getvalue())
|
|
||||||
|
|
||||||
tree = app.env.get_doctree('images')
|
tree = app.env.get_doctree('images')
|
||||||
htmlbuilder = StandaloneHTMLBuilder(app)
|
htmlbuilder = StandaloneHTMLBuilder(app)
|
||||||
|
|||||||
@@ -49,7 +49,6 @@ def apidoc_params(request):
|
|||||||
def test_simple(make_app, apidoc):
|
def test_simple(make_app, apidoc):
|
||||||
outdir = apidoc.outdir
|
outdir = apidoc.outdir
|
||||||
assert (outdir / 'conf.py').isfile()
|
assert (outdir / 'conf.py').isfile()
|
||||||
assert (outdir / 'autodoc_fodder.rst').isfile()
|
|
||||||
assert (outdir / 'index.rst').isfile()
|
assert (outdir / 'index.rst').isfile()
|
||||||
|
|
||||||
app = make_app('text', srcdir=outdir)
|
app = make_app('text', srcdir=outdir)
|
||||||
@@ -273,7 +272,6 @@ def test_excludes_module_should_not_be_skipped(apidoc):
|
|||||||
def test_multibyte_parameters(make_app, apidoc):
|
def test_multibyte_parameters(make_app, apidoc):
|
||||||
outdir = apidoc.outdir
|
outdir = apidoc.outdir
|
||||||
assert (outdir / 'conf.py').isfile()
|
assert (outdir / 'conf.py').isfile()
|
||||||
assert (outdir / 'autodoc_fodder.rst').isfile()
|
|
||||||
assert (outdir / 'index.rst').isfile()
|
assert (outdir / 'index.rst').isfile()
|
||||||
|
|
||||||
conf_py = (outdir / 'conf.py').text()
|
conf_py = (outdir / 'conf.py').text()
|
||||||
|
|||||||
@@ -16,6 +16,21 @@ import pytest
|
|||||||
from sphinx.ext.autodoc.importer import _MockModule, _MockObject, mock
|
from sphinx.ext.autodoc.importer import _MockModule, _MockObject, mock
|
||||||
|
|
||||||
|
|
||||||
|
def test_MockModule():
|
||||||
|
mock = _MockModule('mocked_module', None)
|
||||||
|
assert isinstance(mock.some_attr, _MockObject)
|
||||||
|
assert isinstance(mock.some_method, _MockObject)
|
||||||
|
assert isinstance(mock.attr1.attr2, _MockObject)
|
||||||
|
assert isinstance(mock.attr1.attr2.meth(), _MockObject)
|
||||||
|
|
||||||
|
assert repr(mock.some_attr) == 'mocked_module.some_attr'
|
||||||
|
assert repr(mock.some_method) == 'mocked_module.some_method'
|
||||||
|
assert repr(mock.attr1.attr2) == 'mocked_module.attr1.attr2'
|
||||||
|
assert repr(mock.attr1.attr2.meth) == 'mocked_module.attr1.attr2.meth'
|
||||||
|
|
||||||
|
assert repr(mock) == 'mocked_module'
|
||||||
|
|
||||||
|
|
||||||
def test_MockObject():
|
def test_MockObject():
|
||||||
mock = _MockObject()
|
mock = _MockObject()
|
||||||
assert isinstance(mock.some_attr, _MockObject)
|
assert isinstance(mock.some_attr, _MockObject)
|
||||||
@@ -25,6 +40,7 @@ def test_MockObject():
|
|||||||
|
|
||||||
class SubClass(mock.SomeClass):
|
class SubClass(mock.SomeClass):
|
||||||
"""docstring of SubClass"""
|
"""docstring of SubClass"""
|
||||||
|
|
||||||
def method(self):
|
def method(self):
|
||||||
return "string"
|
return "string"
|
||||||
|
|
||||||
|
|||||||
@@ -12,37 +12,82 @@ import re
|
|||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
|
from sphinx.util import docutils
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.skipif(docutils.__version_info__ < (0, 13),
|
||||||
|
reason='docutils-0.13 or above is required')
|
||||||
@pytest.mark.sphinx('html', testroot='ext-autosectionlabel')
|
@pytest.mark.sphinx('html', testroot='ext-autosectionlabel')
|
||||||
def test_autosectionlabel_html(app, status, warning):
|
def test_autosectionlabel_html(app, status, warning, skipped_labels=False):
|
||||||
app.builder.build_all()
|
app.builder.build_all()
|
||||||
|
|
||||||
content = (app.outdir / 'index.html').text()
|
content = (app.outdir / 'index.html').text()
|
||||||
html = ('<li><a class="reference internal" href="#introduce-of-sphinx">'
|
html = ('<li><p><a class="reference internal" href="#introduce-of-sphinx">'
|
||||||
'<span class=".*?">Introduce of Sphinx</span></a></li>')
|
'<span class=".*?">Introduce of Sphinx</span></a></p></li>')
|
||||||
assert re.search(html, content, re.S)
|
assert re.search(html, content, re.S)
|
||||||
|
|
||||||
html = ('<li><a class="reference internal" href="#installation">'
|
html = ('<li><p><a class="reference internal" href="#installation">'
|
||||||
'<span class="std std-ref">Installation</span></a></li>')
|
'<span class="std std-ref">Installation</span></a></p></li>')
|
||||||
assert re.search(html, content, re.S)
|
assert re.search(html, content, re.S)
|
||||||
|
|
||||||
html = ('<li><a class="reference internal" href="#for-windows-users">'
|
html = ('<li><p><a class="reference internal" href="#for-windows-users">'
|
||||||
'<span class="std std-ref">For Windows users</span></a></li>')
|
'<span class="std std-ref">For Windows users</span></a></p></li>')
|
||||||
assert re.search(html, content, re.S)
|
assert re.search(html, content, re.S)
|
||||||
|
|
||||||
html = ('<li><a class="reference internal" href="#for-unix-users">'
|
html = ('<li><p><a class="reference internal" href="#for-unix-users">'
|
||||||
'<span class="std std-ref">For UNIX users</span></a></li>')
|
'<span class="std std-ref">For UNIX users</span></a></p></li>')
|
||||||
|
assert re.search(html, content, re.S)
|
||||||
|
|
||||||
|
html = ('<li><p><a class="reference internal" href="#linux">'
|
||||||
|
'<span class="std std-ref">Linux</span></a></p></li>')
|
||||||
|
assert re.search(html, content, re.S)
|
||||||
|
|
||||||
|
html = ('<li><p><a class="reference internal" href="#freebsd">'
|
||||||
|
'<span class="std std-ref">FreeBSD</span></a></p></li>')
|
||||||
assert re.search(html, content, re.S)
|
assert re.search(html, content, re.S)
|
||||||
|
|
||||||
# for smart_quotes (refs: #4027)
|
# for smart_quotes (refs: #4027)
|
||||||
html = ('<li><a class="reference internal" '
|
html = ('<li><p><a class="reference internal" '
|
||||||
'href="#this-one-s-got-an-apostrophe">'
|
'href="#this-one-s-got-an-apostrophe">'
|
||||||
'<span class="std std-ref">This one’s got an apostrophe'
|
'<span class="std std-ref">This one’s got an apostrophe'
|
||||||
'</span></a></li>')
|
'</span></a></p></li>')
|
||||||
assert re.search(html, content, re.S)
|
assert re.search(html, content, re.S)
|
||||||
|
|
||||||
|
|
||||||
# Re-use test definition from above, just change the test root directory
|
# Re-use test definition from above, just change the test root directory
|
||||||
|
@pytest.mark.skipif(docutils.__version_info__ < (0, 13),
|
||||||
|
reason='docutils-0.13 or above is required')
|
||||||
@pytest.mark.sphinx('html', testroot='ext-autosectionlabel-prefix-document')
|
@pytest.mark.sphinx('html', testroot='ext-autosectionlabel-prefix-document')
|
||||||
def test_autosectionlabel_prefix_document_html(app, status, warning):
|
def test_autosectionlabel_prefix_document_html(app, status, warning):
|
||||||
return test_autosectionlabel_html(app, status, warning)
|
test_autosectionlabel_html(app, status, warning)
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.skipif(docutils.__version_info__ < (0, 13),
|
||||||
|
reason='docutils-0.13 or above is required')
|
||||||
|
@pytest.mark.sphinx('html', testroot='ext-autosectionlabel',
|
||||||
|
confoverrides={'autosectionlabel_maxdepth': 3})
|
||||||
|
def test_autosectionlabel_maxdepth(app, status, warning):
|
||||||
|
app.builder.build_all()
|
||||||
|
|
||||||
|
content = (app.outdir / 'index.html').text()
|
||||||
|
|
||||||
|
# depth: 1
|
||||||
|
html = ('<li><p><a class="reference internal" href="#test-ext-autosectionlabel">'
|
||||||
|
'<span class=".*?">test-ext-autosectionlabel</span></a></p></li>')
|
||||||
|
assert re.search(html, content, re.S)
|
||||||
|
|
||||||
|
# depth: 2
|
||||||
|
html = ('<li><p><a class="reference internal" href="#installation">'
|
||||||
|
'<span class="std std-ref">Installation</span></a></p></li>')
|
||||||
|
assert re.search(html, content, re.S)
|
||||||
|
|
||||||
|
# depth: 3
|
||||||
|
html = ('<li><p><a class="reference internal" href="#for-windows-users">'
|
||||||
|
'<span class="std std-ref">For Windows users</span></a></p></li>')
|
||||||
|
assert re.search(html, content, re.S)
|
||||||
|
|
||||||
|
# depth: 4
|
||||||
|
html = '<li><p><span class="xref std std-ref">Linux</span></p></li>'
|
||||||
|
assert re.search(html, content, re.S)
|
||||||
|
|
||||||
|
assert 'WARNING: undefined label: linux' in warning.getvalue()
|
||||||
|
|||||||
@@ -8,6 +8,7 @@
|
|||||||
:license: BSD, see LICENSE for details.
|
:license: BSD, see LICENSE for details.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
import sys
|
||||||
from io import StringIO
|
from io import StringIO
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
@@ -203,7 +204,7 @@ def test_autosummary_latex_table_colspec(app, status, warning):
|
|||||||
result = (app.outdir / 'python.tex').text(encoding='utf8')
|
result = (app.outdir / 'python.tex').text(encoding='utf8')
|
||||||
print(status.getvalue())
|
print(status.getvalue())
|
||||||
print(warning.getvalue())
|
print(warning.getvalue())
|
||||||
assert r'\begin{longtable}{\X{1}{2}\X{1}{2}}' in result
|
assert r'\begin{longtable}[c]{\X{1}{2}\X{1}{2}}' in result
|
||||||
assert r'p{0.5\linewidth}' not in result
|
assert r'p{0.5\linewidth}' not in result
|
||||||
|
|
||||||
|
|
||||||
@@ -229,3 +230,15 @@ def test_import_by_name():
|
|||||||
assert obj == sphinx.ext.autosummary.Autosummary.get_items
|
assert obj == sphinx.ext.autosummary.Autosummary.get_items
|
||||||
assert parent is sphinx.ext.autosummary.Autosummary
|
assert parent is sphinx.ext.autosummary.Autosummary
|
||||||
assert modname == 'sphinx.ext.autosummary'
|
assert modname == 'sphinx.ext.autosummary'
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.sphinx('dummy', testroot='ext-autosummary-mock_imports')
|
||||||
|
def test_autosummary_mock_imports(app, status, warning):
|
||||||
|
try:
|
||||||
|
app.build()
|
||||||
|
assert warning.getvalue() == ''
|
||||||
|
|
||||||
|
# generated/foo is generated successfully
|
||||||
|
assert app.env.get_doctree('generated/foo')
|
||||||
|
finally:
|
||||||
|
sys.modules.pop('foo', None) # unload foo module
|
||||||
|
|||||||
@@ -15,3 +15,18 @@ import pytest
|
|||||||
def test_githubpages(app, status, warning):
|
def test_githubpages(app, status, warning):
|
||||||
app.builder.build_all()
|
app.builder.build_all()
|
||||||
assert (app.outdir / '.nojekyll').exists()
|
assert (app.outdir / '.nojekyll').exists()
|
||||||
|
assert not (app.outdir / 'CNAME').exists()
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.sphinx('html', testroot='ext-githubpages', confoverrides={'html_baseurl': 'https://sphinx-doc.github.io'})
|
||||||
|
def test_no_cname_for_github_io_domain(app, status, warning):
|
||||||
|
app.builder.build_all()
|
||||||
|
assert (app.outdir / '.nojekyll').exists()
|
||||||
|
assert not (app.outdir / 'CNAME').exists()
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.sphinx('html', testroot='ext-githubpages', confoverrides={'html_baseurl': 'https://sphinx-doc.org'})
|
||||||
|
def test_cname_for_custom_domain(app, status, warning):
|
||||||
|
app.builder.build_all()
|
||||||
|
assert (app.outdir / '.nojekyll').exists()
|
||||||
|
assert (app.outdir / 'CNAME').text() == 'sphinx-doc.org'
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ def test_graphviz_png_html(app, status, warning):
|
|||||||
app.builder.build_all()
|
app.builder.build_all()
|
||||||
|
|
||||||
content = (app.outdir / 'index.html').text()
|
content = (app.outdir / 'index.html').text()
|
||||||
html = (r'<div class="figure" .*?>\s*'
|
html = (r'<div class="figure align-center" .*?>\s*'
|
||||||
r'<div class="graphviz"><img .*?/></div>\s*<p class="caption">'
|
r'<div class="graphviz"><img .*?/></div>\s*<p class="caption">'
|
||||||
r'<span class="caption-text">caption of graph</span>.*</p>\s*</div>')
|
r'<span class="caption-text">caption of graph</span>.*</p>\s*</div>')
|
||||||
assert re.search(html, content, re.S)
|
assert re.search(html, content, re.S)
|
||||||
@@ -52,7 +52,7 @@ def test_graphviz_svg_html(app, status, warning):
|
|||||||
|
|
||||||
content = (app.outdir / 'index.html').text()
|
content = (app.outdir / 'index.html').text()
|
||||||
|
|
||||||
html = (r'<div class=\"figure\" .*?>\n'
|
html = (r'<div class=\"figure align-center\" .*?>\n'
|
||||||
r'<div class="graphviz"><object data=\".*\.svg\".*>\n'
|
r'<div class="graphviz"><object data=\".*\.svg\".*>\n'
|
||||||
r'\s*<p class=\"warning\">digraph foo {\n'
|
r'\s*<p class=\"warning\">digraph foo {\n'
|
||||||
r'bar -> baz\n'
|
r'bar -> baz\n'
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user