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

29
CHANGES
View File

@ -1,6 +1,11 @@
Release 1.7 (in development)
============================
Dependencies
------------
* Add ``packaging`` package
Incompatible changes
--------------------
@ -16,6 +21,12 @@ Incompatible changes
* #4389: output directory will be created after loading extensions
* autodoc does not generate warnings messages to the generated document even if
: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
----------
@ -65,6 +76,20 @@ Features added
* #947: autodoc now supports ignore-module-all to ignore a module's ``__all__``
* #4332: Let LaTeX obey :confval:`math_numfig` for equation numbering
* #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
----------------
@ -95,6 +120,8 @@ Features removed
* LaTeX environment ``notice``, use ``sphinxadmonition`` instead
* LaTeX ``\sphinxstylethead``, use ``\sphinxstyletheadfamily``
* C++, support of function concepts. Thanks to mickk-on-cpp.
* Not used and previously not documented LaTeX macros ``\shortversion``
and ``\setshortversion``
Bugs fixed
@ -113,11 +140,13 @@ Bugs fixed
* #4198: autosummary emits multiple 'autodoc-process-docstring' event. Thanks
to Joel Nothman.
* #4081: Warnings and errors colored the same when building
* latex: Do not display 'Release' label if :confval:`release` is not set
Testing
--------
* Add support for docutils 0.14
* Add tests for the ``sphinx.ext.inheritance_diagram`` extension.
Release 1.6.7 (in development)
==============================

View File

@ -293,6 +293,24 @@ General configuration
.. 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
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
.. 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:

View File

@ -80,12 +80,24 @@ a comma-separated list of group names.
.. doctest::
:pyversion: > 3.3
The supported operands are ``<``, ``<=``, ``==``, ``>=``, ``>``, and
comparison is performed by `distutils.version.LooseVersion
<https://www.python.org/dev/peps/pep-0386/#distutils>`__.
The following operands are supported:
* ``~=``: 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
.. versionchanged:: 1.7
Supported PEP-440 operands and notations
Note that like with standard doctests, you have to use ``<BLANKLINE>`` to
signal a blank line in the expected output. The ``<BLANKLINE>`` is removed
when building presentation output (HTML, LaTeX etc.).

View File

@ -42,6 +42,54 @@ It adds this directive:
.. versionchanged:: 1.5
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:

View File

@ -15,6 +15,7 @@ Builder API
.. autoattribute:: name
.. autoattribute:: format
.. autoattribute:: epilog
.. autoattribute:: supported_image_types
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
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
possibly subdirectories of docs in there as well), Sphinx can generate a
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.
* 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
to Sphinx: `odt2sphinx <https://pypi.python.org/pypi/odt2sphinx/>`_.

View File

@ -355,7 +355,8 @@ in a different style:
.. rst:role:: manpage
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

View File

@ -323,6 +323,11 @@ following directive exists:
Sphinx's merged cells interact well with ``p{width}``, ``\X{a}{b}``, ``Y{f}``
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
----

View File

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

View File

@ -338,6 +338,13 @@ class Sphinx(object):
(status, self._warncount)))
else:
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:
# delete the saved env to force a fresh build next time
envfile = path.join(self.doctreedir, ENV_PICKLE_FILENAME)

View File

@ -54,6 +54,11 @@ class Builder(object):
name = '' # type: unicode
#: The builder's output format, or '' if no document output is produced.
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
# ``app.set_translator()``.
default_translator_class = None # type: nodes.NodeVisitor

View File

@ -75,6 +75,10 @@ class AppleHelpBuilder(StandaloneHTMLBuilder):
on the ``hiutil`` command line tool.
"""
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
copysource = False

View File

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

View File

@ -43,6 +43,10 @@ class DevhelpBuilder(StandaloneHTMLBuilder):
Builder that also outputs GNOME Devhelp file.
"""
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
copysource = False

View File

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

View File

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

View File

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

View File

@ -153,6 +153,8 @@ class StandaloneHTMLBuilder(Builder):
"""
name = 'html'
format = 'html'
epilog = 'The HTML pages are in %(outdir)s.'
copysource = True
allow_parallel = True
out_suffix = '.html'
@ -1066,6 +1068,8 @@ class SingleFileHTMLBuilder(StandaloneHTMLBuilder):
HTML page.
"""
name = 'singlehtml'
epilog = 'The HTML page is in %(outdir)s.'
copysource = False
def get_outdated_docs(self): # type: ignore
@ -1328,12 +1332,14 @@ class PickleHTMLBuilder(SerializingHTMLBuilder):
"""
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_dumps_unicode = False
additional_dump_args = (pickle.HIGHEST_PROTOCOL,)
indexer_format = pickle
indexer_dumps_unicode = False
name = 'pickle'
out_suffix = '.fpickle'
globalcontext_filename = 'globalcontext.pickle'
searchindex_filename = 'searchindex.pickle'
@ -1347,11 +1353,13 @@ class JSONHTMLBuilder(SerializingHTMLBuilder):
"""
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_dumps_unicode = True
indexer_format = jsonimpl
indexer_dumps_unicode = True
name = 'json'
out_suffix = '.fjson'
globalcontext_filename = 'globalcontext.json'
searchindex_filename = 'searchindex.json'

View File

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

View File

@ -49,6 +49,12 @@ class LaTeXBuilder(Builder):
"""
name = '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_remote_images = False
default_translator_class = LaTeXTranslator

View File

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

View File

@ -40,6 +40,8 @@ class ManualPageBuilder(Builder):
"""
name = 'man'
format = 'man'
epilog = 'The manual pages are in %(outdir)s.'
default_translator_class = ManualPageTranslator
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.
"""
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
copysource = False

View File

@ -9,6 +9,7 @@
:license: BSD, see LICENSE for details.
"""
import os
from os import path
from docutils import nodes
@ -97,6 +98,12 @@ class TexinfoBuilder(Builder):
"""
name = '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',
'image/gif']
default_translator_class = TexinfoTranslator

View File

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

View File

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

View File

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

View File

@ -23,7 +23,7 @@ from sphinx.util.inspect import isenumclass, safe_getattr
if False:
# 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__)
@ -84,13 +84,7 @@ class _MockModule(ModuleType):
class _MockImporter(object):
def __init__(self, names):
# type: (List[str]) -> None
self.base_packages = set() # type: Set[str]
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.names = names
self.mocked_modules = [] # type: List[str]
# enable hook by adding itself to meta_path
sys.meta_path = sys.meta_path + [self]
@ -106,9 +100,10 @@ class _MockImporter(object):
def find_module(self, name, path=None):
# type: (str, str) -> Any
base_package = name.split('.')[0]
if base_package in self.base_packages:
return self
# check if name is (or is a descendant of) one of our base_packages
for n in self.names:
if n == name or name.startswith(n + '.'):
return self
return None
def load_module(self, name):

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -97,101 +97,6 @@ class Make(object):
if not osname or os.name == osname:
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):
# type: () -> int
if self.run_generic_build('latex') > 0:
@ -206,25 +111,6 @@ class Make(object):
with cd(self.builddir_join('latex')):
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):
# type: () -> int
if self.run_generic_build('texinfo') > 0:
@ -237,60 +123,6 @@ class Make(object):
dtdir = self.builddir_join('gettext', '.doctrees')
if self.run_generic_build('gettext', doctreedir=dtdir) > 0:
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
def run_generic_build(self, builder, doctreedir=None):

View File

@ -5,14 +5,16 @@
SPHINXOPTS ?=
SPHINXBUILD ?= sphinx-build
PAPER ?=
SOURCEDIR = {{ rsrcdir }}
BUILDDIR = {{ rbuilddir }}
# Internal variables.
PAPEROPT_a4 = -D latex_elements.papersize=a4
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
I18NSPHINXOPTS = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) {{ rsrcdir }}
I18NSPHINXOPTS = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) $(O) $(SOURCEDIR)
.PHONY: help
help:
@ -49,86 +51,6 @@ help:
clean:
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
latexpdf:
$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
@ -157,26 +79,6 @@ xelatexpdf:
$(MAKE) PDFLATEX=xelatex -C $(BUILDDIR)/latex all-pdf
@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
info:
$(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo
@ -187,49 +89,9 @@ info:
.PHONY: gettext
gettext:
$(SPHINXBUILD) -b gettext $(I18NSPHINXOPTS) $(BUILDDIR)/locale
@echo
@echo "Build finished. The message catalogs are in $(BUILDDIR)/locale."
.PHONY: changes
changes:
$(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes
@echo
@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."
# Catch-all target: route all unknown targets to Sphinx
.PHONY: Makefile
%: Makefile
$(SPHINXBUILD) -b "$@" $(ALLSPHINXOPTS) "$(BUILDDIR)/$@"

View File

@ -1,19 +1,12 @@
{% if PY3 -%}
#!/usr/bin/env python3
{% endif -%}
# -*- coding: utf-8 -*-
#
# {{ project }} documentation build configuration file, created by
# sphinx-quickstart on {{ now }}.
# Configuration file for the Sphinx documentation builder.
#
# This file is execfile()d with the current directory set to its
# containing dir.
#
# Note that not all possible configuration values are present in this
# autogenerated file.
#
# All configuration values have a default; values that are commented out
# serve to show the default.
# This file does only contain a selection of the most common options. For a
# full list see the documentation:
# http://www.sphinx-doc.org/en/stable/config
# -- Path setup --------------------------------------------------------------
# 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
@ -33,7 +26,19 @@ sys.path.insert(0, u'{{ module_path }}')
{% 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.
#
@ -60,20 +65,6 @@ source_suffix = '{{ suffix }}'
# The master toctree document.
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
# for a list of supported languages.
#
@ -90,7 +81,7 @@ exclude_patterns = [{{ exclude_patterns }}]
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
# a list of builtin themes.
@ -119,13 +110,13 @@ html_static_path = ['{{ dot }}static']
# html_sidebars = {}
# -- Options for HTMLHelp output ------------------------------------------
# -- Options for HTMLHelp output ---------------------------------------------
# Output file base name for HTML help builder.
htmlhelp_basename = '{{ project_fn }}doc'
# -- Options for LaTeX output ---------------------------------------------
# -- Options for LaTeX output ------------------------------------------------
latex_elements = {
# 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
# (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
# (source start file, target name, title, author,
@ -177,7 +168,7 @@ texinfo_documents = [
{%- if epub %}
# -- Options for Epub output ----------------------------------------------
# -- Options for Epub output -------------------------------------------------
# Bibliographic Dublin Core info.
epub_title = project
@ -200,18 +191,18 @@ epub_exclude_files = ['search.html']
{%- if extensions %}
# -- Extension configuration ----------------------------------------------
# -- Extension configuration -------------------------------------------------
{%- endif %}
{%- if 'sphinx.ext.intersphinx' in extensions %}
# -- Options for intersphinx extension ------------------------------------
# -- Options for intersphinx extension ---------------------------------------
# Example configuration for intersphinx: refer to the Python standard library.
intersphinx_mapping = {'https://docs.python.org/': None}
{%- endif %}
{%- 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.
todo_include_todos = True

View File

@ -8,8 +8,9 @@ if "%SPHINXBUILD%" == "" (
set SPHINXBUILD=sphinx-build
)
set BUILDDIR={{ rbuilddir }}
set ALLSPHINXOPTS=-d %BUILDDIR%/doctrees %SPHINXOPTS% {{ rsrcdir }}
set I18NSPHINXOPTS=%SPHINXOPTS% {{ rsrcdir }}
set SOURCEDIR={{ rsrcdir }}
set ALLSPHINXOPTS=-d %BUILDDIR%/doctrees %SPHINXOPTS% %SOURCEDIR%
set I18NSPHINXOPTS=%SPHINXOPTS% %SOURCEDIR%
if NOT "%PAPER%" == "" (
set ALLSPHINXOPTS=-D latex_elements.papersize=%PAPER% %ALLSPHINXOPTS%
set I18NSPHINXOPTS=-D latex_elements.papersize=%PAPER% %I18NSPHINXOPTS%
@ -50,7 +51,6 @@ if "%1" == "clean" (
goto end
)
REM Check if sphinx-build is available and fallback to Python version if any
%SPHINXBUILD% 1>NUL 2>NUL
if errorlevel 9009 goto sphinx_python
@ -74,92 +74,6 @@ if errorlevel 9009 (
: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" (
%SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex
cd %BUILDDIR%/latex
@ -180,96 +94,14 @@ if "%1" == "latexpdfja" (
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" (
%SPHINXBUILD% -b gettext %I18NSPHINXOPTS% %BUILDDIR%/locale
if errorlevel 1 exit /b 1
echo.
echo.Build finished. The message catalogs are in %BUILDDIR%/locale.
goto end
)
if "%1" == "changes" (
%SPHINXBUILD% -b changes %ALLSPHINXOPTS% %BUILDDIR%/changes
if errorlevel 1 exit /b 1
echo.
echo.The overview file is in %BUILDDIR%/changes.
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
)
%SPHINXBUILD% -b %1 %ALLSPHINXOPTS% %BUILDDIR%/%1
goto end
:end
popd

View File

@ -504,7 +504,7 @@
\fancyfoot[LE,RO]{{\py@HeaderFamily\thepage}}
\fancyfoot[LO]{{\py@HeaderFamily\nouppercase{\rightmark}}}
\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{\footrulewidth}{0.4pt}
% 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
% release to specify the release that is documented.
%
\newcommand{\py@release}{}
\newcommand{\version}{}
\newcommand{\shortversion}{}
\newcommand{\py@release}{\releasename\space\version}
\newcommand{\version}{}% part of \py@release, used by title page and headers
% \releaseinfo is used on titlepage (sphinxmanual.cls, sphinxhowto.cls)
\newcommand{\releaseinfo}{}
\newcommand{\releasename}{Release}
\newcommand{\release}[1]{%
\renewcommand{\py@release}{\releasename\space\version}%
\renewcommand{\version}{#1}}
\newcommand{\setshortversion}[1]{%
\renewcommand{\shortversion}{#1}}
\newcommand{\setreleaseinfo}[1]{%
\renewcommand{\releaseinfo}{#1}}
\newcommand{\setreleaseinfo}[1]{\renewcommand{\releaseinfo}{#1}}
% this is inserted via template and #1=release config variable
\newcommand{\release}[1]{\renewcommand{\version}{#1}}
% this is defined by template to 'releasename' latex_elements key
\newcommand{\releasename}{}
% Fix issue in case release and releasename deliberately left blank
\newcommand{\sphinxheadercomma}{, }% used in fancyhdr header definition
\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
% 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 %}
{%- macro script() %}
<script type="text/javascript">
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>
<script type="text/javascript" src="{{ pathto('_static/documentation_options.js', 1) }}"></script>
{%- for scriptfile in script_files %}
<script type="text/javascript" src="{{ pathto(scriptfile, 1) }}"></script>
{%- endfor %}

View File

@ -9,6 +9,8 @@
:license: BSD, see LICENSE for details.
"""
import re
from docutils import nodes
from docutils.transforms import Transform, Transformer
from docutils.transforms.parts import ContentsFilter
@ -391,3 +393,21 @@ class SphinxSmartQuotes(SmartQuotes, SphinxTransform):
for txtnode in txtnodes:
notsmartquotable = not is_smartquotable(txtnode)
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:
return '...'
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 annotation else repr(annotation))
if not 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':
return annotation.__qualname__ # type: ignore

View File

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

View File

@ -49,6 +49,7 @@ class HTML5Translator(BaseTranslator):
self.highlightopts = builder.config.highlight_options
self.highlightlinenothreshold = sys.maxsize
self.docnames = [builder.current_docname] # for singlehtml builder
self.manpages_url = builder.config.manpages_url
self.protect_literal_text = 0
self.permalink_text = builder.config.html_add_permalinks
# support backwards-compatible setting to a bool
@ -389,7 +390,7 @@ class HTML5Translator(BaseTranslator):
location=(self.builder.current_docname, node.line), **highlight_args
)
starttag = self.starttag(node, 'div', suffix='',
CLASS='highlight-%s' % lang)
CLASS='highlight-%s notranslate' % lang)
self.body.append(starttag + highlighted + '</div>\n')
raise nodes.SkipNode
@ -439,10 +440,10 @@ class HTML5Translator(BaseTranslator):
# type: (nodes.Node) -> None
if 'kbd' in node['classes']:
self.body.append(self.starttag(node, 'kbd', '',
CLASS='docutils literal'))
CLASS='docutils literal notranslate'))
else:
self.body.append(self.starttag(node, 'code', '',
CLASS='docutils literal'))
CLASS='docutils literal notranslate'))
self.protect_literal_text += 1
def depart_literal(self, node):
@ -758,9 +759,14 @@ class HTML5Translator(BaseTranslator):
def visit_manpage(self, node):
# type: (nodes.Node) -> None
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):
# type: (nodes.Node) -> None
if self.manpages_url:
self.depart_reference(node)
self.depart_literal_emphasis(node)
# 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
'indexname': _('Index'),
})
if not self.elements['releasename']:
if not self.elements['releasename'] and self.elements['release']:
self.elements.update({
'releasename': _('Release'),
})
@ -1376,6 +1376,9 @@ class LaTeXTranslator(nodes.NodeVisitor):
self.table = Table(node)
if 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
def depart_table(self, node):
@ -1853,28 +1856,14 @@ class LaTeXTranslator(nodes.NodeVisitor):
(node['align'] == 'right' and 'r' or 'l', length or '0pt'))
self.context.append(ids + '\\end{wrapfigure}\n')
elif self.in_minipage:
if ('align' not in node.attributes or
node.attributes['align'] == 'center'):
self.body.append('\n\\begin{center}')
self.context.append('\\end{center}\n')
else:
self.body.append('\n\\begin{flush%s}' % node.attributes['align'])
self.context.append('\\end{flush%s}\n' % node.attributes['align'])
self.body.append('\n\\begin{center}')
self.context.append('\\end{center}\n')
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))
self.body.append('\n\\begin{figure}[%s]\n\\centering\n' %
self.elements['figure_align'])
if any(isinstance(child, nodes.caption) for child in node):
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):
# type: (nodes.Node) -> None

View File

@ -183,6 +183,8 @@ class TextTranslator(nodes.NodeVisitor):
else:
self.nl = '\n'
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.stateindent = [0]
self.list_counter = [] # type: List[int]
@ -307,6 +309,17 @@ class TextTranslator(nodes.NodeVisitor):
raise nodes.SkipNode
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):
# type: (nodes.Node) -> None
if isinstance(node.parent, nodes.section):
@ -315,6 +328,8 @@ class TextTranslator(nodes.NodeVisitor):
char = '^'
text = None # type: unicode
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()
title = ['', text, '%s' % (char * column_width(text)), ''] # type: List[unicode]
if len(self.states) == 2 and len(self.states[-1]) == 0:
@ -987,7 +1002,10 @@ class TextTranslator(nodes.NodeVisitor):
def visit_reference(self, node):
# 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):
# type: (nodes.Node) -> None

View File

@ -1,5 +1,8 @@
.. toctree::
:numbered:
doc1
doc2
maxwidth
lineblock
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
from missing_package2 import missing_module2
from missing_package3.missing_module3 import missing_name
import sphinx.missing_module4
from sphinx.missing_module4 import missing_name2
@missing_name
def decoratedFunction():
@ -16,3 +18,5 @@ class TestAutodoc(object):
def decoratedMethod(self):
"""TestAutodoc::decoratedMethod docstring"""
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 = [
'missing_module',
'missing_package1.missing_module1',
'missing_package2.missing_module2',
'missing_package3.missing_module3',
'missing_package1',
'missing_package2',
'missing_package3',
'sphinx.missing_module4',
]
# modify tags from conf.py

View File

@ -163,21 +163,21 @@ def test_html_warnings(app, warning):
(".//pre/span", u'"quotes"'),
(".//pre/span", u"'included'"),
(".//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*$'),
(".//div[@class='inc-pyobj2 highlight-text']//pre",
(".//div[@class='inc-pyobj2 highlight-text notranslate']//pre",
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$'),
(".//div[@class='inc-startend highlight-text']//pre",
(".//div[@class='inc-startend highlight-text notranslate']//pre",
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$'),
(".//div[@class='inc-pyobj-dedent highlight-python']//span",
(".//div[@class='inc-pyobj-dedent highlight-python notranslate']//span",
r'def'),
(".//div[@class='inc-tab3 highlight-text']//pre",
(".//div[@class='inc-tab3 highlight-text notranslate']//pre",
r'-| |-'),
(".//div[@class='inc-tab8 highlight-python']//pre/span",
(".//div[@class='inc-tab8 highlight-python notranslate']//pre/span",
r'-| |-'),
],
'autodoc.html': [
@ -1243,3 +1243,16 @@ def test_html_sidebar(app, status, warning):
assert '<h3>Related Topics</h3>' not in result
assert '<h3>This Page</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"'included'"),
(".//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*$'),
(".//div[@class='inc-pyobj2 highlight-text']//pre",
(".//div[@class='inc-pyobj2 highlight-text notranslate']//pre",
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$'),
(".//div[@class='inc-startend highlight-text']//pre",
(".//div[@class='inc-startend highlight-text notranslate']//pre",
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$'),
(".//div[@class='inc-pyobj-dedent highlight-python']//span",
(".//div[@class='inc-pyobj-dedent highlight-python notranslate']//span",
r'def'),
(".//div[@class='inc-tab3 highlight-text']//pre",
(".//div[@class='inc-tab3 highlight-text notranslate']//pre",
r'-| |-'),
(".//div[@class='inc-tab8 highlight-python']//pre/span",
(".//div[@class='inc-tab8 highlight-python notranslate']//pre/span",
r'-| |-'),
],
'autodoc.html': [

View File

@ -165,13 +165,15 @@ def test_latex_warnings(app, status, warning):
@pytest.mark.sphinx('latex', testroot='basic')
def test_latex_title(app, status, warning):
def test_latex_basic(app, status, warning):
app.builder.build_all()
result = (app.outdir / 'test.tex').text(encoding='utf8')
print(result)
print(status.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')
@ -184,6 +186,18 @@ def test_latex_title_after_admonitions(app, status, warning):
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',
confoverrides={'numfig': True})
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):
app.builder.build_update()
result = (app.outdir / 'nonascii_title.txt').text(encoding='utf-8')
expect_underline = '******'
expect_underline = '*********'
result_underline = result.splitlines()[1].strip()
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[3] == ""
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.
"""
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
@ -26,19 +28,28 @@ def test_build(app, status, warning):
assert cleanup_called == 3, 'testcleanup did not get executed enough times'
def test_compare_version():
assert compare_version('3.3', '3.4', '<') is True
assert compare_version('3.3', '3.2', '<') is False
assert compare_version('3.3', '3.4', '<=') is True
assert compare_version('3.3', '3.2', '<=') is False
assert compare_version('3.3', '3.3', '==') is True
assert compare_version('3.3', '3.4', '==') is False
assert compare_version('3.3', '3.2', '>=') is True
assert compare_version('3.3', '3.4', '>=') is False
assert compare_version('3.3', '3.2', '>') is True
assert compare_version('3.3', '3.4', '>') is False
with pytest.raises(ValueError):
compare_version('3.3', '3.4', '+')
def test_is_allowed_version():
assert is_allowed_version('<3.4', '3.3') is True
assert is_allowed_version('<3.4', '3.3') is True
assert is_allowed_version('<3.2', '3.3') is False
assert is_allowed_version('<=3.4', '3.3') is True
assert is_allowed_version('<=3.2', '3.3') is False
assert is_allowed_version('==3.3', '3.3') is True
assert is_allowed_version('==3.4', '3.3') is False
assert is_allowed_version('>=3.2', '3.3') is True
assert is_allowed_version('>=3.4', '3.3') is False
assert is_allowed_version('>3.2', '3.3') is True
assert is_allowed_version('>3.4', '3.3') is False
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():

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()
assert ('<a class="reference external"'
' 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)
assert ('<a class="reference external"'
' href="https://docs.python.org/index.html#foons"'

View File

@ -35,17 +35,17 @@ def test_jsmath(app, status, warning):
app.builder.build_all()
content = (app.outdir / 'math.html').text()
assert '<div class="math">\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">\na^2 + b^2 = c^2</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" '
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" '
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)
assert '<div class="math">\nn \\in \\mathbb N</div>' in content
assert '<div class="math">\na + 1 &lt; b</div>' in content
assert '<div class="math notranslate">\nn \\in \\mathbb N</div>' in content
assert '<div class="math notranslate">\na + 1 &lt; b</div>' in content
@pytest.mark.skipif(not has_binary('dvipng'),
@ -89,7 +89,7 @@ def test_mathjax_align(app, status, warning):
app.builder.build_all()
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'V \&amp;= \\frac\{4\}\{3\} \\pi r\^3\\end\{aligned\}\\end\{align\} \\\]</div>')
assert re.search(html, content, re.S)
@ -102,7 +102,7 @@ def test_math_number_all_mathjax(app, status, warning):
app.builder.build_all()
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>')
assert re.search(html, content, re.S)
@ -167,7 +167,7 @@ def test_mathjax_numfig_html(app, status, warning):
app.builder.build_all()
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)')
assert html in content
html = ('<p>Referencing equation <a class="reference internal" '

View File

@ -143,8 +143,8 @@ def test_text_warning_node(app):
app.build()
# test warnings in translation
result = (app.outdir / 'warnings.txt').text(encoding='utf-8')
expect = (u"I18N WITH REST WARNINGS"
u"\n***********************\n"
expect = (u"3. I18N WITH REST WARNINGS"
u"\n**************************\n"
u"\nLINE OF >>``<<BROKEN LITERAL MARKUP.\n")
assert result == expect
@ -157,8 +157,8 @@ def test_text_title_underline(app):
app.build()
# --- simple translation; check title underlines
result = (app.outdir / 'bom.txt').text(encoding='utf-8')
expect = (u"Datei mit UTF-8"
u"\n***************\n" # underline matches new translation
expect = (u"2. Datei mit UTF-8"
u"\n******************\n" # underline matches new translation
u"\nThis file has umlauts: äöü.\n")
assert result == expect
@ -170,7 +170,7 @@ def test_text_subdirs(app):
app.build()
# --- check translation in subdirs
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
@ -180,8 +180,8 @@ def test_text_inconsistency_warnings(app, warning):
app.build()
# --- check warnings for inconsistency in number of references
result = (app.outdir / 'refs_inconsistency.txt').text(encoding='utf-8')
expect = (u"I18N WITH REFS INCONSISTENCY"
u"\n****************************\n"
expect = (u"8. I18N WITH REFS INCONSISTENCY"
u"\n*******************************\n"
u"\n* FOR CITATION [ref3].\n"
u"\n* reference FOR reference.\n"
u"\n* ORPHAN REFERENCE: I18N WITH REFS INCONSISTENCY.\n"
@ -230,8 +230,8 @@ def test_text_literalblock_warnings(app, warning):
app.build()
# --- check warning for literal block
result = (app.outdir / 'literalblock.txt').text(encoding='utf-8')
expect = (u"I18N WITH LITERAL BLOCK"
u"\n***********************\n"
expect = (u"9. I18N WITH LITERAL BLOCK"
u"\n**************************\n"
u"\nCORRECT LITERAL BLOCK:\n"
u"\n this is"
u"\n literal block\n"
@ -252,8 +252,8 @@ def test_text_definition_terms(app):
app.build()
# --- definition terms: regression test for #975, #2198, #2205
result = (app.outdir / 'definition_terms.txt').text(encoding='utf-8')
expect = (u"I18N WITH DEFINITION TERMS"
u"\n**************************\n"
expect = (u"13. I18N WITH DEFINITION TERMS"
u"\n******************************\n"
u"\nSOME TERM"
u"\n THE CORRESPONDING DEFINITION\n"
u"\nSOME *TERM* WITH LINK"
@ -273,8 +273,8 @@ def test_text_glossary_term(app, warning):
app.build()
# --- glossary terms: regression test for #1090
result = (app.outdir / 'glossary_terms.txt').text(encoding='utf-8')
expect = (u"I18N WITH GLOSSARY TERMS"
u"\n************************\n"
expect = (u"18. I18N WITH GLOSSARY TERMS"
u"\n****************************\n"
u"\nSOME NEW TERM"
u"\n THE CORRESPONDING GLOSSARY\n"
u"\nSOME OTHER NEW TERM"
@ -292,8 +292,8 @@ def test_text_glossary_term_inconsistencies(app, warning):
app.build()
# --- glossary term inconsistencies: regression test for #1090
result = (app.outdir / 'glossary_terms_inconsistency.txt').text(encoding='utf-8')
expect = (u"I18N WITH GLOSSARY TERMS INCONSISTENCY"
u"\n**************************************\n"
expect = (u"19. I18N WITH GLOSSARY TERMS INCONSISTENCY"
u"\n******************************************\n"
u"\n1. LINK TO *SOME NEW TERM*.\n")
assert result == expect
@ -313,8 +313,8 @@ def test_text_seealso(app):
app.build()
# --- seealso
result = (app.outdir / 'seealso.txt').text(encoding='utf-8')
expect = (u"I18N WITH SEEALSO"
u"\n*****************\n"
expect = (u"12. I18N WITH SEEALSO"
u"\n*********************\n"
u"\nSee also: SHORT TEXT 1\n"
u"\nSee also: LONG TEXT 1\n"
u"\nSee also: SHORT TEXT 2\n"
@ -329,34 +329,34 @@ def test_text_figure_captions(app):
app.build()
# --- figure captions: regression test for #940
result = (app.outdir / 'figure.txt').text(encoding='utf-8')
expect = (u"I18N WITH FIGURE CAPTION"
u"\n************************\n"
expect = (u"14. I18N WITH FIGURE CAPTION"
u"\n****************************\n"
u"\n [image]MY CAPTION OF THE FIGURE\n"
u"\n MY DESCRIPTION PARAGRAPH1 OF THE FIGURE.\n"
u"\n MY DESCRIPTION PARAGRAPH2 OF THE FIGURE.\n"
u"\n"
u"\nFIGURE IN THE BLOCK"
u"\n===================\n"
u"\n14.1. FIGURE IN THE BLOCK"
u"\n=========================\n"
u"\nBLOCK\n"
u"\n [image]MY CAPTION OF THE FIGURE\n"
u"\n MY DESCRIPTION PARAGRAPH1 OF THE FIGURE.\n"
u"\n MY DESCRIPTION PARAGRAPH2 OF THE FIGURE.\n"
u"\n"
u"\n"
u"IMAGE URL AND ALT\n"
u"=================\n"
u"14.2. IMAGE URL AND ALT\n"
u"=======================\n"
u"\n"
u"[image: i18n][image]\n"
u"\n"
u" [image: img][image]\n"
u"\n"
u"\n"
u"IMAGE ON SUBSTITUTION\n"
u"=====================\n"
u"14.3. IMAGE ON SUBSTITUTION\n"
u"===========================\n"
u"\n"
u"\n"
u"IMAGE UNDER NOTE\n"
u"================\n"
u"14.4. IMAGE UNDER NOTE\n"
u"======================\n"
u"\n"
u"Note: [image: i18n under note][image]\n"
u"\n"
@ -390,8 +390,8 @@ def test_text_docfields(app):
app.build()
# --- docfields
result = (app.outdir / 'docfields.txt').text(encoding='utf-8')
expect = (u"I18N WITH DOCFIELDS"
u"\n*******************\n"
expect = (u"21. I18N WITH DOCFIELDS"
u"\n***********************\n"
u"\nclass Cls1\n"
u"\n Parameters:"
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
'verify_re',
'``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>'),
r'\\sphinxcode{\\sphinxupquote{code sample}}',
),
@ -141,7 +141,7 @@ def get_verifier(verify, verify_re):
# correct interpretation of code with whitespace
'verify_re',
':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>'),
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)
'verify',
':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>'
'<span class="pre">c</span></code></p>'),
'\\sphinxcode{\\sphinxupquote{a\\sphinxstyleemphasis{b}c}}',
@ -173,7 +174,7 @@ def get_verifier(verify, verify_re):
# non-interpolation of dashes in option role
'verify_re',
':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>$'),
r'\\sphinxcode{\\sphinxupquote{-{-}with-option}}$',
),
@ -188,7 +189,7 @@ def get_verifier(verify, verify_re):
# ... but not in literal text
'verify',
'``"John"``',
('<p><code class="docutils literal"><span class="pre">'
('<p><code class="docutils literal notranslate"><span class="pre">'
'&quot;John&quot;</span></code></p>'),
'\\sphinxcode{\\sphinxupquote{"John"}}',
),

View File

@ -211,15 +211,15 @@ def test_Signature_annotations():
# Generic types with concrete parameters
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
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
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
sig = inspect.Signature(f4).format_args()
@ -239,14 +239,14 @@ def test_Signature_annotations():
# Callable types
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()
assert sig == '(x: typing.Callable) -> None'
assert sig == '(x: Callable) -> None'
# Tuple types
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
sig = inspect.Signature(f11).format_args()