Merge branch 'master' into refactor_smartquotes2

This commit is contained in:
Takeshi KOMIYA 2018-01-15 01:14:23 +09:00
commit fcc876f35c
75 changed files with 859 additions and 721 deletions

View File

@ -18,6 +18,7 @@ Other co-maintainers:
Other contributors, listed alphabetically, are: Other contributors, listed alphabetically, are:
* Alastair Houghton -- Apple Help builder * Alastair Houghton -- Apple Help builder
* Alexander Todorov -- inheritance_diagram tests and improvements
* Andi Albrecht -- agogo theme * Andi Albrecht -- agogo theme
* Jakob Lykke Andersen -- Rewritten C++ domain * Jakob Lykke Andersen -- Rewritten C++ domain
* Henrique Bastos -- SVG support for graphviz extension * Henrique Bastos -- SVG support for graphviz extension
@ -67,6 +68,7 @@ Other contributors, listed alphabetically, are:
* Barry Warsaw -- setup command improvements * Barry Warsaw -- setup command improvements
* Sebastian Wiesner -- image handling, distutils support * Sebastian Wiesner -- image handling, distutils support
* Michael Wilson -- Intersphinx HTTP basic auth support * Michael Wilson -- Intersphinx HTTP basic auth support
* Matthew Woodcraft -- text output improvements
* Joel Wurtz -- cellspanning support in LaTeX * Joel Wurtz -- cellspanning support in LaTeX
* Hong Xu -- svg support in imgmath extension and various bug fixes * Hong Xu -- svg support in imgmath extension and various bug fixes
* Stephen Finucane -- setup command improvements and documentation * Stephen Finucane -- setup command improvements and documentation

29
CHANGES
View File

@ -1,6 +1,11 @@
Release 1.7 (in development) Release 1.7 (in development)
============================ ============================
Dependencies
------------
* Add ``packaging`` package
Incompatible changes Incompatible changes
-------------------- --------------------
@ -16,6 +21,12 @@ Incompatible changes
* #4389: output directory will be created after loading extensions * #4389: output directory will be created after loading extensions
* autodoc does not generate warnings messages to the generated document even if * autodoc does not generate warnings messages to the generated document even if
:confval:`keep_warnings` is True. They are only emitted to stderr. :confval:`keep_warnings` is True. They are only emitted to stderr.
* shebang line is removed from generated conf.py
* #2557: autodoc: :confval:`autodoc_mock_imports` only mocks specified modules
with their descendants. It does not mock their ancestors. If you want to
mock them, please specify the name of ancestors implicitly.
* #3620: html theme: move DOCUMENTATION_OPTIONS to independent JavaScript file
(refs: #4295)
Deprecated Deprecated
---------- ----------
@ -65,6 +76,20 @@ Features added
* #947: autodoc now supports ignore-module-all to ignore a module's ``__all__`` * #947: autodoc now supports ignore-module-all to ignore a module's ``__all__``
* #4332: Let LaTeX obey :confval:`math_numfig` for equation numbering * #4332: Let LaTeX obey :confval:`math_numfig` for equation numbering
* #4093: sphinx-build creates empty directories for unknown targets/builders * #4093: sphinx-build creates empty directories for unknown targets/builders
* Add ``top-classes`` option for the ``sphinx.ext.inheritance_diagram``
extension to limit the scope of inheritance graphs.
* #4183: doctest: ``:pyversion:`` option also follows PEP-440 specification
* #4235: html: Add :confval:`manpages_url` to make manpage roles to hyperlinks
* #3570: autodoc: Do not display 'typing.' module for type hints
* #4354: sphinx-build now emits finish message. Builders can modify it through
``Builder.epilog`` attribute
* #4245: html themes: Add ``language`` to javascript vars list
* #4079: html: Add ``notranslate`` class to each code-blocks, literals and maths
to let Google Translate know they are not translatable
* #4137: doctest: doctest block is always highlighted as python console (pycon)
* #4137: doctest: testcode block is always highlighted as python
* #3998: text: Assign section numbers by default. You can control it using
:confval:`text_add_secnumbers` and :confval:`text_secnumber_suffix`
Features removed Features removed
---------------- ----------------
@ -95,6 +120,8 @@ Features removed
* LaTeX environment ``notice``, use ``sphinxadmonition`` instead * LaTeX environment ``notice``, use ``sphinxadmonition`` instead
* LaTeX ``\sphinxstylethead``, use ``\sphinxstyletheadfamily`` * LaTeX ``\sphinxstylethead``, use ``\sphinxstyletheadfamily``
* C++, support of function concepts. Thanks to mickk-on-cpp. * C++, support of function concepts. Thanks to mickk-on-cpp.
* Not used and previously not documented LaTeX macros ``\shortversion``
and ``\setshortversion``
Bugs fixed Bugs fixed
@ -113,11 +140,13 @@ Bugs fixed
* #4198: autosummary emits multiple 'autodoc-process-docstring' event. Thanks * #4198: autosummary emits multiple 'autodoc-process-docstring' event. Thanks
to Joel Nothman. to Joel Nothman.
* #4081: Warnings and errors colored the same when building * #4081: Warnings and errors colored the same when building
* latex: Do not display 'Release' label if :confval:`release` is not set
Testing Testing
-------- --------
* Add support for docutils 0.14 * Add support for docutils 0.14
* Add tests for the ``sphinx.ext.inheritance_diagram`` extension.
Release 1.6.7 (in development) Release 1.6.7 (in development)
============================== ==============================

View File

@ -293,6 +293,24 @@ General configuration
.. versionadded:: 1.3 .. versionadded:: 1.3
.. confval:: manpages_url
A URL to cross-reference :rst:role:`manpage` directives. If this is
defined to ``https://manpages.debian.org/{path}``, the
:literal:`:manpage:`man(1)`` role will like to
<https://manpages.debian.org/man(1)>. The patterns available are:
* ``page`` - the manual page (``man``)
* ``section`` - the manual section (``1``)
* ``path`` - the original manual page and section specified (``man(1)``)
This also supports manpages specified as ``man.1``.
.. note:: This currently affects only HTML writers but could be
expanded in the future.
.. versionadded:: 1.7
.. confval:: nitpicky .. confval:: nitpicky
If true, Sphinx will warn about *all* references where the target cannot be If true, Sphinx will warn about *all* references where the target cannot be
@ -2021,6 +2039,20 @@ These options influence text output.
.. versionadded:: 1.1 .. versionadded:: 1.1
.. confval:: text_add_secnumbers
A boolean that decides whether section numbers are included in text output.
Default is ``True``.
.. versionadded:: 1.7
.. confval:: text_secnumber_suffix
Suffix for section numbers in text output. Default: ``". "``. Set to ``" "``
to suppress the final dot on section numbers.
.. versionadded:: 1.7
.. _man-options: .. _man-options:

View File

@ -80,12 +80,24 @@ a comma-separated list of group names.
.. doctest:: .. doctest::
:pyversion: > 3.3 :pyversion: > 3.3
The supported operands are ``<``, ``<=``, ``==``, ``>=``, ``>``, and The following operands are supported:
comparison is performed by `distutils.version.LooseVersion
<https://www.python.org/dev/peps/pep-0386/#distutils>`__. * ``~=``: Compatible release clause
* ``==``: Version matching clause
* ``!=``: Version exclusion clause
* ``<=``, ``>=``: Inclusive ordered comparison clause
* ``<``, ``>``: Exclusive ordered comparison clause
* ``===``: Arbitrary equality clause.
``pyversion`` option is followed `PEP-440: Version Specifiers
<https://www.python.org/dev/peps/pep-0440/#version-specifiers>`__.
.. versionadded:: 1.6 .. versionadded:: 1.6
.. versionchanged:: 1.7
Supported PEP-440 operands and notations
Note that like with standard doctests, you have to use ``<BLANKLINE>`` to Note that like with standard doctests, you have to use ``<BLANKLINE>`` to
signal a blank line in the expected output. The ``<BLANKLINE>`` is removed signal a blank line in the expected output. The ``<BLANKLINE>`` is removed
when building presentation output (HTML, LaTeX etc.). when building presentation output (HTML, LaTeX etc.).

View File

@ -42,6 +42,54 @@ It adds this directive:
.. versionchanged:: 1.5 .. versionchanged:: 1.5
Added ``caption`` option Added ``caption`` option
It also supports a ``top-classes`` option which requires one or more class
names separated by comma. If specified inheritance traversal will stop at the
specified class names. Given the following Python module::
"""
A
/ \
B C
/ \ / \
E D F
"""
class A(object):
pass
class B(A):
pass
class C(A):
pass
class D(B, C):
pass
class E(B):
pass
class F(C):
pass
If you have specified a module in the inheritance diagram like this::
.. inheritance-diagram:: dummy.test
:top-classes: dummy.test.B, dummy.test.C
any base classes which are ancestors to ``top-classes`` and are also defined
in the same module will be rendered as stand alone nodes. In this example
class A will be rendered as stand alone node in the graph. This is a known
issue due to how this extension works internally.
If you don't want class A (or any other ancestors) to be visible then specify
only the classes you would like to generate the diagram for like this::
.. inheritance-diagram:: dummy.test.D dummy.test.E dummy.test.F
:top-classes: dummy.test.B, dummy.test.C
.. versionchanged:: 1.7
Added ``top-classes`` option to limit the scope of inheritance graphs.
New config values are: New config values are:

View File

@ -15,6 +15,7 @@ Builder API
.. autoattribute:: name .. autoattribute:: name
.. autoattribute:: format .. autoattribute:: format
.. autoattribute:: epilog
.. autoattribute:: supported_image_types .. autoattribute:: supported_image_types
These methods are predefined and will be called from the application: These methods are predefined and will be called from the application:

View File

@ -3,7 +3,7 @@ Introduction
This is the documentation for the Sphinx documentation builder. Sphinx is a This is the documentation for the Sphinx documentation builder. Sphinx is a
tool that translates a set of reStructuredText_ source files into various output tool that translates a set of reStructuredText_ source files into various output
formats, automatically producing cross-references, indices etc. That is, if formats, automatically producing cross-references, indices, etc. That is, if
you have a directory containing a bunch of reST-formatted documents (and you have a directory containing a bunch of reST-formatted documents (and
possibly subdirectories of docs in there as well), Sphinx can generate a possibly subdirectories of docs in there as well), Sphinx can generate a
nicely-organized arrangement of HTML files (in some other directory) for easy nicely-organized arrangement of HTML files (in some other directory) for easy
@ -38,7 +38,7 @@ to reStructuredText/Sphinx from other documentation systems.
code to convert Python-doc-style LaTeX markup to Sphinx reST. code to convert Python-doc-style LaTeX markup to Sphinx reST.
* Marcin Wojdyr has written a script to convert Docbook to reST with Sphinx * Marcin Wojdyr has written a script to convert Docbook to reST with Sphinx
markup; it is at `Google Code <https://github.com/wojdyr/db2rst>`_. markup; it is at `GitHub <https://github.com/wojdyr/db2rst>`_.
* Christophe de Vienne wrote a tool to convert from Open/LibreOffice documents * Christophe de Vienne wrote a tool to convert from Open/LibreOffice documents
to Sphinx: `odt2sphinx <https://pypi.python.org/pypi/odt2sphinx/>`_. to Sphinx: `odt2sphinx <https://pypi.python.org/pypi/odt2sphinx/>`_.

View File

@ -355,7 +355,8 @@ in a different style:
.. rst:role:: manpage .. rst:role:: manpage
A reference to a Unix manual page including the section, A reference to a Unix manual page including the section,
e.g. ``:manpage:`ls(1)```. e.g. ``:manpage:`ls(1)```. Creates a hyperlink to an external site
rendering the manpage if :confval:`manpages_url` is defined.
.. rst:role:: menuselection .. rst:role:: menuselection

View File

@ -323,6 +323,11 @@ following directive exists:
Sphinx's merged cells interact well with ``p{width}``, ``\X{a}{b}``, ``Y{f}`` Sphinx's merged cells interact well with ``p{width}``, ``\X{a}{b}``, ``Y{f}``
and tabulary's columns. and tabulary's columns.
.. note::
:rst:dir:`tabularcolumns` conflicts with ``:widths:`` option of table
directives. If both are specified, ``:widths:`` option will be ignored.
Math Math
---- ----

View File

@ -26,6 +26,7 @@ requires = [
'imagesize', 'imagesize',
'requests>=2.0.0', 'requests>=2.0.0',
'setuptools', 'setuptools',
'packaging',
'sphinxcontrib-websupport', 'sphinxcontrib-websupport',
] ]

View File

@ -338,6 +338,13 @@ class Sphinx(object):
(status, self._warncount))) (status, self._warncount)))
else: else:
logger.info(bold(__('build %s.') % status)) logger.info(bold(__('build %s.') % status))
if self.statuscode == 0 and self.builder.epilog:
logger.info('')
logger.info(self.builder.epilog % {
'outdir': path.relpath(self.outdir),
'project': self.config.project
})
except Exception as err: except Exception as err:
# delete the saved env to force a fresh build next time # delete the saved env to force a fresh build next time
envfile = path.join(self.doctreedir, ENV_PICKLE_FILENAME) envfile = path.join(self.doctreedir, ENV_PICKLE_FILENAME)

View File

@ -54,6 +54,11 @@ class Builder(object):
name = '' # type: unicode name = '' # type: unicode
#: The builder's output format, or '' if no document output is produced. #: The builder's output format, or '' if no document output is produced.
format = '' # type: unicode format = '' # type: unicode
#: The message emitted upon successful build completion. This can be a
#: printf-style template string with the following keys: ``outdir``,
#: ``project``
epilog = '' # type: unicode
# default translator class for the builder. This will be overrided by # default translator class for the builder. This will be overrided by
# ``app.set_translator()``. # ``app.set_translator()``.
default_translator_class = None # type: nodes.NodeVisitor default_translator_class = None # type: nodes.NodeVisitor

View File

@ -75,6 +75,10 @@ class AppleHelpBuilder(StandaloneHTMLBuilder):
on the ``hiutil`` command line tool. on the ``hiutil`` command line tool.
""" """
name = 'applehelp' name = 'applehelp'
epilog = ('The help book is in %(outdir)s.\n'
'Note that won\'t be able to view it unless you put it in '
'~/Library/Documentation/Help or install it in your application '
'bundle.')
# don't copy the reST source # don't copy the reST source
copysource = False copysource = False

View File

@ -38,6 +38,7 @@ class ChangesBuilder(Builder):
Write a summary with all versionadded/changed directives. Write a summary with all versionadded/changed directives.
""" """
name = 'changes' name = 'changes'
epilog = 'The overview file is in %(outdir)s.'
def init(self): def init(self):
# type: () -> None # type: () -> None

View File

@ -43,6 +43,10 @@ class DevhelpBuilder(StandaloneHTMLBuilder):
Builder that also outputs GNOME Devhelp file. Builder that also outputs GNOME Devhelp file.
""" """
name = 'devhelp' name = 'devhelp'
epilog = ('To view the help file:\n'
'$ mkdir -p $HOME/.local/share/devhelp/%(project)s\n'
'$ ln -s %(outdir)s $HOME/.local/share/devhelp/%(project)s\n'
'$ devhelp')
# don't copy the reST source # don't copy the reST source
copysource = False copysource = False

View File

@ -21,6 +21,8 @@ if False:
class DummyBuilder(Builder): class DummyBuilder(Builder):
name = 'dummy' name = 'dummy'
epilog = 'The dummy builder generates no files.'
allow_parallel = True allow_parallel = True
def init(self): def init(self):

View File

@ -63,6 +63,7 @@ class Epub3Builder(_epub_base.EpubBuilder):
an epub file. an epub file.
""" """
name = 'epub' name = 'epub'
epilog = 'The ePub file is in %(outdir)s.'
supported_remote_images = False supported_remote_images = False
template_dir = path.join(package_dir, 'templates', 'epub3') template_dir = path.join(package_dir, 'templates', 'epub3')

View File

@ -214,6 +214,7 @@ class MessageCatalogBuilder(I18nBuilder):
Builds gettext-style message catalogs (.pot files). Builds gettext-style message catalogs (.pot files).
""" """
name = 'gettext' name = 'gettext'
epilog = 'The message catalogs are in %(outdir)s.'
def init(self): def init(self):
# type: () -> None # type: () -> None

View File

@ -153,6 +153,8 @@ class StandaloneHTMLBuilder(Builder):
""" """
name = 'html' name = 'html'
format = 'html' format = 'html'
epilog = 'The HTML pages are in %(outdir)s.'
copysource = True copysource = True
allow_parallel = True allow_parallel = True
out_suffix = '.html' out_suffix = '.html'
@ -1066,6 +1068,8 @@ class SingleFileHTMLBuilder(StandaloneHTMLBuilder):
HTML page. HTML page.
""" """
name = 'singlehtml' name = 'singlehtml'
epilog = 'The HTML page is in %(outdir)s.'
copysource = False copysource = False
def get_outdated_docs(self): # type: ignore def get_outdated_docs(self): # type: ignore
@ -1328,12 +1332,14 @@ class PickleHTMLBuilder(SerializingHTMLBuilder):
""" """
A Builder that dumps the generated HTML into pickle files. A Builder that dumps the generated HTML into pickle files.
""" """
name = 'pickle'
epilog = 'You can now process the pickle files in %(outdir)s.'
implementation = pickle implementation = pickle
implementation_dumps_unicode = False implementation_dumps_unicode = False
additional_dump_args = (pickle.HIGHEST_PROTOCOL,) additional_dump_args = (pickle.HIGHEST_PROTOCOL,)
indexer_format = pickle indexer_format = pickle
indexer_dumps_unicode = False indexer_dumps_unicode = False
name = 'pickle'
out_suffix = '.fpickle' out_suffix = '.fpickle'
globalcontext_filename = 'globalcontext.pickle' globalcontext_filename = 'globalcontext.pickle'
searchindex_filename = 'searchindex.pickle' searchindex_filename = 'searchindex.pickle'
@ -1347,11 +1353,13 @@ class JSONHTMLBuilder(SerializingHTMLBuilder):
""" """
A builder that dumps the generated HTML into JSON files. A builder that dumps the generated HTML into JSON files.
""" """
name = 'json'
epilog = 'You can now process the JSON files in %(outdir)s.'
implementation = jsonimpl implementation = jsonimpl
implementation_dumps_unicode = True implementation_dumps_unicode = True
indexer_format = jsonimpl indexer_format = jsonimpl
indexer_dumps_unicode = True indexer_dumps_unicode = True
name = 'json'
out_suffix = '.fjson' out_suffix = '.fjson'
globalcontext_filename = 'globalcontext.json' globalcontext_filename = 'globalcontext.json'
searchindex_filename = 'searchindex.json' searchindex_filename = 'searchindex.json'

View File

@ -174,6 +174,8 @@ class HTMLHelpBuilder(StandaloneHTMLBuilder):
index files. Adapted from the original Doc/tools/prechm.py. index files. Adapted from the original Doc/tools/prechm.py.
""" """
name = 'htmlhelp' name = 'htmlhelp'
epilog = ('You can now run HTML Help Workshop with the .htp file in '
'%(outdir)s.')
# don't copy the reST source # don't copy the reST source
copysource = False copysource = False

View File

@ -49,6 +49,12 @@ class LaTeXBuilder(Builder):
""" """
name = 'latex' name = 'latex'
format = 'latex' format = 'latex'
epilog = 'The LaTeX files are in %(outdir)s.'
if os.name == 'posix':
epilog += ("\nRun 'make' in that directory to run these through "
"(pdf)latex\n"
"(use `make latexpdf' here to do that automatically).")
supported_image_types = ['application/pdf', 'image/png', 'image/jpeg'] supported_image_types = ['application/pdf', 'image/png', 'image/jpeg']
supported_remote_images = False supported_remote_images = False
default_translator_class = LaTeXTranslator default_translator_class = LaTeXTranslator

View File

@ -90,6 +90,8 @@ class CheckExternalLinksBuilder(Builder):
Checks for broken external links. Checks for broken external links.
""" """
name = 'linkcheck' name = 'linkcheck'
epilog = ('Look for any errors in the above output or in '
'%(outdir)s/output.txt')
def init(self): def init(self):
# type: () -> None # type: () -> None

View File

@ -40,6 +40,8 @@ class ManualPageBuilder(Builder):
""" """
name = 'man' name = 'man'
format = 'man' format = 'man'
epilog = 'The manual pages are in %(outdir)s.'
default_translator_class = ManualPageTranslator default_translator_class = ManualPageTranslator
supported_image_types = [] # type: List[unicode] supported_image_types = [] # type: List[unicode]

View File

@ -108,6 +108,11 @@ class QtHelpBuilder(StandaloneHTMLBuilder):
Builder that also outputs Qt help project, contents and index files. Builder that also outputs Qt help project, contents and index files.
""" """
name = 'qthelp' name = 'qthelp'
epilog = ('You can now run "qcollectiongenerator" with the .qhcp '
'project file in %(outdir)s, like this:\n'
'$ qcollectiongenerator %(outdir)s/%(project)s.qhcp\n'
'To view the help file:\n'
'$ assistant -collectionFile %(outdir)s/%(project)s.qhc')
# don't copy the reST source # don't copy the reST source
copysource = False copysource = False

View File

@ -9,6 +9,7 @@
:license: BSD, see LICENSE for details. :license: BSD, see LICENSE for details.
""" """
import os
from os import path from os import path
from docutils import nodes from docutils import nodes
@ -97,6 +98,12 @@ class TexinfoBuilder(Builder):
""" """
name = 'texinfo' name = 'texinfo'
format = 'texinfo' format = 'texinfo'
epilog = 'The Texinfo files are in %(outdir)s.'
if os.name == 'posix':
epilog += ("\nRun 'make' in that directory to run these through "
"makeinfo\n"
"(use 'make info' here to do that automatically).")
supported_image_types = ['image/png', 'image/jpeg', supported_image_types = ['image/png', 'image/jpeg',
'image/gif'] 'image/gif']
default_translator_class = TexinfoTranslator default_translator_class = TexinfoTranslator

View File

@ -21,7 +21,7 @@ from sphinx.writers.text import TextWriter, TextTranslator
if False: if False:
# For type annotation # For type annotation
from typing import Any, Dict, Iterator, Set # NOQA from typing import Any, Dict, Iterator, Set, Tuple # NOQA
from docutils import nodes # NOQA from docutils import nodes # NOQA
from sphinx.application import Sphinx # NOQA from sphinx.application import Sphinx # NOQA
@ -31,6 +31,8 @@ logger = logging.getLogger(__name__)
class TextBuilder(Builder): class TextBuilder(Builder):
name = 'text' name = 'text'
format = 'text' format = 'text'
epilog = 'The text files are in %(outdir)s.'
out_suffix = '.txt' out_suffix = '.txt'
allow_parallel = True allow_parallel = True
default_translator_class = TextTranslator default_translator_class = TextTranslator
@ -39,7 +41,8 @@ class TextBuilder(Builder):
def init(self): def init(self):
# type: () -> None # type: () -> None
pass # section numbers for headings in the currently visited document
self.secnumbers = {} # type: Dict[unicode, Tuple[int, ...]]
def get_outdated_docs(self): def get_outdated_docs(self):
# type: () -> Iterator[unicode] # type: () -> Iterator[unicode]
@ -72,6 +75,7 @@ class TextBuilder(Builder):
def write_doc(self, docname, doctree): def write_doc(self, docname, doctree):
# type: (unicode, nodes.Node) -> None # type: (unicode, nodes.Node) -> None
self.current_docname = docname self.current_docname = docname
self.secnumbers = self.env.toc_secnumbers.get(docname, {})
destination = StringOutput(encoding='utf-8') destination = StringOutput(encoding='utf-8')
self.writer.write(doctree, destination) self.writer.write(doctree, destination)
outfilename = path.join(self.outdir, os_path(docname) + self.out_suffix) outfilename = path.join(self.outdir, os_path(docname) + self.out_suffix)
@ -93,6 +97,8 @@ def setup(app):
app.add_config_value('text_sectionchars', '*=-~"+`', 'env') app.add_config_value('text_sectionchars', '*=-~"+`', 'env')
app.add_config_value('text_newlines', 'unix', 'env') app.add_config_value('text_newlines', 'unix', 'env')
app.add_config_value('text_add_secnumbers', True, 'env')
app.add_config_value('text_secnumber_suffix', '. ', 'env')
return { return {
'version': 'builtin', 'version': 'builtin',

View File

@ -35,6 +35,8 @@ class XMLBuilder(Builder):
""" """
name = 'xml' name = 'xml'
format = 'xml' format = 'xml'
epilog = 'The XML files are in %(outdir)s.'
out_suffix = '.xml' out_suffix = '.xml'
allow_parallel = True allow_parallel = True
@ -108,6 +110,8 @@ class PseudoXMLBuilder(XMLBuilder):
""" """
name = 'pseudoxml' name = 'pseudoxml'
format = 'pseudoxml' format = 'pseudoxml'
epilog = 'The pseudo-XML files are in %(outdir)s.'
out_suffix = '.pseudoxml' out_suffix = '.pseudoxml'
_writer_class = PseudoXMLWriter _writer_class = PseudoXMLWriter

View File

@ -125,6 +125,7 @@ class Config(object):
primary_domain = ('py', 'env', [NoneType]), primary_domain = ('py', 'env', [NoneType]),
needs_sphinx = (None, None, string_classes), needs_sphinx = (None, None, string_classes),
needs_extensions = ({}, None), needs_extensions = ({}, None),
manpages_url = (None, 'env'),
nitpicky = (False, None), nitpicky = (False, None),
nitpick_ignore = ([], None), nitpick_ignore = ([], None),
numfig = (False, 'env'), numfig = (False, 'env'),

View File

@ -23,7 +23,7 @@ from sphinx.util.inspect import isenumclass, safe_getattr
if False: if False:
# For type annotation # For type annotation
from typing import Any, Callable, Dict, Generator, List, Optional, Set # NOQA from typing import Any, Callable, Dict, Generator, List, Optional # NOQA
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
@ -84,13 +84,7 @@ class _MockModule(ModuleType):
class _MockImporter(object): class _MockImporter(object):
def __init__(self, names): def __init__(self, names):
# type: (List[str]) -> None # type: (List[str]) -> None
self.base_packages = set() # type: Set[str] self.names = names
for n in names:
# Convert module names:
# ['a.b.c', 'd.e']
# to a set of base packages:
# set(['a', 'd'])
self.base_packages.add(n.split('.')[0])
self.mocked_modules = [] # type: List[str] self.mocked_modules = [] # type: List[str]
# enable hook by adding itself to meta_path # enable hook by adding itself to meta_path
sys.meta_path = sys.meta_path + [self] sys.meta_path = sys.meta_path + [self]
@ -106,8 +100,9 @@ class _MockImporter(object):
def find_module(self, name, path=None): def find_module(self, name, path=None):
# type: (str, str) -> Any # type: (str, str) -> Any
base_package = name.split('.')[0] # check if name is (or is a descendant of) one of our base_packages
if base_package in self.base_packages: for n in self.names:
if n == name or name.startswith(n + '.'):
return self return self
return None return None

View File

@ -50,8 +50,12 @@ def compile_regex_list(name, exps):
class CoverageBuilder(Builder): class CoverageBuilder(Builder):
"""
Evaluates coverage of code in the documentation.
"""
name = 'coverage' name = 'coverage'
epilog = ('Testing of coverage in the sources finished, look at the '
'results in %(outdir)s/python.txt.')
def init(self): def init(self):
# type: () -> None # type: () -> None

View File

@ -20,7 +20,8 @@ from os import path
import doctest import doctest
from six import itervalues, StringIO, binary_type, text_type, PY2 from six import itervalues, StringIO, binary_type, text_type, PY2
from distutils.version import LooseVersion from packaging.specifiers import SpecifierSet, InvalidSpecifier
from packaging.version import Version
from docutils import nodes from docutils import nodes
from docutils.parsers.rst import Directive, directives from docutils.parsers.rst import Directive, directives
@ -57,28 +58,23 @@ else:
return text return text
def compare_version(ver1, ver2, operand): def is_allowed_version(spec, version):
# type: (unicode, unicode, unicode) -> bool # type: (unicode, unicode) -> bool
"""Compare `ver1` to `ver2`, relying on `operand`. """Check `spec` satisfies `version` or not.
This obeys PEP-440 specifiers:
https://www.python.org/dev/peps/pep-0440/#version-specifiers
Some examples: Some examples:
>>> compare_version('3.3', '3.5', '<=') >>> is_allowed_version('3.3', '<=3.5')
True True
>>> compare_version('3.3', '3.2', '<=') >>> is_allowed_version('3.3', '<=3.2')
False False
>>> compare_version('3.3a0', '3.3', '<=') >>> is_allowed_version('3.3', '>3.2, <4.0')
True True
""" """
if operand not in ('<=', '<', '==', '>=', '>'): return Version(version) in SpecifierSet(spec)
raise ValueError("'%s' is not a valid operand.")
v1 = LooseVersion(ver1)
v2 = LooseVersion(ver2)
return ((operand == '<=' and (v1 <= v2)) or
(operand == '<' and (v1 < v2)) or
(operand == '==' and (v1 == v2)) or
(operand == '>=' and (v1 >= v2)) or
(operand == '>' and (v1 > v2)))
# set up the necessary directives # set up the necessary directives
@ -120,7 +116,11 @@ class TestDirective(Directive):
if test is not None: if test is not None:
# only save if it differs from code # only save if it differs from code
node['test'] = test node['test'] = test
if self.name == 'testoutput': if self.name == 'doctest':
node['language'] = 'pycon'
elif self.name == 'testcode':
node['language'] = 'python'
elif self.name == 'testoutput':
# don't try to highlight output # don't try to highlight output
node['language'] = 'none' node['language'] = 'none'
node['options'] = {} node['options'] = {}
@ -143,16 +143,13 @@ class TestDirective(Directive):
node['options'][flag] = (option[0] == '+') node['options'][flag] = (option[0] == '+')
if self.name == 'doctest' and 'pyversion' in self.options: if self.name == 'doctest' and 'pyversion' in self.options:
try: try:
option = self.options['pyversion'] spec = self.options['pyversion']
# :pyversion: >= 3.6 --> operand='>=', option_version='3.6' if not is_allowed_version(spec, platform.python_version()):
operand, option_version = [item.strip() for item in option.split()]
running_version = platform.python_version()
if not compare_version(running_version, option_version, operand):
flag = doctest.OPTIONFLAGS_BY_NAME['SKIP'] flag = doctest.OPTIONFLAGS_BY_NAME['SKIP']
node['options'][flag] = True # Skip the test node['options'][flag] = True # Skip the test
except ValueError: except InvalidSpecifier:
self.state.document.reporter.warning( self.state.document.reporter.warning(
_("'%s' is not a valid pyversion option") % option, _("'%s' is not a valid pyversion option") % spec,
line=self.lineno) line=self.lineno)
return [node] return [node]
@ -278,6 +275,8 @@ class DocTestBuilder(Builder):
Runs test snippets in the documentation. Runs test snippets in the documentation.
""" """
name = 'doctest' name = 'doctest'
epilog = ('Testing of doctests in the sources finished, look at the '
'results in %(outdir)s/output.txt.')
def init(self): def init(self):
# type: () -> None # type: () -> None

View File

@ -130,8 +130,8 @@ class InheritanceGraph(object):
graphviz dot graph from them. graphviz dot graph from them.
""" """
def __init__(self, class_names, currmodule, show_builtins=False, def __init__(self, class_names, currmodule, show_builtins=False,
private_bases=False, parts=0, aliases=None): private_bases=False, parts=0, aliases=None, top_classes=[]):
# type: (unicode, str, bool, bool, int, Optional[Dict[unicode, unicode]]) -> None # type: (unicode, str, bool, bool, int, Optional[Dict[unicode, unicode]], List[Any]) -> None # NOQA
"""*class_names* is a list of child classes to show bases from. """*class_names* is a list of child classes to show bases from.
If *show_builtins* is True, then Python builtins will be shown If *show_builtins* is True, then Python builtins will be shown
@ -140,7 +140,7 @@ class InheritanceGraph(object):
self.class_names = class_names self.class_names = class_names
classes = self._import_classes(class_names, currmodule) classes = self._import_classes(class_names, currmodule)
self.class_info = self._class_info(classes, show_builtins, self.class_info = self._class_info(classes, show_builtins,
private_bases, parts, aliases) private_bases, parts, aliases, top_classes)
if not self.class_info: if not self.class_info:
raise InheritanceException('No classes found for ' raise InheritanceException('No classes found for '
'inheritance diagram') 'inheritance diagram')
@ -153,13 +153,16 @@ class InheritanceGraph(object):
classes.extend(import_classes(name, currmodule)) classes.extend(import_classes(name, currmodule))
return classes return classes
def _class_info(self, classes, show_builtins, private_bases, parts, aliases): def _class_info(self, classes, show_builtins, private_bases, parts, aliases, top_classes):
# type: (List[Any], bool, bool, int, Optional[Dict[unicode, unicode]]) -> List[Tuple[unicode, unicode, List[unicode], unicode]] # NOQA # type: (List[Any], bool, bool, int, Optional[Dict[unicode, unicode]], List[Any]) -> List[Tuple[unicode, unicode, List[unicode], unicode]] # NOQA
"""Return name and bases for all classes that are ancestors of """Return name and bases for all classes that are ancestors of
*classes*. *classes*.
*parts* gives the number of dotted name parts that is removed from the *parts* gives the number of dotted name parts that is removed from the
displayed node names. displayed node names.
*top_classes* gives the name(s) of the top most ancestor class to traverse
to. Multiple names can be specified separated by comma.
""" """
all_classes = {} all_classes = {}
py_builtins = vars(builtins).values() py_builtins = vars(builtins).values()
@ -189,6 +192,10 @@ class InheritanceGraph(object):
baselist = [] # type: List[unicode] baselist = [] # type: List[unicode]
all_classes[cls] = (nodename, fullname, baselist, tooltip) all_classes[cls] = (nodename, fullname, baselist, tooltip)
if fullname in top_classes:
return
for base in cls.__bases__: for base in cls.__bases__:
if not show_builtins and base in py_builtins: if not show_builtins and base in py_builtins:
continue continue
@ -322,6 +329,7 @@ class InheritanceDiagram(Directive):
'parts': directives.nonnegative_int, 'parts': directives.nonnegative_int,
'private-bases': directives.flag, 'private-bases': directives.flag,
'caption': directives.unchanged, 'caption': directives.unchanged,
'top-classes': directives.unchanged_required,
} }
def run(self): def run(self):
@ -334,6 +342,11 @@ class InheritanceDiagram(Directive):
# Store the original content for use as a hash # Store the original content for use as a hash
node['parts'] = self.options.get('parts', 0) node['parts'] = self.options.get('parts', 0)
node['content'] = ', '.join(class_names) node['content'] = ', '.join(class_names)
node['top-classes'] = []
for cls in self.options.get('top-classes', '').split(','):
cls = cls.strip()
if cls:
node['top-classes'].append(cls)
# Create a graph starting with the list of classes # Create a graph starting with the list of classes
try: try:
@ -341,7 +354,8 @@ class InheritanceDiagram(Directive):
class_names, env.ref_context.get('py:module'), class_names, env.ref_context.get('py:module'),
parts=node['parts'], parts=node['parts'],
private_bases='private-bases' in self.options, private_bases='private-bases' in self.options,
aliases=env.config.inheritance_alias) aliases=env.config.inheritance_alias,
top_classes=node['top-classes'])
except InheritanceException as err: except InheritanceException as err:
return [node.document.reporter.warning(err.args[0], return [node.document.reporter.warning(err.args[0],
line=self.lineno)] line=self.lineno)]

View File

@ -20,14 +20,14 @@ from sphinx.ext.mathbase import get_node_equation_number
def html_visit_math(self, node): def html_visit_math(self, node):
self.body.append(self.starttag(node, 'span', '', CLASS='math')) self.body.append(self.starttag(node, 'span', '', CLASS='math notranslate'))
self.body.append(self.encode(node['latex']) + '</span>') self.body.append(self.encode(node['latex']) + '</span>')
raise nodes.SkipNode raise nodes.SkipNode
def html_visit_displaymath(self, node): def html_visit_displaymath(self, node):
if node['nowrap']: if node['nowrap']:
self.body.append(self.starttag(node, 'div', CLASS='math')) self.body.append(self.starttag(node, 'div', CLASS='math notranslate'))
self.body.append(self.encode(node['latex'])) self.body.append(self.encode(node['latex']))
self.body.append('</div>') self.body.append('</div>')
raise nodes.SkipNode raise nodes.SkipNode
@ -40,7 +40,7 @@ def html_visit_displaymath(self, node):
self.body.append('<span class="eqno">(%s)' % number) self.body.append('<span class="eqno">(%s)' % number)
self.add_permalink_ref(node, _('Permalink to this equation')) self.add_permalink_ref(node, _('Permalink to this equation'))
self.body.append('</span>') self.body.append('</span>')
self.body.append(self.starttag(node, 'div', CLASS='math')) self.body.append(self.starttag(node, 'div', CLASS='math notranslate'))
else: else:
# but only once! # but only once!
self.body.append('<div class="math">') self.body.append('<div class="math">')

View File

@ -21,7 +21,7 @@ from sphinx.ext.mathbase import get_node_equation_number
def html_visit_math(self, node): def html_visit_math(self, node):
self.body.append(self.starttag(node, 'span', '', CLASS='math')) self.body.append(self.starttag(node, 'span', '', CLASS='math notranslate'))
self.body.append(self.builder.config.mathjax_inline[0] + self.body.append(self.builder.config.mathjax_inline[0] +
self.encode(node['latex']) + self.encode(node['latex']) +
self.builder.config.mathjax_inline[1] + '</span>') self.builder.config.mathjax_inline[1] + '</span>')
@ -29,7 +29,7 @@ def html_visit_math(self, node):
def html_visit_displaymath(self, node): def html_visit_displaymath(self, node):
self.body.append(self.starttag(node, 'div', CLASS='math')) self.body.append(self.starttag(node, 'div', CLASS='math notranslate'))
if node['nowrap']: if node['nowrap']:
self.body.append(self.encode(node['latex'])) self.body.append(self.encode(node['latex']))
self.body.append('</div>') self.body.append('</div>')

View File

@ -24,7 +24,7 @@ from sphinx.transforms import (
ApplySourceWorkaround, ExtraTranslatableNodes, CitationReferences, ApplySourceWorkaround, ExtraTranslatableNodes, CitationReferences,
DefaultSubstitutions, MoveModuleTargets, HandleCodeBlocks, SortIds, DefaultSubstitutions, MoveModuleTargets, HandleCodeBlocks, SortIds,
AutoNumbering, AutoIndexUpgrader, FilterSystemMessages, AutoNumbering, AutoIndexUpgrader, FilterSystemMessages,
UnreferencedFootnotesDetector, SphinxSmartQuotes UnreferencedFootnotesDetector, SphinxSmartQuotes, ManpageLink
) )
from sphinx.transforms.compact_bullet_list import RefOnlyBulletListTransform from sphinx.transforms.compact_bullet_list import RefOnlyBulletListTransform
from sphinx.transforms.i18n import ( from sphinx.transforms.i18n import (
@ -94,6 +94,7 @@ class SphinxStandaloneReader(SphinxBaseReader):
HandleCodeBlocks, AutoNumbering, AutoIndexUpgrader, SortIds, HandleCodeBlocks, AutoNumbering, AutoIndexUpgrader, SortIds,
RemoveTranslatableInline, PreserveTranslatableMessages, FilterSystemMessages, RemoveTranslatableInline, PreserveTranslatableMessages, FilterSystemMessages,
RefOnlyBulletListTransform, UnreferencedFootnotesDetector, SphinxSmartQuotes, RefOnlyBulletListTransform, UnreferencedFootnotesDetector, SphinxSmartQuotes,
ManpageLink
] # type: List[Transform] ] # type: List[Transform]
def __init__(self, app, *args, **kwargs): def __init__(self, app, *args, **kwargs):
@ -116,7 +117,7 @@ class SphinxI18nReader(SphinxBaseReader):
DefaultSubstitutions, MoveModuleTargets, HandleCodeBlocks, DefaultSubstitutions, MoveModuleTargets, HandleCodeBlocks,
AutoNumbering, SortIds, RemoveTranslatableInline, AutoNumbering, SortIds, RemoveTranslatableInline,
FilterSystemMessages, RefOnlyBulletListTransform, FilterSystemMessages, RefOnlyBulletListTransform,
UnreferencedFootnotesDetector] UnreferencedFootnotesDetector, ManpageLink]
def set_lineno_for_reporter(self, lineno): def set_lineno_for_reporter(self, lineno):
# type: (int) -> None # type: (int) -> None

View File

@ -97,101 +97,6 @@ class Make(object):
if not osname or os.name == osname: if not osname or os.name == osname:
print(' %s %s' % (blue(bname.ljust(10)), description)) print(' %s %s' % (blue(bname.ljust(10)), description))
def build_html(self):
# type: () -> int
if self.run_generic_build('html') > 0:
return 1
print()
print('Build finished. The HTML pages are in %s.' % self.builddir_join('html'))
return 0
def build_dirhtml(self):
# type: () -> int
if self.run_generic_build('dirhtml') > 0:
return 1
print()
print('Build finished. The HTML pages are in %s.' %
self.builddir_join('dirhtml'))
return 0
def build_singlehtml(self):
# type: () -> int
if self.run_generic_build('singlehtml') > 0:
return 1
print()
print('Build finished. The HTML page is in %s.' %
self.builddir_join('singlehtml'))
return 0
def build_pickle(self):
# type: () -> int
if self.run_generic_build('pickle') > 0:
return 1
print()
print('Build finished; now you can process the pickle files.')
return 0
def build_json(self):
# type: () -> int
if self.run_generic_build('json') > 0:
return 1
print()
print('Build finished; now you can process the JSON files.')
return 0
def build_htmlhelp(self):
# type: () -> int
if self.run_generic_build('htmlhelp') > 0:
return 1
print()
print('Build finished; now you can run HTML Help Workshop with the '
'.hhp project file in %s.' % self.builddir_join('htmlhelp'))
return 0
def build_qthelp(self):
# type: () -> int
if self.run_generic_build('qthelp') > 0:
return 1
print()
print('Build finished; now you can run "qcollectiongenerator" with the '
'.qhcp project file in %s, like this:' % self.builddir_join('qthelp'))
print('$ qcollectiongenerator %s.qhcp' % self.builddir_join('qthelp', proj_name))
print('To view the help file:')
print('$ assistant -collectionFile %s.qhc' %
self.builddir_join('qthelp', proj_name))
return 0
def build_devhelp(self):
# type: () -> int
if self.run_generic_build('devhelp') > 0:
return 1
print()
print("Build finished.")
print("To view the help file:")
print("$ mkdir -p $HOME/.local/share/devhelp/" + proj_name)
print("$ ln -s %s $HOME/.local/share/devhelp/%s" %
(self.builddir_join('devhelp'), proj_name))
print("$ devhelp")
return 0
def build_epub(self):
# type: () -> int
if self.run_generic_build('epub') > 0:
return 1
print()
print('Build finished. The ePub file is in %s.' % self.builddir_join('epub'))
return 0
def build_latex(self):
# type: () -> int
if self.run_generic_build('latex') > 0:
return 1
print("Build finished; the LaTeX files are in %s." % self.builddir_join('latex'))
if os.name == 'posix':
print("Run `make' in that directory to run these through (pdf)latex")
print("(use `make latexpdf' here to do that automatically).")
return 0
def build_latexpdf(self): def build_latexpdf(self):
# type: () -> int # type: () -> int
if self.run_generic_build('latex') > 0: if self.run_generic_build('latex') > 0:
@ -206,25 +111,6 @@ class Make(object):
with cd(self.builddir_join('latex')): with cd(self.builddir_join('latex')):
return subprocess.call([self.makecmd, 'all-pdf-ja']) return subprocess.call([self.makecmd, 'all-pdf-ja'])
def build_text(self):
# type: () -> int
if self.run_generic_build('text') > 0:
return 1
print()
print('Build finished. The text files are in %s.' % self.builddir_join('text'))
return 0
def build_texinfo(self):
# type: () -> int
if self.run_generic_build('texinfo') > 0:
return 1
print("Build finished; the Texinfo files are in %s." %
self.builddir_join('texinfo'))
if os.name == 'posix':
print("Run `make' in that directory to run these through makeinfo")
print("(use `make info' here to do that automatically).")
return 0
def build_info(self): def build_info(self):
# type: () -> int # type: () -> int
if self.run_generic_build('texinfo') > 0: if self.run_generic_build('texinfo') > 0:
@ -237,60 +123,6 @@ class Make(object):
dtdir = self.builddir_join('gettext', '.doctrees') dtdir = self.builddir_join('gettext', '.doctrees')
if self.run_generic_build('gettext', doctreedir=dtdir) > 0: if self.run_generic_build('gettext', doctreedir=dtdir) > 0:
return 1 return 1
print()
print('Build finished. The message catalogs are in %s.' %
self.builddir_join('gettext'))
return 0
def build_changes(self):
# type: () -> int
if self.run_generic_build('changes') > 0:
return 1
print()
print('Build finished. The overview file is in %s.' %
self.builddir_join('changes'))
return 0
def build_linkcheck(self):
# type: () -> int
res = self.run_generic_build('linkcheck')
print()
print('Link check complete; look for any errors in the above output '
'or in %s.' % self.builddir_join('linkcheck', 'output.txt'))
return res
def build_doctest(self):
# type: () -> int
res = self.run_generic_build('doctest')
print("Testing of doctests in the sources finished, look at the "
"results in %s." % self.builddir_join('doctest', 'output.txt'))
return res
def build_coverage(self):
# type: () -> int
if self.run_generic_build('coverage') > 0:
print("Has the coverage extension been enabled?")
return 1
print()
print("Testing of coverage in the sources finished, look at the "
"results in %s." % self.builddir_join('coverage'))
return 0
def build_xml(self):
# type: () -> int
if self.run_generic_build('xml') > 0:
return 1
print()
print('Build finished. The XML files are in %s.' % self.builddir_join('xml'))
return 0
def build_pseudoxml(self):
# type: () -> int
if self.run_generic_build('pseudoxml') > 0:
return 1
print()
print('Build finished. The pseudo-XML files are in %s.' %
self.builddir_join('pseudoxml'))
return 0 return 0
def run_generic_build(self, builder, doctreedir=None): def run_generic_build(self, builder, doctreedir=None):

View File

@ -5,14 +5,16 @@
SPHINXOPTS ?= SPHINXOPTS ?=
SPHINXBUILD ?= sphinx-build SPHINXBUILD ?= sphinx-build
PAPER ?= PAPER ?=
SOURCEDIR = {{ rsrcdir }}
BUILDDIR = {{ rbuilddir }} BUILDDIR = {{ rbuilddir }}
# Internal variables. # Internal variables.
PAPEROPT_a4 = -D latex_elements.papersize=a4 PAPEROPT_a4 = -D latex_elements.papersize=a4
PAPEROPT_letter = -D latex_elements.papersize=letter PAPEROPT_letter = -D latex_elements.papersize=letter
ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) {{ rsrcdir }} # $(O) is meant as a shortcut for $(SPHINXOPTS)
ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) $(O) $(SOURCEDIR)
# the i18n builder cannot share the environment and doctrees with the others # the i18n builder cannot share the environment and doctrees with the others
I18NSPHINXOPTS = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) {{ rsrcdir }} I18NSPHINXOPTS = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) $(O) $(SOURCEDIR)
.PHONY: help .PHONY: help
help: help:
@ -49,86 +51,6 @@ help:
clean: clean:
rm -rf $(BUILDDIR)/* rm -rf $(BUILDDIR)/*
.PHONY: html
html:
$(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html
@echo
@echo "Build finished. The HTML pages are in $(BUILDDIR)/html."
.PHONY: dirhtml
dirhtml:
$(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml
@echo
@echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml."
.PHONY: singlehtml
singlehtml:
$(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml
@echo
@echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml."
.PHONY: pickle
pickle:
$(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle
@echo
@echo "Build finished; now you can process the pickle files."
.PHONY: json
json:
$(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json
@echo
@echo "Build finished; now you can process the JSON files."
.PHONY: htmlhelp
htmlhelp:
$(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp
@echo
@echo "Build finished; now you can run HTML Help Workshop with the" \
".hhp project file in $(BUILDDIR)/htmlhelp."
.PHONY: qthelp
qthelp:
$(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp
@echo
@echo "Build finished; now you can run "qcollectiongenerator" with the" \
".qhcp project file in $(BUILDDIR)/qthelp, like this:"
@echo "# qcollectiongenerator $(BUILDDIR)/qthelp/{{ project_fn }}.qhcp"
@echo "To view the help file:"
@echo "# assistant -collectionFile $(BUILDDIR)/qthelp/{{ project_fn }}.qhc"
.PHONY: applehelp
applehelp:
$(SPHINXBUILD) -b applehelp $(ALLSPHINXOPTS) $(BUILDDIR)/applehelp
@echo
@echo "Build finished. The help book is in $(BUILDDIR)/applehelp."
@echo "N.B. You won't be able to view it unless you put it in" \
"~/Library/Documentation/Help or install it in your application" \
"bundle."
.PHONY: devhelp
devhelp:
$(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp
@echo
@echo "Build finished."
@echo "To view the help file:"
@echo "# mkdir -p $$HOME/.local/share/devhelp/{{ project_fn }}"
@echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/{{ project_fn }}"
@echo "# devhelp"
.PHONY: epub
epub:
$(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub
@echo
@echo "Build finished. The epub file is in $(BUILDDIR)/epub."
.PHONY: latex
latex:
$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
@echo
@echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex."
@echo "Run \`make' in that directory to run these through (pdf)latex" \
"(use \`make latexpdf' here to do that automatically)."
.PHONY: latexpdf .PHONY: latexpdf
latexpdf: latexpdf:
$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
@ -157,26 +79,6 @@ xelatexpdf:
$(MAKE) PDFLATEX=xelatex -C $(BUILDDIR)/latex all-pdf $(MAKE) PDFLATEX=xelatex -C $(BUILDDIR)/latex all-pdf
@echo "xelatex finished; the PDF files are in $(BUILDDIR)/latex." @echo "xelatex finished; the PDF files are in $(BUILDDIR)/latex."
.PHONY: text
text:
$(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text
@echo
@echo "Build finished. The text files are in $(BUILDDIR)/text."
.PHONY: man
man:
$(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man
@echo
@echo "Build finished. The manual pages are in $(BUILDDIR)/man."
.PHONY: texinfo
texinfo:
$(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo
@echo
@echo "Build finished. The Texinfo files are in $(BUILDDIR)/texinfo."
@echo "Run \`make' in that directory to run these through makeinfo" \
"(use \`make info' here to do that automatically)."
.PHONY: info .PHONY: info
info: info:
$(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo
@ -187,49 +89,9 @@ info:
.PHONY: gettext .PHONY: gettext
gettext: gettext:
$(SPHINXBUILD) -b gettext $(I18NSPHINXOPTS) $(BUILDDIR)/locale $(SPHINXBUILD) -b gettext $(I18NSPHINXOPTS) $(BUILDDIR)/locale
@echo
@echo "Build finished. The message catalogs are in $(BUILDDIR)/locale."
.PHONY: changes # Catch-all target: route all unknown targets to Sphinx
changes: .PHONY: Makefile
$(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes %: Makefile
@echo $(SPHINXBUILD) -b "$@" $(ALLSPHINXOPTS) "$(BUILDDIR)/$@"
@echo "The overview file is in $(BUILDDIR)/changes."
.PHONY: linkcheck
linkcheck:
$(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck
@echo
@echo "Link check complete; look for any errors in the above output " \
"or in $(BUILDDIR)/linkcheck/output.txt."
.PHONY: doctest
doctest:
$(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest
@echo "Testing of doctests in the sources finished, look at the " \
"results in $(BUILDDIR)/doctest/output.txt."
.PHONY: coverage
coverage:
$(SPHINXBUILD) -b coverage $(ALLSPHINXOPTS) $(BUILDDIR)/coverage
@echo "Testing of coverage in the sources finished, look at the " \
"results in $(BUILDDIR)/coverage/python.txt."
.PHONY: xml
xml:
$(SPHINXBUILD) -b xml $(ALLSPHINXOPTS) $(BUILDDIR)/xml
@echo
@echo "Build finished. The XML files are in $(BUILDDIR)/xml."
.PHONY: pseudoxml
pseudoxml:
$(SPHINXBUILD) -b pseudoxml $(ALLSPHINXOPTS) $(BUILDDIR)/pseudoxml
@echo
@echo "Build finished. The pseudo-XML files are in $(BUILDDIR)/pseudoxml."
.PHONY: dummy
dummy:
$(SPHINXBUILD) -b dummy $(ALLSPHINXOPTS) $(BUILDDIR)/dummy
@echo
@echo "Build finished. Dummy builder generates no files."

View File

@ -1,19 +1,12 @@
{% if PY3 -%}
#!/usr/bin/env python3
{% endif -%}
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# #
# {{ project }} documentation build configuration file, created by # Configuration file for the Sphinx documentation builder.
# sphinx-quickstart on {{ now }}.
# #
# This file is execfile()d with the current directory set to its # This file does only contain a selection of the most common options. For a
# containing dir. # full list see the documentation:
# # http://www.sphinx-doc.org/en/stable/config
# Note that not all possible configuration values are present in this
# autogenerated file. # -- Path setup --------------------------------------------------------------
#
# All configuration values have a default; values that are commented out
# serve to show the default.
# If extensions (or modules to document with autodoc) are in another directory, # If extensions (or modules to document with autodoc) are in another directory,
# add these directories to sys.path here. If the directory is relative to the # add these directories to sys.path here. If the directory is relative to the
@ -33,7 +26,19 @@ sys.path.insert(0, u'{{ module_path }}')
{% endif -%} {% endif -%}
{% endif %} {% endif %}
# -- General configuration ------------------------------------------------ # -- Project information -----------------------------------------------------
project = u'{{ project_str }}'
copyright = u'{{ copyright_str }}'
author = u'{{ author_str }}'
# The short X.Y version
version = u'{{ version_str }}'
# The full version, including alpha/beta/rc tags
release = u'{{ release_str }}'
# -- General configuration ---------------------------------------------------
# If your documentation needs a minimal Sphinx version, state it here. # If your documentation needs a minimal Sphinx version, state it here.
# #
@ -60,20 +65,6 @@ source_suffix = '{{ suffix }}'
# The master toctree document. # The master toctree document.
master_doc = '{{ master_str }}' master_doc = '{{ master_str }}'
# General information about the project.
project = u'{{ project_str }}'
copyright = u'{{ copyright_str }}'
author = u'{{ author_str }}'
# The version info for the project you're documenting, acts as replacement for
# |version| and |release|, also used in various other places throughout the
# built documents.
#
# The short X.Y version.
version = u'{{ version_str }}'
# The full version, including alpha/beta/rc tags.
release = u'{{ release_str }}'
# The language for content autogenerated by Sphinx. Refer to documentation # The language for content autogenerated by Sphinx. Refer to documentation
# for a list of supported languages. # for a list of supported languages.
# #
@ -90,7 +81,7 @@ exclude_patterns = [{{ exclude_patterns }}]
pygments_style = 'sphinx' pygments_style = 'sphinx'
# -- Options for HTML output ---------------------------------------------- # -- Options for HTML output -------------------------------------------------
# The theme to use for HTML and HTML Help pages. See the documentation for # The theme to use for HTML and HTML Help pages. See the documentation for
# a list of builtin themes. # a list of builtin themes.
@ -119,13 +110,13 @@ html_static_path = ['{{ dot }}static']
# html_sidebars = {} # html_sidebars = {}
# -- Options for HTMLHelp output ------------------------------------------ # -- Options for HTMLHelp output ---------------------------------------------
# Output file base name for HTML help builder. # Output file base name for HTML help builder.
htmlhelp_basename = '{{ project_fn }}doc' htmlhelp_basename = '{{ project_fn }}doc'
# -- Options for LaTeX output --------------------------------------------- # -- Options for LaTeX output ------------------------------------------------
latex_elements = { latex_elements = {
# The paper size ('letterpaper' or 'a4paper'). # The paper size ('letterpaper' or 'a4paper').
@ -154,7 +145,7 @@ latex_documents = [
] ]
# -- Options for manual page output --------------------------------------- # -- Options for manual page output ------------------------------------------
# One entry per manual page. List of tuples # One entry per manual page. List of tuples
# (source start file, name, description, authors, manual section). # (source start file, name, description, authors, manual section).
@ -164,7 +155,7 @@ man_pages = [
] ]
# -- Options for Texinfo output ------------------------------------------- # -- Options for Texinfo output ----------------------------------------------
# Grouping the document tree into Texinfo files. List of tuples # Grouping the document tree into Texinfo files. List of tuples
# (source start file, target name, title, author, # (source start file, target name, title, author,
@ -177,7 +168,7 @@ texinfo_documents = [
{%- if epub %} {%- if epub %}
# -- Options for Epub output ---------------------------------------------- # -- Options for Epub output -------------------------------------------------
# Bibliographic Dublin Core info. # Bibliographic Dublin Core info.
epub_title = project epub_title = project
@ -200,18 +191,18 @@ epub_exclude_files = ['search.html']
{%- if extensions %} {%- if extensions %}
# -- Extension configuration ---------------------------------------------- # -- Extension configuration -------------------------------------------------
{%- endif %} {%- endif %}
{%- if 'sphinx.ext.intersphinx' in extensions %} {%- if 'sphinx.ext.intersphinx' in extensions %}
# -- Options for intersphinx extension ------------------------------------ # -- Options for intersphinx extension ---------------------------------------
# Example configuration for intersphinx: refer to the Python standard library. # Example configuration for intersphinx: refer to the Python standard library.
intersphinx_mapping = {'https://docs.python.org/': None} intersphinx_mapping = {'https://docs.python.org/': None}
{%- endif %} {%- endif %}
{%- if 'sphinx.ext.todo' in extensions %} {%- if 'sphinx.ext.todo' in extensions %}
# -- Options for todo extension ------------------------------------------- # -- Options for todo extension ----------------------------------------------
# If true, `todo` and `todoList` produce output, else they produce nothing. # If true, `todo` and `todoList` produce output, else they produce nothing.
todo_include_todos = True todo_include_todos = True

View File

@ -8,8 +8,9 @@ if "%SPHINXBUILD%" == "" (
set SPHINXBUILD=sphinx-build set SPHINXBUILD=sphinx-build
) )
set BUILDDIR={{ rbuilddir }} set BUILDDIR={{ rbuilddir }}
set ALLSPHINXOPTS=-d %BUILDDIR%/doctrees %SPHINXOPTS% {{ rsrcdir }} set SOURCEDIR={{ rsrcdir }}
set I18NSPHINXOPTS=%SPHINXOPTS% {{ rsrcdir }} set ALLSPHINXOPTS=-d %BUILDDIR%/doctrees %SPHINXOPTS% %SOURCEDIR%
set I18NSPHINXOPTS=%SPHINXOPTS% %SOURCEDIR%
if NOT "%PAPER%" == "" ( if NOT "%PAPER%" == "" (
set ALLSPHINXOPTS=-D latex_elements.papersize=%PAPER% %ALLSPHINXOPTS% set ALLSPHINXOPTS=-D latex_elements.papersize=%PAPER% %ALLSPHINXOPTS%
set I18NSPHINXOPTS=-D latex_elements.papersize=%PAPER% %I18NSPHINXOPTS% set I18NSPHINXOPTS=-D latex_elements.papersize=%PAPER% %I18NSPHINXOPTS%
@ -50,7 +51,6 @@ if "%1" == "clean" (
goto end goto end
) )
REM Check if sphinx-build is available and fallback to Python version if any REM Check if sphinx-build is available and fallback to Python version if any
%SPHINXBUILD% 1>NUL 2>NUL %SPHINXBUILD% 1>NUL 2>NUL
if errorlevel 9009 goto sphinx_python if errorlevel 9009 goto sphinx_python
@ -74,92 +74,6 @@ if errorlevel 9009 (
:sphinx_ok :sphinx_ok
if "%1" == "html" (
%SPHINXBUILD% -b html %ALLSPHINXOPTS% %BUILDDIR%/html
if errorlevel 1 exit /b 1
echo.
echo.Build finished. The HTML pages are in %BUILDDIR%/html.
goto end
)
if "%1" == "dirhtml" (
%SPHINXBUILD% -b dirhtml %ALLSPHINXOPTS% %BUILDDIR%/dirhtml
if errorlevel 1 exit /b 1
echo.
echo.Build finished. The HTML pages are in %BUILDDIR%/dirhtml.
goto end
)
if "%1" == "singlehtml" (
%SPHINXBUILD% -b singlehtml %ALLSPHINXOPTS% %BUILDDIR%/singlehtml
if errorlevel 1 exit /b 1
echo.
echo.Build finished. The HTML pages are in %BUILDDIR%/singlehtml.
goto end
)
if "%1" == "pickle" (
%SPHINXBUILD% -b pickle %ALLSPHINXOPTS% %BUILDDIR%/pickle
if errorlevel 1 exit /b 1
echo.
echo.Build finished; now you can process the pickle files.
goto end
)
if "%1" == "json" (
%SPHINXBUILD% -b json %ALLSPHINXOPTS% %BUILDDIR%/json
if errorlevel 1 exit /b 1
echo.
echo.Build finished; now you can process the JSON files.
goto end
)
if "%1" == "htmlhelp" (
%SPHINXBUILD% -b htmlhelp %ALLSPHINXOPTS% %BUILDDIR%/htmlhelp
if errorlevel 1 exit /b 1
echo.
echo.Build finished; now you can run HTML Help Workshop with the ^
.hhp project file in %BUILDDIR%/htmlhelp.
goto end
)
if "%1" == "qthelp" (
%SPHINXBUILD% -b qthelp %ALLSPHINXOPTS% %BUILDDIR%/qthelp
if errorlevel 1 exit /b 1
echo.
echo.Build finished; now you can run "qcollectiongenerator" with the ^
.qhcp project file in %BUILDDIR%/qthelp, like this:
echo.^> qcollectiongenerator %BUILDDIR%\qthelp\{{ project_fn }}.qhcp
echo.To view the help file:
echo.^> assistant -collectionFile %BUILDDIR%\qthelp\{{ project_fn }}.ghc
goto end
)
if "%1" == "devhelp" (
%SPHINXBUILD% -b devhelp %ALLSPHINXOPTS% %BUILDDIR%/devhelp
if errorlevel 1 exit /b 1
echo.
echo.Build finished.
goto end
)
if "%1" == "epub" (
%SPHINXBUILD% -b epub %ALLSPHINXOPTS% %BUILDDIR%/epub
if errorlevel 1 exit /b 1
echo.
echo.Build finished. The epub file is in %BUILDDIR%/epub.
goto end
)
if "%1" == "latex" (
%SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex
if errorlevel 1 exit /b 1
echo.
echo.Build finished; the LaTeX files are in %BUILDDIR%/latex.
goto end
)
if "%1" == "latexpdf" ( if "%1" == "latexpdf" (
%SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex %SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex
cd %BUILDDIR%/latex cd %BUILDDIR%/latex
@ -180,96 +94,14 @@ if "%1" == "latexpdfja" (
goto end goto end
) )
if "%1" == "text" (
%SPHINXBUILD% -b text %ALLSPHINXOPTS% %BUILDDIR%/text
if errorlevel 1 exit /b 1
echo.
echo.Build finished. The text files are in %BUILDDIR%/text.
goto end
)
if "%1" == "man" (
%SPHINXBUILD% -b man %ALLSPHINXOPTS% %BUILDDIR%/man
if errorlevel 1 exit /b 1
echo.
echo.Build finished. The manual pages are in %BUILDDIR%/man.
goto end
)
if "%1" == "texinfo" (
%SPHINXBUILD% -b texinfo %ALLSPHINXOPTS% %BUILDDIR%/texinfo
if errorlevel 1 exit /b 1
echo.
echo.Build finished. The Texinfo files are in %BUILDDIR%/texinfo.
goto end
)
if "%1" == "gettext" ( if "%1" == "gettext" (
%SPHINXBUILD% -b gettext %I18NSPHINXOPTS% %BUILDDIR%/locale %SPHINXBUILD% -b gettext %I18NSPHINXOPTS% %BUILDDIR%/locale
if errorlevel 1 exit /b 1 if errorlevel 1 exit /b 1
echo.
echo.Build finished. The message catalogs are in %BUILDDIR%/locale.
goto end goto end
) )
if "%1" == "changes" ( %SPHINXBUILD% -b %1 %ALLSPHINXOPTS% %BUILDDIR%/%1
%SPHINXBUILD% -b changes %ALLSPHINXOPTS% %BUILDDIR%/changes
if errorlevel 1 exit /b 1
echo.
echo.The overview file is in %BUILDDIR%/changes.
goto end goto end
)
if "%1" == "linkcheck" (
%SPHINXBUILD% -b linkcheck %ALLSPHINXOPTS% %BUILDDIR%/linkcheck
if errorlevel 1 exit /b 1
echo.
echo.Link check complete; look for any errors in the above output ^
or in %BUILDDIR%/linkcheck/output.txt.
goto end
)
if "%1" == "doctest" (
%SPHINXBUILD% -b doctest %ALLSPHINXOPTS% %BUILDDIR%/doctest
if errorlevel 1 exit /b 1
echo.
echo.Testing of doctests in the sources finished, look at the ^
results in %BUILDDIR%/doctest/output.txt.
goto end
)
if "%1" == "coverage" (
%SPHINXBUILD% -b coverage %ALLSPHINXOPTS% %BUILDDIR%/coverage
if errorlevel 1 exit /b 1
echo.
echo.Testing of coverage in the sources finished, look at the ^
results in %BUILDDIR%/coverage/python.txt.
goto end
)
if "%1" == "xml" (
%SPHINXBUILD% -b xml %ALLSPHINXOPTS% %BUILDDIR%/xml
if errorlevel 1 exit /b 1
echo.
echo.Build finished. The XML files are in %BUILDDIR%/xml.
goto end
)
if "%1" == "pseudoxml" (
%SPHINXBUILD% -b pseudoxml %ALLSPHINXOPTS% %BUILDDIR%/pseudoxml
if errorlevel 1 exit /b 1
echo.
echo.Build finished. The pseudo-XML files are in %BUILDDIR%/pseudoxml.
goto end
)
if "%1" == "dummy" (
%SPHINXBUILD% -b dummy %ALLSPHINXOPTS% %BUILDDIR%/dummy
if errorlevel 1 exit /b 1
echo.
echo.Build finished. Dummy builder generates no files.
goto end
)
:end :end
popd popd

View File

@ -504,7 +504,7 @@
\fancyfoot[LE,RO]{{\py@HeaderFamily\thepage}} \fancyfoot[LE,RO]{{\py@HeaderFamily\thepage}}
\fancyfoot[LO]{{\py@HeaderFamily\nouppercase{\rightmark}}} \fancyfoot[LO]{{\py@HeaderFamily\nouppercase{\rightmark}}}
\fancyfoot[RE]{{\py@HeaderFamily\nouppercase{\leftmark}}} \fancyfoot[RE]{{\py@HeaderFamily\nouppercase{\leftmark}}}
\fancyhead[LE,RO]{{\py@HeaderFamily \@title, \py@release}} \fancyhead[LE,RO]{{\py@HeaderFamily \@title\sphinxheadercomma\py@release}}
\renewcommand{\headrulewidth}{0.4pt} \renewcommand{\headrulewidth}{0.4pt}
\renewcommand{\footrulewidth}{0.4pt} \renewcommand{\footrulewidth}{0.4pt}
% define chaptermark with \@chappos when \@chappos is available for Japanese % define chaptermark with \@chappos when \@chappos is available for Japanese
@ -1401,18 +1401,26 @@
% \date{}. This allows the date to reflect the document's date and % \date{}. This allows the date to reflect the document's date and
% release to specify the release that is documented. % release to specify the release that is documented.
% %
\newcommand{\py@release}{} \newcommand{\py@release}{\releasename\space\version}
\newcommand{\version}{} \newcommand{\version}{}% part of \py@release, used by title page and headers
\newcommand{\shortversion}{} % \releaseinfo is used on titlepage (sphinxmanual.cls, sphinxhowto.cls)
\newcommand{\releaseinfo}{} \newcommand{\releaseinfo}{}
\newcommand{\releasename}{Release} \newcommand{\setreleaseinfo}[1]{\renewcommand{\releaseinfo}{#1}}
\newcommand{\release}[1]{% % this is inserted via template and #1=release config variable
\renewcommand{\py@release}{\releasename\space\version}% \newcommand{\release}[1]{\renewcommand{\version}{#1}}
\renewcommand{\version}{#1}} % this is defined by template to 'releasename' latex_elements key
\newcommand{\setshortversion}[1]{% \newcommand{\releasename}{}
\renewcommand{\shortversion}{#1}} % Fix issue in case release and releasename deliberately left blank
\newcommand{\setreleaseinfo}[1]{% \newcommand{\sphinxheadercomma}{, }% used in fancyhdr header definition
\renewcommand{\releaseinfo}{#1}} \newcommand{\sphinxifemptyorblank}[1]{%
% test after one expansion of macro #1 if contents is empty or spaces
\if&\expandafter\@firstofone\detokenize\expandafter{#1}&%
\expandafter\@firstoftwo\else\expandafter\@secondoftwo\fi}%
\AtBeginDocument {%
\sphinxifemptyorblank{\releasename}
{\sphinxifemptyorblank{\version}{\let\sphinxheadercomma\empty}{}}
{}%
}%
% Allow specification of the author's address separately from the % Allow specification of the author's address separately from the
% author's name. This can be used to format them differently, which % author's name. This can be used to format them differently, which

View File

@ -0,0 +1,9 @@
var DOCUMENTATION_OPTIONS = {
URL_ROOT: '{{ url_root }}',
VERSION: '{{ release|e }}',
LANGUAGE: '{{ language }}',
COLLAPSE_INDEX: false,
FILE_SUFFIX: '{{ '' if no_search_suffix else file_suffix }}',
HAS_SOURCE: {{ has_source|lower }},
SOURCELINK_SUFFIX: '{{ sourcelink_suffix }}'
};

View File

@ -87,16 +87,7 @@
{%- endmacro %} {%- endmacro %}
{%- macro script() %} {%- macro script() %}
<script type="text/javascript"> <script type="text/javascript" src="{{ pathto('_static/documentation_options.js', 1) }}"></script>
var DOCUMENTATION_OPTIONS = {
URL_ROOT: '{{ url_root }}',
VERSION: '{{ release|e }}',
COLLAPSE_INDEX: false,
FILE_SUFFIX: '{{ '' if no_search_suffix else file_suffix }}',
HAS_SOURCE: {{ has_source|lower }},
SOURCELINK_SUFFIX: '{{ sourcelink_suffix }}'
};
</script>
{%- for scriptfile in script_files %} {%- for scriptfile in script_files %}
<script type="text/javascript" src="{{ pathto(scriptfile, 1) }}"></script> <script type="text/javascript" src="{{ pathto(scriptfile, 1) }}"></script>
{%- endfor %} {%- endfor %}

View File

@ -9,6 +9,8 @@
:license: BSD, see LICENSE for details. :license: BSD, see LICENSE for details.
""" """
import re
from docutils import nodes from docutils import nodes
from docutils.transforms import Transform, Transformer from docutils.transforms import Transform, Transformer
from docutils.transforms.parts import ContentsFilter from docutils.transforms.parts import ContentsFilter
@ -391,3 +393,21 @@ class SphinxSmartQuotes(SmartQuotes, SphinxTransform):
for txtnode in txtnodes: for txtnode in txtnodes:
notsmartquotable = not is_smartquotable(txtnode) notsmartquotable = not is_smartquotable(txtnode)
yield (texttype[notsmartquotable], txtnode.astext()) yield (texttype[notsmartquotable], txtnode.astext())
class ManpageLink(SphinxTransform):
"""Find manpage section numbers and names"""
default_priority = 999
def apply(self):
for node in self.document.traverse(addnodes.manpage):
manpage = ' '.join([str(x) for x in node.children
if isinstance(x, nodes.Text)])
pattern = r'^(?P<path>(?P<page>.+)[\(\.](?P<section>[1-9]\w*)?\)?)$' # noqa
info = {'path': manpage,
'page': manpage,
'section': ''}
r = re.match(pattern, manpage)
if r:
info = r.groupdict()
node.attributes.update(info)

View File

@ -404,10 +404,18 @@ class Signature(object):
if annotation == Ellipsis: if annotation == Ellipsis:
return '...' return '...'
if not isinstance(annotation, type): if not isinstance(annotation, type):
return repr(annotation) qualified_name = repr(annotation)
if qualified_name.startswith('typing.'): # for typing.Union
return qualified_name.split('.', 1)[1]
else:
return qualified_name
qualified_name = (annotation.__module__ + '.' + annotation.__qualname__ # type: ignore if not annotation:
if annotation else repr(annotation)) qualified_name = repr(annotation)
elif annotation.__module__ == 'typing':
qualified_name = annotation.__qualname__ # type: ignore
else:
qualified_name = (annotation.__module__ + '.' + annotation.__qualname__) # type: ignore # NOQA
if annotation.__module__ == 'builtins': if annotation.__module__ == 'builtins':
return annotation.__qualname__ # type: ignore return annotation.__qualname__ # type: ignore

View File

@ -79,6 +79,7 @@ class HTMLTranslator(BaseTranslator):
self.highlightopts = builder.config.highlight_options self.highlightopts = builder.config.highlight_options
self.highlightlinenothreshold = sys.maxsize self.highlightlinenothreshold = sys.maxsize
self.docnames = [builder.current_docname] # for singlehtml builder self.docnames = [builder.current_docname] # for singlehtml builder
self.manpages_url = builder.config.manpages_url
self.protect_literal_text = 0 self.protect_literal_text = 0
self.permalink_text = builder.config.html_add_permalinks self.permalink_text = builder.config.html_add_permalinks
# support backwards-compatible setting to a bool # support backwards-compatible setting to a bool
@ -443,7 +444,7 @@ class HTMLTranslator(BaseTranslator):
location=(self.builder.current_docname, node.line), **highlight_args location=(self.builder.current_docname, node.line), **highlight_args
) )
starttag = self.starttag(node, 'div', suffix='', starttag = self.starttag(node, 'div', suffix='',
CLASS='highlight-%s' % lang) CLASS='highlight-%s notranslate' % lang)
self.body.append(starttag + highlighted + '</div>\n') self.body.append(starttag + highlighted + '</div>\n')
raise nodes.SkipNode raise nodes.SkipNode
@ -493,10 +494,10 @@ class HTMLTranslator(BaseTranslator):
# type: (nodes.Node) -> None # type: (nodes.Node) -> None
if 'kbd' in node['classes']: if 'kbd' in node['classes']:
self.body.append(self.starttag(node, 'kbd', '', self.body.append(self.starttag(node, 'kbd', '',
CLASS='docutils literal')) CLASS='docutils literal notranslate'))
else: else:
self.body.append(self.starttag(node, 'code', '', self.body.append(self.starttag(node, 'code', '',
CLASS='docutils literal')) CLASS='docutils literal notranslate'))
self.protect_literal_text += 1 self.protect_literal_text += 1
def depart_literal(self, node): def depart_literal(self, node):
@ -816,9 +817,14 @@ class HTMLTranslator(BaseTranslator):
def visit_manpage(self, node): def visit_manpage(self, node):
# type: (nodes.Node) -> None # type: (nodes.Node) -> None
self.visit_literal_emphasis(node) self.visit_literal_emphasis(node)
if self.manpages_url:
node['refuri'] = self.manpages_url.format(**node.attributes)
self.visit_reference(node)
def depart_manpage(self, node): def depart_manpage(self, node):
# type: (nodes.Node) -> None # type: (nodes.Node) -> None
if self.manpages_url:
self.depart_reference(node)
self.depart_literal_emphasis(node) self.depart_literal_emphasis(node)
# overwritten to add even/odd classes # overwritten to add even/odd classes

View File

@ -49,6 +49,7 @@ class HTML5Translator(BaseTranslator):
self.highlightopts = builder.config.highlight_options self.highlightopts = builder.config.highlight_options
self.highlightlinenothreshold = sys.maxsize self.highlightlinenothreshold = sys.maxsize
self.docnames = [builder.current_docname] # for singlehtml builder self.docnames = [builder.current_docname] # for singlehtml builder
self.manpages_url = builder.config.manpages_url
self.protect_literal_text = 0 self.protect_literal_text = 0
self.permalink_text = builder.config.html_add_permalinks self.permalink_text = builder.config.html_add_permalinks
# support backwards-compatible setting to a bool # support backwards-compatible setting to a bool
@ -389,7 +390,7 @@ class HTML5Translator(BaseTranslator):
location=(self.builder.current_docname, node.line), **highlight_args location=(self.builder.current_docname, node.line), **highlight_args
) )
starttag = self.starttag(node, 'div', suffix='', starttag = self.starttag(node, 'div', suffix='',
CLASS='highlight-%s' % lang) CLASS='highlight-%s notranslate' % lang)
self.body.append(starttag + highlighted + '</div>\n') self.body.append(starttag + highlighted + '</div>\n')
raise nodes.SkipNode raise nodes.SkipNode
@ -439,10 +440,10 @@ class HTML5Translator(BaseTranslator):
# type: (nodes.Node) -> None # type: (nodes.Node) -> None
if 'kbd' in node['classes']: if 'kbd' in node['classes']:
self.body.append(self.starttag(node, 'kbd', '', self.body.append(self.starttag(node, 'kbd', '',
CLASS='docutils literal')) CLASS='docutils literal notranslate'))
else: else:
self.body.append(self.starttag(node, 'code', '', self.body.append(self.starttag(node, 'code', '',
CLASS='docutils literal')) CLASS='docutils literal notranslate'))
self.protect_literal_text += 1 self.protect_literal_text += 1
def depart_literal(self, node): def depart_literal(self, node):
@ -758,9 +759,14 @@ class HTML5Translator(BaseTranslator):
def visit_manpage(self, node): def visit_manpage(self, node):
# type: (nodes.Node) -> None # type: (nodes.Node) -> None
self.visit_literal_emphasis(node) self.visit_literal_emphasis(node)
if self.manpages_url:
node['refuri'] = self.manpages_url.format(**dict(node))
self.visit_reference(node)
def depart_manpage(self, node): def depart_manpage(self, node):
# type: (nodes.Node) -> None # type: (nodes.Node) -> None
if self.manpages_url:
self.depart_reference(node)
self.depart_literal_emphasis(node) self.depart_literal_emphasis(node)
# overwritten to add even/odd classes # overwritten to add even/odd classes

View File

@ -549,7 +549,7 @@ class LaTeXTranslator(nodes.NodeVisitor):
'author': document.settings.author, # treat as a raw LaTeX code 'author': document.settings.author, # treat as a raw LaTeX code
'indexname': _('Index'), 'indexname': _('Index'),
}) })
if not self.elements['releasename']: if not self.elements['releasename'] and self.elements['release']:
self.elements.update({ self.elements.update({
'releasename': _('Release'), 'releasename': _('Release'),
}) })
@ -1376,6 +1376,9 @@ class LaTeXTranslator(nodes.NodeVisitor):
self.table = Table(node) self.table = Table(node)
if self.next_table_colspec: if self.next_table_colspec:
self.table.colspec = '{%s}\n' % self.next_table_colspec self.table.colspec = '{%s}\n' % self.next_table_colspec
if 'colwidths-given' in node.get('classes', []):
logger.info('both tabularcolumns and :widths: option are given. '
':widths: is ignored.', location=node)
self.next_table_colspec = None self.next_table_colspec = None
def depart_table(self, node): def depart_table(self, node):
@ -1853,28 +1856,14 @@ class LaTeXTranslator(nodes.NodeVisitor):
(node['align'] == 'right' and 'r' or 'l', length or '0pt')) (node['align'] == 'right' and 'r' or 'l', length or '0pt'))
self.context.append(ids + '\\end{wrapfigure}\n') self.context.append(ids + '\\end{wrapfigure}\n')
elif self.in_minipage: elif self.in_minipage:
if ('align' not in node.attributes or
node.attributes['align'] == 'center'):
self.body.append('\n\\begin{center}') self.body.append('\n\\begin{center}')
self.context.append('\\end{center}\n') self.context.append('\\end{center}\n')
else: else:
self.body.append('\n\\begin{flush%s}' % node.attributes['align']) self.body.append('\n\\begin{figure}[%s]\n\\centering\n' %
self.context.append('\\end{flush%s}\n' % node.attributes['align']) self.elements['figure_align'])
else:
if ('align' not in node.attributes or
node.attributes['align'] == 'center'):
# centering does not add vertical space like center.
align = '\n\\centering'
align_end = ''
else:
# TODO non vertical space for other alignments.
align = '\\begin{flush%s}' % node.attributes['align']
align_end = '\\end{flush%s}' % node.attributes['align']
self.body.append('\n\\begin{figure}[%s]%s\n' % (
self.elements['figure_align'], align))
if any(isinstance(child, nodes.caption) for child in node): if any(isinstance(child, nodes.caption) for child in node):
self.body.append('\\capstart\n') self.body.append('\\capstart\n')
self.context.append(ids + align_end + '\\end{figure}\n') self.context.append(ids + '\\end{figure}\n')
def depart_figure(self, node): def depart_figure(self, node):
# type: (nodes.Node) -> None # type: (nodes.Node) -> None

View File

@ -183,6 +183,8 @@ class TextTranslator(nodes.NodeVisitor):
else: else:
self.nl = '\n' self.nl = '\n'
self.sectionchars = builder.config.text_sectionchars self.sectionchars = builder.config.text_sectionchars
self.add_secnumbers = builder.config.text_add_secnumbers
self.secnumber_suffix = builder.config.text_secnumber_suffix
self.states = [[]] # type: List[List[Tuple[int, Union[unicode, List[unicode]]]]] self.states = [[]] # type: List[List[Tuple[int, Union[unicode, List[unicode]]]]]
self.stateindent = [0] self.stateindent = [0]
self.list_counter = [] # type: List[int] self.list_counter = [] # type: List[int]
@ -307,6 +309,17 @@ class TextTranslator(nodes.NodeVisitor):
raise nodes.SkipNode raise nodes.SkipNode
self.new_state(0) self.new_state(0)
def get_section_number_string(self, node):
# type: (nodes.Node) -> unicode
if isinstance(node.parent, nodes.section):
anchorname = '#' + node.parent['ids'][0]
numbers = self.builder.secnumbers.get(anchorname)
if numbers is None:
numbers = self.builder.secnumbers.get('')
if numbers is not None:
return '.'.join(map(str, numbers)) + self.secnumber_suffix
return ''
def depart_title(self, node): def depart_title(self, node):
# type: (nodes.Node) -> None # type: (nodes.Node) -> None
if isinstance(node.parent, nodes.section): if isinstance(node.parent, nodes.section):
@ -315,6 +328,8 @@ class TextTranslator(nodes.NodeVisitor):
char = '^' char = '^'
text = None # type: unicode text = None # type: unicode
text = ''.join(x[1] for x in self.states.pop() if x[0] == -1) # type: ignore text = ''.join(x[1] for x in self.states.pop() if x[0] == -1) # type: ignore
if self.add_secnumbers:
text = self.get_section_number_string(node) + text
self.stateindent.pop() self.stateindent.pop()
title = ['', text, '%s' % (char * column_width(text)), ''] # type: List[unicode] title = ['', text, '%s' % (char * column_width(text)), ''] # type: List[unicode]
if len(self.states) == 2 and len(self.states[-1]) == 0: if len(self.states) == 2 and len(self.states[-1]) == 0:
@ -987,7 +1002,10 @@ class TextTranslator(nodes.NodeVisitor):
def visit_reference(self, node): def visit_reference(self, node):
# type: (nodes.Node) -> None # type: (nodes.Node) -> None
pass if self.add_secnumbers:
numbers = node.get("secnumber")
if numbers is not None:
self.add_text('.'.join(map(str, numbers)) + self.secnumber_suffix)
def depart_reference(self, node): def depart_reference(self, node):
# type: (nodes.Node) -> None # type: (nodes.Node) -> None

View File

@ -1,5 +1,8 @@
.. toctree:: .. toctree::
:numbered:
doc1
doc2
maxwidth maxwidth
lineblock lineblock
nonascii_title nonascii_title

View File

@ -0,0 +1,2 @@
Section A
=========

View File

@ -0,0 +1,9 @@
Section B
=========
Sub Ba
------
Sub Bb
------

View File

@ -0,0 +1,5 @@
Basic Diagram
==============
.. inheritance-diagram::
dummy.test

View File

@ -0,0 +1,6 @@
import sys, os
sys.path.insert(0, os.path.abspath('.'))
extensions = ['sphinx.ext.inheritance_diagram']
source_suffix = '.rst'

View File

@ -0,0 +1,4 @@
.. toctree::
:glob:
*

View File

@ -0,0 +1,6 @@
Diagram using module with 2 top classes
=======================================
.. inheritance-diagram::
dummy.test
:top-classes: dummy.test.B, dummy.test.C

View File

@ -0,0 +1,7 @@
Diagram using 1 top class
=========================
.. inheritance-diagram::
dummy.test
:top-classes: dummy.test.B

View File

@ -0,0 +1,9 @@
Diagram using 2 top classes
===========================
.. inheritance-diagram::
dummy.test.F
dummy.test.D
dummy.test.E
:top-classes: dummy.test.B, dummy.test.C

View File

@ -0,0 +1,7 @@
Diagram using the parts option
==============================
.. inheritance-diagram::
dummy.test
:parts: 1

View File

@ -0,0 +1,30 @@
"""
Test with a class diagram like this::
A
/ \
B C
/ \ / \
E D F
"""
class A(object):
pass
class B(A):
pass
class C(A):
pass
class D(B, C):
pass
class E(B):
pass
class F(C):
pass

View File

@ -0,0 +1,5 @@
# -*- coding: utf-8 -*-
master_doc = 'index'
html_theme = 'classic'
exclude_patterns = ['_build']

View File

@ -0,0 +1,3 @@
* :manpage:`man(1)`
* :manpage:`ls.1`
* :manpage:`sphinx`

View File

@ -4,6 +4,8 @@ from missing_module import missing_name
import missing_package1.missing_module1 import missing_package1.missing_module1
from missing_package2 import missing_module2 from missing_package2 import missing_module2
from missing_package3.missing_module3 import missing_name from missing_package3.missing_module3 import missing_name
import sphinx.missing_module4
from sphinx.missing_module4 import missing_name2
@missing_name @missing_name
def decoratedFunction(): def decoratedFunction():
@ -16,3 +18,5 @@ class TestAutodoc(object):
def decoratedMethod(self): def decoratedMethod(self):
"""TestAutodoc::decoratedMethod docstring""" """TestAutodoc::decoratedMethod docstring"""
return None return None
sphinx.missing_module4.missing_function(len(missing_name2))

View File

@ -69,9 +69,10 @@ extlinks = {'issue': ('http://bugs.python.org/issue%s', 'issue '),
autodoc_mock_imports = [ autodoc_mock_imports = [
'missing_module', 'missing_module',
'missing_package1.missing_module1', 'missing_package1',
'missing_package2.missing_module2', 'missing_package2',
'missing_package3.missing_module3', 'missing_package3',
'sphinx.missing_module4',
] ]
# modify tags from conf.py # modify tags from conf.py

View File

@ -163,21 +163,21 @@ def test_html_warnings(app, warning):
(".//pre/span", u'"quotes"'), (".//pre/span", u'"quotes"'),
(".//pre/span", u"'included'"), (".//pre/span", u"'included'"),
(".//pre/span[@class='s2']", u'üöä'), (".//pre/span[@class='s2']", u'üöä'),
(".//div[@class='inc-pyobj1 highlight-text']//pre", (".//div[@class='inc-pyobj1 highlight-text notranslate']//pre",
r'^class Foo:\n pass\n\s*$'), r'^class Foo:\n pass\n\s*$'),
(".//div[@class='inc-pyobj2 highlight-text']//pre", (".//div[@class='inc-pyobj2 highlight-text notranslate']//pre",
r'^ def baz\(\):\n pass\n\s*$'), r'^ def baz\(\):\n pass\n\s*$'),
(".//div[@class='inc-lines highlight-text']//pre", (".//div[@class='inc-lines highlight-text notranslate']//pre",
r'^class Foo:\n pass\nclass Bar:\n$'), r'^class Foo:\n pass\nclass Bar:\n$'),
(".//div[@class='inc-startend highlight-text']//pre", (".//div[@class='inc-startend highlight-text notranslate']//pre",
u'^foo = "Including Unicode characters: üöä"\\n$'), u'^foo = "Including Unicode characters: üöä"\\n$'),
(".//div[@class='inc-preappend highlight-text']//pre", (".//div[@class='inc-preappend highlight-text notranslate']//pre",
r'(?m)^START CODE$'), r'(?m)^START CODE$'),
(".//div[@class='inc-pyobj-dedent highlight-python']//span", (".//div[@class='inc-pyobj-dedent highlight-python notranslate']//span",
r'def'), r'def'),
(".//div[@class='inc-tab3 highlight-text']//pre", (".//div[@class='inc-tab3 highlight-text notranslate']//pre",
r'-| |-'), r'-| |-'),
(".//div[@class='inc-tab8 highlight-python']//pre/span", (".//div[@class='inc-tab8 highlight-python notranslate']//pre/span",
r'-| |-'), r'-| |-'),
], ],
'autodoc.html': [ 'autodoc.html': [
@ -1243,3 +1243,16 @@ def test_html_sidebar(app, status, warning):
assert '<h3>Related Topics</h3>' not in result assert '<h3>Related Topics</h3>' not in result
assert '<h3>This Page</h3>' not in result assert '<h3>This Page</h3>' not in result
assert '<h3>Quick search</h3>' not in result assert '<h3>Quick search</h3>' not in result
@pytest.mark.parametrize('fname,expect', flat_dict({
'index.html': [(".//em/a[@href='https://example.com/man.1']", "", True),
(".//em/a[@href='https://example.com/ls.1']", "", True),
(".//em/a[@href='https://example.com/sphinx.']", "", True)]
}))
@pytest.mark.sphinx('html', testroot='manpage_url', confoverrides={
'manpages_url': 'https://example.com/{page}.{section}'})
@pytest.mark.test_params(shared_result='test_build_html_manpage_url')
def test_html_manpage(app, cached_etree_parse, fname, expect):
app.build()
check_xpath(cached_etree_parse(app.outdir / fname), fname, *expect)

View File

@ -72,21 +72,21 @@ def cached_etree_parse():
(".//pre/span", u'"quotes"'), (".//pre/span", u'"quotes"'),
(".//pre/span", u"'included'"), (".//pre/span", u"'included'"),
(".//pre/span[@class='s2']", u'üöä'), (".//pre/span[@class='s2']", u'üöä'),
(".//div[@class='inc-pyobj1 highlight-text']//pre", (".//div[@class='inc-pyobj1 highlight-text notranslate']//pre",
r'^class Foo:\n pass\n\s*$'), r'^class Foo:\n pass\n\s*$'),
(".//div[@class='inc-pyobj2 highlight-text']//pre", (".//div[@class='inc-pyobj2 highlight-text notranslate']//pre",
r'^ def baz\(\):\n pass\n\s*$'), r'^ def baz\(\):\n pass\n\s*$'),
(".//div[@class='inc-lines highlight-text']//pre", (".//div[@class='inc-lines highlight-text notranslate']//pre",
r'^class Foo:\n pass\nclass Bar:\n$'), r'^class Foo:\n pass\nclass Bar:\n$'),
(".//div[@class='inc-startend highlight-text']//pre", (".//div[@class='inc-startend highlight-text notranslate']//pre",
u'^foo = "Including Unicode characters: üöä"\\n$'), u'^foo = "Including Unicode characters: üöä"\\n$'),
(".//div[@class='inc-preappend highlight-text']//pre", (".//div[@class='inc-preappend highlight-text notranslate']//pre",
r'(?m)^START CODE$'), r'(?m)^START CODE$'),
(".//div[@class='inc-pyobj-dedent highlight-python']//span", (".//div[@class='inc-pyobj-dedent highlight-python notranslate']//span",
r'def'), r'def'),
(".//div[@class='inc-tab3 highlight-text']//pre", (".//div[@class='inc-tab3 highlight-text notranslate']//pre",
r'-| |-'), r'-| |-'),
(".//div[@class='inc-tab8 highlight-python']//pre/span", (".//div[@class='inc-tab8 highlight-python notranslate']//pre/span",
r'-| |-'), r'-| |-'),
], ],
'autodoc.html': [ 'autodoc.html': [

View File

@ -165,13 +165,15 @@ def test_latex_warnings(app, status, warning):
@pytest.mark.sphinx('latex', testroot='basic') @pytest.mark.sphinx('latex', testroot='basic')
def test_latex_title(app, status, warning): def test_latex_basic(app, status, warning):
app.builder.build_all() app.builder.build_all()
result = (app.outdir / 'test.tex').text(encoding='utf8') result = (app.outdir / 'test.tex').text(encoding='utf8')
print(result) print(result)
print(status.getvalue()) print(status.getvalue())
print(warning.getvalue()) print(warning.getvalue())
assert '\\title{The basic Sphinx documentation for testing}' in result assert r'\title{The basic Sphinx documentation for testing}' in result
assert r'\release{}' in result
assert r'\renewcommand{\releasename}{}' in result
@pytest.mark.sphinx('latex', testroot='latex-title') @pytest.mark.sphinx('latex', testroot='latex-title')
@ -184,6 +186,18 @@ def test_latex_title_after_admonitions(app, status, warning):
assert '\\title{test-latex-title}' in result assert '\\title{test-latex-title}' in result
@pytest.mark.sphinx('latex', testroot='basic',
confoverrides={'release': '1.0'})
def test_latex_release(app, status, warning):
app.builder.build_all()
result = (app.outdir / 'test.tex').text(encoding='utf8')
print(result)
print(status.getvalue())
print(warning.getvalue())
assert r'\release{1.0}' in result
assert r'\renewcommand{\releasename}{Release}' in result
@pytest.mark.sphinx('latex', testroot='numfig', @pytest.mark.sphinx('latex', testroot='numfig',
confoverrides={'numfig': True}) confoverrides={'numfig': True})
def test_numref(app, status, warning): def test_numref(app, status, warning):

View File

@ -63,7 +63,7 @@ def test_lineblock(app, status, warning):
def test_nonascii_title_line(app, status, warning): def test_nonascii_title_line(app, status, warning):
app.builder.build_update() app.builder.build_update()
result = (app.outdir / 'nonascii_title.txt').text(encoding='utf-8') result = (app.outdir / 'nonascii_title.txt').text(encoding='utf-8')
expect_underline = '******' expect_underline = '*********'
result_underline = result.splitlines()[1].strip() result_underline = result.splitlines()[1].strip()
assert expect_underline == result_underline assert expect_underline == result_underline
@ -110,3 +110,83 @@ def test_list_items_in_admonition(app, status, warning):
assert lines[2] == " * item 1" assert lines[2] == " * item 1"
assert lines[3] == "" assert lines[3] == ""
assert lines[4] == " * item 2" assert lines[4] == " * item 2"
@with_text_app()
def test_secnums(app, status, warning):
app.builder.build_all()
contents = (app.outdir / 'contents.txt').text(encoding='utf8')
lines = contents.splitlines()
assert lines[0] == "* 1. Section A"
assert lines[1] == ""
assert lines[2] == "* 2. Section B"
assert lines[3] == ""
assert lines[4] == " * 2.1. Sub Ba"
assert lines[5] == ""
assert lines[6] == " * 2.2. Sub Bb"
doc2 = (app.outdir / 'doc2.txt').text(encoding='utf8')
expect = (
"2. Section B\n"
"************\n"
"\n"
"\n"
"2.1. Sub Ba\n"
"===========\n"
"\n"
"\n"
"2.2. Sub Bb\n"
"===========\n"
)
assert doc2 == expect
app.config.text_secnumber_suffix = " "
app.builder.build_all()
contents = (app.outdir / 'contents.txt').text(encoding='utf8')
lines = contents.splitlines()
assert lines[0] == "* 1 Section A"
assert lines[1] == ""
assert lines[2] == "* 2 Section B"
assert lines[3] == ""
assert lines[4] == " * 2.1 Sub Ba"
assert lines[5] == ""
assert lines[6] == " * 2.2 Sub Bb"
doc2 = (app.outdir / 'doc2.txt').text(encoding='utf8')
expect = (
"2 Section B\n"
"***********\n"
"\n"
"\n"
"2.1 Sub Ba\n"
"==========\n"
"\n"
"\n"
"2.2 Sub Bb\n"
"==========\n"
)
assert doc2 == expect
app.config.text_add_secnumbers = False
app.builder.build_all()
contents = (app.outdir / 'contents.txt').text(encoding='utf8')
lines = contents.splitlines()
assert lines[0] == "* Section A"
assert lines[1] == ""
assert lines[2] == "* Section B"
assert lines[3] == ""
assert lines[4] == " * Sub Ba"
assert lines[5] == ""
assert lines[6] == " * Sub Bb"
doc2 = (app.outdir / 'doc2.txt').text(encoding='utf8')
expect = (
"Section B\n"
"*********\n"
"\n"
"\n"
"Sub Ba\n"
"======\n"
"\n"
"\n"
"Sub Bb\n"
"======\n"
)
assert doc2 == expect

View File

@ -9,7 +9,9 @@
:license: BSD, see LICENSE for details. :license: BSD, see LICENSE for details.
""" """
import pytest import pytest
from sphinx.ext.doctest import compare_version from sphinx.ext.doctest import is_allowed_version
from packaging.version import InvalidVersion
from packaging.specifiers import InvalidSpecifier
cleanup_called = 0 cleanup_called = 0
@ -26,19 +28,28 @@ def test_build(app, status, warning):
assert cleanup_called == 3, 'testcleanup did not get executed enough times' assert cleanup_called == 3, 'testcleanup did not get executed enough times'
def test_compare_version(): def test_is_allowed_version():
assert compare_version('3.3', '3.4', '<') is True assert is_allowed_version('<3.4', '3.3') is True
assert compare_version('3.3', '3.2', '<') is False assert is_allowed_version('<3.4', '3.3') is True
assert compare_version('3.3', '3.4', '<=') is True assert is_allowed_version('<3.2', '3.3') is False
assert compare_version('3.3', '3.2', '<=') is False assert is_allowed_version('<=3.4', '3.3') is True
assert compare_version('3.3', '3.3', '==') is True assert is_allowed_version('<=3.2', '3.3') is False
assert compare_version('3.3', '3.4', '==') is False assert is_allowed_version('==3.3', '3.3') is True
assert compare_version('3.3', '3.2', '>=') is True assert is_allowed_version('==3.4', '3.3') is False
assert compare_version('3.3', '3.4', '>=') is False assert is_allowed_version('>=3.2', '3.3') is True
assert compare_version('3.3', '3.2', '>') is True assert is_allowed_version('>=3.4', '3.3') is False
assert compare_version('3.3', '3.4', '>') is False assert is_allowed_version('>3.2', '3.3') is True
with pytest.raises(ValueError): assert is_allowed_version('>3.4', '3.3') is False
compare_version('3.3', '3.4', '+') assert is_allowed_version('~=3.4', '3.4.5') is True
assert is_allowed_version('~=3.4', '3.5.0') is True
# invalid spec
with pytest.raises(InvalidSpecifier):
is_allowed_version('&3.4', '3.5')
# invalid version
with pytest.raises(InvalidVersion):
is_allowed_version('>3.4', 'Sphinx')
def cleanup_call(): def cleanup_call():

View File

@ -0,0 +1,133 @@
# -*- coding: utf-8 -*-
"""
test_inheritance
~~~~~~~~~~~~~~~~
Tests for :mod:`sphinx.ext.inheritance_diagram` module.
:copyright: Copyright 2015 by the Sphinx team, see AUTHORS.
:license: BSD, see LICENSE for details.
"""
import os
import pytest
from sphinx.ext.inheritance_diagram import InheritanceDiagram
@pytest.mark.sphinx(buildername="html", testroot="inheritance")
@pytest.mark.usefixtures('if_graphviz_found')
def test_inheritance_diagram(app, status, warning):
# monkey-patch InheritaceDiagram.run() so we can get access to its
# results.
orig_run = InheritanceDiagram.run
graphs = {}
def new_run(self):
result = orig_run(self)
node = result[0]
source = os.path.basename(node.document.current_source).replace(".rst", "")
graphs[source] = node['graph']
return result
InheritanceDiagram.run = new_run
try:
app.builder.build_all()
finally:
InheritanceDiagram.run = orig_run
assert app.statuscode == 0
html_warnings = warning.getvalue()
assert html_warnings == ""
# note: it is better to split these asserts into separate test functions
# but I can't figure out how to build only a specific .rst file
# basic inheritance diagram showing all classes
for cls in graphs['basic_diagram'].class_info:
# use in b/c traversing order is different sometimes
assert cls in [
('dummy.test.A', 'dummy.test.A', [], None),
('dummy.test.F', 'dummy.test.F', ['dummy.test.C'], None),
('dummy.test.C', 'dummy.test.C', ['dummy.test.A'], None),
('dummy.test.E', 'dummy.test.E', ['dummy.test.B'], None),
('dummy.test.D', 'dummy.test.D',
['dummy.test.B', 'dummy.test.C'], None),
('dummy.test.B', 'dummy.test.B', ['dummy.test.A'], None)
]
# inheritance diagram using :parts: 1 option
for cls in graphs['diagram_w_parts'].class_info:
assert cls in [
('A', 'dummy.test.A', [], None),
('F', 'dummy.test.F', ['C'], None),
('C', 'dummy.test.C', ['A'], None),
('E', 'dummy.test.E', ['B'], None),
('D', 'dummy.test.D', ['B', 'C'], None),
('B', 'dummy.test.B', ['A'], None)
]
# inheritance diagram with 1 top class
# :top-classes: dummy.test.B
# rendering should be
# A
# \
# B C
# / \ / \
# E D F
#
for cls in graphs['diagram_w_1_top_class'].class_info:
assert cls in [
('dummy.test.A', 'dummy.test.A', [], None),
('dummy.test.F', 'dummy.test.F', ['dummy.test.C'], None),
('dummy.test.C', 'dummy.test.C', ['dummy.test.A'], None),
('dummy.test.E', 'dummy.test.E', ['dummy.test.B'], None),
('dummy.test.D', 'dummy.test.D',
['dummy.test.B', 'dummy.test.C'], None),
('dummy.test.B', 'dummy.test.B', [], None)
]
# inheritance diagram with 2 top classes
# :top-classes: dummy.test.B, dummy.test.C
# Note: we're specifying separate classes, not the entire module here
# rendering should be
#
# B C
# / \ / \
# E D F
#
for cls in graphs['diagram_w_2_top_classes'].class_info:
assert cls in [
('dummy.test.F', 'dummy.test.F', ['dummy.test.C'], None),
('dummy.test.C', 'dummy.test.C', [], None),
('dummy.test.E', 'dummy.test.E', ['dummy.test.B'], None),
('dummy.test.D', 'dummy.test.D',
['dummy.test.B', 'dummy.test.C'], None),
('dummy.test.B', 'dummy.test.B', [], None)
]
# inheritance diagram with 2 top classes and specifiying the entire module
# rendering should be
#
# A
# B C
# / \ / \
# E D F
#
# Note: dummy.test.A is included in the graph before its descendants are even processed
# b/c we've specified to load the entire module. The way InheritanceGraph works it is very
# hard to exclude parent classes once after they have been included in the graph.
# If you'd like to not show class A in the graph don't specify the entire module.
# this is a known issue.
for cls in graphs['diagram_module_w_2_top_classes'].class_info:
assert cls in [
('dummy.test.F', 'dummy.test.F', ['dummy.test.C'], None),
('dummy.test.C', 'dummy.test.C', [], None),
('dummy.test.E', 'dummy.test.E', ['dummy.test.B'], None),
('dummy.test.D', 'dummy.test.D',
['dummy.test.B', 'dummy.test.C'], None),
('dummy.test.B', 'dummy.test.B', [], None),
('dummy.test.A', 'dummy.test.A', [], None),
]

View File

@ -236,7 +236,8 @@ def test_missing_reference_cppdomain(tempdir, app, status, warning):
html = (app.outdir / 'index.html').text() html = (app.outdir / 'index.html').text()
assert ('<a class="reference external"' assert ('<a class="reference external"'
' href="https://docs.python.org/index.html#cpp_foo_bar"' ' href="https://docs.python.org/index.html#cpp_foo_bar"'
' title="(in foo v2.0)"><code class="xref cpp cpp-class docutils literal">' ' title="(in foo v2.0)">'
'<code class="xref cpp cpp-class docutils literal notranslate">'
'<span class="pre">Bar</span></code></a>' in html) '<span class="pre">Bar</span></code></a>' in html)
assert ('<a class="reference external"' assert ('<a class="reference external"'
' href="https://docs.python.org/index.html#foons"' ' href="https://docs.python.org/index.html#foons"'

View File

@ -35,17 +35,17 @@ def test_jsmath(app, status, warning):
app.builder.build_all() app.builder.build_all()
content = (app.outdir / 'math.html').text() content = (app.outdir / 'math.html').text()
assert '<div class="math">\na^2 + b^2 = c^2</div>' in content assert '<div class="math notranslate">\na^2 + b^2 = c^2</div>' in content
assert '<div class="math">\n\\begin{split}a + 1 &lt; b\\end{split}</div>' in content assert '<div class="math notranslate">\n\\begin{split}a + 1 &lt; b\\end{split}</div>' in content
assert (u'<span class="eqno">(1)<a class="headerlink" href="#equation-foo" ' assert (u'<span class="eqno">(1)<a class="headerlink" href="#equation-foo" '
u'title="Permalink to this equation">\xb6</a></span>' u'title="Permalink to this equation">\xb6</a></span>'
u'<div class="math" id="equation-foo">\ne^{i\\pi} = 1</div>' in content) u'<div class="math notranslate" id="equation-foo">\ne^{i\\pi} = 1</div>' in content)
assert (u'<span class="eqno">(2)<a class="headerlink" href="#equation-math:0" ' assert (u'<span class="eqno">(2)<a class="headerlink" href="#equation-math:0" '
u'title="Permalink to this equation">\xb6</a></span>' u'title="Permalink to this equation">\xb6</a></span>'
u'<div class="math" id="equation-math:0">\n' u'<div class="math notranslate" id="equation-math:0">\n'
u'e^{ix} = \\cos x + i\\sin x</div>' in content) u'e^{ix} = \\cos x + i\\sin x</div>' in content)
assert '<div class="math">\nn \\in \\mathbb N</div>' in content assert '<div class="math notranslate">\nn \\in \\mathbb N</div>' in content
assert '<div class="math">\na + 1 &lt; b</div>' in content assert '<div class="math notranslate">\na + 1 &lt; b</div>' in content
@pytest.mark.skipif(not has_binary('dvipng'), @pytest.mark.skipif(not has_binary('dvipng'),
@ -89,7 +89,7 @@ def test_mathjax_align(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="math">\s*' html = (r'<div class="math notranslate">\s*'
r'\\\[ \\begin\{align\}\\begin\{aligned\}S \&amp;= \\pi r\^2\\\\' r'\\\[ \\begin\{align\}\\begin\{aligned\}S \&amp;= \\pi r\^2\\\\'
r'V \&amp;= \\frac\{4\}\{3\} \\pi r\^3\\end\{aligned\}\\end\{align\} \\\]</div>') r'V \&amp;= \\frac\{4\}\{3\} \\pi r\^3\\end\{aligned\}\\end\{align\} \\\]</div>')
assert re.search(html, content, re.S) assert re.search(html, content, re.S)
@ -102,7 +102,7 @@ def test_math_number_all_mathjax(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="math" id="equation-index:0">\s*' html = (r'<div class="math notranslate" id="equation-index:0">\s*'
r'<span class="eqno">\(1\)<a .*>\xb6</a></span>\\\[a\^2\+b\^2=c\^2\\\]</div>') r'<span class="eqno">\(1\)<a .*>\xb6</a></span>\\\[a\^2\+b\^2=c\^2\\\]</div>')
assert re.search(html, content, re.S) assert re.search(html, content, re.S)
@ -167,7 +167,7 @@ def test_mathjax_numfig_html(app, status, warning):
app.builder.build_all() app.builder.build_all()
content = (app.outdir / 'math.html').text() content = (app.outdir / 'math.html').text()
html = ('<div class="math" id="equation-math:0">\n' html = ('<div class="math notranslate" id="equation-math:0">\n'
'<span class="eqno">(1.2)') '<span class="eqno">(1.2)')
assert html in content assert html in content
html = ('<p>Referencing equation <a class="reference internal" ' html = ('<p>Referencing equation <a class="reference internal" '

View File

@ -143,8 +143,8 @@ def test_text_warning_node(app):
app.build() app.build()
# test warnings in translation # test warnings in translation
result = (app.outdir / 'warnings.txt').text(encoding='utf-8') result = (app.outdir / 'warnings.txt').text(encoding='utf-8')
expect = (u"I18N WITH REST WARNINGS" expect = (u"3. I18N WITH REST WARNINGS"
u"\n***********************\n" u"\n**************************\n"
u"\nLINE OF >>``<<BROKEN LITERAL MARKUP.\n") u"\nLINE OF >>``<<BROKEN LITERAL MARKUP.\n")
assert result == expect assert result == expect
@ -157,8 +157,8 @@ def test_text_title_underline(app):
app.build() app.build()
# --- simple translation; check title underlines # --- simple translation; check title underlines
result = (app.outdir / 'bom.txt').text(encoding='utf-8') result = (app.outdir / 'bom.txt').text(encoding='utf-8')
expect = (u"Datei mit UTF-8" expect = (u"2. Datei mit UTF-8"
u"\n***************\n" # underline matches new translation u"\n******************\n" # underline matches new translation
u"\nThis file has umlauts: äöü.\n") u"\nThis file has umlauts: äöü.\n")
assert result == expect assert result == expect
@ -170,7 +170,7 @@ def test_text_subdirs(app):
app.build() app.build()
# --- check translation in subdirs # --- check translation in subdirs
result = (app.outdir / 'subdir' / 'contents.txt').text(encoding='utf-8') result = (app.outdir / 'subdir' / 'contents.txt').text(encoding='utf-8')
assert_startswith(result, u"subdir contents\n***************\n") assert_startswith(result, u"1. subdir contents\n******************\n")
@sphinx_intl @sphinx_intl
@ -180,8 +180,8 @@ def test_text_inconsistency_warnings(app, warning):
app.build() app.build()
# --- check warnings for inconsistency in number of references # --- check warnings for inconsistency in number of references
result = (app.outdir / 'refs_inconsistency.txt').text(encoding='utf-8') result = (app.outdir / 'refs_inconsistency.txt').text(encoding='utf-8')
expect = (u"I18N WITH REFS INCONSISTENCY" expect = (u"8. I18N WITH REFS INCONSISTENCY"
u"\n****************************\n" u"\n*******************************\n"
u"\n* FOR CITATION [ref3].\n" u"\n* FOR CITATION [ref3].\n"
u"\n* reference FOR reference.\n" u"\n* reference FOR reference.\n"
u"\n* ORPHAN REFERENCE: I18N WITH REFS INCONSISTENCY.\n" u"\n* ORPHAN REFERENCE: I18N WITH REFS INCONSISTENCY.\n"
@ -230,8 +230,8 @@ def test_text_literalblock_warnings(app, warning):
app.build() app.build()
# --- check warning for literal block # --- check warning for literal block
result = (app.outdir / 'literalblock.txt').text(encoding='utf-8') result = (app.outdir / 'literalblock.txt').text(encoding='utf-8')
expect = (u"I18N WITH LITERAL BLOCK" expect = (u"9. I18N WITH LITERAL BLOCK"
u"\n***********************\n" u"\n**************************\n"
u"\nCORRECT LITERAL BLOCK:\n" u"\nCORRECT LITERAL BLOCK:\n"
u"\n this is" u"\n this is"
u"\n literal block\n" u"\n literal block\n"
@ -252,8 +252,8 @@ def test_text_definition_terms(app):
app.build() app.build()
# --- definition terms: regression test for #975, #2198, #2205 # --- definition terms: regression test for #975, #2198, #2205
result = (app.outdir / 'definition_terms.txt').text(encoding='utf-8') result = (app.outdir / 'definition_terms.txt').text(encoding='utf-8')
expect = (u"I18N WITH DEFINITION TERMS" expect = (u"13. I18N WITH DEFINITION TERMS"
u"\n**************************\n" u"\n******************************\n"
u"\nSOME TERM" u"\nSOME TERM"
u"\n THE CORRESPONDING DEFINITION\n" u"\n THE CORRESPONDING DEFINITION\n"
u"\nSOME *TERM* WITH LINK" u"\nSOME *TERM* WITH LINK"
@ -273,8 +273,8 @@ def test_text_glossary_term(app, warning):
app.build() app.build()
# --- glossary terms: regression test for #1090 # --- glossary terms: regression test for #1090
result = (app.outdir / 'glossary_terms.txt').text(encoding='utf-8') result = (app.outdir / 'glossary_terms.txt').text(encoding='utf-8')
expect = (u"I18N WITH GLOSSARY TERMS" expect = (u"18. I18N WITH GLOSSARY TERMS"
u"\n************************\n" u"\n****************************\n"
u"\nSOME NEW TERM" u"\nSOME NEW TERM"
u"\n THE CORRESPONDING GLOSSARY\n" u"\n THE CORRESPONDING GLOSSARY\n"
u"\nSOME OTHER NEW TERM" u"\nSOME OTHER NEW TERM"
@ -292,8 +292,8 @@ def test_text_glossary_term_inconsistencies(app, warning):
app.build() app.build()
# --- glossary term inconsistencies: regression test for #1090 # --- glossary term inconsistencies: regression test for #1090
result = (app.outdir / 'glossary_terms_inconsistency.txt').text(encoding='utf-8') result = (app.outdir / 'glossary_terms_inconsistency.txt').text(encoding='utf-8')
expect = (u"I18N WITH GLOSSARY TERMS INCONSISTENCY" expect = (u"19. I18N WITH GLOSSARY TERMS INCONSISTENCY"
u"\n**************************************\n" u"\n******************************************\n"
u"\n1. LINK TO *SOME NEW TERM*.\n") u"\n1. LINK TO *SOME NEW TERM*.\n")
assert result == expect assert result == expect
@ -313,8 +313,8 @@ def test_text_seealso(app):
app.build() app.build()
# --- seealso # --- seealso
result = (app.outdir / 'seealso.txt').text(encoding='utf-8') result = (app.outdir / 'seealso.txt').text(encoding='utf-8')
expect = (u"I18N WITH SEEALSO" expect = (u"12. I18N WITH SEEALSO"
u"\n*****************\n" u"\n*********************\n"
u"\nSee also: SHORT TEXT 1\n" u"\nSee also: SHORT TEXT 1\n"
u"\nSee also: LONG TEXT 1\n" u"\nSee also: LONG TEXT 1\n"
u"\nSee also: SHORT TEXT 2\n" u"\nSee also: SHORT TEXT 2\n"
@ -329,34 +329,34 @@ def test_text_figure_captions(app):
app.build() app.build()
# --- figure captions: regression test for #940 # --- figure captions: regression test for #940
result = (app.outdir / 'figure.txt').text(encoding='utf-8') result = (app.outdir / 'figure.txt').text(encoding='utf-8')
expect = (u"I18N WITH FIGURE CAPTION" expect = (u"14. I18N WITH FIGURE CAPTION"
u"\n************************\n" u"\n****************************\n"
u"\n [image]MY CAPTION OF THE FIGURE\n" u"\n [image]MY CAPTION OF THE FIGURE\n"
u"\n MY DESCRIPTION PARAGRAPH1 OF THE FIGURE.\n" u"\n MY DESCRIPTION PARAGRAPH1 OF THE FIGURE.\n"
u"\n MY DESCRIPTION PARAGRAPH2 OF THE FIGURE.\n" u"\n MY DESCRIPTION PARAGRAPH2 OF THE FIGURE.\n"
u"\n" u"\n"
u"\nFIGURE IN THE BLOCK" u"\n14.1. FIGURE IN THE BLOCK"
u"\n===================\n" u"\n=========================\n"
u"\nBLOCK\n" u"\nBLOCK\n"
u"\n [image]MY CAPTION OF THE FIGURE\n" u"\n [image]MY CAPTION OF THE FIGURE\n"
u"\n MY DESCRIPTION PARAGRAPH1 OF THE FIGURE.\n" u"\n MY DESCRIPTION PARAGRAPH1 OF THE FIGURE.\n"
u"\n MY DESCRIPTION PARAGRAPH2 OF THE FIGURE.\n" u"\n MY DESCRIPTION PARAGRAPH2 OF THE FIGURE.\n"
u"\n" u"\n"
u"\n" u"\n"
u"IMAGE URL AND ALT\n" u"14.2. IMAGE URL AND ALT\n"
u"=================\n" u"=======================\n"
u"\n" u"\n"
u"[image: i18n][image]\n" u"[image: i18n][image]\n"
u"\n" u"\n"
u" [image: img][image]\n" u" [image: img][image]\n"
u"\n" u"\n"
u"\n" u"\n"
u"IMAGE ON SUBSTITUTION\n" u"14.3. IMAGE ON SUBSTITUTION\n"
u"=====================\n" u"===========================\n"
u"\n" u"\n"
u"\n" u"\n"
u"IMAGE UNDER NOTE\n" u"14.4. IMAGE UNDER NOTE\n"
u"================\n" u"======================\n"
u"\n" u"\n"
u"Note: [image: i18n under note][image]\n" u"Note: [image: i18n under note][image]\n"
u"\n" u"\n"
@ -390,8 +390,8 @@ def test_text_docfields(app):
app.build() app.build()
# --- docfields # --- docfields
result = (app.outdir / 'docfields.txt').text(encoding='utf-8') result = (app.outdir / 'docfields.txt').text(encoding='utf-8')
expect = (u"I18N WITH DOCFIELDS" expect = (u"21. I18N WITH DOCFIELDS"
u"\n*******************\n" u"\n***********************\n"
u"\nclass Cls1\n" u"\nclass Cls1\n"
u"\n Parameters:" u"\n Parameters:"
u"\n **param** -- DESCRIPTION OF PARAMETER param\n" u"\n **param** -- DESCRIPTION OF PARAMETER param\n"

View File

@ -133,7 +133,7 @@ def get_verifier(verify, verify_re):
# correct interpretation of code with whitespace # correct interpretation of code with whitespace
'verify_re', 'verify_re',
'``code sample``', '``code sample``',
('<p><code class="(samp )?docutils literal"><span class="pre">' ('<p><code class="(samp )?docutils literal notranslate"><span class="pre">'
'code</span>&#160;&#160; <span class="pre">sample</span></code></p>'), 'code</span>&#160;&#160; <span class="pre">sample</span></code></p>'),
r'\\sphinxcode{\\sphinxupquote{code sample}}', r'\\sphinxcode{\\sphinxupquote{code sample}}',
), ),
@ -141,7 +141,7 @@ def get_verifier(verify, verify_re):
# correct interpretation of code with whitespace # correct interpretation of code with whitespace
'verify_re', 'verify_re',
':samp:`code sample`', ':samp:`code sample`',
('<p><code class="(samp )?docutils literal"><span class="pre">' ('<p><code class="(samp )?docutils literal notranslate"><span class="pre">'
'code</span>&#160;&#160; <span class="pre">sample</span></code></p>'), 'code</span>&#160;&#160; <span class="pre">sample</span></code></p>'),
r'\\sphinxcode{\\sphinxupquote{code sample}}', r'\\sphinxcode{\\sphinxupquote{code sample}}',
), ),
@ -149,7 +149,8 @@ def get_verifier(verify, verify_re):
# interpolation of braces in samp and file roles (HTML only) # interpolation of braces in samp and file roles (HTML only)
'verify', 'verify',
':samp:`a{b}c`', ':samp:`a{b}c`',
('<p><code class="samp docutils literal"><span class="pre">a</span>' ('<p><code class="samp docutils literal notranslate">'
'<span class="pre">a</span>'
'<em><span class="pre">b</span></em>' '<em><span class="pre">b</span></em>'
'<span class="pre">c</span></code></p>'), '<span class="pre">c</span></code></p>'),
'\\sphinxcode{\\sphinxupquote{a\\sphinxstyleemphasis{b}c}}', '\\sphinxcode{\\sphinxupquote{a\\sphinxstyleemphasis{b}c}}',
@ -173,7 +174,7 @@ def get_verifier(verify, verify_re):
# non-interpolation of dashes in option role # non-interpolation of dashes in option role
'verify_re', 'verify_re',
':option:`--with-option`', ':option:`--with-option`',
('<p><code( class="xref std std-option docutils literal")?>' ('<p><code( class="xref std std-option docutils literal notranslate")?>'
'<span class="pre">--with-option</span></code></p>$'), '<span class="pre">--with-option</span></code></p>$'),
r'\\sphinxcode{\\sphinxupquote{-{-}with-option}}$', r'\\sphinxcode{\\sphinxupquote{-{-}with-option}}$',
), ),
@ -188,7 +189,7 @@ def get_verifier(verify, verify_re):
# ... but not in literal text # ... but not in literal text
'verify', 'verify',
'``"John"``', '``"John"``',
('<p><code class="docutils literal"><span class="pre">' ('<p><code class="docutils literal notranslate"><span class="pre">'
'&quot;John&quot;</span></code></p>'), '&quot;John&quot;</span></code></p>'),
'\\sphinxcode{\\sphinxupquote{"John"}}', '\\sphinxcode{\\sphinxupquote{"John"}}',
), ),

View File

@ -211,15 +211,15 @@ def test_Signature_annotations():
# Generic types with concrete parameters # Generic types with concrete parameters
sig = inspect.Signature(f1).format_args() sig = inspect.Signature(f1).format_args()
assert sig == '(x: typing.List[int]) -> typing.List[int]' assert sig == '(x: List[int]) -> List[int]'
# TypeVars and generic types with TypeVars # TypeVars and generic types with TypeVars
sig = inspect.Signature(f2).format_args() sig = inspect.Signature(f2).format_args()
assert sig == '(x: typing.List[T], y: typing.List[T_co], z: T) -> typing.List[T_contra]' assert sig == '(x: List[T], y: List[T_co], z: T) -> List[T_contra]'
# Union types # Union types
sig = inspect.Signature(f3).format_args() sig = inspect.Signature(f3).format_args()
assert sig == '(x: typing.Union[str, numbers.Integral]) -> None' assert sig == '(x: Union[str, numbers.Integral]) -> None'
# Quoted annotations # Quoted annotations
sig = inspect.Signature(f4).format_args() sig = inspect.Signature(f4).format_args()
@ -239,14 +239,14 @@ def test_Signature_annotations():
# Callable types # Callable types
sig = inspect.Signature(f8).format_args() sig = inspect.Signature(f8).format_args()
assert sig == '(x: typing.Callable[[int, str], int]) -> None' assert sig == '(x: Callable[[int, str], int]) -> None'
sig = inspect.Signature(f9).format_args() sig = inspect.Signature(f9).format_args()
assert sig == '(x: typing.Callable) -> None' assert sig == '(x: Callable) -> None'
# Tuple types # Tuple types
sig = inspect.Signature(f10).format_args() sig = inspect.Signature(f10).format_args()
assert sig == '(x: typing.Tuple[int, str], y: typing.Tuple[int, ...]) -> None' assert sig == '(x: Tuple[int, str], y: Tuple[int, ...]) -> None'
# Instance annotations # Instance annotations
sig = inspect.Signature(f11).format_args() sig = inspect.Signature(f11).format_args()