Merge branch 'master' into 3698_migrate_docref_to_stddomain

This commit is contained in:
Takeshi KOMIYA 2017-05-07 14:44:30 +09:00 committed by GitHub
commit 64b2f292ff
36 changed files with 1773 additions and 1453 deletions

79
CHANGES
View File

@ -1,5 +1,5 @@
Release 1.6 beta3 (in development) Release 1.7 (in development)
================================== ============================
Incompatible changes Incompatible changes
-------------------- --------------------
@ -10,15 +10,73 @@ Deprecated
Features added Features added
-------------- --------------
- C++, handle ``decltype(auto)``.
- #2406: C++, add proper parsing of expressions, including linking of identifiers.
- C++, add a ``cpp:expr`` role for inserting inline C++ expressions or types.
Features removed
----------------
* Configuration variables
- html_use_smartypants
- latex_keep_old_macro_names
- latex_elements['footer']
* utility methods of ``sphinx.application.Sphinx`` class
- buildername (property)
- _display_chunk()
- old_status_iterator()
- status_iterator()
- _directive_helper()
* utility methods of ``sphinx.environment.BuildEnvironment`` class
- currmodule (property)
- currclass (property)
* epub2 builder
* prefix and colorfunc parameter for warn()
* ``sphinx.util.compat`` module
* ``sphinx.util.nodes.process_only_nodes()``
* LaTeX environment ``notice``, use ``sphinxadmonition`` instead
Bugs fixed
----------
Testing
--------
Release 1.6 beta3 (in development)
==================================
Incompatible changes
--------------------
* LaTeX package ``eqparbox`` is not used and not loaded by Sphinx anymore
* LaTeX package ``multirow`` is not used and not loaded by Sphinx anymore
Deprecated
----------
Features added
--------------
* ``LATEXMKOPTS`` variable for the Makefile in ``$BUILDDIR/latex`` to pass
options to ``latexmk`` when executing ``make latexpdf``. Default is ``-f``.
(refs #3695)
Bugs fixed Bugs fixed
---------- ----------
* #3588: No compact (p tag) html output in the i18n document build even when * #3588: No compact (p tag) html output in the i18n document build even when
:confval:`html_compact_lists` is True. :confval:`html_compact_lists` is True.
* The ``make latexpdf`` (which uses ``latexmk``) aborted earlier in case of * The ``make latexpdf`` from 1.6b1 (for GNU/Linux and Mac OS, using
LaTeX errors than was the case with 1.5 series. Now, ``LATEXMKOPTS`` ``latexmk``) aborted earlier in case of LaTeX errors than was the case with
variable is provided whose default value ``-f`` mimics former behaviour. 1.5 series, due to hard-coded usage of ``--halt-on-error`` option. (refs #3695)
(refs #3695) * #3683: sphinx.websupport module is not provided by default
* #3683: Failed to build document if builder.css_file.insert() is called
* #3698: Moving :doc: to std domain broke backwards compatibility * #3698: Moving :doc: to std domain broke backwards compatibility
Testing Testing
@ -244,6 +302,8 @@ Bugs fixed
* #3657: EPUB builder crashes if document startswith genindex exists * #3657: EPUB builder crashes if document startswith genindex exists
* #3588: No compact (p tag) html output in the i18n document build even when * #3588: No compact (p tag) html output in the i18n document build even when
:confval:`html_compact_lists` is True. :confval:`html_compact_lists` is True.
* #3685: AttributeError when using 3rd party domains
* #3702: LaTeX writer styles figure legends with a hard-coded ``\small``
Testing Testing
-------- --------
@ -444,10 +504,8 @@ Incompatible changes
* QtHelpBuilder doens't generate search page (ref: #2352) * QtHelpBuilder doens't generate search page (ref: #2352)
* QtHelpBuilder uses ``nonav`` theme instead of default one * QtHelpBuilder uses ``nonav`` theme instead of default one
to improve readability. to improve readability.
* latex: To provide good default settings to Japanese docs, Sphinx uses ``jsbook`` * latex: To provide good default settings to Japanese documents, Sphinx uses
as a docclass by default if the ``language`` is ``ja``. ``jreport`` and ``jsbook`` as docclass if :confval:`language` is
* latex: To provide good default settings to Japanese docs, Sphinx uses
``jreport`` and ``jsbooks`` as a docclass by default if the ``language`` is
``ja``. ``ja``.
* ``sphinx-quickstart`` now allows a project version is empty * ``sphinx-quickstart`` now allows a project version is empty
* Fix :download: role on epub/qthelp builder. They ignore the role because they don't support it. * Fix :download: role on epub/qthelp builder. They ignore the role because they don't support it.
@ -487,6 +545,7 @@ Incompatible changes
* Emit warnings that will be deprecated in Sphinx 1.6 by default. * Emit warnings that will be deprecated in Sphinx 1.6 by default.
Users can change the behavior by setting the environment variable Users can change the behavior by setting the environment variable
PYTHONWARNINGS. Please refer :ref:`when-deprecation-warnings-are-displayed`. PYTHONWARNINGS. Please refer :ref:`when-deprecation-warnings-are-displayed`.
* #2454: new JavaScript variable ``SOURCELINK_SUFFIX`` is added
Deprecated Deprecated
---------- ----------

View File

@ -167,11 +167,6 @@ html_static_path = ['_static']
# #
# html_last_updated_fmt = None # html_last_updated_fmt = None
# If true, SmartyPants will be used to convert quotes and dashes to
# typographically correct entities.
#
# html_use_smartypants = True
# Custom sidebar templates, maps document names to template names. # Custom sidebar templates, maps document names to template names.
# #
# html_sidebars = {} # html_sidebars = {}
@ -280,12 +275,6 @@ latex_documents = [
# #
# latex_appendices = [] # latex_appendices = []
# If false, will not define \strong, \code, \titleref, \crossref ... but only
# \sphinxstrong, ..., \sphinxtitleref, ... to help avoid clash with user added
# packages.
#
# latex_keep_old_macro_names = True
# If false, no module index is generated. # If false, no module index is generated.
# #
# latex_domain_indices = True # latex_domain_indices = True

View File

@ -125,26 +125,6 @@ The builder's "name" must be given to the **-b** command-line option of
.. autoattribute:: supported_image_types .. autoattribute:: supported_image_types
.. module:: sphinx.builders.epub2
.. class:: Epub2Builder
This builder produces the same output as the standalone HTML builder, but
also generates an *epub* file for ebook readers. See :ref:`epub-faq` for
details about it. For definition of the epub format, have a look at
`<http://idpf.org/epub>`_ or `<https://en.wikipedia.org/wiki/EPUB>`_.
The builder creates *EPUB 2* files.
.. autoattribute:: name
.. autoattribute:: format
.. autoattribute:: supported_image_types
.. deprecated:: 1.5
Since Sphinx-1.5, the epub3 builder is used for the default builder of epub.
Now EpubBuilder is renamed to epub2.
.. module:: sphinx.builders.epub3 .. module:: sphinx.builders.epub3
.. class:: Epub3Builder .. class:: Epub3Builder

View File

@ -50,6 +50,9 @@ Important points to note:
Note that the current builder tag is not available in ``conf.py``, as it is Note that the current builder tag is not available in ``conf.py``, as it is
created *after* the builder is initialized. created *after* the builder is initialized.
.. seealso:: Additional configurations, such as adding stylesheets,
javascripts, builders, etc. can be made through the :doc:`/extdev/appapi`.
General configuration General configuration
--------------------- ---------------------
@ -762,18 +765,6 @@ that use Sphinx's HTMLWriter class.
The empty string is equivalent to ``'%b %d, %Y'`` (or a The empty string is equivalent to ``'%b %d, %Y'`` (or a
locale-dependent equivalent). locale-dependent equivalent).
.. confval:: html_use_smartypants
If true, `SmartyPants <http://daringfireball.net/projects/smartypants/>`_
will be used to convert quotes and dashes to typographically correct
entities. Default: ``True``.
.. deprecated:: 1.6
Use the `smart_quotes option`_ in the Docutils configuration file
(``docutils.conf``) instead.
.. _`smart_quotes option`: http://docutils.sourceforge.net/docs/user/config.html#smart-quotes
.. confval:: html_add_permalinks .. confval:: html_add_permalinks
Sphinx will add "permalinks" for each heading and description environment as Sphinx will add "permalinks" for each heading and description environment as
@ -1618,26 +1609,6 @@ These options influence LaTeX output. See further :doc:`latex`.
value selected the ``'inline'`` display. For backwards compatibility, value selected the ``'inline'`` display. For backwards compatibility,
``True`` is still accepted. ``True`` is still accepted.
.. confval:: latex_keep_old_macro_names
If ``True`` the ``\strong``, ``\code``, ``\bfcode``, ``\email``,
``\tablecontinued``, ``\titleref``, ``\menuselection``, ``\accelerator``,
``\crossref``, ``\termref``, and ``\optional`` text styling macros are
pre-defined by Sphinx and may be user-customized by some
``\renewcommand``'s inserted either via ``'preamble'`` key or :dudir:`raw
<raw-data-pass-through>` directive. If ``False``, only ``\sphinxstrong``,
etc... macros are defined (and may be redefined by user).
The default is ``False`` as it prevents macro name conflicts caused by
latex packages. For example (``lualatex`` or ``xelatex``) ``fontspec v2.6``
has its own ``\strong`` macro.
.. versionadded:: 1.4.5
.. versionchanged:: 1.6
Default was changed from ``True`` to ``False``.
.. deprecated:: 1.6
This setting will be removed at Sphinx 1.7.
.. confval:: latex_use_latex_multicolumn .. confval:: latex_use_latex_multicolumn
If ``False`` (default), the LaTeX writer uses for merged cells in grid If ``False`` (default), the LaTeX writer uses for merged cells in grid

View File

@ -563,7 +563,7 @@ a visibility statement (``public``, ``private`` or ``protected``).
.. cpp:class:: OuterScope::MyClass : public MyBase, MyOtherBase .. cpp:class:: OuterScope::MyClass : public MyBase, MyOtherBase
A template class can be declared:: A class template can be declared::
.. cpp:class:: template<typename T, std::size_t N> std::array .. cpp:class:: template<typename T, std::size_t N> std::array
@ -728,6 +728,17 @@ a visibility statement (``public``, ``private`` or ``protected``).
Proxy to an element of a notional sequence that can be compared, Proxy to an element of a notional sequence that can be compared,
indirected, or incremented. indirected, or incremented.
**Notation**
.. cpp:var:: It r
An lvalue.
**Valid Expressions**
- :cpp:expr:`*r`, when :cpp:expr:`r` is dereferenceable.
- :cpp:expr:`++r`, with return type :cpp:expr:`It&`, when :cpp:expr:`r` is incrementable.
.. cpp:concept:: template<typename Cont> std::Container() .. cpp:concept:: template<typename Cont> std::Container()
Holder of elements, to which it can provide access via Holder of elements, to which it can provide access via
@ -740,6 +751,17 @@ a visibility statement (``public``, ``private`` or ``protected``).
Proxy to an element of a notional sequence that can be compared, Proxy to an element of a notional sequence that can be compared,
indirected, or incremented. indirected, or incremented.
**Notation**
.. cpp:var:: It r
An lvalue.
**Valid Expressions**
- :cpp:expr:`*r`, when :cpp:expr:`r` is dereferenceable.
- :cpp:expr:`++r`, with return type :cpp:expr:`It&`, when :cpp:expr:`r` is incrementable.
.. cpp:concept:: template<typename Cont> std::Container() .. cpp:concept:: template<typename Cont> std::Container()
Holder of elements, to which it can provide access via Holder of elements, to which it can provide access via
@ -807,6 +829,30 @@ compatibility. E.g., ``Iterator{A, B, C}`` will be accepted as an introduction
even though it would not be valid C++. even though it would not be valid C++.
Inline Expressions and Tpes
~~~~~~~~~~~~~~~~~~~~~~~~~~~
.. rst:role:: cpp:expr
A role for inserting a C++ expression or type as inline text.
For example::
.. cpp:var:: int a = 42
.. cpp:function:: int f(int i)
An expression: :cpp:expr:`a * f(a)`.
A type: :cpp:expr:`const MySortedContainer<int>&`.
will be rendered as follows:
.. cpp:var:: int a = 42
.. cpp:function:: int f(int i)
An expression: :cpp:expr:`a * f(a)`.
A type: :cpp:expr:`const MySortedContainer<int>&`.
Namespacing Namespacing
~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~
@ -842,7 +888,7 @@ directive.
.. cpp:function:: std::size_t size() const .. cpp:function:: std::size_t size() const
declares ``size`` as a member function of the template class ``std::vector``. declares ``size`` as a member function of the class template ``std::vector``.
Equivalently this could have been declared using:: Equivalently this could have been declared using::
.. cpp:class:: template<typename T> \ .. cpp:class:: template<typename T> \
@ -922,7 +968,7 @@ These roles link to the given declaration types:
.. admonition:: Note on References with Templates Parameters/Arguments .. admonition:: Note on References with Templates Parameters/Arguments
Sphinx's syntax to give references a custom title can interfere with Sphinx's syntax to give references a custom title can interfere with
linking to template classes, if nothing follows the closing angle linking to class templates, if nothing follows the closing angle
bracket, i.e. if the link looks like this: ``:cpp:class:`MyClass<int>```. bracket, i.e. if the link looks like this: ``:cpp:class:`MyClass<int>```.
This is interpreted as a link to ``int`` with a title of ``MyClass``. This is interpreted as a link to ``int`` with a title of ``MyClass``.
In this case, please escape the opening angle bracket with a backslash, In this case, please escape the opening angle bracket with a backslash,
@ -961,7 +1007,7 @@ In general the reference must include the template paraemter declarations, e.g.,
Currently the lookup only succeed if the template parameter identifiers are equal strings. That is, Currently the lookup only succeed if the template parameter identifiers are equal strings. That is,
``template\<typename UOuter> Wrapper::Outer`` will not work. ``template\<typename UOuter> Wrapper::Outer`` will not work.
The inner template class can not be directly referenced, unless the current namespace The inner class template can not be directly referenced, unless the current namespace
is changed or the following shorthand is used. is changed or the following shorthand is used.
If a template parameter list is omitted, then the lookup will assume either a template or a non-template, If a template parameter list is omitted, then the lookup will assume either a template or a non-template,
but not a partial template specialisation. but not a partial template specialisation.

View File

@ -480,6 +480,18 @@ The :program:`sphinx-apidoc` script has several options:
With this option given, no files will be written at all. With this option given, no files will be written at all.
.. option:: -e, --separate
Put documentation for each module on its own page.
.. versionadded:: 1.2
.. option:: -P, --private
Include "_private" modules.
.. versionadded:: 1.2
.. option:: -s suffix .. option:: -s suffix
This option selects the file name suffix of output files. By default, this This option selects the file name suffix of output files. By default, this
@ -505,6 +517,13 @@ The :program:`sphinx-apidoc` script has several options:
This prevents the generation of a table-of-contents file ``modules.rst``. This prevents the generation of a table-of-contents file ``modules.rst``.
This has no effect when :option:`--full` is given. This has no effect when :option:`--full` is given.
.. option:: -E, --no-headings
Don't create headings for the module/package packages (e.g. when the
docstrings already contain them).
.. versionadded:: 1.2
.. option:: -F, --full .. option:: -F, --full
This option makes sphinx-apidoc create a full Sphinx project, using the same This option makes sphinx-apidoc create a full Sphinx project, using the same

View File

@ -414,19 +414,7 @@ Let us now list some macros from the package file
- text styling commands (they have one argument): ``\sphinx<foo>`` with - text styling commands (they have one argument): ``\sphinx<foo>`` with
``<foo>`` being one of ``strong``, ``bfcode``, ``email``, ``tablecontinued``, ``<foo>`` being one of ``strong``, ``bfcode``, ``email``, ``tablecontinued``,
``titleref``, ``menuselection``, ``accelerator``, ``crossref``, ``termref``, ``titleref``, ``menuselection``, ``accelerator``, ``crossref``, ``termref``,
``optional``. The non-prefixed macros will still be defined if option ``optional``.
:confval:`latex_keep_old_macro_names` has been set to ``True`` (default is
``False``), in which case the prefixed macros expand to the
non-prefixed ones.
.. versionadded:: 1.4.5
Use of ``\sphinx`` prefixed macro names to limit possibilities of conflict
with LaTeX packages.
.. versionchanged:: 1.6
The default value of :confval:`latex_keep_old_macro_names` changes to
``False``, and even if set to ``True``, if a non-prefixed macro
already exists at ``sphinx.sty`` loading time, only the ``\sphinx``
prefixed one will be defined. The setting will be removed at 1.7.
- more text styling commands: ``\sphinxstyle<bar>`` with ``<bar>`` one of - more text styling commands: ``\sphinxstyle<bar>`` with ``<bar>`` one of
``indexentry``, ``indexextra``, ``indexpageref``, ``topictitle``, ``indexentry``, ``indexextra``, ``indexpageref``, ``topictitle``,
@ -438,7 +426,14 @@ Let us now list some macros from the package file
the new macros are wrappers of the formerly hard-coded ``\texttt``, the new macros are wrappers of the formerly hard-coded ``\texttt``,
``\emph``, ... The default definitions can be found in ``\emph``, ... The default definitions can be found in
:file:`sphinx.sty`. :file:`sphinx.sty`.
- paragraph level environments: for each admonition type ``<foo>``, the - a :dudir:`figure` may have an optional legend with arbitrary body
elements: they are rendered in a ``sphinxlegend`` environment. The default
definition issues ``\small``, and ends with ``\par``.
.. versionadded:: 1.5.6
formerly, the ``\small`` was hardcoded in LaTeX writer and the ending
``\par`` was lacking.
- for each admonition type ``<foo>``, the
used environment is named ``sphinx<foo>``. They may be ``\renewenvironment`` used environment is named ``sphinx<foo>``. They may be ``\renewenvironment``
'd individually, and must then be defined with one argument (it is the heading 'd individually, and must then be defined with one argument (it is the heading
of the notice, for example ``Warning:`` for :dudir:`warning` directive, if of the notice, for example ``Warning:`` for :dudir:`warning` directive, if

View File

@ -53,6 +53,7 @@ requires = [
'requests>=2.0.0', 'requests>=2.0.0',
'typing', 'typing',
'setuptools', 'setuptools',
'sphinxcontrib-websupport',
] ]
extras_require = { extras_require = {
# Environment Marker works for wheel 0.24 or later # Environment Marker works for wheel 0.24 or later
@ -60,7 +61,8 @@ extras_require = {
'colorama>=0.3.5', 'colorama>=0.3.5',
], ],
'websupport': [ 'websupport': [
'sphinxcontrib-websupport', 'sqlalchemy>=0.9',
'whoosh>=2.0',
], ],
'test': [ 'test': [
'pytest', 'pytest',

View File

@ -34,13 +34,13 @@ if 'PYTHONWARNINGS' not in os.environ:
warnings.filterwarnings('ignore', "'U' mode is deprecated", warnings.filterwarnings('ignore', "'U' mode is deprecated",
DeprecationWarning, module='docutils.io') DeprecationWarning, module='docutils.io')
__version__ = '1.6+' __version__ = '1.7+'
__released__ = '1.6' # used when Sphinx builds its own docs __released__ = '1.7' # used when Sphinx builds its own docs
# version info for better programmatic use # version info for better programmatic use
# possible values for 3rd element: 'alpha', 'beta', 'rc', 'final' # possible values for 3rd element: 'alpha', 'beta', 'rc', 'final'
# 'final' has 0 as the last element # 'final' has 0 as the last element
version_info = (1, 6, 0, 'beta', 3) version_info = (1, 7, 0, 'beta', 0)
package_dir = path.abspath(path.dirname(__file__)) package_dir = path.abspath(path.dirname(__file__))

View File

@ -29,7 +29,7 @@ import sphinx
from sphinx import package_dir, locale from sphinx import package_dir, locale
from sphinx.config import Config from sphinx.config import Config
from sphinx.errors import ConfigError, ExtensionError, VersionRequirementError from sphinx.errors import ConfigError, ExtensionError, VersionRequirementError
from sphinx.deprecation import RemovedInSphinx17Warning, RemovedInSphinx20Warning from sphinx.deprecation import RemovedInSphinx20Warning
from sphinx.environment import BuildEnvironment from sphinx.environment import BuildEnvironment
from sphinx.events import EventManager from sphinx.events import EventManager
from sphinx.extension import verify_required_extensions from sphinx.extension import verify_required_extensions
@ -39,10 +39,9 @@ from sphinx.registry import SphinxComponentRegistry
from sphinx.util import pycompat # noqa: F401 from sphinx.util import pycompat # noqa: F401
from sphinx.util import import_object from sphinx.util import import_object
from sphinx.util import logging from sphinx.util import logging
from sphinx.util import status_iterator, old_status_iterator, display_chunk
from sphinx.util.tags import Tags from sphinx.util.tags import Tags
from sphinx.util.osutil import ENOENT from sphinx.util.osutil import ENOENT
from sphinx.util.console import bold, darkgreen # type: ignore from sphinx.util.console import bold # type: ignore
from sphinx.util.docutils import is_html5_writer_available, directive_helper from sphinx.util.docutils import is_html5_writer_available, directive_helper
from sphinx.util.i18n import find_catalog_source_files from sphinx.util.i18n import find_catalog_source_files
@ -60,7 +59,6 @@ if False:
builtin_extensions = ( builtin_extensions = (
'sphinx.builders.applehelp', 'sphinx.builders.applehelp',
'sphinx.builders.changes', 'sphinx.builders.changes',
'sphinx.builders.epub2',
'sphinx.builders.epub3', 'sphinx.builders.epub3',
'sphinx.builders.devhelp', 'sphinx.builders.devhelp',
'sphinx.builders.dummy', 'sphinx.builders.dummy',
@ -315,13 +313,6 @@ class Sphinx(object):
for node, settings in iteritems(self.enumerable_nodes): for node, settings in iteritems(self.enumerable_nodes):
self.env.get_domain('std').enumerable_nodes[node] = settings # type: ignore self.env.get_domain('std').enumerable_nodes[node] = settings # type: ignore
@property
def buildername(self):
# type: () -> unicode
warnings.warn('app.buildername is deprecated. Please use app.builder.name instead',
RemovedInSphinx17Warning)
return self.builder.name
# ---- main "build" method ------------------------------------------------- # ---- main "build" method -------------------------------------------------
def build(self, force_all=False, filenames=None): def build(self, force_all=False, filenames=None):
@ -357,31 +348,15 @@ class Sphinx(object):
self.builder.cleanup() self.builder.cleanup()
# ---- logging handling ---------------------------------------------------- # ---- logging handling ----------------------------------------------------
def warn(self, message, location=None, prefix=None, def warn(self, message, location=None, type=None, subtype=None):
type=None, subtype=None, colorfunc=None): # type: (unicode, unicode, unicode, unicode) -> None
# type: (unicode, unicode, unicode, unicode, unicode, Callable) -> None
"""Emit a warning. """Emit a warning.
If *location* is given, it should either be a tuple of (docname, lineno) If *location* is given, it should either be a tuple of (docname, lineno)
or a string describing the location of the warning as well as possible. or a string describing the location of the warning as well as possible.
*prefix* usually should not be changed.
*type* and *subtype* are used to suppress warnings with :confval:`suppress_warnings`. *type* and *subtype* are used to suppress warnings with :confval:`suppress_warnings`.
.. note::
For warnings emitted during parsing, you should use
:meth:`.BuildEnvironment.warn` since that will collect all
warnings during parsing for later output.
""" """
if prefix:
warnings.warn('prefix option of warn() is now deprecated.',
RemovedInSphinx17Warning)
if colorfunc:
warnings.warn('colorfunc option of warn() is now deprecated.',
RemovedInSphinx17Warning)
warnings.warn('app.warning() is now deprecated. Use sphinx.util.logging instead.', warnings.warn('app.warning() is now deprecated. Use sphinx.util.logging instead.',
RemovedInSphinx20Warning) RemovedInSphinx20Warning)
logger.warning(message, type=type, subtype=subtype, location=location) logger.warning(message, type=type, subtype=subtype, location=location)
@ -418,34 +393,6 @@ class Sphinx(object):
RemovedInSphinx20Warning) RemovedInSphinx20Warning)
logger.debug(message, *args, **kwargs) logger.debug(message, *args, **kwargs)
def _display_chunk(chunk):
# type: (Any) -> unicode
warnings.warn('app._display_chunk() is now deprecated. '
'Use sphinx.util.display_chunk() instead.',
RemovedInSphinx17Warning)
return display_chunk(chunk)
def old_status_iterator(self, iterable, summary, colorfunc=darkgreen,
stringify_func=display_chunk):
# type: (Iterable, unicode, Callable, Callable[[Any], unicode]) -> Iterator
warnings.warn('app.old_status_iterator() is now deprecated. '
'Use sphinx.util.status_iterator() instead.',
RemovedInSphinx17Warning)
for item in old_status_iterator(iterable, summary,
color="darkgreen", stringify_func=stringify_func):
yield item
# new version with progress info
def status_iterator(self, iterable, summary, colorfunc=darkgreen, length=0,
stringify_func=_display_chunk):
# type: (Iterable, unicode, Callable, int, Callable[[Any], unicode]) -> Iterable
warnings.warn('app.status_iterator() is now deprecated. '
'Use sphinx.util.status_iterator() instead.',
RemovedInSphinx17Warning)
for item in status_iterator(iterable, summary, length=length, verbosity=self.verbosity,
color="darkgreen", stringify_func=stringify_func):
yield item
# ---- general extensibility interface ------------------------------------- # ---- general extensibility interface -------------------------------------
def setup_extension(self, extname): def setup_extension(self, extname):
@ -567,13 +514,6 @@ class Sphinx(object):
self.enumerable_nodes[node] = (figtype, title_getter) self.enumerable_nodes[node] = (figtype, title_getter)
self.add_node(node, **kwds) self.add_node(node, **kwds)
def _directive_helper(self, obj, has_content=None, argument_spec=None, **option_spec):
# type: (Any, bool, Tuple[int, int, bool], Any) -> Any
warnings.warn('_directive_helper() is now deprecated. '
'Please use sphinx.util.docutils.directive_helper() instead.',
RemovedInSphinx17Warning)
return directive_helper(obj, has_content, argument_spec, **option_spec)
def add_directive(self, name, obj, content=None, arguments=None, **options): def add_directive(self, name, obj, content=None, arguments=None, **options):
# type: (unicode, Any, bool, Tuple[int, int, bool], Any) -> None # type: (unicode, Any, bool, Tuple[int, int, bool], Any) -> None
logger.debug('[app] adding directive: %r', logger.debug('[app] adding directive: %r',

View File

@ -91,9 +91,6 @@ class Builder(object):
self.tags.add(self.name) self.tags.add(self.name)
self.tags.add("format_%s" % self.format) self.tags.add("format_%s" % self.format)
self.tags.add("builder_%s" % self.name) self.tags.add("builder_%s" % self.name)
# compatibility aliases
self.status_iterator = app.status_iterator
self.old_status_iterator = app.old_status_iterator
# images that need to be copied over (source -> dest) # images that need to be copied over (source -> dest)
self.images = {} # type: Dict[unicode, unicode] self.images = {} # type: Dict[unicode, unicode]

View File

@ -1,100 +0,0 @@
# -*- coding: utf-8 -*-
"""
sphinx.builders.epub2
~~~~~~~~~~~~~~~~~~~~~
Build epub2 files.
Originally derived from qthelp.py.
:copyright: Copyright 2007-2016 by the Sphinx team, see AUTHORS.
:license: BSD, see LICENSE for details.
"""
import warnings
from os import path
from sphinx import package_dir
from sphinx.builders import _epub_base
from sphinx.util.osutil import make_filename
from sphinx.deprecation import RemovedInSphinx17Warning
if False:
# For type annotation
from typing import Any, Dict # NOQA
from sphinx.application import Sphinx # NOQA
DOCTYPE = '''<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">'''
# The epub publisher
class Epub2Builder(_epub_base.EpubBuilder):
"""
Builder that outputs epub files.
It creates the metainfo files container.opf, toc.ncx, mimetype, and
META-INF/container.xml. Afterwards, all necessary files are zipped to an
epub file.
"""
name = 'epub2'
template_dir = path.join(package_dir, 'templates', 'epub2')
doctype = DOCTYPE
# Finish by building the epub file
def handle_finish(self):
# type: () -> None
"""Create the metainfo files and finally the epub."""
self.get_toc()
self.build_mimetype(self.outdir, 'mimetype')
self.build_container(self.outdir, 'META-INF/container.xml')
self.build_content(self.outdir, 'content.opf')
self.build_toc(self.outdir, 'toc.ncx')
self.build_epub(self.outdir, self.config.epub_basename + '.epub')
def emit_deprecation_warning(app):
# type: (Sphinx) -> None
if app.builder.__class__ is Epub2Builder:
warnings.warn('epub2 builder is deprecated. Please use epub3 builder instead.',
RemovedInSphinx17Warning)
def setup(app):
# type: (Sphinx) -> Dict[unicode, Any]
app.setup_extension('sphinx.builders.html')
app.add_builder(Epub2Builder)
app.connect('builder-inited', emit_deprecation_warning)
# config values
app.add_config_value('epub_basename', lambda self: make_filename(self.project), None)
app.add_config_value('epub_theme', 'epub', 'html')
app.add_config_value('epub_theme_options', {}, 'html')
app.add_config_value('epub_title', lambda self: self.html_title, 'html')
app.add_config_value('epub_author', 'unknown', 'html')
app.add_config_value('epub_language', lambda self: self.language or 'en', 'html')
app.add_config_value('epub_publisher', 'unknown', 'html')
app.add_config_value('epub_copyright', lambda self: self.copyright, 'html')
app.add_config_value('epub_identifier', 'unknown', 'html')
app.add_config_value('epub_scheme', 'unknown', 'html')
app.add_config_value('epub_uid', 'unknown', 'env')
app.add_config_value('epub_cover', (), 'env')
app.add_config_value('epub_guide', (), 'env')
app.add_config_value('epub_pre_files', [], 'env')
app.add_config_value('epub_post_files', [], 'env')
app.add_config_value('epub_exclude_files', [], 'env')
app.add_config_value('epub_tocdepth', 3, 'env')
app.add_config_value('epub_tocdup', True, 'env')
app.add_config_value('epub_tocscope', 'default', 'env')
app.add_config_value('epub_fix_images', False, 'env')
app.add_config_value('epub_max_image_width', 0, 'env')
app.add_config_value('epub_show_urls', 'inline', 'html')
app.add_config_value('epub_use_index', lambda self: self.html_use_index, 'html')
return {
'version': 'builtin',
'parallel_read_safe': True,
'parallel_write_safe': True,
}

View File

@ -19,6 +19,7 @@ from sphinx.config import string_classes, ENUM
from sphinx.builders import _epub_base from sphinx.builders import _epub_base
from sphinx.util import logging from sphinx.util import logging
from sphinx.util.fileutil import copy_asset_file from sphinx.util.fileutil import copy_asset_file
from sphinx.util.osutil import make_filename
if False: if False:
# For type annotation # For type annotation
@ -225,12 +226,32 @@ class Epub3Builder(_epub_base.EpubBuilder):
def setup(app): def setup(app):
# type: (Sphinx) -> Dict[unicode, Any] # type: (Sphinx) -> Dict[unicode, Any]
app.setup_extension('sphinx.builders.epub2')
app.add_builder(Epub3Builder) app.add_builder(Epub3Builder)
# config values # config values
app.add_config_value('epub_basename', lambda self: make_filename(self.project), None)
app.add_config_value('epub_theme', 'epub', 'html')
app.add_config_value('epub_theme_options', {}, 'html')
app.add_config_value('epub_title', lambda self: self.html_title, 'html')
app.add_config_value('epub_author', 'unknown', 'html')
app.add_config_value('epub_language', lambda self: self.language or 'en', 'html')
app.add_config_value('epub_publisher', 'unknown', 'html')
app.add_config_value('epub_copyright', lambda self: self.copyright, 'html')
app.add_config_value('epub_identifier', 'unknown', 'html')
app.add_config_value('epub_scheme', 'unknown', 'html')
app.add_config_value('epub_uid', 'unknown', 'env')
app.add_config_value('epub_cover', (), 'env')
app.add_config_value('epub_guide', (), 'env')
app.add_config_value('epub_pre_files', [], 'env')
app.add_config_value('epub_post_files', [], 'env')
app.add_config_value('epub_exclude_files', [], 'env')
app.add_config_value('epub_tocdepth', 3, 'env')
app.add_config_value('epub_tocdup', True, 'env')
app.add_config_value('epub_tocscope', 'default', 'env')
app.add_config_value('epub_fix_images', False, 'env')
app.add_config_value('epub_max_image_width', 0, 'env')
app.add_config_value('epub_show_urls', 'inline', 'html')
app.add_config_value('epub_use_index', lambda self: self.html_use_index, 'html')
app.add_config_value('epub_description', 'unknown', 'epub3', string_classes) app.add_config_value('epub_description', 'unknown', 'epub3', string_classes)
app.add_config_value('epub_contributor', 'unknown', 'epub3', string_classes) app.add_config_value('epub_contributor', 'unknown', 'epub3', string_classes)
app.add_config_value('epub_writing_mode', 'horizontal', 'epub3', app.add_config_value('epub_writing_mode', 'horizontal', 'epub3',

View File

@ -100,6 +100,15 @@ class CSSContainer(list):
else: else:
super(CSSContainer, self).append(Stylesheet(obj, None, 'stylesheet')) super(CSSContainer, self).append(Stylesheet(obj, None, 'stylesheet'))
def insert(self, index, obj):
warnings.warn('builder.css_files is deprecated. '
'Please use app.add_stylesheet() instead.',
RemovedInSphinx20Warning)
if isinstance(obj, Stylesheet):
super(CSSContainer, self).insert(index, obj)
else:
super(CSSContainer, self).insert(index, Stylesheet(obj, None, 'stylesheet'))
def extend(self, other): def extend(self, other):
warnings.warn('builder.css_files is deprecated. ' warnings.warn('builder.css_files is deprecated. '
'Please use app.add_stylesheet() instead.', 'Please use app.add_stylesheet() instead.',
@ -1346,7 +1355,6 @@ def setup(app):
app.add_config_value('html_static_path', [], 'html') app.add_config_value('html_static_path', [], 'html')
app.add_config_value('html_extra_path', [], 'html') app.add_config_value('html_extra_path', [], 'html')
app.add_config_value('html_last_updated_fmt', None, 'html', string_classes) app.add_config_value('html_last_updated_fmt', None, 'html', string_classes)
app.add_config_value('html_use_smartypants', None, 'html')
app.add_config_value('html_sidebars', {}, 'html') app.add_config_value('html_sidebars', {}, 'html')
app.add_config_value('html_additional_pages', {}, 'html') app.add_config_value('html_additional_pages', {}, 'html')
app.add_config_value('html_domain_indices', True, 'html', [list]) app.add_config_value('html_domain_indices', True, 'html', [list])

View File

@ -10,7 +10,6 @@
""" """
import os import os
import warnings
from os import path from os import path
from docutils import nodes from docutils import nodes
@ -19,7 +18,6 @@ from docutils.utils import new_document
from docutils.frontend import OptionParser from docutils.frontend import OptionParser
from sphinx import package_dir, addnodes, highlighting from sphinx import package_dir, addnodes, highlighting
from sphinx.deprecation import RemovedInSphinx17Warning
from sphinx.config import string_classes, ENUM from sphinx.config import string_classes, ENUM
from sphinx.errors import SphinxError from sphinx.errors import SphinxError
from sphinx.locale import _ from sphinx.locale import _
@ -250,29 +248,6 @@ class LaTeXBuilder(Builder):
path.join(self.srcdir, src), err) path.join(self.srcdir, src), err)
def validate_config_values(app):
# type: (Sphinx) -> None
if app.config.latex_toplevel_sectioning not in (None, 'part', 'chapter', 'section'):
logger.warning('invalid latex_toplevel_sectioning, ignored: %s',
app.config.latex_toplevel_sectioning)
app.config.latex_toplevel_sectioning = None # type: ignore
if 'footer' in app.config.latex_elements:
if 'postamble' in app.config.latex_elements:
logger.warning("latex_elements['footer'] conflicts with "
"latex_elements['postamble'], ignored.")
else:
warnings.warn("latex_elements['footer'] is deprecated. "
"Use latex_elements['preamble'] instead.",
RemovedInSphinx17Warning)
app.config.latex_elements['postamble'] = app.config.latex_elements['footer']
if app.config.latex_keep_old_macro_names:
warnings.warn("latex_keep_old_macro_names is deprecated. "
"LaTeX markup since Sphinx 1.4.5 uses only prefixed macro names.",
RemovedInSphinx17Warning)
def default_latex_engine(config): def default_latex_engine(config):
# type: (Config) -> unicode # type: (Config) -> unicode
""" Better default latex_engine settings for specific languages. """ """ Better default latex_engine settings for specific languages. """
@ -295,7 +270,6 @@ def default_latex_docclass(config):
def setup(app): def setup(app):
# type: (Sphinx) -> Dict[unicode, Any] # type: (Sphinx) -> Dict[unicode, Any]
app.add_builder(LaTeXBuilder) app.add_builder(LaTeXBuilder)
app.connect('builder-inited', validate_config_values)
app.add_config_value('latex_engine', default_latex_engine, None, app.add_config_value('latex_engine', default_latex_engine, None,
ENUM('pdflatex', 'xelatex', 'lualatex', 'platex')) ENUM('pdflatex', 'xelatex', 'lualatex', 'platex'))
@ -305,9 +279,9 @@ def setup(app):
None) None)
app.add_config_value('latex_logo', None, None, string_classes) app.add_config_value('latex_logo', None, None, string_classes)
app.add_config_value('latex_appendices', [], None) app.add_config_value('latex_appendices', [], None)
app.add_config_value('latex_keep_old_macro_names', False, None)
app.add_config_value('latex_use_latex_multicolumn', False, None) app.add_config_value('latex_use_latex_multicolumn', False, None)
app.add_config_value('latex_toplevel_sectioning', None, None, [str]) app.add_config_value('latex_toplevel_sectioning', None, None,
ENUM('part', 'chapter', 'section'))
app.add_config_value('latex_domain_indices', True, None, [list]) app.add_config_value('latex_domain_indices', True, None, [list])
app.add_config_value('latex_show_urls', 'no', None) app.add_config_value('latex_show_urls', 'no', None)
app.add_config_value('latex_show_pagerefs', False, None) app.add_config_value('latex_show_pagerefs', False, None)

View File

@ -10,11 +10,11 @@
""" """
class RemovedInSphinx17Warning(DeprecationWarning): class RemovedInSphinx18Warning(DeprecationWarning):
pass pass
class RemovedInSphinx18Warning(PendingDeprecationWarning): class RemovedInSphinx19Warning(PendingDeprecationWarning):
pass pass
@ -22,4 +22,4 @@ class RemovedInSphinx20Warning(PendingDeprecationWarning):
pass pass
RemovedInNextVersionWarning = RemovedInSphinx17Warning RemovedInNextVersionWarning = RemovedInSphinx18Warning

File diff suppressed because it is too large Load Diff

View File

@ -47,7 +47,7 @@ from sphinx.errors import SphinxError, ExtensionError
from sphinx.locale import _ from sphinx.locale import _
from sphinx.transforms import SphinxTransformer from sphinx.transforms import SphinxTransformer
from sphinx.versioning import add_uids, merge_doctrees from sphinx.versioning import add_uids, merge_doctrees
from sphinx.deprecation import RemovedInSphinx17Warning, RemovedInSphinx20Warning from sphinx.deprecation import RemovedInSphinx20Warning
from sphinx.environment.adapters.indexentries import IndexEntries from sphinx.environment.adapters.indexentries import IndexEntries
from sphinx.environment.adapters.toctree import TocTree from sphinx.environment.adapters.toctree import TocTree
@ -674,13 +674,7 @@ class BuildEnvironment(object):
self.settings['gettext_compact'] = self.config.gettext_compact self.settings['gettext_compact'] = self.config.gettext_compact
language = (self.config.language or 'en').replace('_', '-') language = (self.config.language or 'en').replace('_', '-')
self.settings['language_code'] = language self.settings['language_code'] = language
if self.config.html_use_smartypants is not None: if language in smartchars.quotes: # We enable smartypants by default
warnings.warn("html_use_smartypants option is deprecated. Use the "
"smart_quotes option in docutils.conf instead.",
RemovedInSphinx17Warning)
if language in smartchars.quotes:
self.settings['smart_quotes'] = self.config.html_use_smartypants
elif language in smartchars.quotes: # We enable smartypants by default
self.settings['smart_quotes'] = True self.settings['smart_quotes'] = True
docutilsconf = path.join(self.srcdir, 'docutils.conf') docutilsconf = path.join(self.srcdir, 'docutils.conf')
@ -778,24 +772,6 @@ class BuildEnvironment(object):
"""Returns the docname of the document currently being parsed.""" """Returns the docname of the document currently being parsed."""
return self.temp_data['docname'] return self.temp_data['docname']
@property
def currmodule(self):
# type: () -> None
"""Backwards compatible alias. Will be removed."""
warnings.warn('env.currmodule is deprecated. '
'Use env.ref_context["py:module"] instead.',
RemovedInSphinx17Warning)
return self.ref_context.get('py:module')
@property
def currclass(self):
# type: () -> None
"""Backwards compatible alias. Will be removed."""
warnings.warn('env.currclass is deprecated. '
'Use env.ref_context["py:class"] instead.',
RemovedInSphinx17Warning)
return self.ref_context.get('py:class')
def new_serialno(self, category=''): def new_serialno(self, category=''):
# type: (unicode) -> int # type: (unicode) -> int
"""Return a serial number, e.g. for index entry targets. """Return a serial number, e.g. for index entry targets.

View File

@ -25,16 +25,6 @@
\usepackage<%= sphinxpkgoptions %>{sphinx} \usepackage<%= sphinxpkgoptions %>{sphinx}
<%= sphinxsetup %> <%= sphinxsetup %>
<%= geometry %> <%= geometry %>
\usepackage{multirow}
\let\originalmutirow\multirow\protected\def\multirow{%
\sphinxdeprecationwarning{\multirow}{1.6}{1.7}
{Sphinx does not use package multirow. Its loading will be removed at 1.7.}%
\originalmultirow}%
\usepackage{eqparbox}
\let\originaleqparbox\eqparbox\protected\def\eqparbox{%
\sphinxdeprecationwarning{\eqparbox}{1.6}{1.7}
{Sphinx does not use package eqparbox. Its loading will be removed at 1.7.}%
\originaleqparbox}%
<%= usepackages %> <%= usepackages %>
<%= hyperref %> <%= hyperref %>
<%= contentsname %> <%= contentsname %>

View File

@ -16,15 +16,16 @@
%% for deprecation warnings %% for deprecation warnings
\newcommand\sphinxdeprecationwarning[4]{% #1 the deprecated macro or name, \newcommand\sphinxdeprecationwarning[4]{% #1 the deprecated macro or name,
% #2 = version when deprecated, #3 = version when removed, #4 = message % #2 = when deprecated, #3 = when removed, #4 = additional info
\edef\spx@tempa{\detokenize{#1}}% \edef\spx@tempa{\detokenize{#1}}%
\ltx@ifundefined{sphinx_depr_\spx@tempa}{% \ltx@ifundefined{sphinx_depr_\spx@tempa}{%
\global\expandafter\let\csname sphinx_depr_\spx@tempa\endcsname\spx@tempa \global\expandafter\let\csname sphinx_depr_\spx@tempa\endcsname\spx@tempa
\expandafter\AtEndDocument\expandafter{\expandafter\let\expandafter \expandafter\AtEndDocument\expandafter{\expandafter\let\expandafter
\sphinxdeprecatedmacro\csname sphinx_depr_\spx@tempa\endcsname \sphinxdeprecatedmacro\csname sphinx_depr_\spx@tempa\endcsname
\PackageWarningNoLine{sphinx}{^^J**** SPHINX DEPRECATION WARNING:^^J \PackageWarningNoLine{sphinx}{^^J**** SPHINX DEPRECATION WARNING:^^J
\sphinxdeprecatedmacro\space will be (or has been) \sphinxdeprecatedmacro^^J
deprecated at Sphinx #2^^J and will be removed at Sphinx #3.^^J \@spaces- is deprecated at Sphinx #2^^J
\@spaces- and removed at Sphinx #3.^^J
#4^^J****}}% #4^^J****}}%
}{% warning already emitted (at end of latex log), don't repeat }{% warning already emitted (at end of latex log), don't repeat
}} }}
@ -204,7 +205,6 @@
\DeclareStringOption[.5\dimexpr\inv@mag in\relax]{marginpar} \DeclareStringOption[.5\dimexpr\inv@mag in\relax]{marginpar}
\fi \fi
\DeclareBoolOption{dontkeepoldnames} % \ifspx@opt@dontkeepoldnames = \iffalse
\DeclareStringOption[0]{maxlistdepth}% \newcommand*\spx@opt@maxlistdepth{0} \DeclareStringOption[0]{maxlistdepth}% \newcommand*\spx@opt@maxlistdepth{0}
% dimensions, we declare the \dimen registers here. % dimensions, we declare the \dimen registers here.
@ -1159,14 +1159,6 @@
\begin{sphinx#1}{#2}} \begin{sphinx#1}{#2}}
% in end part, need to go around a LaTeX's "feature" % in end part, need to go around a LaTeX's "feature"
{\edef\spx@temp{\noexpand\end{sphinx\spx@noticetype}}\spx@temp} {\edef\spx@temp{\noexpand\end{sphinx\spx@noticetype}}\spx@temp}
% use of ``notice'' is for backwards compatibility and will be removed in
% Sphinx 1.7.
\newenvironment{notice}
{\sphinxdeprecationwarning {notice}{1.6}{1.7}{%
This document was probably built with a Sphinx extension using ``notice''^^J
environment. At Sphinx 1.7, ``notice'' environment will be removed. Please^^J
report to extension author to use ``sphinxadmonition'' instead.^^J%
****}\begin{sphinxadmonition}}{\end{sphinxadmonition}}
%% PYTHON DOCS MACROS AND ENVIRONMENTS %% PYTHON DOCS MACROS AND ENVIRONMENTS
@ -1323,7 +1315,6 @@
%% TEXT STYLING %% TEXT STYLING
% %
% Some custom font markup commands. % Some custom font markup commands.
% *** the macros without \sphinx prefix are still defined farther down ***
\protected\def\sphinxstrong#1{{\textbf{#1}}} \protected\def\sphinxstrong#1{{\textbf{#1}}}
% to obtain straight quotes we execute \@noligs as patched by upquote, and % to obtain straight quotes we execute \@noligs as patched by upquote, and
% \scantokens is needed in cases where it would be too late for the macro to % \scantokens is needed in cases where it would be too late for the macro to
@ -1359,37 +1350,6 @@
\long\protected\def\sphinxoptional#1{% \long\protected\def\sphinxoptional#1{%
{\textnormal{\Large[}}{#1}\hspace{0.5mm}{\textnormal{\Large]}}} {\textnormal{\Large[}}{#1}\hspace{0.5mm}{\textnormal{\Large]}}}
\ifspx@opt@dontkeepoldnames\else
\let\spx@alreadydefinedlist\@empty
\typeout{** (sphinx) defining (legacy) text style macros without \string\sphinx\space prefix}
\typeout{** if clashes with packages, do not set latex_keep_old_macro_names=True
in conf.py}
\@for\@tempa:=code,strong,bfcode,email,tablecontinued,titleref,%
menuselection,accelerator,crossref,termref,optional\do
{% first, check if command with no prefix already exists
\ltx@ifundefined{\@tempa}{%
% give it the meaning defined so far with \sphinx prefix
\expandafter\let\csname\@tempa\expandafter\endcsname
\csname sphinx\@tempa\endcsname
% redefine the \sphinx prefixed macro to expand to non-prefixed one
\expandafter\def\csname sphinx\@tempa\expandafter\endcsname
\expandafter{\csname\@tempa\endcsname}%
}{\edef\spx@alreadydefinedlist{\spx@alreadydefinedlist{\@tempa}}}%
}%
\ifx\spx@alreadydefinedlist\@empty\else
\expandafter\@tfor\expandafter\@tempa\expandafter:\expandafter=\spx@alreadydefinedlist\do
{% emit warning now
\PackageWarning{sphinx}{not redefining already existing \@backslashchar\@tempa\space!^^J%
Anyhow, Sphinx mark-up uses only \string\sphinx\@tempa.}%
% and also at end of log for better visibility
\expandafter\sphinxdeprecationwarning\expandafter{\csname\@tempa\endcsname}{1.6}{1.7}
{\sphinxdeprecatedmacro\space already existed at Sphinx loading time! Not redefined!^^J
Sphinx mark-up uses only \string\sphinx\expandafter\@gobble\sphinxdeprecatedmacro.}%
}%
\fi
\sphinxdeprecationwarning{latex_keep_old_macro_names=True}{1.6}{1.7}{}%
\fi
% additional customizable styling % additional customizable styling
% FIXME: convert this to package options ? % FIXME: convert this to package options ?
\protected\def\sphinxstyleindexentry {\texttt} \protected\def\sphinxstyleindexentry {\texttt}
@ -1406,6 +1366,8 @@
\protected\def\sphinxstyleliteralstrong {\sphinxbfcode} \protected\def\sphinxstyleliteralstrong {\sphinxbfcode}
\protected\def\sphinxstyleabbreviation {\textsc} \protected\def\sphinxstyleabbreviation {\textsc}
\protected\def\sphinxstyleliteralintitle {\sphinxcode} \protected\def\sphinxstyleliteralintitle {\sphinxcode}
% figure legend comes after caption and may contain arbitrary body elements
\newenvironment{sphinxlegend}{\par\small}{\par}
% Tell TeX about pathological hyphenation cases: % Tell TeX about pathological hyphenation cases:
\hyphenation{Base-HTTP-Re-quest-Hand-ler} \hyphenation{Base-HTTP-Re-quest-Hand-ler}

View File

@ -1,48 +0,0 @@
# -*- coding: utf-8 -*-
"""
sphinx.util.compat
~~~~~~~~~~~~~~~~~~
Stuff for docutils compatibility.
:copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS.
:license: BSD, see LICENSE for details.
"""
from __future__ import absolute_import
import sys
import warnings
from docutils.parsers.rst import Directive # noqa
from docutils import __version__ as _du_version
from sphinx.deprecation import RemovedInSphinx17Warning
docutils_version = tuple(int(x) for x in _du_version.split('.')[:2])
if False:
# For type annotation
from typing import Any, Dict # NOQA
class _DeprecationWrapper(object):
def __init__(self, mod, deprecated):
# type: (Any, Dict) -> None
self._mod = mod
self._deprecated = deprecated
def __getattr__(self, attr):
# type: (str) -> Any
if attr in self._deprecated:
warnings.warn("sphinx.util.compat.%s is deprecated and will be "
"removed in Sphinx 1.7, please use the standard "
"library version instead." % attr,
RemovedInSphinx17Warning, stacklevel=2)
return self._deprecated[attr]
return getattr(self._mod, attr)
sys.modules[__name__] = _DeprecationWrapper(sys.modules[__name__], dict( # type: ignore
docutils_version = docutils_version,
Directive = Directive,
))

View File

@ -359,7 +359,8 @@ class DocFieldTransformer(object):
else: else:
fieldtype, content = entry fieldtype, content = entry
fieldtypes = types.get(fieldtype.name, {}) fieldtypes = types.get(fieldtype.name, {})
env = self.directive.state.document.settings.env
new_list += fieldtype.make_field(fieldtypes, self.directive.domain, new_list += fieldtype.make_field(fieldtypes, self.directive.domain,
content, env=self.directive.env) content, env=env)
node.replace_self(new_list) node.replace_self(new_list)

View File

@ -11,14 +11,12 @@
from __future__ import absolute_import from __future__ import absolute_import
import re import re
import warnings
from six import text_type from six import text_type
from docutils import nodes from docutils import nodes
from sphinx import addnodes from sphinx import addnodes
from sphinx.deprecation import RemovedInSphinx17Warning
from sphinx.locale import pairindextypes from sphinx.locale import pairindextypes
from sphinx.util import logging from sphinx.util import logging
@ -354,30 +352,6 @@ def set_role_source_info(inliner, lineno, node):
node.source, node.line = inliner.reporter.get_source_and_line(lineno) node.source, node.line = inliner.reporter.get_source_and_line(lineno)
def process_only_nodes(doctree, tags):
# type: (nodes.Node, Tags) -> None
# A comment on the comment() nodes being inserted: replacing by [] would
# result in a "Losing ids" exception if there is a target node before
# the only node, so we make sure docutils can transfer the id to
# something, even if it's just a comment and will lose the id anyway...
warnings.warn('process_only_nodes() is deprecated. '
'Use sphinx.environment.apply_post_transforms() instead.',
RemovedInSphinx17Warning)
for node in doctree.traverse(addnodes.only):
try:
ret = tags.eval_condition(node['expr'])
except Exception as err:
logger.warning('exception while evaluating only directive expression: %s', err,
location=node)
node.replace_self(node.children or nodes.comment())
else:
if ret:
node.replace_self(node.children or nodes.comment())
else:
node.replace_self(nodes.comment())
# monkey-patch Element.copy to copy the rawsource and line # monkey-patch Element.copy to copy the rawsource and line
def _new_copy(self): def _new_copy(self):

View File

@ -57,7 +57,7 @@ DEFAULT_SETTINGS = {
'classoptions': '', 'classoptions': '',
'extraclassoptions': '', 'extraclassoptions': '',
'maxlistdepth': '', 'maxlistdepth': '',
'sphinxpkgoptions': 'dontkeepoldnames', 'sphinxpkgoptions': '',
'sphinxsetup': '', 'sphinxsetup': '',
'passoptionstopackages': '', 'passoptionstopackages': '',
'geometry': '\\usepackage{geometry}', 'geometry': '\\usepackage{geometry}',
@ -547,8 +547,6 @@ class LaTeXTranslator(nodes.NodeVisitor):
self.elements.update({ self.elements.update({
'releasename': _('Release'), 'releasename': _('Release'),
}) })
if builder.config.latex_keep_old_macro_names:
self.elements['sphinxpkgoptions'] = ''
if document.settings.docclass == 'howto': if document.settings.docclass == 'howto':
docclass = builder.config.latex_docclass.get('howto', 'article') docclass = builder.config.latex_docclass.get('howto', 'article')
else: else:
@ -1833,12 +1831,10 @@ class LaTeXTranslator(nodes.NodeVisitor):
self.unrestrict_footnote(node) self.unrestrict_footnote(node)
def visit_legend(self, node): def visit_legend(self, node):
# type: (nodes.Node) -> None self.body.append('\n\\begin{sphinxlegend}')
self.body.append('{\\small ')
def depart_legend(self, node): def depart_legend(self, node):
# type: (nodes.Node) -> None self.body.append('\\end{sphinxlegend}\n')
self.body.append('}')
def visit_admonition(self, node): def visit_admonition(self, node):
# type: (nodes.Node) -> None # type: (nodes.Node) -> None

View File

@ -58,7 +58,7 @@ def nonascii_srcdir(request):
[ [
# note: no 'html' - if it's ok with dirhtml it's ok with html # note: no 'html' - if it's ok with dirhtml it's ok with html
'dirhtml', 'singlehtml', 'latex', 'texinfo', 'pickle', 'json', 'text', 'dirhtml', 'singlehtml', 'latex', 'texinfo', 'pickle', 'json', 'text',
'htmlhelp', 'qthelp', 'epub2', 'epub', 'applehelp', 'changes', 'xml', 'htmlhelp', 'qthelp', 'epub', 'applehelp', 'changes', 'xml',
'pseudoxml', 'man', 'linkcheck', 'pseudoxml', 'man', 'linkcheck',
], ],
) )

View File

@ -14,19 +14,13 @@
:license: BSD, see LICENSE for details. :license: BSD, see LICENSE for details.
""" """
import os
import re
from itertools import cycle, chain
import xml.etree.cElementTree as ElementTree import xml.etree.cElementTree as ElementTree
from six import PY3
import pytest import pytest
from html5lib import getTreeBuilder, HTMLParser from html5lib import getTreeBuilder, HTMLParser
from sphinx import __display_version__
from sphinx.util.docutils import is_html5_writer_available from sphinx.util.docutils import is_html5_writer_available
from util import remove_unicode_literals, strip_escseq, skip_unless
from test_build_html import flat_dict, tail_check, check_xpath from test_build_html import flat_dict, tail_check, check_xpath
TREE_BUILDER = getTreeBuilder('etree', implementation=ElementTree) TREE_BUILDER = getTreeBuilder('etree', implementation=ElementTree)
@ -35,7 +29,8 @@ HTML_PARSER = HTMLParser(TREE_BUILDER, namespaceHTMLElements=False)
etree_cache = {} etree_cache = {}
@skip_unless(is_html5_writer_available())
@pytest.mark.skipif(not is_html5_writer_available(), reason='HTML5 writer is not available')
@pytest.fixture(scope='module') @pytest.fixture(scope='module')
def cached_etree_parse(): def cached_etree_parse():
def parse(fname): def parse(fname):
@ -50,7 +45,7 @@ def cached_etree_parse():
etree_cache.clear() etree_cache.clear()
@skip_unless(is_html5_writer_available()) @pytest.mark.skipif(not is_html5_writer_available(), reason='HTML5 writer is not available')
@pytest.mark.parametrize("fname,expect", flat_dict({ @pytest.mark.parametrize("fname,expect", flat_dict({
'images.html': [ 'images.html': [
(".//img[@src='_images/img.png']", ''), (".//img[@src='_images/img.png']", ''),

View File

@ -24,7 +24,7 @@ from sphinx.util.osutil import cd, ensuredir
from sphinx.util import docutils from sphinx.util import docutils
from sphinx.writers.latex import LaTeXTranslator from sphinx.writers.latex import LaTeXTranslator
from util import SkipTest, remove_unicode_literals, strip_escseq, skip_if from util import remove_unicode_literals, strip_escseq
from test_build_html import ENV_WARNINGS from test_build_html import ENV_WARNINGS
@ -77,7 +77,7 @@ def compile_latex_document(app):
'SphinxTests.tex'], 'SphinxTests.tex'],
stdout=PIPE, stderr=PIPE) stdout=PIPE, stderr=PIPE)
except OSError: # most likely the latex executable was not found except OSError: # most likely the latex executable was not found
raise SkipTest raise pytest.skip.Exception
else: else:
stdout, stderr = p.communicate() stdout, stderr = p.communicate()
if p.returncode != 0: if p.returncode != 0:
@ -90,7 +90,7 @@ def compile_latex_document(app):
def skip_if_requested(testfunc): def skip_if_requested(testfunc):
if 'SKIP_LATEX_BUILD' in os.environ: if 'SKIP_LATEX_BUILD' in os.environ:
msg = 'Skip LaTeX builds because SKIP_LATEX_BUILD is set' msg = 'Skip LaTeX builds because SKIP_LATEX_BUILD is set'
return skip_if(True, msg)(testfunc) return pytest.mark.skipif(True, reason=msg)(testfunc)
else: else:
return testfunc return testfunc
@ -98,7 +98,7 @@ def skip_if_requested(testfunc):
def skip_if_stylefiles_notfound(testfunc): def skip_if_stylefiles_notfound(testfunc):
if kpsetest(*STYLEFILES) is False: if kpsetest(*STYLEFILES) is False:
msg = 'not running latex, the required styles do not seem to be installed' msg = 'not running latex, the required styles do not seem to be installed'
return skip_if(True, msg)(testfunc) return pytest.mark.skipif(True, reason=msg)(testfunc)
else: else:
return testfunc return testfunc

View File

@ -19,7 +19,7 @@ import pytest
from sphinx.writers.texinfo import TexinfoTranslator from sphinx.writers.texinfo import TexinfoTranslator
from util import SkipTest, remove_unicode_literals, strip_escseq from util import remove_unicode_literals, strip_escseq
from test_build_html import ENV_WARNINGS from test_build_html import ENV_WARNINGS
@ -58,7 +58,7 @@ def test_texinfo(app, status, warning):
p = Popen(['makeinfo', '--no-split', 'SphinxTests.texi'], p = Popen(['makeinfo', '--no-split', 'SphinxTests.texi'],
stdout=PIPE, stderr=PIPE) stdout=PIPE, stderr=PIPE)
except OSError: except OSError:
raise SkipTest # most likely makeinfo was not found raise pytest.skip.Exception # most likely makeinfo was not found
else: else:
stdout, stderr = p.communicate() stdout, stderr = p.communicate()
retcode = p.returncode retcode = p.returncode

View File

@ -8,12 +8,11 @@
:copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS. :copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS.
:license: BSD, see LICENSE for details. :license: BSD, see LICENSE for details.
""" """
import pytest
from docutils.utils import column_width from docutils.utils import column_width
from sphinx.writers.text import MAXWIDTH from sphinx.writers.text import MAXWIDTH
from util import with_app
def with_text_app(*args, **kw): def with_text_app(*args, **kw):
default_kw = { default_kw = {
@ -21,7 +20,7 @@ def with_text_app(*args, **kw):
'testroot': 'build-text', 'testroot': 'build-text',
} }
default_kw.update(kw) default_kw.update(kw)
return with_app(*args, **default_kw) return pytest.mark.sphinx(*args, **default_kw)
@with_text_app() @with_text_app()

View File

@ -12,7 +12,6 @@
import re import re
from docutils import nodes from docutils import nodes
from sphinx.util.nodes import process_only_nodes
import pytest import pytest
@ -46,7 +45,7 @@ def test_sectioning(app, status, warning):
app.builder.build(['only']) app.builder.build(['only'])
doctree = app.env.get_doctree('only') doctree = app.env.get_doctree('only')
process_only_nodes(doctree, app.builder.tags) app.env.apply_post_transforms(doctree, 'only')
parts = [getsects(n) parts = [getsects(n)
for n in [_n for _n in doctree.children if isinstance(_n, nodes.section)]] for n in [_n for _n in doctree.children if isinstance(_n, nodes.section)]]

View File

@ -12,7 +12,7 @@
import re import re
import pytest import pytest
from util import path, SkipTest from util import path
def regex_count(expr, result): def regex_count(expr, result):
@ -78,7 +78,7 @@ def test_docutils_source_link_with_nonascii_file(app, status, warning):
(srcdir / (mb_name + '.txt')).write_text('') (srcdir / (mb_name + '.txt')).write_text('')
except UnicodeEncodeError: except UnicodeEncodeError:
from path import FILESYSTEMENCODING from path import FILESYSTEMENCODING
raise SkipTest( raise pytest.skip.Exception(
'nonascii filename not supported on this filesystem encoding: ' 'nonascii filename not supported on this filesystem encoding: '
'%s', FILESYSTEMENCODING) '%s', FILESYSTEMENCODING)

View File

@ -16,11 +16,9 @@ import pytest
from sphinx import addnodes from sphinx import addnodes
from sphinx.domains.cpp import DefinitionParser, DefinitionError, NoOldIdError from sphinx.domains.cpp import DefinitionParser, DefinitionError, NoOldIdError
from sphinx.domains.cpp import Symbol from sphinx.domains.cpp import Symbol, _max_id, _id_prefix
import sphinx.domains.cpp as cppDomain import sphinx.domains.cpp as cppDomain
ids = []
def parse(name, string): def parse(name, string):
class Config(object): class Config(object):
@ -28,18 +26,14 @@ def parse(name, string):
cpp_paren_attributes = ["paren_attr"] cpp_paren_attributes = ["paren_attr"]
parser = DefinitionParser(string, None, Config()) parser = DefinitionParser(string, None, Config())
ast = parser.parse_declaration(name) ast = parser.parse_declaration(name)
if not parser.eof: parser.assert_end()
print("Parsing stopped at", parser.pos)
print(string)
print('-' * parser.pos + '^')
raise DefinitionError("")
# The scopedness would usually have been set by CPPEnumObject # The scopedness would usually have been set by CPPEnumObject
if name == "enum": if name == "enum":
ast.scoped = None # simulate unscoped enum ast.scoped = None # simulate unscoped enum
return ast return ast
def check(name, input, idv1output=None, idv2output=None, output=None): def check(name, input, idDict, output=None):
# first a simple check of the AST # first a simple check of the AST
if output is None: if output is None:
output = input output = input
@ -58,37 +52,43 @@ def check(name, input, idv1output=None, idv2output=None, output=None):
parentNode += signode parentNode += signode
ast.describe_signature(signode, 'lastIsName', symbol, options={}) ast.describe_signature(signode, 'lastIsName', symbol, options={})
if idv2output: idExpected = [None]
idv2output = "_CPPv2" + idv2output for i in range(1, _max_id + 1):
try: if i in idDict:
idv1 = ast.get_id_v1() idExpected.append(idDict[i])
assert idv1 is not None else:
except NoOldIdError: idExpected.append(idExpected[i - 1])
idv1 = None idActual = [None]
try: for i in range(1, _max_id + 1):
idv2 = ast.get_id_v2() try:
assert idv2 is not None id = ast.get_id(version=i)
except NoOldIdError: assert id is not None
idv2 = None idActual.append(id[len(_id_prefix[i]):])
if idv1 != idv1output or idv2 != idv2output: except NoOldIdError:
idActual.append(None)
res = [True]
for i in range(1, _max_id + 1):
res.append(idExpected[i] == idActual[i])
if not all(res):
print("input: %s" % text_type(input).rjust(20)) print("input: %s" % text_type(input).rjust(20))
print(" %s %s" % ("Id v1".rjust(20), "Id v2".rjust(20))) for i in range(1, _max_id + 1):
print("result: %s %s" % (str(idv1).rjust(20), str(idv2).rjust(20))) if res[i]:
print("expected: %s %s" % (str(idv1output).rjust(20), continue
str(idv2output).rjust(20))) print("Error in id version %d." % i)
print("result: %s" % str(idActual[i]))
print("expected: %s" % str(idExpected[i]))
print(rootSymbol.dump(0)) print(rootSymbol.dump(0))
raise DefinitionError("") raise DefinitionError("")
ids.append(ast.get_id_v2())
# print ".. %s:: %s" % (name, input)
def test_fundamental_types(): def test_fundamental_types():
# see http://en.cppreference.com/w/cpp/language/types # see http://en.cppreference.com/w/cpp/language/types
for t, id_v2 in cppDomain._id_fundamental_v2.items(): for t, id_v2 in cppDomain._id_fundamental_v2.items():
if t == "decltype(auto)":
continue
def makeIdV1(): def makeIdV1():
if t == 'decltype(auto)':
return None
id = t.replace(" ", "-").replace("long", "l").replace("int", "i") id = t.replace(" ", "-").replace("long", "l").replace("int", "i")
id = id.replace("bool", "b").replace("char", "c") id = id.replace("bool", "b").replace("char", "c")
id = id.replace("wc_t", "wchar_t").replace("c16_t", "char16_t") id = id.replace("wc_t", "wchar_t").replace("c16_t", "char16_t")
@ -100,55 +100,141 @@ def test_fundamental_types():
if t == "std::nullptr_t": if t == "std::nullptr_t":
id = "NSt9nullptr_tE" id = "NSt9nullptr_tE"
return "1f%s" % id return "1f%s" % id
check("function", "void f(%s arg)" % t, makeIdV1(), makeIdV2()) check("function", "void f(%s arg)" % t, {1: makeIdV1(), 2:makeIdV2()})
def test_expressions():
def exprCheck(expr, id):
ids = 'IE1CIA%s_1aE'
check('class', 'template<> C<a[%s]>' % expr, {2:ids % expr, 3:ids % id})
# primary
exprCheck('nullptr', 'LDnE')
exprCheck('true', 'L1E')
exprCheck('false', 'L0E')
exprCheck('5', 'L5E')
exprCheck('5.0', 'L5.0E')
exprCheck('"abc\\"cba"', 'LA8_KcE')
# TODO: test the rest
exprCheck('(... + Ns)', '(... + Ns)')
exprCheck('(5)', 'L5E')
exprCheck('C', '1C')
# postfix
exprCheck('A(2)', 'cl1AL2EE')
exprCheck('A[2]', 'ix1AL2E')
exprCheck('a.b.c', 'dtdt1a1b1c')
exprCheck('a->b->c', 'ptpt1a1b1c')
exprCheck('i++', 'pp1i')
exprCheck('i--', 'mm1i')
# TODO, those with prefixes
# unary
exprCheck('++5', 'pp_L5E')
exprCheck('--5', 'mm_L5E')
exprCheck('*5', 'deL5E')
exprCheck('&5', 'adL5E')
exprCheck('+5', 'psL5E')
exprCheck('-5', 'ngL5E')
exprCheck('!5', 'ntL5E')
exprCheck('~5', 'coL5E')
# cast
exprCheck('(int)2', 'cviL2E')
# binary op
exprCheck('5 || 42', 'ooL5EL42E')
exprCheck('5 && 42', 'aaL5EL42E')
exprCheck('5 | 42', 'orL5EL42E')
exprCheck('5 ^ 42', 'eoL5EL42E')
exprCheck('5 & 42', 'anL5EL42E')
# ['==', '!=']
exprCheck('5 == 42', 'eqL5EL42E')
exprCheck('5 != 42', 'neL5EL42E')
# ['<=', '>=', '<', '>']
exprCheck('5 <= 42', 'leL5EL42E')
exprCheck('5 >= 42', 'geL5EL42E')
exprCheck('5 < 42', 'ltL5EL42E')
exprCheck('5 > 42', 'gtL5EL42E')
# ['<<', '>>']
exprCheck('5 << 42', 'lsL5EL42E')
exprCheck('5 >> 42', 'rsL5EL42E')
# ['+', '-']
exprCheck('5 + 42', 'plL5EL42E')
exprCheck('5 - 42', 'miL5EL42E')
# ['*', '/', '%']
exprCheck('5 * 42', 'mlL5EL42E')
exprCheck('5 / 42', 'dvL5EL42E')
exprCheck('5 % 42', 'rmL5EL42E')
# ['.*', '->*']
exprCheck('5 .* 42', 'dsL5EL42E')
exprCheck('5 ->* 42', 'pmL5EL42E')
# conditional
# TODO
# assignment
exprCheck('a = 5', 'aS1aL5E')
exprCheck('a *= 5', 'mL1aL5E')
exprCheck('a /= 5', 'dV1aL5E')
exprCheck('a %= 5', 'rM1aL5E')
exprCheck('a += 5', 'pL1aL5E')
exprCheck('a -= 5', 'mI1aL5E')
exprCheck('a >>= 5', 'rS1aL5E')
exprCheck('a <<= 5', 'lS1aL5E')
exprCheck('a &= 5', 'aN1aL5E')
exprCheck('a ^= 5', 'eO1aL5E')
exprCheck('a |= 5', 'oR1aL5E')
# Additional tests
# a < expression that starts with something that could be a template
exprCheck('A < 42', 'lt1AL42E')
check('function', 'template<> void f(A<B, 2> &v)',
{2:"IE1fR1AI1BX2EE", 3:"IE1fR1AI1BXL2EEE"})
exprCheck('A<1>::value', 'N1AIXL1EEE5valueE')
check('class', "template<int T = 42> A", {2:"I_iE1A"})
check('enumerator', 'A = std::numeric_limits<unsigned long>::max()', {2:"1A"})
def test_type_definitions(): def test_type_definitions():
check("type", "public bool b", "b", "1b", "bool b") check("type", "public bool b", {1:"b", 2:"1b"}, "bool b")
check("type", "bool A::b", "A::b", "N1A1bE") check("type", "bool A::b", {1:"A::b", 2:"N1A1bE"})
check("type", "bool *b", "b", "1b") check("type", "bool *b", {1:"b", 2:"1b"})
check("type", "bool *const b", "b", "1b") check("type", "bool *const b", {1:"b", 2:"1b"})
check("type", "bool *volatile const b", "b", "1b") check("type", "bool *volatile const b", {1:"b", 2:"1b"})
check("type", "bool *volatile const b", "b", "1b") check("type", "bool *volatile const b", {1:"b", 2:"1b"})
check("type", "bool *volatile const *b", "b", "1b") check("type", "bool *volatile const *b", {1:"b", 2:"1b"})
check("type", "bool &b", "b", "1b") check("type", "bool &b", {1:"b", 2:"1b"})
check("type", "bool b[]", "b", "1b") check("type", "bool b[]", {1:"b", 2:"1b"})
check("type", "std::pair<int, int> coord", "coord", "5coord") check("type", "std::pair<int, int> coord", {1:"coord", 2:"5coord"})
check("type", "long long int foo", "foo", "3foo") check("type", "long long int foo", {1:"foo", 2:"3foo"})
check("type", 'std::vector<std::pair<std::string, long long>> module::blah', check("type", 'std::vector<std::pair<std::string, long long>> module::blah',
"module::blah", "N6module4blahE") {1:"module::blah", 2:"N6module4blahE"})
check("type", "std::function<void()> F", "F", "1F") check("type", "std::function<void()> F", {1:"F", 2:"1F"})
check("type", "std::function<R(A1, A2)> F", "F", "1F") check("type", "std::function<R(A1, A2)> F", {1:"F", 2:"1F"})
check("type", "std::function<R(A1, A2, A3)> F", "F", "1F") check("type", "std::function<R(A1, A2, A3)> F", {1:"F", 2:"1F"})
check("type", "std::function<R(A1, A2, A3, As...)> F", "F", "1F") check("type", "std::function<R(A1, A2, A3, As...)> F", {1:"F", 2:"1F"})
check("type", "MyContainer::const_iterator", check("type", "MyContainer::const_iterator",
"MyContainer::const_iterator", "N11MyContainer14const_iteratorE") {1:"MyContainer::const_iterator", 2:"N11MyContainer14const_iteratorE"})
check("type", check("type",
"public MyContainer::const_iterator", "public MyContainer::const_iterator",
"MyContainer::const_iterator", "N11MyContainer14const_iteratorE", {1:"MyContainer::const_iterator", 2:"N11MyContainer14const_iteratorE"},
output="MyContainer::const_iterator") output="MyContainer::const_iterator")
# test decl specs on right # test decl specs on right
check("type", "bool const b", "b", "1b") check("type", "bool const b", {1:"b", 2:"1b"})
# test name in global scope # test name in global scope
check("type", "bool ::B::b", "B::b", "N1B1bE") check("type", "bool ::B::b", {1:"B::b", 2:"N1B1bE"})
check('type', 'A = B', None, '1A') check('type', 'A = B', {2:'1A'})
# from breathe#267 (named function parameters for function pointers # from breathe#267 (named function parameters for function pointers
check('type', 'void (*gpio_callback_t)(struct device *port, uint32_t pin)', check('type', 'void (*gpio_callback_t)(struct device *port, uint32_t pin)',
'gpio_callback_t', '15gpio_callback_t') {1:'gpio_callback_t', 2:'15gpio_callback_t'})
check('type', 'void (*f)(std::function<void(int i)> g)', 'f', '1f') check('type', 'void (*f)(std::function<void(int i)> g)', {1:'f', 2:'1f'})
def test_concept_definitions(): def test_concept_definitions():
check('concept', 'template<typename Param> A::B::Concept', check('concept', 'template<typename Param> A::B::Concept',
None, 'I0EN1A1B7ConceptE') {2:'I0EN1A1B7ConceptE'})
check('concept', 'template<typename A, typename B, typename ...C> Foo', check('concept', 'template<typename A, typename B, typename ...C> Foo',
None, 'I00DpE3Foo') {2:'I00DpE3Foo'})
check('concept', 'template<typename Param> A::B::Concept()', check('concept', 'template<typename Param> A::B::Concept()',
None, 'I0EN1A1B7ConceptE') {2:'I0EN1A1B7ConceptE'})
check('concept', 'template<typename A, typename B, typename ...C> Foo()', check('concept', 'template<typename A, typename B, typename ...C> Foo()',
None, 'I00DpE3Foo') {2:'I00DpE3Foo'})
with pytest.raises(DefinitionError): with pytest.raises(DefinitionError):
parse('concept', 'Foo') parse('concept', 'Foo')
with pytest.raises(DefinitionError): with pytest.raises(DefinitionError):
@ -157,256 +243,257 @@ def test_concept_definitions():
def test_member_definitions(): def test_member_definitions():
check('member', ' const std::string & name = 42', check('member', ' const std::string & name = 42',
"name__ssCR", "4name", output='const std::string &name = 42') {1:"name__ssCR", 2:"4name"}, output='const std::string &name = 42')
check('member', ' const std::string & name', "name__ssCR", "4name", check('member', ' const std::string & name', {1:"name__ssCR", 2:"4name"},
output='const std::string &name') output='const std::string &name')
check('member', ' const std::string & name [ n ]', check('member', ' const std::string & name [ n ]',
"name__ssCRA", "4name", output='const std::string &name[n]') {1:"name__ssCRA", 2:"4name"}, output='const std::string &name[n]')
check('member', 'const std::vector< unsigned int, long> &name', check('member', 'const std::vector< unsigned int, long> &name',
"name__std::vector:unsigned-i.l:CR", {1:"name__std::vector:unsigned-i.l:CR", 2:"4name"},
"4name", output='const std::vector<unsigned int, long> &name') output='const std::vector<unsigned int, long> &name')
check('member', 'module::myclass foo[n]', "foo__module::myclassA", "3foo") check('member', 'module::myclass foo[n]', {1:"foo__module::myclassA", 2:"3foo"})
check('member', 'int *const p', 'p__iPC', '1p') check('member', 'int *const p', {1:'p__iPC', 2:'1p'})
check('member', 'extern int myInt', 'myInt__i', '5myInt') check('member', 'extern int myInt', {1:'myInt__i', 2:'5myInt'})
check('member', 'thread_local int myInt', 'myInt__i', '5myInt') check('member', 'thread_local int myInt', {1:'myInt__i', 2:'5myInt'})
check('member', 'extern thread_local int myInt', 'myInt__i', '5myInt') check('member', 'extern thread_local int myInt', {1:'myInt__i', 2:'5myInt'})
check('member', 'thread_local extern int myInt', 'myInt__i', '5myInt', check('member', 'thread_local extern int myInt', {1:'myInt__i', 2:'5myInt'},
'extern thread_local int myInt') 'extern thread_local int myInt')
def test_function_definitions(): def test_function_definitions():
check('function', 'operator bool() const', "castto-b-operatorC", "NKcvbEv") check('function', 'operator bool() const', {1:"castto-b-operatorC", 2:"NKcvbEv"})
check('function', 'A::operator bool() const', check('function', 'A::operator bool() const',
"A::castto-b-operatorC", "NK1AcvbEv") {1:"A::castto-b-operatorC", 2:"NK1AcvbEv"})
check('function', 'A::operator bool() volatile const &', check('function', 'A::operator bool() volatile const &',
"A::castto-b-operatorVCR", "NVKR1AcvbEv") {1:"A::castto-b-operatorVCR", 2:"NVKR1AcvbEv"})
check('function', 'A::operator bool() volatile const &&', check('function', 'A::operator bool() volatile const &&',
"A::castto-b-operatorVCO", "NVKO1AcvbEv") {1:"A::castto-b-operatorVCO", 2:"NVKO1AcvbEv"})
check('function', 'bool namespaced::theclass::method(arg1, arg2)', check('function', 'bool namespaced::theclass::method(arg1, arg2)',
"namespaced::theclass::method__arg1.arg2", {1:"namespaced::theclass::method__arg1.arg2",
"N10namespaced8theclass6methodE4arg14arg2") 2:"N10namespaced8theclass6methodE4arg14arg2"})
x = 'std::vector<std::pair<std::string, int>> &module::test(register int ' \ x = 'std::vector<std::pair<std::string, int>> &module::test(register int ' \
'foo, bar, std::string baz = "foobar, blah, bleh") const = 0' 'foo, bar, std::string baz = "foobar, blah, bleh") const = 0'
check('function', x, "module::test__i.bar.ssC", check('function', x, {1:"module::test__i.bar.ssC",
"NK6module4testEi3barNSt6stringE") 2:"NK6module4testEi3barNSt6stringE"})
check('function', 'void f(std::pair<A, B>)', check('function', 'void f(std::pair<A, B>)',
"f__std::pair:A.B:", "1fNSt4pairI1A1BEE") {1:"f__std::pair:A.B:", 2:"1fNSt4pairI1A1BEE"})
check('function', 'explicit module::myclass::foo::foo()', check('function', 'explicit module::myclass::foo::foo()',
"module::myclass::foo::foo", "N6module7myclass3foo3fooEv") {1:"module::myclass::foo::foo", 2:"N6module7myclass3foo3fooEv"})
check('function', 'module::myclass::foo::~foo()', check('function', 'module::myclass::foo::~foo()',
"module::myclass::foo::~foo", "N6module7myclass3fooD0Ev") {1:"module::myclass::foo::~foo", 2:"N6module7myclass3fooD0Ev"})
check('function', 'int printf(const char *fmt, ...)', check('function', 'int printf(const char *fmt, ...)',
"printf__cCP.z", "6printfPKcz") {1:"printf__cCP.z", 2:"6printfPKcz"})
check('function', 'int foo(const unsigned int j)', check('function', 'int foo(const unsigned int j)',
"foo__unsigned-iC", "3fooKj") {1:"foo__unsigned-iC", 2:"3fooKj"})
check('function', 'int foo(const int *const ptr)', check('function', 'int foo(const int *const ptr)',
"foo__iCPC", "3fooPCKi") {1:"foo__iCPC", 2:"3fooPCKi"})
check('function', 'module::myclass::operator std::vector<std::string>()', check('function', 'module::myclass::operator std::vector<std::string>()',
"module::myclass::castto-std::vector:ss:-operator", {1:"module::myclass::castto-std::vector:ss:-operator",
"N6module7myclasscvNSt6vectorINSt6stringEEEEv") 2:"N6module7myclasscvNSt6vectorINSt6stringEEEEv"})
check('function', check('function',
'void operator()(const boost::array<VertexID, 2> &v) const', 'void operator()(const boost::array<VertexID, 2> &v) const',
"call-operator__boost::array:VertexID.2:CRC", {1:"call-operator__boost::array:VertexID.2:CRC",
"NKclERKN5boost5arrayI8VertexIDX2EEE") 2:"NKclERKN5boost5arrayI8VertexIDX2EEE",
3:"NKclERKN5boost5arrayI8VertexIDXL2EEEE"})
check('function', check('function',
'void operator()(const boost::array<VertexID, 2, "foo, bar"> &v) const', 'void operator()(const boost::array<VertexID, 2, "foo, bar"> &v) const',
'call-operator__boost::array:VertexID.2."foo,--bar":CRC', {1:'call-operator__boost::array:VertexID.2."foo,--bar":CRC',
'NKclERKN5boost5arrayI8VertexIDX2EX"foo, bar"EEE') 2:'NKclERKN5boost5arrayI8VertexIDX2EX"foo, bar"EEE',
3:'NKclERKN5boost5arrayI8VertexIDXL2EEXLA9_KcEEEE'})
check('function', 'MyClass::MyClass(MyClass::MyClass&&)', check('function', 'MyClass::MyClass(MyClass::MyClass&&)',
"MyClass::MyClass__MyClass::MyClassRR", {1:"MyClass::MyClass__MyClass::MyClassRR",
"N7MyClass7MyClassERRN7MyClass7MyClassE") 2:"N7MyClass7MyClassERRN7MyClass7MyClassE"})
check('function', 'constexpr int get_value()', "get_valueCE", "9get_valuev") check('function', 'constexpr int get_value()', {1:"get_valueCE", 2:"9get_valuev"})
check('function', 'static constexpr int get_value()', check('function', 'static constexpr int get_value()',
"get_valueCE", "9get_valuev") {1:"get_valueCE", 2:"9get_valuev"})
check('function', 'int get_value() const noexcept', check('function', 'int get_value() const noexcept',
"get_valueC", "NK9get_valueEv") {1:"get_valueC", 2:"NK9get_valueEv"})
check('function', 'int get_value() const noexcept = delete', check('function', 'int get_value() const noexcept = delete',
"get_valueC", "NK9get_valueEv") {1:"get_valueC", 2:"NK9get_valueEv"})
check('function', 'int get_value() volatile const', check('function', 'int get_value() volatile const',
"get_valueVC", "NVK9get_valueEv") {1:"get_valueVC", 2:"NVK9get_valueEv"})
check('function', 'MyClass::MyClass(MyClass::MyClass&&) = default', check('function', 'MyClass::MyClass(MyClass::MyClass&&) = default',
"MyClass::MyClass__MyClass::MyClassRR", {1:"MyClass::MyClass__MyClass::MyClassRR",
"N7MyClass7MyClassERRN7MyClass7MyClassE") 2:"N7MyClass7MyClassERRN7MyClass7MyClassE"})
check('function', 'virtual MyClass::a_virtual_function() const override', check('function', 'virtual MyClass::a_virtual_function() const override',
"MyClass::a_virtual_functionC", "NK7MyClass18a_virtual_functionEv") {1:"MyClass::a_virtual_functionC", 2:"NK7MyClass18a_virtual_functionEv"})
check('function', 'A B() override', "B", "1Bv") check('function', 'A B() override', {1:"B", 2:"1Bv"})
check('function', 'A B() final', "B", "1Bv") check('function', 'A B() final', {1:"B", 2:"1Bv"})
check('function', 'A B() final override', "B", "1Bv") check('function', 'A B() final override', {1:"B", 2:"1Bv"})
check('function', 'A B() override final', "B", "1Bv", check('function', 'A B() override final', {1:"B", 2:"1Bv"},
output='A B() final override') output='A B() final override')
check('function', 'MyClass::a_member_function() volatile', check('function', 'MyClass::a_member_function() volatile',
"MyClass::a_member_functionV", "NV7MyClass17a_member_functionEv") {1:"MyClass::a_member_functionV", 2:"NV7MyClass17a_member_functionEv"})
check('function', 'MyClass::a_member_function() volatile const', check('function', 'MyClass::a_member_function() volatile const',
"MyClass::a_member_functionVC", "NVK7MyClass17a_member_functionEv") {1:"MyClass::a_member_functionVC", 2:"NVK7MyClass17a_member_functionEv"})
check('function', 'MyClass::a_member_function() &&', check('function', 'MyClass::a_member_function() &&',
"MyClass::a_member_functionO", "NO7MyClass17a_member_functionEv") {1:"MyClass::a_member_functionO", 2:"NO7MyClass17a_member_functionEv"})
check('function', 'MyClass::a_member_function() &', check('function', 'MyClass::a_member_function() &',
"MyClass::a_member_functionR", "NR7MyClass17a_member_functionEv") {1:"MyClass::a_member_functionR", 2:"NR7MyClass17a_member_functionEv"})
check('function', 'MyClass::a_member_function() const &', check('function', 'MyClass::a_member_function() const &',
"MyClass::a_member_functionCR", "NKR7MyClass17a_member_functionEv") {1:"MyClass::a_member_functionCR", 2:"NKR7MyClass17a_member_functionEv"})
check('function', 'int main(int argc, char *argv[])', check('function', 'int main(int argc, char *argv[])',
"main__i.cPA", "4mainiA_Pc") {1:"main__i.cPA", 2:"4mainiA_Pc"})
check('function', 'MyClass &MyClass::operator++()', check('function', 'MyClass &MyClass::operator++()',
"MyClass::inc-operator", "N7MyClassppEv") {1:"MyClass::inc-operator", 2:"N7MyClassppEv"})
check('function', 'MyClass::pointer MyClass::operator->()', check('function', 'MyClass::pointer MyClass::operator->()',
"MyClass::pointer-operator", "N7MyClassptEv") {1:"MyClass::pointer-operator", 2:"N7MyClassptEv"})
x = 'std::vector<std::pair<std::string, int>> &module::test(register int ' \ x = 'std::vector<std::pair<std::string, int>> &module::test(register int ' \
'foo, bar[n], std::string baz = "foobar, blah, bleh") const = 0' 'foo, bar[n], std::string baz = "foobar, blah, bleh") const = 0'
check('function', x, "module::test__i.barA.ssC", check('function', x, {1:"module::test__i.barA.ssC",
"NK6module4testEiAn_3barNSt6stringE") 2:"NK6module4testEiAn_3barNSt6stringE",
3:"NK6module4testEiA1n_3barNSt6stringE"})
check('function', check('function',
'int foo(Foo f = Foo(double(), std::make_pair(int(2), double(3.4))))', 'int foo(Foo f = Foo(double(), std::make_pair(int(2), double(3.4))))',
"foo__Foo", "3foo3Foo") {1:"foo__Foo", 2:"3foo3Foo"})
check('function', 'int foo(A a = x(a))', "foo__A", "3foo1A") check('function', 'int foo(A a = x(a))', {1:"foo__A", 2:"3foo1A"})
with pytest.raises(DefinitionError): with pytest.raises(DefinitionError):
parse('function', 'int foo(B b=x(a)') parse('function', 'int foo(B b=x(a)')
with pytest.raises(DefinitionError): with pytest.raises(DefinitionError):
parse('function', 'int foo)C c=x(a))') parse('function', 'int foo)C c=x(a))')
with pytest.raises(DefinitionError): with pytest.raises(DefinitionError):
parse('function', 'int foo(D d=x(a') parse('function', 'int foo(D d=x(a')
check('function', 'int foo(const A&... a)', "foo__ACRDp", "3fooDpRK1A") check('function', 'int foo(const A&... a)', {1:"foo__ACRDp", 2:"3fooDpRK1A"})
check('function', 'virtual void f()', "f", "1fv") check('function', 'virtual void f()', {1:"f", 2:"1fv"})
# test for ::nestedName, from issue 1738 # test for ::nestedName, from issue 1738
check("function", "result(int val, ::std::error_category const &cat)", check("function", "result(int val, ::std::error_category const &cat)",
"result__i.std::error_categoryCR", "6resultiRNSt14error_categoryE") {1:"result__i.std::error_categoryCR", 2:"6resultiRNSt14error_categoryE"})
check("function", "int *f()", "f", "1fv") check("function", "int *f()", {1:"f", 2:"1fv"})
# tests derived from issue #1753 (skip to keep sanity) # tests derived from issue #1753 (skip to keep sanity)
check("function", "f(int (&array)[10])", None, "1fRA10_i") check("function", "f(int (&array)[10])", {2:"1fRA10_i", 3:"1fRAL10E_i"})
check("function", "void f(int (&array)[10])", None, "1fRA10_i") check("function", "void f(int (&array)[10])", {2:"1fRA10_i", 3:"1fRAL10E_i"})
check("function", "void f(float *q(double))", None, "1fFPfdE") check("function", "void f(float *q(double))", {2:"1fFPfdE"})
check("function", "void f(float *(*q)(double))", None, "1fPFPfdE") check("function", "void f(float *(*q)(double))", {2:"1fPFPfdE"})
check("function", "void f(float (*q)(double))", None, "1fPFfdE") check("function", "void f(float (*q)(double))", {2:"1fPFfdE"})
check("function", "int (*f(double d))(float)", "f__double", "1fd") check("function", "int (*f(double d))(float)", {1:"f__double", 2:"1fd"})
check("function", "int (*f(bool b))[5]", "f__b", "1fb") check("function", "int (*f(bool b))[5]", {1:"f__b", 2:"1fb"})
check("function", "int (*A::f(double d) const)(float)", check("function", "int (*A::f(double d) const)(float)",
"A::f__doubleC", "NK1A1fEd") {1:"A::f__doubleC", 2:"NK1A1fEd"})
check("function", "void f(std::shared_ptr<int(double)> ptr)", check("function", "void f(std::shared_ptr<int(double)> ptr)",
None, "1fNSt10shared_ptrIFidEEE") {2:"1fNSt10shared_ptrIFidEEE"})
check("function", "void f(int *const p)", "f__iPC", "1fPCi") check("function", "void f(int *const p)", {1:"f__iPC", 2:"1fPCi"})
check("function", "void f(int *volatile const p)", "f__iPVC", "1fPVCi") check("function", "void f(int *volatile const p)", {1:"f__iPVC", 2:"1fPVCi"})
check('function', 'extern int f()', 'f', '1fv') check('function', 'extern int f()', {1:'f', 2:'1fv'})
# TODO: make tests for functions in a template, e.g., Test<int&&()> # TODO: make tests for functions in a template, e.g., Test<int&&()>
# such that the id generation for function type types is correct. # such that the id generation for function type types is correct.
check('function', 'friend std::ostream &f(std::ostream&, int)', check('function', 'friend std::ostream &f(std::ostream&, int)',
'f__osR.i', '1fRNSt7ostreamEi') {1:'f__osR.i', 2:'1fRNSt7ostreamEi'})
# from breathe#223 # from breathe#223
check('function', 'void f(struct E e)', 'f__E', '1f1E') check('function', 'void f(struct E e)', {1:'f__E', 2:'1f1E'})
check('function', 'void f(class E e)', 'f__E', '1f1E') check('function', 'void f(class E e)', {1:'f__E', 2:'1f1E'})
check('function', 'void f(typename E e)', 'f__E', '1f1E') check('function', 'void f(typename E e)', {1:'f__E', 2:'1f1E'})
check('function', 'void f(enum E e)', 'f__E', '1f1E') check('function', 'void f(enum E e)', {1:'f__E', 2:'1f1E'})
check('function', 'void f(union E e)', 'f__E', '1f1E') check('function', 'void f(union E e)', {1:'f__E', 2:'1f1E'})
# pointer to member (function) # pointer to member (function)
check('function', 'void f(int C::*)', None, '1fM1Ci') check('function', 'void f(int C::*)', {2:'1fM1Ci'})
check('function', 'void f(int C::* p)', None, '1fM1Ci') check('function', 'void f(int C::* p)', {2:'1fM1Ci'})
check('function', 'void f(int ::C::* p)', None, '1fM1Ci') check('function', 'void f(int ::C::* p)', {2:'1fM1Ci'})
check('function', 'void f(int C::* const)', None, '1fKM1Ci') check('function', 'void f(int C::* const)', {2:'1fKM1Ci'})
check('function', 'void f(int C::* const&)', None, '1fRKM1Ci') check('function', 'void f(int C::* const&)', {2:'1fRKM1Ci'})
check('function', 'void f(int C::* volatile)', None, '1fVM1Ci') check('function', 'void f(int C::* volatile)', {2:'1fVM1Ci'})
check('function', 'void f(int C::* const volatile)', None, '1fVKM1Ci', check('function', 'void f(int C::* const volatile)', {2:'1fVKM1Ci'},
output='void f(int C::* volatile const)') output='void f(int C::* volatile const)')
check('function', 'void f(int C::* volatile const)', None, '1fVKM1Ci') check('function', 'void f(int C::* volatile const)', {2:'1fVKM1Ci'})
check('function', 'void f(int (C::*)(float, double))', None, '1fM1CFifdE') check('function', 'void f(int (C::*)(float, double))', {2:'1fM1CFifdE'})
check('function', 'void f(int (C::* p)(float, double))', None, '1fM1CFifdE') check('function', 'void f(int (C::* p)(float, double))', {2:'1fM1CFifdE'})
check('function', 'void f(int (::C::* p)(float, double))', None, '1fM1CFifdE') check('function', 'void f(int (::C::* p)(float, double))', {2:'1fM1CFifdE'})
check('function', 'void f(void (C::*)() const &)', None, '1fM1CKRFvvE') check('function', 'void f(void (C::*)() const &)', {2:'1fM1CKRFvvE'})
check('function', 'int C::* f(int, double)', None, '1fid') check('function', 'int C::* f(int, double)', {2:'1fid'})
check('function', 'void f(int C::* *)', None, '1fPM1Ci') check('function', 'void f(int C::* *)', {2:'1fPM1Ci'})
def test_operators(): def test_operators():
check('function', 'void operator new [ ] ()', check('function', 'void operator new [ ] ()',
"new-array-operator", "nav", output='void operator new[]()') {1:"new-array-operator", 2:"nav"}, output='void operator new[]()')
check('function', 'void operator delete ()', check('function', 'void operator delete ()',
"delete-operator", "dlv", output='void operator delete()') {1:"delete-operator", 2:"dlv"}, output='void operator delete()')
check('function', 'operator bool() const', check('function', 'operator bool() const',
"castto-b-operatorC", "NKcvbEv", output='operator bool() const') {1:"castto-b-operatorC", 2:"NKcvbEv"}, output='operator bool() const')
check('function', 'void operator * ()', check('function', 'void operator * ()',
"mul-operator", "mlv", output='void operator*()') {1:"mul-operator", 2:"mlv"}, output='void operator*()')
check('function', 'void operator - ()', check('function', 'void operator - ()',
"sub-operator", "miv", output='void operator-()') {1:"sub-operator", 2:"miv"}, output='void operator-()')
check('function', 'void operator + ()', check('function', 'void operator + ()',
"add-operator", "plv", output='void operator+()') {1:"add-operator", 2:"plv"}, output='void operator+()')
check('function', 'void operator = ()', check('function', 'void operator = ()',
"assign-operator", "aSv", output='void operator=()') {1:"assign-operator", 2:"aSv"}, output='void operator=()')
check('function', 'void operator / ()', check('function', 'void operator / ()',
"div-operator", "dvv", output='void operator/()') {1:"div-operator", 2:"dvv"}, output='void operator/()')
check('function', 'void operator % ()', check('function', 'void operator % ()',
"mod-operator", "rmv", output='void operator%()') {1:"mod-operator", 2:"rmv"}, output='void operator%()')
check('function', 'void operator ! ()', check('function', 'void operator ! ()',
"not-operator", "ntv", output='void operator!()') {1:"not-operator", 2:"ntv"}, output='void operator!()')
check('function', 'void operator "" _udl()', check('function', 'void operator "" _udl()',
None, 'li4_udlv', output='void operator""_udl()') {2:'li4_udlv'}, output='void operator""_udl()')
def test_class_definitions(): def test_class_definitions():
check('class', 'public A', "A", "1A", output='A') check('class', 'public A', {1:"A", 2:"1A"}, output='A')
check('class', 'private A', "A", "1A") check('class', 'private A', {1:"A", 2:"1A"})
check('class', 'A final', 'A', '1A') check('class', 'A final', {1:'A', 2:'1A'})
# test bases # test bases
check('class', 'A', "A", "1A") check('class', 'A', {1:"A", 2:"1A"})
check('class', 'A::B::C', "A::B::C", "N1A1B1CE") check('class', 'A::B::C', {1:"A::B::C", 2:"N1A1B1CE"})
check('class', 'A : B', "A", "1A") check('class', 'A : B', {1:"A", 2:"1A"})
check('class', 'A : private B', "A", "1A", output='A : B') check('class', 'A : private B', {1:"A", 2:"1A"}, output='A : B')
check('class', 'A : public B', "A", "1A") check('class', 'A : public B', {1:"A", 2:"1A"})
check('class', 'A : B, C', "A", "1A") check('class', 'A : B, C', {1:"A", 2:"1A"})
check('class', 'A : B, protected C, D', "A", "1A") check('class', 'A : B, protected C, D', {1:"A", 2:"1A"})
check('class', 'A : virtual private B', 'A', '1A', output='A : virtual B') check('class', 'A : virtual private B', {1:'A', 2:'1A'}, output='A : virtual B')
check('class', 'A : B, virtual C', 'A', '1A') check('class', 'A : B, virtual C', {1:'A', 2:'1A'})
check('class', 'A : public virtual B', 'A', '1A') check('class', 'A : public virtual B', {1:'A', 2:'1A'})
check('class', 'A : B, C...', 'A', '1A') check('class', 'A : B, C...', {1:'A', 2:'1A'})
check('class', 'A : B..., C', 'A', '1A') check('class', 'A : B..., C', {1:'A', 2:'1A'})
def test_enum_definitions(): def test_enum_definitions():
check('enum', 'A', None, "1A") check('enum', 'A', {2:"1A"})
check('enum', 'A : std::underlying_type<B>::type', None, "1A") check('enum', 'A : std::underlying_type<B>::type', {2:"1A"})
check('enum', 'A : unsigned int', None, "1A") check('enum', 'A : unsigned int', {2:"1A"})
check('enum', 'public A', None, "1A", output='A') check('enum', 'public A', {2:"1A"}, output='A')
check('enum', 'private A', None, "1A") check('enum', 'private A', {2:"1A"})
check('enumerator', 'A', None, "1A") check('enumerator', 'A', {2:"1A"})
check('enumerator', 'A = std::numeric_limits<unsigned long>::max()', check('enumerator', 'A = std::numeric_limits<unsigned long>::max()', {2:"1A"})
None, "1A")
def test_templates(): def test_templates():
check('class', "A<T>", None, "IE1AI1TE", output="template<> A<T>") check('class', "A<T>", {2:"IE1AI1TE"}, output="template<> A<T>")
# first just check which objects support templating # first just check which objects support templating
check('class', "template<> A", None, "IE1A") check('class', "template<> A", {2:"IE1A"})
check('function', "template<> void A()", None, "IE1Av") check('function', "template<> void A()", {2:"IE1Av"})
check('member', "template<> A a", None, "IE1a") check('member', "template<> A a", {2:"IE1a"})
check('type', "template<> a = A", None, "IE1a") check('type', "template<> a = A", {2:"IE1a"})
with pytest.raises(DefinitionError): with pytest.raises(DefinitionError):
parse('enum', "template<> A") parse('enum', "template<> A")
with pytest.raises(DefinitionError): with pytest.raises(DefinitionError):
parse('enumerator', "template<> A") parse('enumerator', "template<> A")
# then all the real tests # then all the real tests
check('class', "template<typename T1, typename T2> A", None, "I00E1A") check('class', "template<typename T1, typename T2> A", {2:"I00E1A"})
check('type', "template<> a", None, "IE1a") check('type', "template<> a", {2:"IE1a"})
check('class', "template<typename T> A", None, "I0E1A") check('class', "template<typename T> A", {2:"I0E1A"})
check('class', "template<class T> A", None, "I0E1A") check('class', "template<class T> A", {2:"I0E1A"})
check('class', "template<typename ...T> A", None, "IDpE1A") check('class', "template<typename ...T> A", {2:"IDpE1A"})
check('class', "template<typename...> A", None, "IDpE1A") check('class', "template<typename...> A", {2:"IDpE1A"})
check('class', "template<typename = Test> A", None, "I0E1A") check('class', "template<typename = Test> A", {2:"I0E1A"})
check('class', "template<typename T = Test> A", None, "I0E1A") check('class', "template<typename T = Test> A", {2:"I0E1A"})
check('class', "template<template<typename> typename T> A", check('class', "template<template<typename> typename T> A", {2:"II0E0E1A"})
None, "II0E0E1A") check('class', "template<int> A", {2:"I_iE1A"})
check('class', "template<int> A", None, "I_iE1A") check('class', "template<int T> A", {2:"I_iE1A"})
check('class', "template<int T> A", None, "I_iE1A") check('class', "template<int... T> A", {2:"I_DpiE1A"})
check('class', "template<int... T> A", None, "I_DpiE1A") check('class', "template<int T = 42> A", {2:"I_iE1A"})
check('class', "template<int T = 42> A", None, "I_iE1A") check('class', "template<int = 42> A", {2:"I_iE1A"})
check('class', "template<int = 42> A", None, "I_iE1A")
# from #2058 # from #2058
check('function', check('function',
@ -414,8 +501,8 @@ def test_templates():
"inline std::basic_ostream<Char, Traits> &operator<<(" "inline std::basic_ostream<Char, Traits> &operator<<("
"std::basic_ostream<Char, Traits> &os, " "std::basic_ostream<Char, Traits> &os, "
"const c_string_view_base<const Char, Traits> &str)", "const c_string_view_base<const Char, Traits> &str)",
None, "I00ElsRNSt13basic_ostreamI4Char6TraitsEE" {2:"I00ElsRNSt13basic_ostreamI4Char6TraitsEE"
"RK18c_string_view_baseIK4Char6TraitsE") "RK18c_string_view_baseIK4Char6TraitsE"})
# template introductions # template introductions
with pytest.raises(DefinitionError): with pytest.raises(DefinitionError):
@ -423,63 +510,64 @@ def test_templates():
with pytest.raises(DefinitionError): with pytest.raises(DefinitionError):
parse('enumerator', 'abc::ns::foo{id_0, id_1, id_2} A') parse('enumerator', 'abc::ns::foo{id_0, id_1, id_2} A')
check('class', 'abc::ns::foo{id_0, id_1, id_2} xyz::bar', check('class', 'abc::ns::foo{id_0, id_1, id_2} xyz::bar',
None, 'I000EXN3abc2ns3fooEI4id_04id_14id_2EEN3xyz3barE') {2:'I000EXN3abc2ns3fooEI4id_04id_14id_2EEN3xyz3barE'})
check('class', 'abc::ns::foo{id_0, id_1, ...id_2} xyz::bar', check('class', 'abc::ns::foo{id_0, id_1, ...id_2} xyz::bar',
None, 'I00DpEXN3abc2ns3fooEI4id_04id_1sp4id_2EEN3xyz3barE') {2:'I00DpEXN3abc2ns3fooEI4id_04id_1sp4id_2EEN3xyz3barE'})
check('class', 'abc::ns::foo{id_0, id_1, id_2} xyz::bar<id_0, id_1, id_2>', check('class', 'abc::ns::foo{id_0, id_1, id_2} xyz::bar<id_0, id_1, id_2>',
None, 'I000EXN3abc2ns3fooEI4id_04id_14id_2EEN3xyz3barI4id_04id_14id_2EE') {2:'I000EXN3abc2ns3fooEI4id_04id_14id_2EEN3xyz3barI4id_04id_14id_2EE'})
check('class', 'abc::ns::foo{id_0, id_1, ...id_2} xyz::bar<id_0, id_1, id_2...>', check('class', 'abc::ns::foo{id_0, id_1, ...id_2} xyz::bar<id_0, id_1, id_2...>',
None, 'I00DpEXN3abc2ns3fooEI4id_04id_1sp4id_2EEN3xyz3barI4id_04id_1Dp4id_2EE') {2:'I00DpEXN3abc2ns3fooEI4id_04id_1sp4id_2EEN3xyz3barI4id_04id_1Dp4id_2EE'})
check('class', 'template<> Concept{U} A<int>::B', check('class', 'template<> Concept{U} A<int>::B', {2:'IEI0EX7ConceptI1UEEN1AIiE1BE'})
None, 'IEI0EX7ConceptI1UEEN1AIiE1BE')
check('type', 'abc::ns::foo{id_0, id_1, id_2} xyz::bar = ghi::qux', check('type', 'abc::ns::foo{id_0, id_1, id_2} xyz::bar = ghi::qux',
None, 'I000EXN3abc2ns3fooEI4id_04id_14id_2EEN3xyz3barE') {2:'I000EXN3abc2ns3fooEI4id_04id_14id_2EEN3xyz3barE'})
check('type', 'abc::ns::foo{id_0, id_1, ...id_2} xyz::bar = ghi::qux', check('type', 'abc::ns::foo{id_0, id_1, ...id_2} xyz::bar = ghi::qux',
None, 'I00DpEXN3abc2ns3fooEI4id_04id_1sp4id_2EEN3xyz3barE') {2:'I00DpEXN3abc2ns3fooEI4id_04id_1sp4id_2EEN3xyz3barE'})
check('function', 'abc::ns::foo{id_0, id_1, id_2} void xyz::bar()', check('function', 'abc::ns::foo{id_0, id_1, id_2} void xyz::bar()',
None, 'I000EXN3abc2ns3fooEI4id_04id_14id_2EEN3xyz3barEv') {2:'I000EXN3abc2ns3fooEI4id_04id_14id_2EEN3xyz3barEv'})
check('function', 'abc::ns::foo{id_0, id_1, ...id_2} void xyz::bar()', check('function', 'abc::ns::foo{id_0, id_1, ...id_2} void xyz::bar()',
None, 'I00DpEXN3abc2ns3fooEI4id_04id_1sp4id_2EEN3xyz3barEv') {2:'I00DpEXN3abc2ns3fooEI4id_04id_1sp4id_2EEN3xyz3barEv'})
check('member', 'abc::ns::foo{id_0, id_1, id_2} ghi::qux xyz::bar', check('member', 'abc::ns::foo{id_0, id_1, id_2} ghi::qux xyz::bar',
None, 'I000EXN3abc2ns3fooEI4id_04id_14id_2EEN3xyz3barE') {2:'I000EXN3abc2ns3fooEI4id_04id_14id_2EEN3xyz3barE'})
check('member', 'abc::ns::foo{id_0, id_1, ...id_2} ghi::qux xyz::bar', check('member', 'abc::ns::foo{id_0, id_1, ...id_2} ghi::qux xyz::bar',
None, 'I00DpEXN3abc2ns3fooEI4id_04id_1sp4id_2EEN3xyz3barE') {2:'I00DpEXN3abc2ns3fooEI4id_04id_1sp4id_2EEN3xyz3barE'})
check('concept', 'Iterator{T, U} Another', check('concept', 'Iterator{T, U} Another', {2:'I00EX8IteratorI1T1UEE7Another'})
None, 'I00EX8IteratorI1T1UEE7Another')
check('concept', 'template<typename ...Pack> Numerics = (... && Numeric<Pack>)', check('concept', 'template<typename ...Pack> Numerics = (... && Numeric<Pack>)',
None, 'IDpE8Numerics') {2:'IDpE8Numerics'})
def test_template_args(): def test_template_args():
# from breathe#218 # from breathe#218
check('function', check('function',
"template<typename F> " "template<typename F> "
"void allow(F *f, typename func<F, B, G!=1>::type tt)", "void allow(F *f, typename func<F, B, G != 1>::type tt)",
None, "I0E5allowP1FN4funcI1F1BXG!=1EE4typeE") {2:"I0E5allowP1FN4funcI1F1BXG != 1EE4typeE",
3:"I0E5allowP1FN4funcI1F1BXne1GL1EEE4typeE"})
# from #3542 # from #3542
check('type', "template<typename T> " check('type', "template<typename T> "
"enable_if_not_array_t = std::enable_if_t<!is_array<T>::value, int>", "enable_if_not_array_t = std::enable_if_t<!is_array<T>::value, int>",
None, "I0E21enable_if_not_array_t") {2:"I0E21enable_if_not_array_t"})
def test_attributes(): def test_attributes():
# style: C++ # style: C++
check('member', '[[]] int f', 'f__i', '1f') check('member', '[[]] int f', {1:'f__i', 2:'1f'})
check('member', '[ [ ] ] int f', 'f__i', '1f', check('member', '[ [ ] ] int f', {1:'f__i', 2:'1f'},
# this will fail when the proper grammar is implemented # this will fail when the proper grammar is implemented
output='[[ ]] int f') output='[[ ]] int f')
check('member', '[[a]] int f', 'f__i', '1f') check('member', '[[a]] int f', {1:'f__i', 2:'1f'})
# style: GNU # style: GNU
check('member', '__attribute__(()) int f', 'f__i', '1f') check('member', '__attribute__(()) int f', {1:'f__i', 2:'1f'})
check('member', '__attribute__((a)) int f', 'f__i', '1f') check('member', '__attribute__((a)) int f', {1:'f__i', 2:'1f'})
check('member', '__attribute__((a, b)) int f', 'f__i', '1f') check('member', '__attribute__((a, b)) int f', {1:'f__i', 2:'1f'})
# style: user-defined id # style: user-defined id
check('member', 'id_attr int f', 'f__i', '1f') check('member', 'id_attr int f', {1:'f__i', 2:'1f'})
# style: user-defined paren # style: user-defined paren
check('member', 'paren_attr() int f', 'f__i', '1f') check('member', 'paren_attr() int f', {1:'f__i', 2:'1f'})
check('member', 'paren_attr(a) int f', 'f__i', '1f') check('member', 'paren_attr(a) int f', {1:'f__i', 2:'1f'})
check('member', 'paren_attr("") int f', 'f__i', '1f') check('member', 'paren_attr("") int f', {1:'f__i', 2:'1f'})
check('member', 'paren_attr(()[{}][]{}) int f', 'f__i', '1f') check('member', 'paren_attr(()[{}][]{}) int f', {1:'f__i', 2:'1f'})
with pytest.raises(DefinitionError): with pytest.raises(DefinitionError):
parse('member', 'paren_attr(() int f') parse('member', 'paren_attr(() int f')
with pytest.raises(DefinitionError): with pytest.raises(DefinitionError):
@ -495,7 +583,7 @@ def test_attributes():
# position: decl specs # position: decl specs
check('function', 'static inline __attribute__(()) void f()', check('function', 'static inline __attribute__(()) void f()',
'f', '1fv', {1:'f', 2:'1fv'},
output='__attribute__(()) static inline void f()') output='__attribute__(()) static inline void f()')

View File

@ -12,7 +12,6 @@
import re import re
import pytest import pytest
from util import SkipTest
@pytest.mark.sphinx( @pytest.mark.sphinx(
@ -40,9 +39,9 @@ def test_jsmath(app, status, warning):
def test_imgmath_png(app, status, warning): def test_imgmath_png(app, status, warning):
app.builder.build_all() app.builder.build_all()
if "LaTeX command 'latex' cannot be run" in warning.getvalue(): if "LaTeX command 'latex' cannot be run" in warning.getvalue():
raise SkipTest('LaTeX command "latex" is not available') raise pytest.skip.Exception('LaTeX command "latex" is not available')
if "dvipng command 'dvipng' cannot be run" in warning.getvalue(): if "dvipng command 'dvipng' cannot be run" in warning.getvalue():
raise SkipTest('dvipng command "dvipng" is not available') raise pytest.skip.Exception('dvipng command "dvipng" is not available')
content = (app.outdir / 'index.html').text() content = (app.outdir / 'index.html').text()
html = (r'<div class="math">\s*<p>\s*<img src="_images/math/\w+.png"' html = (r'<div class="math">\s*<p>\s*<img src="_images/math/\w+.png"'
@ -56,9 +55,9 @@ def test_imgmath_png(app, status, warning):
def test_imgmath_svg(app, status, warning): def test_imgmath_svg(app, status, warning):
app.builder.build_all() app.builder.build_all()
if "LaTeX command 'latex' cannot be run" in warning.getvalue(): if "LaTeX command 'latex' cannot be run" in warning.getvalue():
raise SkipTest('LaTeX command "latex" is not available') raise pytest.skip.Exception('LaTeX command "latex" is not available')
if "dvisvgm command 'dvisvgm' cannot be run" in warning.getvalue(): if "dvisvgm command 'dvisvgm' cannot be run" in warning.getvalue():
raise SkipTest('dvisvgm command "dvisvgm" is not available') raise pytest.skip.Exception('dvisvgm command "dvisvgm" is not available')
content = (app.outdir / 'index.html').text() content = (app.outdir / 'index.html').text()
html = (r'<div class="math">\s*<p>\s*<img src="_images/math/\w+.svg"' html = (r'<div class="math">\s*<p>\s*<img src="_images/math/\w+.svg"'

View File

@ -16,8 +16,6 @@ from six import PY2, text_type, StringIO
from six.moves import input from six.moves import input
import pytest import pytest
from util import SkipTest
from sphinx import application from sphinx import application
from sphinx import quickstart as qs from sphinx import quickstart as qs
from sphinx.util.console import nocolor, coloron from sphinx.util.console import nocolor, coloron
@ -121,7 +119,7 @@ def test_do_prompt_with_nonascii():
try: try:
qs.do_prompt(d, 'k1', 'Q1', default=u'\u65e5\u672c') qs.do_prompt(d, 'k1', 'Q1', default=u'\u65e5\u672c')
except UnicodeEncodeError: except UnicodeEncodeError:
raise SkipTest( raise pytest.skip.Exception(
'non-ASCII console input not supported on this encoding: %s', 'non-ASCII console input not supported on this encoding: %s',
qs.TERM_ENCODING) qs.TERM_ENCODING)
assert d['k1'] == u'\u30c9\u30a4\u30c4' assert d['k1'] == u'\u30c9\u30a4\u30c4'

View File

@ -11,11 +11,9 @@ import os
import re import re
import sys import sys
import warnings import warnings
from functools import wraps
from xml.etree import ElementTree from xml.etree import ElementTree
from six import string_types from six import string_types
from six import StringIO
import pytest import pytest
@ -26,7 +24,6 @@ from sphinx import application
from sphinx.builders.latex import LaTeXBuilder from sphinx.builders.latex import LaTeXBuilder
from sphinx.ext.autodoc import AutoDirective from sphinx.ext.autodoc import AutoDirective
from sphinx.pycode import ModuleAnalyzer from sphinx.pycode import ModuleAnalyzer
from sphinx.deprecation import RemovedInSphinx17Warning
from path import path from path import path
@ -201,160 +198,3 @@ def find_files(root, suffix=None):
def strip_escseq(text): def strip_escseq(text):
return re.sub('\x1b.*?m', '', text) return re.sub('\x1b.*?m', '', text)
# #############################################
# DEPRECATED implementations
def gen_with_app(*args, **kwargs):
"""
**DEPRECATED**: use pytest.mark.parametrize instead.
Decorate a test generator to pass a SphinxTestApp as the first argument to
the test generator when it's executed.
"""
def generator(func):
@wraps(func)
def deco(*args2, **kwargs2):
status, warning = StringIO(), StringIO()
kwargs['status'] = status
kwargs['warning'] = warning
app = SphinxTestApp(*args, **kwargs)
try:
for item in func(app, status, warning, *args2, **kwargs2):
yield item
finally:
app.cleanup()
return deco
return generator
def skip_if(condition, msg=None):
"""
**DEPRECATED**: use pytest.mark.skipif instead.
Decorator to skip test if condition is true.
"""
return pytest.mark.skipif(condition, reason=(msg or 'conditional skip'))
def skip_unless(condition, msg=None):
"""
**DEPRECATED**: use pytest.mark.skipif instead.
Decorator to skip test if condition is false.
"""
return pytest.mark.skipif(not condition, reason=(msg or 'conditional skip'))
def with_tempdir(func):
"""
**DEPRECATED**: use tempdir fixture instead.
"""
return func
def raises(exc, func, *args, **kwds):
"""
**DEPRECATED**: use pytest.raises instead.
Raise AssertionError if ``func(*args, **kwds)`` does not raise *exc*.
"""
with pytest.raises(exc):
func(*args, **kwds)
def raises_msg(exc, msg, func, *args, **kwds):
"""
**DEPRECATED**: use pytest.raises instead.
Raise AssertionError if ``func(*args, **kwds)`` does not raise *exc*,
and check if the message contains *msg*.
"""
with pytest.raises(exc) as excinfo:
func(*args, **kwds)
assert msg in str(excinfo.value)
def assert_true(v1, msg=''):
"""
**DEPRECATED**: use assert instead.
"""
assert v1, msg
def assert_equal(v1, v2, msg=''):
"""
**DEPRECATED**: use assert instead.
"""
assert v1 == v2, msg
def assert_in(x, thing, msg=''):
"""
**DEPRECATED**: use assert instead.
"""
if x not in thing:
assert False, msg or '%r is not in %r' % (x, thing)
def assert_not_in(x, thing, msg=''):
"""
**DEPRECATED**: use assert instead.
"""
if x in thing:
assert False, msg or '%r is in %r' % (x, thing)
class ListOutput(object):
"""
File-like object that collects written text in a list.
"""
def __init__(self, name):
self.name = name
self.content = []
def reset(self):
del self.content[:]
def write(self, text):
self.content.append(text)
# **DEPRECATED**: use pytest.skip instead.
SkipTest = pytest.skip.Exception
class _DeprecationWrapper(object):
def __init__(self, mod, deprecated):
self._mod = mod
self._deprecated = deprecated
def __getattr__(self, attr):
if attr in self._deprecated:
obj, instead = self._deprecated[attr]
warnings.warn("tests/util.py::%s is deprecated and will be "
"removed in Sphinx 1.7, please use %s instead."
% (attr, instead),
RemovedInSphinx17Warning, stacklevel=2)
return obj
return getattr(self._mod, attr)
sys.modules[__name__] = _DeprecationWrapper(sys.modules[__name__], dict( # type: ignore
with_app=(pytest.mark.sphinx, 'pytest.mark.sphinx'),
TestApp=(SphinxTestApp, 'SphinxTestApp'),
gen_with_app=(gen_with_app, 'pytest.mark.parametrize'),
skip_if=(skip_if, 'pytest.skipif'),
skip_unless=(skip_unless, 'pytest.skipif'),
with_tempdir=(with_tempdir, 'tmpdir pytest fixture'),
raises=(raises, 'pytest.raises'),
raises_msg=(raises_msg, 'pytest.raises'),
assert_true=(assert_true, 'assert'),
assert_equal=(assert_equal, 'assert'),
assert_in=(assert_in, 'assert'),
assert_not_in=(assert_not_in, 'assert'),
ListOutput=(ListOutput, 'StringIO'),
SkipTest=(SkipTest, 'pytest.skip'),
))

View File

@ -9,7 +9,6 @@ deps=
mock mock
enum34 enum34
typing typing
sphinxcontrib-websupport
setenv = setenv =
SPHINX_TEST_TEMPDIR = {envdir}/testbuild SPHINX_TEST_TEMPDIR = {envdir}/testbuild
PYTHONDONTWRITEBYTECODE = true PYTHONDONTWRITEBYTECODE = true