mirror of
https://github.com/sphinx-doc/sphinx.git
synced 2025-02-25 18:55:22 -06:00
Merge branch '2.0' into 6311_autosummary_confused_by_complex_typehints2
This commit is contained in:
commit
59d0f076ec
20
CHANGES
20
CHANGES
@ -11,6 +11,7 @@ Incompatible changes
|
|||||||
API directly
|
API directly
|
||||||
* #6230: The anchor of term in glossary directive is changed if it is consisted
|
* #6230: The anchor of term in glossary directive is changed if it is consisted
|
||||||
by non-ASCII characters
|
by non-ASCII characters
|
||||||
|
* #4550: html: Centering tables by default using CSS
|
||||||
|
|
||||||
Deprecated
|
Deprecated
|
||||||
----------
|
----------
|
||||||
@ -73,7 +74,8 @@ Features added
|
|||||||
* #6180: Support ``--keep-going`` with BuildDoc setup command
|
* #6180: Support ``--keep-going`` with BuildDoc setup command
|
||||||
* ``math`` directive now supports ``:class:`` option
|
* ``math`` directive now supports ``:class:`` option
|
||||||
* todo: ``todo`` directive now supports ``:name:`` option
|
* todo: ``todo`` directive now supports ``:name:`` option
|
||||||
* #6232: Enable CLI override of Makefile variables
|
* Enable override via environment of ``SPHINXOPTS`` and ``SPHINXBUILD`` Makefile
|
||||||
|
variables (refs: #6232, #6303)
|
||||||
* #6287: autodoc: Unable to document bound instance methods exported as module
|
* #6287: autodoc: Unable to document bound instance methods exported as module
|
||||||
functions
|
functions
|
||||||
* #6289: autodoc: :confval:`autodoc_default_options` now supports
|
* #6289: autodoc: :confval:`autodoc_default_options` now supports
|
||||||
@ -83,8 +85,16 @@ Features added
|
|||||||
imported members on autosummary
|
imported members on autosummary
|
||||||
* #6271: ``make clean`` is catastrophically broken if building into '.'
|
* #6271: ``make clean`` is catastrophically broken if building into '.'
|
||||||
* #4777: py domain: Add ``:async:`` option to :rst:dir:`py:function` directive
|
* #4777: py domain: Add ``:async:`` option to :rst:dir:`py:function` directive
|
||||||
* py domain: Add ``:async:``, ``:classmethod:`` and ``:staticmethod:`` options
|
* py domain: Add new options to :rst:dir:`py:method` directive
|
||||||
to :rst:dir:`py:method` directive
|
|
||||||
|
- ``:async:``
|
||||||
|
- ``:classmethod:``
|
||||||
|
- ``:property:``
|
||||||
|
- ``:staticmethod:``
|
||||||
|
|
||||||
|
* rst domain: Add :rst:dir:`directive:option` directive to describe the option
|
||||||
|
for directive
|
||||||
|
* #6306: html: Add a label to search form for accessability purposes
|
||||||
|
|
||||||
Bugs fixed
|
Bugs fixed
|
||||||
----------
|
----------
|
||||||
@ -95,7 +105,11 @@ Bugs fixed
|
|||||||
* commented term in glossary directive is wrongly recognized
|
* commented term in glossary directive is wrongly recognized
|
||||||
* #6299: rst domain: rst:directive directive generates waste space
|
* #6299: rst domain: rst:directive directive generates waste space
|
||||||
* #6331: man: invalid output when doctest follows rubric
|
* #6331: man: invalid output when doctest follows rubric
|
||||||
|
* #6351: "Hyperlink target is not referenced" message is shown even if
|
||||||
|
referenced
|
||||||
|
* #6165: autodoc: ``tab_width`` setting of docutils has been ignored
|
||||||
* #6311: autosummary: autosummary table gets confused by complex type hints
|
* #6311: autosummary: autosummary table gets confused by complex type hints
|
||||||
|
* Generated Makefiles lack a final EOL (refs: #6232)
|
||||||
|
|
||||||
Testing
|
Testing
|
||||||
--------
|
--------
|
||||||
|
@ -31,7 +31,8 @@ This is the current list of contributed extensions in that repository:
|
|||||||
- actdiag: embed activity diagrams by using actdiag_
|
- actdiag: embed activity diagrams by using actdiag_
|
||||||
- adadomain: an extension for Ada support (Sphinx 1.0 needed)
|
- adadomain: an extension for Ada support (Sphinx 1.0 needed)
|
||||||
- ansi: parse ANSI color sequences inside documents
|
- ansi: parse ANSI color sequences inside documents
|
||||||
- argdoc: automatically generate documentation for command-line arguments, descriptions, and help text
|
- argdoc: automatically generate documentation for command-line arguments,
|
||||||
|
descriptions and help text
|
||||||
- astah: embed diagram by using astah
|
- astah: embed diagram by using astah
|
||||||
- autoanysrc: Gather reST documentation from any source files
|
- autoanysrc: Gather reST documentation from any source files
|
||||||
- autorun: Execute code in a ``runblock`` directive
|
- autorun: Execute code in a ``runblock`` directive
|
||||||
@ -64,7 +65,8 @@ This is the current list of contributed extensions in that repository:
|
|||||||
- imgur: embed Imgur images, albums, and metadata in documents
|
- imgur: embed Imgur images, albums, and metadata in documents
|
||||||
- inlinesyntaxhighlight_: inline syntax highlighting
|
- inlinesyntaxhighlight_: inline syntax highlighting
|
||||||
- lassodomain: a domain for documenting Lasso_ source code
|
- lassodomain: a domain for documenting Lasso_ source code
|
||||||
- libreoffice: an extension to include any drawing supported by LibreOffice (e.g. odg, vsd, ...)
|
- libreoffice: an extension to include any drawing supported by LibreOffice
|
||||||
|
(e.g. odg, vsd, ...)
|
||||||
- lilypond: an extension inserting music scripts from Lilypond_ in PNG format
|
- lilypond: an extension inserting music scripts from Lilypond_ in PNG format
|
||||||
- makedomain_: a domain for `GNU Make`_
|
- makedomain_: a domain for `GNU Make`_
|
||||||
- matlabdomain: document MATLAB_ code
|
- matlabdomain: document MATLAB_ code
|
||||||
@ -100,8 +102,8 @@ This is the current list of contributed extensions in that repository:
|
|||||||
- zopeext: provide an ``autointerface`` directive for using `Zope interfaces`_
|
- zopeext: provide an ``autointerface`` directive for using `Zope interfaces`_
|
||||||
|
|
||||||
|
|
||||||
See the :doc:`extension tutorials <../development/tutorials/index>` on getting started with writing your
|
See the :doc:`extension tutorials <../development/tutorials/index>` on getting
|
||||||
own extensions.
|
started with writing your own extensions.
|
||||||
|
|
||||||
|
|
||||||
.. _aafigure: https://launchpad.net/aafigure
|
.. _aafigure: https://launchpad.net/aafigure
|
||||||
|
@ -97,7 +97,8 @@ extension. These are:
|
|||||||
|
|
||||||
The config is available as ``app.config`` or ``env.config``.
|
The config is available as ``app.config`` or ``env.config``.
|
||||||
|
|
||||||
To see an example of use of these objects, refer to :doc:`../development/tutorials/index`.
|
To see an example of use of these objects, refer to
|
||||||
|
:doc:`../development/tutorials/index`.
|
||||||
|
|
||||||
.. _build-phases:
|
.. _build-phases:
|
||||||
|
|
||||||
|
@ -147,5 +147,6 @@ return ``node.children`` from the Directive.
|
|||||||
|
|
||||||
.. seealso::
|
.. seealso::
|
||||||
|
|
||||||
`Creating directives <http://docutils.sourceforge.net/docs/howto/rst-directives.html>`_
|
`Creating directives`_ HOWTO of the Docutils documentation
|
||||||
HOWTO of the Docutils documentation
|
|
||||||
|
.. _Creating directives: http://docutils.sourceforge.net/docs/howto/rst-directives.html
|
||||||
|
@ -354,8 +354,8 @@ are in HTML form), these variables are also available:
|
|||||||
|
|
||||||
.. data:: body
|
.. data:: body
|
||||||
|
|
||||||
A string containing the content of the page in HTML form as produced by the HTML builder,
|
A string containing the content of the page in HTML form as produced by the
|
||||||
before the theme is applied.
|
HTML builder, before the theme is applied.
|
||||||
|
|
||||||
.. data:: display_toc
|
.. data:: display_toc
|
||||||
|
|
||||||
@ -382,8 +382,9 @@ are in HTML form), these variables are also available:
|
|||||||
|
|
||||||
.. data:: page_source_suffix
|
.. data:: page_source_suffix
|
||||||
|
|
||||||
The suffix of the file that was rendered. Since we support a list of :confval:`source_suffix`,
|
The suffix of the file that was rendered. Since we support a list of
|
||||||
this will allow you to properly link to the original source file.
|
:confval:`source_suffix`, this will allow you to properly link to the
|
||||||
|
original source file.
|
||||||
|
|
||||||
.. data:: parents
|
.. data:: parents
|
||||||
|
|
||||||
|
@ -229,9 +229,13 @@ The following directives are provided for module and class contents:
|
|||||||
The ``classmethod`` option and ``staticmethod`` option can be given (with
|
The ``classmethod`` option and ``staticmethod`` option can be given (with
|
||||||
no value) to indicate the method is a class method (or a static method).
|
no value) to indicate the method is a class method (or a static method).
|
||||||
|
|
||||||
|
The ``property`` option can be given (with no value) to indicate the method
|
||||||
|
is a property.
|
||||||
|
|
||||||
.. versionchanged:: 2.1
|
.. versionchanged:: 2.1
|
||||||
|
|
||||||
``:async:``, ``:classmethod:`` and ``:staticmethod:`` options added.
|
``:async:``, ``:classmethod:``, ``:property:`` and ``:staticmethod:``
|
||||||
|
options added.
|
||||||
|
|
||||||
.. rst:directive:: .. py:staticmethod:: name(parameters)
|
.. rst:directive:: .. py:staticmethod:: name(parameters)
|
||||||
|
|
||||||
@ -1079,15 +1083,16 @@ These roles link to the given declaration types:
|
|||||||
|
|
||||||
.. admonition:: Note on References with Templates Parameters/Arguments
|
.. admonition:: Note on References with Templates Parameters/Arguments
|
||||||
|
|
||||||
These roles follow the Sphinx :ref:`xref-syntax` rules. This means care must be
|
These roles follow the Sphinx :ref:`xref-syntax` rules. This means care must
|
||||||
taken when referencing a (partial) template specialization, e.g. if the link looks like
|
be taken when referencing a (partial) template specialization, e.g. if the
|
||||||
this: ``:cpp:class:`MyClass<int>```.
|
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, escape the opening angle bracket with a backslash,
|
In this case, escape the opening angle bracket with a backslash,
|
||||||
like this: ``:cpp:class:`MyClass\<int>```.
|
like this: ``:cpp:class:`MyClass\<int>```.
|
||||||
|
|
||||||
When a custom title is not needed it may be useful to use the roles for inline expressions,
|
When a custom title is not needed it may be useful to use the roles for
|
||||||
:rst:role:`cpp:expr` and :rst:role:`cpp:texpr`, where angle brackets do not need escaping.
|
inline expressions, :rst:role:`cpp:expr` and :rst:role:`cpp:texpr`, where
|
||||||
|
angle brackets do not need escaping.
|
||||||
|
|
||||||
Declarations without template parameters and template arguments
|
Declarations without template parameters and template arguments
|
||||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
@ -1419,6 +1424,43 @@ The reStructuredText domain (name **rst**) provides the following directives:
|
|||||||
|
|
||||||
Bar description.
|
Bar description.
|
||||||
|
|
||||||
|
.. rst:directive:: .. rst:directive:option:: name
|
||||||
|
|
||||||
|
Describes an option for reST directive. The *name* can be a single option
|
||||||
|
name or option name with arguments which separated with colon (``:``).
|
||||||
|
For example::
|
||||||
|
|
||||||
|
.. rst:directive:: toctree
|
||||||
|
|
||||||
|
.. rst:directive:option:: caption: caption of ToC
|
||||||
|
|
||||||
|
.. rst:directive:option:: glob
|
||||||
|
|
||||||
|
will be rendered as:
|
||||||
|
|
||||||
|
.. rst:directive:: toctree
|
||||||
|
:noindex:
|
||||||
|
|
||||||
|
.. rst:directive:option:: caption: caption of ToC
|
||||||
|
|
||||||
|
.. rst:directive:option:: glob
|
||||||
|
|
||||||
|
.. rubric:: options
|
||||||
|
|
||||||
|
.. rst:directive:option:: type
|
||||||
|
:type: description for the option of directive
|
||||||
|
|
||||||
|
Describe the type of option value.
|
||||||
|
|
||||||
|
For example::
|
||||||
|
|
||||||
|
.. rst:directive:: toctree
|
||||||
|
|
||||||
|
.. rst:directive:option:: maxdepth
|
||||||
|
:type: integer or no value
|
||||||
|
|
||||||
|
.. versionadded:: 2.1
|
||||||
|
|
||||||
.. rst:directive:: .. rst:role:: name
|
.. rst:directive:: .. rst:role:: name
|
||||||
|
|
||||||
Describes a reST role. For example::
|
Describes a reST role. For example::
|
||||||
|
@ -55,6 +55,11 @@ strict_optional = False
|
|||||||
filterwarnings =
|
filterwarnings =
|
||||||
all
|
all
|
||||||
ignore::DeprecationWarning:docutils.io
|
ignore::DeprecationWarning:docutils.io
|
||||||
|
markers =
|
||||||
|
sphinx
|
||||||
|
apidoc
|
||||||
|
setup_command
|
||||||
|
test_params
|
||||||
|
|
||||||
[coverage:run]
|
[coverage:run]
|
||||||
branch = True
|
branch = True
|
||||||
|
@ -587,22 +587,28 @@ class PyMethod(PyObject):
|
|||||||
option_spec.update({
|
option_spec.update({
|
||||||
'async': directives.flag,
|
'async': directives.flag,
|
||||||
'classmethod': directives.flag,
|
'classmethod': directives.flag,
|
||||||
|
'property': directives.flag,
|
||||||
'staticmethod': directives.flag,
|
'staticmethod': directives.flag,
|
||||||
})
|
})
|
||||||
|
|
||||||
def needs_arglist(self):
|
def needs_arglist(self):
|
||||||
# type: () -> bool
|
# type: () -> bool
|
||||||
return True
|
if 'property' in self.options:
|
||||||
|
return False
|
||||||
|
else:
|
||||||
|
return True
|
||||||
|
|
||||||
def get_signature_prefix(self, sig):
|
def get_signature_prefix(self, sig):
|
||||||
# type: (str) -> str
|
# type: (str) -> str
|
||||||
prefix = []
|
prefix = []
|
||||||
if 'async' in self.options:
|
if 'async' in self.options:
|
||||||
prefix.append('async')
|
prefix.append('async')
|
||||||
if 'staticmethod' in self.options:
|
|
||||||
prefix.append('static')
|
|
||||||
if 'classmethod' in self.options:
|
if 'classmethod' in self.options:
|
||||||
prefix.append('classmethod')
|
prefix.append('classmethod')
|
||||||
|
if 'property' in self.options:
|
||||||
|
prefix.append('property')
|
||||||
|
if 'staticmethod' in self.options:
|
||||||
|
prefix.append('static')
|
||||||
|
|
||||||
if prefix:
|
if prefix:
|
||||||
return ' '.join(prefix) + ' '
|
return ' '.join(prefix) + ' '
|
||||||
@ -622,10 +628,12 @@ class PyMethod(PyObject):
|
|||||||
else:
|
else:
|
||||||
return '%s()' % name
|
return '%s()' % name
|
||||||
|
|
||||||
if 'staticmethod' in self.options:
|
if 'classmethod' in self.options:
|
||||||
return _('%s() (%s static method)') % (methname, clsname)
|
|
||||||
elif 'classmethod' in self.options:
|
|
||||||
return _('%s() (%s class method)') % (methname, clsname)
|
return _('%s() (%s class method)') % (methname, clsname)
|
||||||
|
elif 'property' in self.options:
|
||||||
|
return _('%s() (%s property)') % (methname, clsname)
|
||||||
|
elif 'staticmethod' in self.options:
|
||||||
|
return _('%s() (%s static method)') % (methname, clsname)
|
||||||
else:
|
else:
|
||||||
return _('%s() (%s method)') % (methname, clsname)
|
return _('%s() (%s method)') % (methname, clsname)
|
||||||
|
|
||||||
|
@ -11,6 +11,8 @@
|
|||||||
import re
|
import re
|
||||||
from typing import cast
|
from typing import cast
|
||||||
|
|
||||||
|
from docutils.parsers.rst import directives
|
||||||
|
|
||||||
from sphinx import addnodes
|
from sphinx import addnodes
|
||||||
from sphinx.directives import ObjectDescription
|
from sphinx.directives import ObjectDescription
|
||||||
from sphinx.domains import Domain, ObjType
|
from sphinx.domains import Domain, ObjType
|
||||||
@ -98,6 +100,74 @@ class ReSTDirective(ReSTMarkup):
|
|||||||
# type: (str, str) -> str
|
# type: (str, str) -> str
|
||||||
return _('%s (directive)') % name
|
return _('%s (directive)') % name
|
||||||
|
|
||||||
|
def before_content(self):
|
||||||
|
# type: () -> None
|
||||||
|
if self.names:
|
||||||
|
directives = self.env.ref_context.setdefault('rst:directives', [])
|
||||||
|
directives.append(self.names[0])
|
||||||
|
|
||||||
|
def after_content(self):
|
||||||
|
# type: () -> None
|
||||||
|
directives = self.env.ref_context.setdefault('rst:directives', [])
|
||||||
|
if directives:
|
||||||
|
directives.pop()
|
||||||
|
|
||||||
|
|
||||||
|
class ReSTDirectiveOption(ReSTMarkup):
|
||||||
|
"""
|
||||||
|
Description of an option for reST directive.
|
||||||
|
"""
|
||||||
|
option_spec = ReSTMarkup.option_spec.copy()
|
||||||
|
option_spec.update({
|
||||||
|
'type': directives.unchanged,
|
||||||
|
})
|
||||||
|
|
||||||
|
def handle_signature(self, sig, signode):
|
||||||
|
# type: (str, addnodes.desc_signature) -> str
|
||||||
|
try:
|
||||||
|
name, argument = re.split(r'\s*:\s+', sig.strip(), 1)
|
||||||
|
except ValueError:
|
||||||
|
name, argument = sig, None
|
||||||
|
|
||||||
|
signode += addnodes.desc_name(':%s:' % name, ':%s:' % name)
|
||||||
|
if argument:
|
||||||
|
signode += addnodes.desc_annotation(' ' + argument, ' ' + argument)
|
||||||
|
if self.options.get('type'):
|
||||||
|
text = ' (%s)' % self.options['type']
|
||||||
|
signode += addnodes.desc_annotation(text, text)
|
||||||
|
return name
|
||||||
|
|
||||||
|
def add_target_and_index(self, name, sig, signode):
|
||||||
|
# type: (str, str, addnodes.desc_signature) -> None
|
||||||
|
targetname = '-'.join([self.objtype, self.current_directive, name])
|
||||||
|
if targetname not in self.state.document.ids:
|
||||||
|
signode['names'].append(targetname)
|
||||||
|
signode['ids'].append(targetname)
|
||||||
|
signode['first'] = (not self.names)
|
||||||
|
self.state.document.note_explicit_target(signode)
|
||||||
|
|
||||||
|
domain = cast(ReSTDomain, self.env.get_domain('rst'))
|
||||||
|
domain.note_object(self.objtype, name, location=(self.env.docname, self.lineno))
|
||||||
|
|
||||||
|
if self.current_directive:
|
||||||
|
key = name[0].upper()
|
||||||
|
pair = [_('%s (directive)') % self.current_directive,
|
||||||
|
_(':%s: (directive option)') % name]
|
||||||
|
self.indexnode['entries'].append(('pair', '; '.join(pair), targetname, '', key))
|
||||||
|
else:
|
||||||
|
key = name[0].upper()
|
||||||
|
text = _(':%s: (directive option)') % name
|
||||||
|
self.indexnode['entries'].append(('single', text, targetname, '', key))
|
||||||
|
|
||||||
|
@property
|
||||||
|
def current_directive(self):
|
||||||
|
# type: () -> str
|
||||||
|
directives = self.env.ref_context.get('rst:directives')
|
||||||
|
if directives:
|
||||||
|
return directives[-1]
|
||||||
|
else:
|
||||||
|
return ''
|
||||||
|
|
||||||
|
|
||||||
class ReSTRole(ReSTMarkup):
|
class ReSTRole(ReSTMarkup):
|
||||||
"""
|
"""
|
||||||
@ -119,11 +189,13 @@ class ReSTDomain(Domain):
|
|||||||
label = 'reStructuredText'
|
label = 'reStructuredText'
|
||||||
|
|
||||||
object_types = {
|
object_types = {
|
||||||
'directive': ObjType(_('directive'), 'dir'),
|
'directive': ObjType(_('directive'), 'dir'),
|
||||||
'role': ObjType(_('role'), 'role'),
|
'directive:option': ObjType(_('directive-option'), 'dir'),
|
||||||
|
'role': ObjType(_('role'), 'role'),
|
||||||
}
|
}
|
||||||
directives = {
|
directives = {
|
||||||
'directive': ReSTDirective,
|
'directive': ReSTDirective,
|
||||||
|
'directive:option': ReSTDirectiveOption,
|
||||||
'role': ReSTRole,
|
'role': ReSTRole,
|
||||||
}
|
}
|
||||||
roles = {
|
roles = {
|
||||||
|
@ -448,7 +448,8 @@ class Documenter:
|
|||||||
docstring = getdoc(self.object, self.get_attr,
|
docstring = getdoc(self.object, self.get_attr,
|
||||||
self.env.config.autodoc_inherit_docstrings)
|
self.env.config.autodoc_inherit_docstrings)
|
||||||
if docstring:
|
if docstring:
|
||||||
return [prepare_docstring(docstring, ignore)]
|
tab_width = self.directive.state.document.settings.tab_width
|
||||||
|
return [prepare_docstring(docstring, ignore, tab_width)]
|
||||||
return []
|
return []
|
||||||
|
|
||||||
def process_doc(self, docstrings):
|
def process_doc(self, docstrings):
|
||||||
@ -942,7 +943,9 @@ class DocstringSignatureMixin:
|
|||||||
if base not in valid_names:
|
if base not in valid_names:
|
||||||
continue
|
continue
|
||||||
# re-prepare docstring to ignore more leading indentation
|
# re-prepare docstring to ignore more leading indentation
|
||||||
self._new_docstrings[i] = prepare_docstring('\n'.join(doclines[1:]))
|
tab_width = self.directive.state.document.settings.tab_width # type: ignore
|
||||||
|
self._new_docstrings[i] = prepare_docstring('\n'.join(doclines[1:]),
|
||||||
|
tabsize=tab_width)
|
||||||
result = args, retann
|
result = args, retann
|
||||||
# don't look any further
|
# don't look any further
|
||||||
break
|
break
|
||||||
@ -1186,7 +1189,9 @@ class ClassDocumenter(DocstringSignatureMixin, ModuleLevelDocumenter): # type:
|
|||||||
docstrings = [initdocstring]
|
docstrings = [initdocstring]
|
||||||
else:
|
else:
|
||||||
docstrings.append(initdocstring)
|
docstrings.append(initdocstring)
|
||||||
return [prepare_docstring(docstring, ignore) for docstring in docstrings]
|
|
||||||
|
tab_width = self.directive.state.document.settings.tab_width
|
||||||
|
return [prepare_docstring(docstring, ignore, tab_width) for docstring in docstrings]
|
||||||
|
|
||||||
def add_content(self, more_content, no_docstring=False):
|
def add_content(self, more_content, no_docstring=False):
|
||||||
# type: (Any, bool) -> None
|
# type: (Any, bool) -> None
|
||||||
@ -1422,6 +1427,37 @@ class AttributeDocumenter(DocstringStripSignatureMixin, ClassLevelDocumenter):
|
|||||||
super().add_content(more_content, no_docstring)
|
super().add_content(more_content, no_docstring)
|
||||||
|
|
||||||
|
|
||||||
|
class PropertyDocumenter(DocstringStripSignatureMixin, ClassLevelDocumenter): # type: ignore
|
||||||
|
"""
|
||||||
|
Specialized Documenter subclass for properties.
|
||||||
|
"""
|
||||||
|
objtype = 'property'
|
||||||
|
directivetype = 'method'
|
||||||
|
member_order = 60
|
||||||
|
|
||||||
|
# before AttributeDocumenter
|
||||||
|
priority = AttributeDocumenter.priority + 1
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def can_document_member(cls, member, membername, isattr, parent):
|
||||||
|
# type: (Any, str, bool, Any) -> bool
|
||||||
|
return inspect.isproperty(member) and isinstance(parent, ClassDocumenter)
|
||||||
|
|
||||||
|
def document_members(self, all_members=False):
|
||||||
|
# type: (bool) -> None
|
||||||
|
pass
|
||||||
|
|
||||||
|
def get_real_modname(self):
|
||||||
|
# type: () -> str
|
||||||
|
return self.get_attr(self.parent or self.object, '__module__', None) \
|
||||||
|
or self.modname
|
||||||
|
|
||||||
|
def add_directive_header(self, sig):
|
||||||
|
# type: (str) -> None
|
||||||
|
super().add_directive_header(sig)
|
||||||
|
self.add_line(' :property:', self.get_sourcename())
|
||||||
|
|
||||||
|
|
||||||
class InstanceAttributeDocumenter(AttributeDocumenter):
|
class InstanceAttributeDocumenter(AttributeDocumenter):
|
||||||
"""
|
"""
|
||||||
Specialized Documenter subclass for attributes that cannot be imported
|
Specialized Documenter subclass for attributes that cannot be imported
|
||||||
@ -1513,6 +1549,7 @@ def setup(app):
|
|||||||
app.add_autodocumenter(DecoratorDocumenter)
|
app.add_autodocumenter(DecoratorDocumenter)
|
||||||
app.add_autodocumenter(MethodDocumenter)
|
app.add_autodocumenter(MethodDocumenter)
|
||||||
app.add_autodocumenter(AttributeDocumenter)
|
app.add_autodocumenter(AttributeDocumenter)
|
||||||
|
app.add_autodocumenter(PropertyDocumenter)
|
||||||
app.add_autodocumenter(InstanceAttributeDocumenter)
|
app.add_autodocumenter(InstanceAttributeDocumenter)
|
||||||
|
|
||||||
app.add_config_value('autoclass_content', 'class', True)
|
app.add_config_value('autoclass_content', 'class', True)
|
||||||
|
@ -6,10 +6,14 @@
|
|||||||
:license: BSD, see LICENSE for details.
|
:license: BSD, see LICENSE for details.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
import warnings
|
||||||
|
|
||||||
from docutils import nodes
|
from docutils import nodes
|
||||||
|
from docutils.parsers.rst.states import Struct
|
||||||
from docutils.statemachine import StringList
|
from docutils.statemachine import StringList
|
||||||
from docutils.utils import assemble_option_dict
|
from docutils.utils import assemble_option_dict
|
||||||
|
|
||||||
|
from sphinx.deprecation import RemovedInSphinx40Warning
|
||||||
from sphinx.ext.autodoc import Options, get_documenters
|
from sphinx.ext.autodoc import Options, get_documenters
|
||||||
from sphinx.util import logging
|
from sphinx.util import logging
|
||||||
from sphinx.util.docutils import SphinxDirective, switch_source_input
|
from sphinx.util.docutils import SphinxDirective, switch_source_input
|
||||||
@ -17,7 +21,7 @@ from sphinx.util.nodes import nested_parse_with_titles
|
|||||||
|
|
||||||
if False:
|
if False:
|
||||||
# For type annotation
|
# For type annotation
|
||||||
from typing import Callable, Dict, List, Set, Type # NOQA
|
from typing import Any, Callable, Dict, List, Set, Type # NOQA
|
||||||
from docutils.parsers.rst.state import RSTState # NOQA
|
from docutils.parsers.rst.state import RSTState # NOQA
|
||||||
from docutils.utils import Reporter # NOQA
|
from docutils.utils import Reporter # NOQA
|
||||||
from sphinx.config import Config # NOQA
|
from sphinx.config import Config # NOQA
|
||||||
@ -50,8 +54,8 @@ class DummyOptionSpec(dict):
|
|||||||
class DocumenterBridge:
|
class DocumenterBridge:
|
||||||
"""A parameters container for Documenters."""
|
"""A parameters container for Documenters."""
|
||||||
|
|
||||||
def __init__(self, env, reporter, options, lineno):
|
def __init__(self, env, reporter, options, lineno, state=None):
|
||||||
# type: (BuildEnvironment, Reporter, Options, int) -> None
|
# type: (BuildEnvironment, Reporter, Options, int, Any) -> None
|
||||||
self.env = env
|
self.env = env
|
||||||
self.reporter = reporter
|
self.reporter = reporter
|
||||||
self.genopt = options
|
self.genopt = options
|
||||||
@ -59,6 +63,16 @@ class DocumenterBridge:
|
|||||||
self.filename_set = set() # type: Set[str]
|
self.filename_set = set() # type: Set[str]
|
||||||
self.result = StringList()
|
self.result = StringList()
|
||||||
|
|
||||||
|
if state:
|
||||||
|
self.state = state
|
||||||
|
else:
|
||||||
|
# create fake object for self.state.document.settings.tab_width
|
||||||
|
warnings.warn('DocumenterBridge requires a state object on instantiation.',
|
||||||
|
RemovedInSphinx40Warning)
|
||||||
|
settings = Struct(tab_width=8)
|
||||||
|
document = Struct(settings=settings)
|
||||||
|
self.state = Struct(document=document)
|
||||||
|
|
||||||
def warn(self, msg):
|
def warn(self, msg):
|
||||||
# type: (str) -> None
|
# type: (str) -> None
|
||||||
logger.warning(msg, location=(self.env.docname, self.lineno))
|
logger.warning(msg, location=(self.env.docname, self.lineno))
|
||||||
@ -131,7 +145,7 @@ class AutodocDirective(SphinxDirective):
|
|||||||
return []
|
return []
|
||||||
|
|
||||||
# generate the output
|
# generate the output
|
||||||
params = DocumenterBridge(self.env, reporter, documenter_options, lineno)
|
params = DocumenterBridge(self.env, reporter, documenter_options, lineno, self.state)
|
||||||
documenter = doccls(params, self.arguments[0])
|
documenter = doccls(params, self.arguments[0])
|
||||||
documenter.generate(more_content=self.content)
|
documenter.generate(more_content=self.content)
|
||||||
if not params.result:
|
if not params.result:
|
||||||
|
@ -175,7 +175,7 @@ _app = None # type: Sphinx
|
|||||||
class FakeDirective(DocumenterBridge):
|
class FakeDirective(DocumenterBridge):
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
# type: () -> None
|
# type: () -> None
|
||||||
super().__init__({}, None, Options(), 0) # type: ignore
|
super().__init__({}, None, Options(), 0, None) # type: ignore
|
||||||
|
|
||||||
|
|
||||||
def get_documenter(app, obj, parent):
|
def get_documenter(app, obj, parent):
|
||||||
@ -236,7 +236,7 @@ class Autosummary(SphinxDirective):
|
|||||||
def run(self):
|
def run(self):
|
||||||
# type: () -> List[nodes.Node]
|
# type: () -> List[nodes.Node]
|
||||||
self.bridge = DocumenterBridge(self.env, self.state.document.reporter,
|
self.bridge = DocumenterBridge(self.env, self.state.document.reporter,
|
||||||
Options(), self.lineno)
|
Options(), self.lineno, self.state)
|
||||||
|
|
||||||
names = [x.strip().split()[0] for x in self.content
|
names = [x.strip().split()[0] for x in self.content
|
||||||
if x.strip() and re.search(r'^[~a-zA-Z_]', x.strip()[0])]
|
if x.strip() and re.search(r'^[~a-zA-Z_]', x.strip()[0])]
|
||||||
|
@ -40,7 +40,7 @@ from sphinx.util.rst import escape as rst_escape
|
|||||||
|
|
||||||
if False:
|
if False:
|
||||||
# For type annotation
|
# For type annotation
|
||||||
from typing import Any, Callable, Dict, List, Tuple, Type, Union # NOQA
|
from typing import Any, Callable, Dict, List, Set, Tuple, Type, Union # NOQA
|
||||||
from sphinx.builders import Builder # NOQA
|
from sphinx.builders import Builder # NOQA
|
||||||
from sphinx.ext.autodoc import Documenter # NOQA
|
from sphinx.ext.autodoc import Documenter # NOQA
|
||||||
|
|
||||||
@ -169,8 +169,8 @@ def generate_autosummary_docs(sources, output_dir=None, suffix='.rst',
|
|||||||
except TemplateNotFound:
|
except TemplateNotFound:
|
||||||
template = template_env.get_template('autosummary/base.rst')
|
template = template_env.get_template('autosummary/base.rst')
|
||||||
|
|
||||||
def get_members(obj, typ, include_public=[], imported=True):
|
def get_members(obj, types, include_public=[], imported=True):
|
||||||
# type: (Any, str, List[str], bool) -> Tuple[List[str], List[str]]
|
# type: (Any, Set[str], List[str], bool) -> Tuple[List[str], List[str]] # NOQA
|
||||||
items = [] # type: List[str]
|
items = [] # type: List[str]
|
||||||
for name in dir(obj):
|
for name in dir(obj):
|
||||||
try:
|
try:
|
||||||
@ -178,7 +178,7 @@ def generate_autosummary_docs(sources, output_dir=None, suffix='.rst',
|
|||||||
except AttributeError:
|
except AttributeError:
|
||||||
continue
|
continue
|
||||||
documenter = get_documenter(app, value, obj)
|
documenter = get_documenter(app, value, obj)
|
||||||
if documenter.objtype == typ:
|
if documenter.objtype in types:
|
||||||
if imported or getattr(value, '__module__', None) == obj.__name__:
|
if imported or getattr(value, '__module__', None) == obj.__name__:
|
||||||
# skip imported members if expected
|
# skip imported members if expected
|
||||||
items.append(name)
|
items.append(name)
|
||||||
@ -191,19 +191,19 @@ def generate_autosummary_docs(sources, output_dir=None, suffix='.rst',
|
|||||||
if doc.objtype == 'module':
|
if doc.objtype == 'module':
|
||||||
ns['members'] = dir(obj)
|
ns['members'] = dir(obj)
|
||||||
ns['functions'], ns['all_functions'] = \
|
ns['functions'], ns['all_functions'] = \
|
||||||
get_members(obj, 'function', imported=imported_members)
|
get_members(obj, {'function'}, imported=imported_members)
|
||||||
ns['classes'], ns['all_classes'] = \
|
ns['classes'], ns['all_classes'] = \
|
||||||
get_members(obj, 'class', imported=imported_members)
|
get_members(obj, {'class'}, imported=imported_members)
|
||||||
ns['exceptions'], ns['all_exceptions'] = \
|
ns['exceptions'], ns['all_exceptions'] = \
|
||||||
get_members(obj, 'exception', imported=imported_members)
|
get_members(obj, {'exception'}, imported=imported_members)
|
||||||
elif doc.objtype == 'class':
|
elif doc.objtype == 'class':
|
||||||
ns['members'] = dir(obj)
|
ns['members'] = dir(obj)
|
||||||
ns['inherited_members'] = \
|
ns['inherited_members'] = \
|
||||||
set(dir(obj)) - set(obj.__dict__.keys())
|
set(dir(obj)) - set(obj.__dict__.keys())
|
||||||
ns['methods'], ns['all_methods'] = \
|
ns['methods'], ns['all_methods'] = \
|
||||||
get_members(obj, 'method', ['__init__'])
|
get_members(obj, {'method'}, ['__init__'])
|
||||||
ns['attributes'], ns['all_attributes'] = \
|
ns['attributes'], ns['all_attributes'] = \
|
||||||
get_members(obj, 'attribute')
|
get_members(obj, {'attribute', 'property'})
|
||||||
|
|
||||||
parts = name.split('.')
|
parts = name.split('.')
|
||||||
if doc.objtype in ('method', 'attribute'):
|
if doc.objtype in ('method', 'attribute'):
|
||||||
|
@ -32,6 +32,7 @@ if False:
|
|||||||
# For type annotation
|
# For type annotation
|
||||||
from typing import Any, Dict # NOQA
|
from typing import Any, Dict # NOQA
|
||||||
from pygments.formatter import Formatter # NOQA
|
from pygments.formatter import Formatter # NOQA
|
||||||
|
from pygments.style import Style # NOQA
|
||||||
|
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
@ -69,16 +70,8 @@ class PygmentsBridge:
|
|||||||
def __init__(self, dest='html', stylename='sphinx', trim_doctest_flags=None):
|
def __init__(self, dest='html', stylename='sphinx', trim_doctest_flags=None):
|
||||||
# type: (str, str, bool) -> None
|
# type: (str, str, bool) -> None
|
||||||
self.dest = dest
|
self.dest = dest
|
||||||
if stylename is None or stylename == 'sphinx':
|
|
||||||
style = SphinxStyle
|
style = self.get_style(stylename)
|
||||||
elif stylename == 'none':
|
|
||||||
style = NoneStyle
|
|
||||||
elif '.' in stylename:
|
|
||||||
module, stylename = stylename.rsplit('.', 1)
|
|
||||||
style = getattr(__import__(module, None, None, ['__name__']),
|
|
||||||
stylename)
|
|
||||||
else:
|
|
||||||
style = get_style_by_name(stylename)
|
|
||||||
self.formatter_args = {'style': style} # type: Dict[str, Any]
|
self.formatter_args = {'style': style} # type: Dict[str, Any]
|
||||||
if dest == 'html':
|
if dest == 'html':
|
||||||
self.formatter = self.html_formatter
|
self.formatter = self.html_formatter
|
||||||
@ -91,6 +84,18 @@ class PygmentsBridge:
|
|||||||
warnings.warn('trim_doctest_flags option for PygmentsBridge is now deprecated.',
|
warnings.warn('trim_doctest_flags option for PygmentsBridge is now deprecated.',
|
||||||
RemovedInSphinx30Warning, stacklevel=2)
|
RemovedInSphinx30Warning, stacklevel=2)
|
||||||
|
|
||||||
|
def get_style(self, stylename):
|
||||||
|
# type: (str) -> Style
|
||||||
|
if stylename is None or stylename == 'sphinx':
|
||||||
|
return SphinxStyle
|
||||||
|
elif stylename == 'none':
|
||||||
|
return NoneStyle
|
||||||
|
elif '.' in stylename:
|
||||||
|
module, stylename = stylename.rsplit('.', 1)
|
||||||
|
return getattr(__import__(module, None, None, ['__name__']), stylename)
|
||||||
|
else:
|
||||||
|
return get_style_by_name(stylename)
|
||||||
|
|
||||||
def get_formatter(self, **kwargs):
|
def get_formatter(self, **kwargs):
|
||||||
# type: (Any) -> Formatter
|
# type: (Any) -> Formatter
|
||||||
kwargs.update(self.formatter_args)
|
kwargs.update(self.formatter_args)
|
||||||
@ -110,11 +115,8 @@ class PygmentsBridge:
|
|||||||
return '\\begin{Verbatim}[commandchars=\\\\\\{\\}]\n' + \
|
return '\\begin{Verbatim}[commandchars=\\\\\\{\\}]\n' + \
|
||||||
source + '\\end{Verbatim}\n'
|
source + '\\end{Verbatim}\n'
|
||||||
|
|
||||||
def highlight_block(self, source, lang, opts=None, location=None, force=False, **kwargs):
|
def get_lexer(self, source, lang, opts=None, location=None):
|
||||||
# type: (str, str, Any, Any, bool, Any) -> str
|
# type: (str, str, Any, Any) -> Lexer
|
||||||
if not isinstance(source, str):
|
|
||||||
source = source.decode()
|
|
||||||
|
|
||||||
# find out which lexer to use
|
# find out which lexer to use
|
||||||
if lang in ('py', 'python'):
|
if lang in ('py', 'python'):
|
||||||
if source.startswith('>>>'):
|
if source.startswith('>>>'):
|
||||||
@ -145,6 +147,15 @@ class PygmentsBridge:
|
|||||||
else:
|
else:
|
||||||
lexer.add_filter('raiseonerror')
|
lexer.add_filter('raiseonerror')
|
||||||
|
|
||||||
|
return lexer
|
||||||
|
|
||||||
|
def highlight_block(self, source, lang, opts=None, location=None, force=False, **kwargs):
|
||||||
|
# type: (str, str, Any, Any, bool, Any) -> str
|
||||||
|
if not isinstance(source, str):
|
||||||
|
source = source.decode()
|
||||||
|
|
||||||
|
lexer = self.get_lexer(source, lang, opts, location)
|
||||||
|
|
||||||
# trim doctest options if wanted
|
# trim doctest options if wanted
|
||||||
if isinstance(lexer, PythonConsoleLexer) and self.trim_doctest_flags:
|
if isinstance(lexer, PythonConsoleLexer) and self.trim_doctest_flags:
|
||||||
source = doctest.blankline_re.sub('', source)
|
source = doctest.blankline_re.sub('', source)
|
||||||
@ -165,6 +176,7 @@ class PygmentsBridge:
|
|||||||
type='misc', subtype='highlighting_failure',
|
type='misc', subtype='highlighting_failure',
|
||||||
location=location)
|
location=location)
|
||||||
hlsource = highlight(source, lexers['none'], formatter)
|
hlsource = highlight(source, lexers['none'], formatter)
|
||||||
|
|
||||||
if self.dest == 'html':
|
if self.dest == 'html':
|
||||||
return hlsource
|
return hlsource
|
||||||
else:
|
else:
|
||||||
|
11
sphinx/io.py
11
sphinx/io.py
@ -16,6 +16,7 @@ from docutils.io import FileInput, NullOutput
|
|||||||
from docutils.parsers.rst import Parser as RSTParser
|
from docutils.parsers.rst import Parser as RSTParser
|
||||||
from docutils.readers import standalone
|
from docutils.readers import standalone
|
||||||
from docutils.statemachine import StringList, string2lines
|
from docutils.statemachine import StringList, string2lines
|
||||||
|
from docutils.transforms.references import DanglingReferences
|
||||||
from docutils.writers import UnfilteredWriter
|
from docutils.writers import UnfilteredWriter
|
||||||
|
|
||||||
from sphinx.deprecation import RemovedInSphinx30Warning
|
from sphinx.deprecation import RemovedInSphinx30Warning
|
||||||
@ -64,7 +65,15 @@ class SphinxBaseReader(standalone.Reader):
|
|||||||
|
|
||||||
def get_transforms(self):
|
def get_transforms(self):
|
||||||
# type: () -> List[Type[Transform]]
|
# type: () -> List[Type[Transform]]
|
||||||
return super().get_transforms() + self.transforms
|
transforms = super().get_transforms() + self.transforms
|
||||||
|
|
||||||
|
# remove transforms which is not needed for Sphinx
|
||||||
|
unused = [DanglingReferences]
|
||||||
|
for transform in unused:
|
||||||
|
if transform in transforms:
|
||||||
|
transforms.remove(transform)
|
||||||
|
|
||||||
|
return transforms
|
||||||
|
|
||||||
def new_document(self):
|
def new_document(self):
|
||||||
# type: () -> nodes.document
|
# type: () -> nodes.document
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
\begin{savenotes}\sphinxatlongtablestart\begin{longtable}
|
\begin{savenotes}\sphinxatlongtablestart\begin{longtable}
|
||||||
<%- if table.align == 'center' -%>
|
<%- if table.align in ('center', 'default') -%>
|
||||||
[c]
|
[c]
|
||||||
<%- elif table.align == 'left' -%>
|
<%- elif table.align == 'left' -%>
|
||||||
[l]
|
[l]
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
\begin{savenotes}\sphinxattablestart
|
\begin{savenotes}\sphinxattablestart
|
||||||
<% if table.align -%>
|
<% if table.align -%>
|
||||||
<%- if table.align == 'center' -%>
|
<%- if table.align in ('center', 'default') -%>
|
||||||
\centering
|
\centering
|
||||||
<%- elif table.align == 'left' -%>
|
<%- elif table.align == 'left' -%>
|
||||||
\raggedright
|
\raggedright
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
\begin{savenotes}\sphinxattablestart
|
\begin{savenotes}\sphinxattablestart
|
||||||
<% if table.align -%>
|
<% if table.align -%>
|
||||||
<%- if table.align == 'center' -%>
|
<%- if table.align in ('center', 'default') -%>
|
||||||
\centering
|
\centering
|
||||||
<%- elif table.align == 'left' -%>
|
<%- elif table.align == 'left' -%>
|
||||||
\raggedright
|
\raggedright
|
||||||
|
@ -1,14 +1,12 @@
|
|||||||
# Minimal makefile for Sphinx documentation
|
# Minimal makefile for Sphinx documentation
|
||||||
#
|
#
|
||||||
|
|
||||||
# You can set these variables from the command line. For example:
|
# You can set these variables from the command line, and also
|
||||||
# SPHINXOPTS='-E -W -n' make html
|
# from the environment for the first two.
|
||||||
# will run the html builder in a clean environment (-E), treating warnings
|
|
||||||
# as errors (-W), in nitpicky mode (-n).
|
|
||||||
SPHINXOPTS ?=
|
SPHINXOPTS ?=
|
||||||
SPHINXBUILD ?= sphinx-build
|
SPHINXBUILD ?= sphinx-build
|
||||||
SOURCEDIR ?= {{ rsrcdir }}
|
SOURCEDIR = {{ rsrcdir }}
|
||||||
BUILDDIR ?= {{ rbuilddir }}
|
BUILDDIR = {{ rbuilddir }}
|
||||||
|
|
||||||
# Put it first so that "make" without argument is like "make help".
|
# Put it first so that "make" without argument is like "make help".
|
||||||
help:
|
help:
|
||||||
|
@ -9,10 +9,10 @@
|
|||||||
#}
|
#}
|
||||||
{%- if pagename != "search" and builder != "singlehtml" %}
|
{%- if pagename != "search" and builder != "singlehtml" %}
|
||||||
<div id="searchbox" style="display: none" role="search">
|
<div id="searchbox" style="display: none" role="search">
|
||||||
<h3>{{ _('Quick search') }}</h3>
|
<h3 id="searchlabel">{{ _('Quick search') }}</h3>
|
||||||
<div class="searchformwrapper">
|
<div class="searchformwrapper">
|
||||||
<form class="search" action="{{ pathto('search') }}" method="get">
|
<form class="search" action="{{ pathto('search') }}" method="get">
|
||||||
<input type="text" name="q" />
|
<input type="text" name="q" aria-labelledby="searchlabel" />
|
||||||
<input type="submit" value="{{ _('Go') }}" />
|
<input type="submit" value="{{ _('Go') }}" />
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
|
@ -289,6 +289,12 @@ img.align-center, .figure.align-center, object.align-center {
|
|||||||
margin-right: auto;
|
margin-right: auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
img.align-default, .figure.align-default {
|
||||||
|
display: block;
|
||||||
|
margin-left: auto;
|
||||||
|
margin-right: auto;
|
||||||
|
}
|
||||||
|
|
||||||
.align-left {
|
.align-left {
|
||||||
text-align: left;
|
text-align: left;
|
||||||
}
|
}
|
||||||
@ -297,6 +303,10 @@ img.align-center, .figure.align-center, object.align-center {
|
|||||||
text-align: center;
|
text-align: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.align-default {
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
.align-right {
|
.align-right {
|
||||||
text-align: right;
|
text-align: right;
|
||||||
}
|
}
|
||||||
@ -368,6 +378,11 @@ table.align-center {
|
|||||||
margin-right: auto;
|
margin-right: auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
table.align-default {
|
||||||
|
margin-left: auto;
|
||||||
|
margin-right: auto;
|
||||||
|
}
|
||||||
|
|
||||||
table caption span.caption-number {
|
table caption span.caption-number {
|
||||||
font-style: italic;
|
font-style: italic;
|
||||||
}
|
}
|
||||||
|
@ -293,7 +293,7 @@ class FigureAligner(SphinxTransform):
|
|||||||
# type: (Any) -> None
|
# type: (Any) -> None
|
||||||
matcher = NodeMatcher(nodes.table, nodes.figure)
|
matcher = NodeMatcher(nodes.table, nodes.figure)
|
||||||
for node in self.document.traverse(matcher): # type: nodes.Element
|
for node in self.document.traverse(matcher): # type: nodes.Element
|
||||||
node.setdefault('align', 'center')
|
node.setdefault('align', 'default')
|
||||||
|
|
||||||
|
|
||||||
class FilterSystemMessages(SphinxTransform):
|
class FilterSystemMessages(SphinxTransform):
|
||||||
|
@ -9,7 +9,7 @@
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
from docutils import nodes
|
from docutils import nodes
|
||||||
from docutils.transforms.references import Substitutions
|
from docutils.transforms.references import DanglingReferences, Substitutions
|
||||||
|
|
||||||
from sphinx.transforms import SphinxTransform
|
from sphinx.transforms import SphinxTransform
|
||||||
|
|
||||||
@ -31,6 +31,22 @@ class SubstitutionDefinitionsRemover(SphinxTransform):
|
|||||||
node.parent.remove(node)
|
node.parent.remove(node)
|
||||||
|
|
||||||
|
|
||||||
|
class SphinxDanglingReferences(DanglingReferences):
|
||||||
|
"""DanglingReferences transform which does not output info messages."""
|
||||||
|
|
||||||
|
def apply(self, **kwargs):
|
||||||
|
# type: (Any) -> None
|
||||||
|
try:
|
||||||
|
reporter = self.document.reporter
|
||||||
|
report_level = reporter.report_level
|
||||||
|
|
||||||
|
# suppress INFO level messages for a while
|
||||||
|
reporter.report_level = max(reporter.WARNING_LEVEL, reporter.report_level)
|
||||||
|
super().apply()
|
||||||
|
finally:
|
||||||
|
reporter.report_level = report_level
|
||||||
|
|
||||||
|
|
||||||
class SphinxDomains(SphinxTransform):
|
class SphinxDomains(SphinxTransform):
|
||||||
"""Collect objects to Sphinx domains for cross references."""
|
"""Collect objects to Sphinx domains for cross references."""
|
||||||
default_priority = 850
|
default_priority = 850
|
||||||
@ -44,6 +60,7 @@ class SphinxDomains(SphinxTransform):
|
|||||||
def setup(app):
|
def setup(app):
|
||||||
# type: (Sphinx) -> Dict[str, Any]
|
# type: (Sphinx) -> Dict[str, Any]
|
||||||
app.add_transform(SubstitutionDefinitionsRemover)
|
app.add_transform(SubstitutionDefinitionsRemover)
|
||||||
|
app.add_transform(SphinxDanglingReferences)
|
||||||
app.add_transform(SphinxDomains)
|
app.add_transform(SphinxDomains)
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
@ -15,8 +15,8 @@ if False:
|
|||||||
from typing import List # NOQA
|
from typing import List # NOQA
|
||||||
|
|
||||||
|
|
||||||
def prepare_docstring(s, ignore=1):
|
def prepare_docstring(s, ignore=1, tabsize=8):
|
||||||
# type: (str, int) -> List[str]
|
# type: (str, int, int) -> List[str]
|
||||||
"""Convert a docstring into lines of parseable reST. Remove common leading
|
"""Convert a docstring into lines of parseable reST. Remove common leading
|
||||||
indentation, where the indentation of a given number of lines (usually just
|
indentation, where the indentation of a given number of lines (usually just
|
||||||
one) is ignored.
|
one) is ignored.
|
||||||
@ -25,7 +25,7 @@ def prepare_docstring(s, ignore=1):
|
|||||||
ViewList (used as argument of nested_parse().) An empty line is added to
|
ViewList (used as argument of nested_parse().) An empty line is added to
|
||||||
act as a separator between this docstring and following content.
|
act as a separator between this docstring and following content.
|
||||||
"""
|
"""
|
||||||
lines = s.expandtabs().splitlines()
|
lines = s.expandtabs(tabsize).splitlines()
|
||||||
# Find minimum indentation of any non-blank lines after ignored lines.
|
# Find minimum indentation of any non-blank lines after ignored lines.
|
||||||
margin = sys.maxsize
|
margin = sys.maxsize
|
||||||
for line in lines[ignore:]:
|
for line in lines[ignore:]:
|
||||||
|
@ -224,6 +224,12 @@ def iscoroutinefunction(obj):
|
|||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
def isproperty(obj):
|
||||||
|
# type: (Any) -> bool
|
||||||
|
"""Check if the object is property."""
|
||||||
|
return isinstance(obj, property)
|
||||||
|
|
||||||
|
|
||||||
def safe_getattr(obj, name, *defargs):
|
def safe_getattr(obj, name, *defargs):
|
||||||
# type: (Any, str, str) -> object
|
# type: (Any, str, str) -> object
|
||||||
"""A getattr() that turns all exceptions into AttributeErrors."""
|
"""A getattr() that turns all exceptions into AttributeErrors."""
|
||||||
|
@ -1565,6 +1565,7 @@ class LaTeXTranslator(SphinxTranslator):
|
|||||||
(1, 'middle'): ('\\raisebox{-0.5\\height}{', '}'),
|
(1, 'middle'): ('\\raisebox{-0.5\\height}{', '}'),
|
||||||
(1, 'bottom'): ('\\raisebox{-\\height}{', '}'),
|
(1, 'bottom'): ('\\raisebox{-\\height}{', '}'),
|
||||||
(0, 'center'): ('{\\hspace*{\\fill}', '\\hspace*{\\fill}}'),
|
(0, 'center'): ('{\\hspace*{\\fill}', '\\hspace*{\\fill}}'),
|
||||||
|
(0, 'default'): ('{\\hspace*{\\fill}', '\\hspace*{\\fill}}'),
|
||||||
# These 2 don't exactly do the right thing. The image should
|
# These 2 don't exactly do the right thing. The image should
|
||||||
# be floated alongside the paragraph. See
|
# be floated alongside the paragraph. See
|
||||||
# https://www.w3.org/TR/html4/struct/objects.html#adef-align-IMG
|
# https://www.w3.org/TR/html4/struct/objects.html#adef-align-IMG
|
||||||
|
@ -11,6 +11,7 @@
|
|||||||
|
|
||||||
import platform
|
import platform
|
||||||
import sys
|
import sys
|
||||||
|
from unittest.mock import Mock
|
||||||
from warnings import catch_warnings
|
from warnings import catch_warnings
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
@ -36,7 +37,9 @@ def do_autodoc(app, objtype, name, options=None):
|
|||||||
app.env.temp_data.setdefault('docname', 'index') # set dummy docname
|
app.env.temp_data.setdefault('docname', 'index') # set dummy docname
|
||||||
doccls = app.registry.documenters[objtype]
|
doccls = app.registry.documenters[objtype]
|
||||||
docoptions = process_documenter_options(doccls, app.config, options)
|
docoptions = process_documenter_options(doccls, app.config, options)
|
||||||
bridge = DocumenterBridge(app.env, LoggingReporter(''), docoptions, 1)
|
state = Mock()
|
||||||
|
state.document.settings.tab_width = 8
|
||||||
|
bridge = DocumenterBridge(app.env, LoggingReporter(''), docoptions, 1, state)
|
||||||
documenter = doccls(bridge, name)
|
documenter = doccls(bridge, name)
|
||||||
documenter.generate()
|
documenter.generate()
|
||||||
|
|
||||||
@ -95,7 +98,9 @@ def setup_test():
|
|||||||
genopt = options,
|
genopt = options,
|
||||||
result = ViewList(),
|
result = ViewList(),
|
||||||
filename_set = set(),
|
filename_set = set(),
|
||||||
|
state = Mock(),
|
||||||
)
|
)
|
||||||
|
directive.state.document.settings.tab_width = 8
|
||||||
|
|
||||||
processed_docstrings = []
|
processed_docstrings = []
|
||||||
processed_signatures = []
|
processed_signatures = []
|
||||||
@ -756,7 +761,7 @@ def test_autodoc_undoc_members(app):
|
|||||||
' .. py:attribute:: Class.mdocattr',
|
' .. py:attribute:: Class.mdocattr',
|
||||||
' .. py:method:: Class.meth()',
|
' .. py:method:: Class.meth()',
|
||||||
' .. py:method:: Class.moore(a, e, f) -> happiness',
|
' .. py:method:: Class.moore(a, e, f) -> happiness',
|
||||||
' .. py:attribute:: Class.prop',
|
' .. py:method:: Class.prop',
|
||||||
' .. py:method:: Class.roger(a, *, b=2, c=3, d=4, e=5, f=6)',
|
' .. py:method:: Class.roger(a, *, b=2, c=3, d=4, e=5, f=6)',
|
||||||
' .. py:attribute:: Class.skipattr',
|
' .. py:attribute:: Class.skipattr',
|
||||||
' .. py:method:: Class.skipmeth()',
|
' .. py:method:: Class.skipmeth()',
|
||||||
@ -777,6 +782,7 @@ def test_autodoc_inherited_members(app):
|
|||||||
' .. py:method:: Class.inheritedstaticmeth(cls)',
|
' .. py:method:: Class.inheritedstaticmeth(cls)',
|
||||||
' .. py:method:: Class.meth()',
|
' .. py:method:: Class.meth()',
|
||||||
' .. py:method:: Class.moore(a, e, f) -> happiness',
|
' .. py:method:: Class.moore(a, e, f) -> happiness',
|
||||||
|
' .. py:method:: Class.prop',
|
||||||
' .. py:method:: Class.skipmeth()'
|
' .. py:method:: Class.skipmeth()'
|
||||||
]
|
]
|
||||||
|
|
||||||
@ -836,7 +842,7 @@ def test_autodoc_special_members(app):
|
|||||||
' .. py:attribute:: Class.mdocattr',
|
' .. py:attribute:: Class.mdocattr',
|
||||||
' .. py:method:: Class.meth()',
|
' .. py:method:: Class.meth()',
|
||||||
' .. py:method:: Class.moore(a, e, f) -> happiness',
|
' .. py:method:: Class.moore(a, e, f) -> happiness',
|
||||||
' .. py:attribute:: Class.prop',
|
' .. py:method:: Class.prop',
|
||||||
' .. py:method:: Class.roger(a, *, b=2, c=3, d=4, e=5, f=6)',
|
' .. py:method:: Class.roger(a, *, b=2, c=3, d=4, e=5, f=6)',
|
||||||
' .. py:attribute:: Class.skipattr',
|
' .. py:attribute:: Class.skipattr',
|
||||||
' .. py:method:: Class.skipmeth()',
|
' .. py:method:: Class.skipmeth()',
|
||||||
@ -1028,7 +1034,7 @@ def test_autodoc_member_order(app):
|
|||||||
' .. py:method:: Class.excludemeth()',
|
' .. py:method:: Class.excludemeth()',
|
||||||
' .. py:attribute:: Class.skipattr',
|
' .. py:attribute:: Class.skipattr',
|
||||||
' .. py:attribute:: Class.attr',
|
' .. py:attribute:: Class.attr',
|
||||||
' .. py:attribute:: Class.prop',
|
' .. py:method:: Class.prop',
|
||||||
' .. py:attribute:: Class.docattr',
|
' .. py:attribute:: Class.docattr',
|
||||||
' .. py:attribute:: Class.udocattr',
|
' .. py:attribute:: Class.udocattr',
|
||||||
' .. py:attribute:: Class.mdocattr',
|
' .. py:attribute:: Class.mdocattr',
|
||||||
@ -1062,7 +1068,7 @@ def test_autodoc_member_order(app):
|
|||||||
' .. py:attribute:: Class.inst_attr_inline',
|
' .. py:attribute:: Class.inst_attr_inline',
|
||||||
' .. py:attribute:: Class.inst_attr_string',
|
' .. py:attribute:: Class.inst_attr_string',
|
||||||
' .. py:attribute:: Class.mdocattr',
|
' .. py:attribute:: Class.mdocattr',
|
||||||
' .. py:attribute:: Class.prop',
|
' .. py:method:: Class.prop',
|
||||||
' .. py:attribute:: Class.skipattr',
|
' .. py:attribute:: Class.skipattr',
|
||||||
' .. py:attribute:: Class.udocattr'
|
' .. py:attribute:: Class.udocattr'
|
||||||
]
|
]
|
||||||
@ -1085,7 +1091,7 @@ def test_autodoc_member_order(app):
|
|||||||
' .. py:attribute:: Class.mdocattr',
|
' .. py:attribute:: Class.mdocattr',
|
||||||
' .. py:method:: Class.meth()',
|
' .. py:method:: Class.meth()',
|
||||||
' .. py:method:: Class.moore(a, e, f) -> happiness',
|
' .. py:method:: Class.moore(a, e, f) -> happiness',
|
||||||
' .. py:attribute:: Class.prop',
|
' .. py:method:: Class.prop',
|
||||||
' .. py:method:: Class.roger(a, *, b=2, c=3, d=4, e=5, f=6)',
|
' .. py:method:: Class.roger(a, *, b=2, c=3, d=4, e=5, f=6)',
|
||||||
' .. py:attribute:: Class.skipattr',
|
' .. py:attribute:: Class.skipattr',
|
||||||
' .. py:method:: Class.skipmeth()',
|
' .. py:method:: Class.skipmeth()',
|
||||||
@ -1152,14 +1158,16 @@ def test_autodoc_docstring_signature(app):
|
|||||||
' indented line',
|
' indented line',
|
||||||
' ',
|
' ',
|
||||||
' ',
|
' ',
|
||||||
' .. py:attribute:: DocstringSig.prop1',
|
' .. py:method:: DocstringSig.prop1',
|
||||||
' :module: target',
|
' :module: target',
|
||||||
|
' :property:',
|
||||||
' ',
|
' ',
|
||||||
' First line of docstring',
|
' First line of docstring',
|
||||||
' ',
|
' ',
|
||||||
' ',
|
' ',
|
||||||
' .. py:attribute:: DocstringSig.prop2',
|
' .. py:method:: DocstringSig.prop2',
|
||||||
' :module: target',
|
' :module: target',
|
||||||
|
' :property:',
|
||||||
' ',
|
' ',
|
||||||
' First line of docstring',
|
' First line of docstring',
|
||||||
' Second line of docstring',
|
' Second line of docstring',
|
||||||
@ -1194,15 +1202,17 @@ def test_autodoc_docstring_signature(app):
|
|||||||
' indented line',
|
' indented line',
|
||||||
' ',
|
' ',
|
||||||
' ',
|
' ',
|
||||||
' .. py:attribute:: DocstringSig.prop1',
|
' .. py:method:: DocstringSig.prop1',
|
||||||
' :module: target',
|
' :module: target',
|
||||||
|
' :property:',
|
||||||
' ',
|
' ',
|
||||||
' DocstringSig.prop1(self)',
|
' DocstringSig.prop1(self)',
|
||||||
' First line of docstring',
|
' First line of docstring',
|
||||||
' ',
|
' ',
|
||||||
' ',
|
' ',
|
||||||
' .. py:attribute:: DocstringSig.prop2',
|
' .. py:method:: DocstringSig.prop2',
|
||||||
' :module: target',
|
' :module: target',
|
||||||
|
' :property:',
|
||||||
' ',
|
' ',
|
||||||
' First line of docstring',
|
' First line of docstring',
|
||||||
' Second line of docstring',
|
' Second line of docstring',
|
||||||
@ -1717,7 +1727,7 @@ def test_autodoc_default_options_with_values(app):
|
|||||||
' .. py:method:: Class.skipmeth()',
|
' .. py:method:: Class.skipmeth()',
|
||||||
' .. py:method:: Class.excludemeth()',
|
' .. py:method:: Class.excludemeth()',
|
||||||
' .. py:attribute:: Class.attr',
|
' .. py:attribute:: Class.attr',
|
||||||
' .. py:attribute:: Class.prop',
|
' .. py:method:: Class.prop',
|
||||||
' .. py:attribute:: Class.docattr',
|
' .. py:attribute:: Class.docattr',
|
||||||
' .. py:attribute:: Class.udocattr',
|
' .. py:attribute:: Class.udocattr',
|
||||||
' .. py:attribute:: Class.mdocattr',
|
' .. py:attribute:: Class.mdocattr',
|
||||||
|
@ -565,7 +565,7 @@ def test_numfig_disabled_warn(app, warning):
|
|||||||
|
|
||||||
@pytest.mark.parametrize("fname,expect", flat_dict({
|
@pytest.mark.parametrize("fname,expect", flat_dict({
|
||||||
'index.html': [
|
'index.html': [
|
||||||
(".//div[@class='figure align-center']/p[@class='caption']/"
|
(".//div[@class='figure align-default']/p[@class='caption']/"
|
||||||
"span[@class='caption-number']", None, True),
|
"span[@class='caption-number']", None, True),
|
||||||
(".//table/caption/span[@class='caption-number']", None, True),
|
(".//table/caption/span[@class='caption-number']", None, True),
|
||||||
(".//div[@class='code-block-caption']/"
|
(".//div[@class='code-block-caption']/"
|
||||||
@ -582,21 +582,21 @@ def test_numfig_disabled_warn(app, warning):
|
|||||||
(".//li/p/a/span", '^Sect.1 Foo$', True),
|
(".//li/p/a/span", '^Sect.1 Foo$', True),
|
||||||
],
|
],
|
||||||
'foo.html': [
|
'foo.html': [
|
||||||
(".//div[@class='figure align-center']/p[@class='caption']/"
|
(".//div[@class='figure align-default']/p[@class='caption']/"
|
||||||
"span[@class='caption-number']", None, True),
|
"span[@class='caption-number']", None, True),
|
||||||
(".//table/caption/span[@class='caption-number']", None, True),
|
(".//table/caption/span[@class='caption-number']", None, True),
|
||||||
(".//div[@class='code-block-caption']/"
|
(".//div[@class='code-block-caption']/"
|
||||||
"span[@class='caption-number']", None, True),
|
"span[@class='caption-number']", None, True),
|
||||||
],
|
],
|
||||||
'bar.html': [
|
'bar.html': [
|
||||||
(".//div[@class='figure align-center']/p[@class='caption']/"
|
(".//div[@class='figure align-default']/p[@class='caption']/"
|
||||||
"span[@class='caption-number']", None, True),
|
"span[@class='caption-number']", None, True),
|
||||||
(".//table/caption/span[@class='caption-number']", None, True),
|
(".//table/caption/span[@class='caption-number']", None, True),
|
||||||
(".//div[@class='code-block-caption']/"
|
(".//div[@class='code-block-caption']/"
|
||||||
"span[@class='caption-number']", None, True),
|
"span[@class='caption-number']", None, True),
|
||||||
],
|
],
|
||||||
'baz.html': [
|
'baz.html': [
|
||||||
(".//div[@class='figure align-center']/p[@class='caption']/"
|
(".//div[@class='figure align-default']/p[@class='caption']/"
|
||||||
"span[@class='caption-number']", None, True),
|
"span[@class='caption-number']", None, True),
|
||||||
(".//table/caption/span[@class='caption-number']", None, True),
|
(".//table/caption/span[@class='caption-number']", None, True),
|
||||||
(".//div[@class='code-block-caption']/"
|
(".//div[@class='code-block-caption']/"
|
||||||
@ -633,9 +633,9 @@ def test_numfig_without_numbered_toctree_warn(app, warning):
|
|||||||
|
|
||||||
@pytest.mark.parametrize("fname,expect", flat_dict({
|
@pytest.mark.parametrize("fname,expect", flat_dict({
|
||||||
'index.html': [
|
'index.html': [
|
||||||
(".//div[@class='figure align-center']/p[@class='caption']/"
|
(".//div[@class='figure align-default']/p[@class='caption']/"
|
||||||
"span[@class='caption-number']", '^Fig. 9 $', True),
|
"span[@class='caption-number']", '^Fig. 9 $', True),
|
||||||
(".//div[@class='figure align-center']/p[@class='caption']/"
|
(".//div[@class='figure align-default']/p[@class='caption']/"
|
||||||
"span[@class='caption-number']", '^Fig. 10 $', True),
|
"span[@class='caption-number']", '^Fig. 10 $', True),
|
||||||
(".//table/caption/span[@class='caption-number']",
|
(".//table/caption/span[@class='caption-number']",
|
||||||
'^Table 9 $', True),
|
'^Table 9 $', True),
|
||||||
@ -657,13 +657,13 @@ def test_numfig_without_numbered_toctree_warn(app, warning):
|
|||||||
(".//li/p/code/span", '^Sect.{number}$', True),
|
(".//li/p/code/span", '^Sect.{number}$', True),
|
||||||
],
|
],
|
||||||
'foo.html': [
|
'foo.html': [
|
||||||
(".//div[@class='figure align-center']/p[@class='caption']/"
|
(".//div[@class='figure align-default']/p[@class='caption']/"
|
||||||
"span[@class='caption-number']", '^Fig. 1 $', True),
|
"span[@class='caption-number']", '^Fig. 1 $', True),
|
||||||
(".//div[@class='figure align-center']/p[@class='caption']/"
|
(".//div[@class='figure align-default']/p[@class='caption']/"
|
||||||
"span[@class='caption-number']", '^Fig. 2 $', True),
|
"span[@class='caption-number']", '^Fig. 2 $', True),
|
||||||
(".//div[@class='figure align-center']/p[@class='caption']/"
|
(".//div[@class='figure align-default']/p[@class='caption']/"
|
||||||
"span[@class='caption-number']", '^Fig. 3 $', True),
|
"span[@class='caption-number']", '^Fig. 3 $', True),
|
||||||
(".//div[@class='figure align-center']/p[@class='caption']/"
|
(".//div[@class='figure align-default']/p[@class='caption']/"
|
||||||
"span[@class='caption-number']", '^Fig. 4 $', True),
|
"span[@class='caption-number']", '^Fig. 4 $', True),
|
||||||
(".//table/caption/span[@class='caption-number']",
|
(".//table/caption/span[@class='caption-number']",
|
||||||
'^Table 1 $', True),
|
'^Table 1 $', True),
|
||||||
@ -683,11 +683,11 @@ def test_numfig_without_numbered_toctree_warn(app, warning):
|
|||||||
"span[@class='caption-number']", '^Listing 4 $', True),
|
"span[@class='caption-number']", '^Listing 4 $', True),
|
||||||
],
|
],
|
||||||
'bar.html': [
|
'bar.html': [
|
||||||
(".//div[@class='figure align-center']/p[@class='caption']/"
|
(".//div[@class='figure align-default']/p[@class='caption']/"
|
||||||
"span[@class='caption-number']", '^Fig. 5 $', True),
|
"span[@class='caption-number']", '^Fig. 5 $', True),
|
||||||
(".//div[@class='figure align-center']/p[@class='caption']/"
|
(".//div[@class='figure align-default']/p[@class='caption']/"
|
||||||
"span[@class='caption-number']", '^Fig. 7 $', True),
|
"span[@class='caption-number']", '^Fig. 7 $', True),
|
||||||
(".//div[@class='figure align-center']/p[@class='caption']/"
|
(".//div[@class='figure align-default']/p[@class='caption']/"
|
||||||
"span[@class='caption-number']", '^Fig. 8 $', True),
|
"span[@class='caption-number']", '^Fig. 8 $', True),
|
||||||
(".//table/caption/span[@class='caption-number']",
|
(".//table/caption/span[@class='caption-number']",
|
||||||
'^Table 5 $', True),
|
'^Table 5 $', True),
|
||||||
@ -703,7 +703,7 @@ def test_numfig_without_numbered_toctree_warn(app, warning):
|
|||||||
"span[@class='caption-number']", '^Listing 8 $', True),
|
"span[@class='caption-number']", '^Listing 8 $', True),
|
||||||
],
|
],
|
||||||
'baz.html': [
|
'baz.html': [
|
||||||
(".//div[@class='figure align-center']/p[@class='caption']/"
|
(".//div[@class='figure align-default']/p[@class='caption']/"
|
||||||
"span[@class='caption-number']", '^Fig. 6 $', True),
|
"span[@class='caption-number']", '^Fig. 6 $', True),
|
||||||
(".//table/caption/span[@class='caption-number']",
|
(".//table/caption/span[@class='caption-number']",
|
||||||
'^Table 6 $', True),
|
'^Table 6 $', True),
|
||||||
@ -741,9 +741,9 @@ def test_numfig_with_numbered_toctree_warn(app, warning):
|
|||||||
|
|
||||||
@pytest.mark.parametrize("fname,expect", flat_dict({
|
@pytest.mark.parametrize("fname,expect", flat_dict({
|
||||||
'index.html': [
|
'index.html': [
|
||||||
(".//div[@class='figure align-center']/p[@class='caption']/"
|
(".//div[@class='figure align-default']/p[@class='caption']/"
|
||||||
"span[@class='caption-number']", '^Fig. 1 $', True),
|
"span[@class='caption-number']", '^Fig. 1 $', True),
|
||||||
(".//div[@class='figure align-center']/p[@class='caption']/"
|
(".//div[@class='figure align-default']/p[@class='caption']/"
|
||||||
"span[@class='caption-number']", '^Fig. 2 $', True),
|
"span[@class='caption-number']", '^Fig. 2 $', True),
|
||||||
(".//table/caption/span[@class='caption-number']",
|
(".//table/caption/span[@class='caption-number']",
|
||||||
'^Table 1 $', True),
|
'^Table 1 $', True),
|
||||||
@ -765,13 +765,13 @@ def test_numfig_with_numbered_toctree_warn(app, warning):
|
|||||||
(".//li/p/a/span", '^Sect.1 Foo$', True),
|
(".//li/p/a/span", '^Sect.1 Foo$', True),
|
||||||
],
|
],
|
||||||
'foo.html': [
|
'foo.html': [
|
||||||
(".//div[@class='figure align-center']/p[@class='caption']/"
|
(".//div[@class='figure align-default']/p[@class='caption']/"
|
||||||
"span[@class='caption-number']", '^Fig. 1.1 $', True),
|
"span[@class='caption-number']", '^Fig. 1.1 $', True),
|
||||||
(".//div[@class='figure align-center']/p[@class='caption']/"
|
(".//div[@class='figure align-default']/p[@class='caption']/"
|
||||||
"span[@class='caption-number']", '^Fig. 1.2 $', True),
|
"span[@class='caption-number']", '^Fig. 1.2 $', True),
|
||||||
(".//div[@class='figure align-center']/p[@class='caption']/"
|
(".//div[@class='figure align-default']/p[@class='caption']/"
|
||||||
"span[@class='caption-number']", '^Fig. 1.3 $', True),
|
"span[@class='caption-number']", '^Fig. 1.3 $', True),
|
||||||
(".//div[@class='figure align-center']/p[@class='caption']/"
|
(".//div[@class='figure align-default']/p[@class='caption']/"
|
||||||
"span[@class='caption-number']", '^Fig. 1.4 $', True),
|
"span[@class='caption-number']", '^Fig. 1.4 $', True),
|
||||||
(".//table/caption/span[@class='caption-number']",
|
(".//table/caption/span[@class='caption-number']",
|
||||||
'^Table 1.1 $', True),
|
'^Table 1.1 $', True),
|
||||||
@ -791,11 +791,11 @@ def test_numfig_with_numbered_toctree_warn(app, warning):
|
|||||||
"span[@class='caption-number']", '^Listing 1.4 $', True),
|
"span[@class='caption-number']", '^Listing 1.4 $', True),
|
||||||
],
|
],
|
||||||
'bar.html': [
|
'bar.html': [
|
||||||
(".//div[@class='figure align-center']/p[@class='caption']/"
|
(".//div[@class='figure align-default']/p[@class='caption']/"
|
||||||
"span[@class='caption-number']", '^Fig. 2.1 $', True),
|
"span[@class='caption-number']", '^Fig. 2.1 $', True),
|
||||||
(".//div[@class='figure align-center']/p[@class='caption']/"
|
(".//div[@class='figure align-default']/p[@class='caption']/"
|
||||||
"span[@class='caption-number']", '^Fig. 2.3 $', True),
|
"span[@class='caption-number']", '^Fig. 2.3 $', True),
|
||||||
(".//div[@class='figure align-center']/p[@class='caption']/"
|
(".//div[@class='figure align-default']/p[@class='caption']/"
|
||||||
"span[@class='caption-number']", '^Fig. 2.4 $', True),
|
"span[@class='caption-number']", '^Fig. 2.4 $', True),
|
||||||
(".//table/caption/span[@class='caption-number']",
|
(".//table/caption/span[@class='caption-number']",
|
||||||
'^Table 2.1 $', True),
|
'^Table 2.1 $', True),
|
||||||
@ -811,7 +811,7 @@ def test_numfig_with_numbered_toctree_warn(app, warning):
|
|||||||
"span[@class='caption-number']", '^Listing 2.4 $', True),
|
"span[@class='caption-number']", '^Listing 2.4 $', True),
|
||||||
],
|
],
|
||||||
'baz.html': [
|
'baz.html': [
|
||||||
(".//div[@class='figure align-center']/p[@class='caption']/"
|
(".//div[@class='figure align-default']/p[@class='caption']/"
|
||||||
"span[@class='caption-number']", '^Fig. 2.2 $', True),
|
"span[@class='caption-number']", '^Fig. 2.2 $', True),
|
||||||
(".//table/caption/span[@class='caption-number']",
|
(".//table/caption/span[@class='caption-number']",
|
||||||
'^Table 2.2 $', True),
|
'^Table 2.2 $', True),
|
||||||
@ -846,9 +846,9 @@ def test_numfig_with_prefix_warn(app, warning):
|
|||||||
|
|
||||||
@pytest.mark.parametrize("fname,expect", flat_dict({
|
@pytest.mark.parametrize("fname,expect", flat_dict({
|
||||||
'index.html': [
|
'index.html': [
|
||||||
(".//div[@class='figure align-center']/p[@class='caption']/"
|
(".//div[@class='figure align-default']/p[@class='caption']/"
|
||||||
"span[@class='caption-number']", '^Figure:1 $', True),
|
"span[@class='caption-number']", '^Figure:1 $', True),
|
||||||
(".//div[@class='figure align-center']/p[@class='caption']/"
|
(".//div[@class='figure align-default']/p[@class='caption']/"
|
||||||
"span[@class='caption-number']", '^Figure:2 $', True),
|
"span[@class='caption-number']", '^Figure:2 $', True),
|
||||||
(".//table/caption/span[@class='caption-number']",
|
(".//table/caption/span[@class='caption-number']",
|
||||||
'^Tab_1 $', True),
|
'^Tab_1 $', True),
|
||||||
@ -870,13 +870,13 @@ def test_numfig_with_prefix_warn(app, warning):
|
|||||||
(".//li/p/a/span", '^Sect.1 Foo$', True),
|
(".//li/p/a/span", '^Sect.1 Foo$', True),
|
||||||
],
|
],
|
||||||
'foo.html': [
|
'foo.html': [
|
||||||
(".//div[@class='figure align-center']/p[@class='caption']/"
|
(".//div[@class='figure align-default']/p[@class='caption']/"
|
||||||
"span[@class='caption-number']", '^Figure:1.1 $', True),
|
"span[@class='caption-number']", '^Figure:1.1 $', True),
|
||||||
(".//div[@class='figure align-center']/p[@class='caption']/"
|
(".//div[@class='figure align-default']/p[@class='caption']/"
|
||||||
"span[@class='caption-number']", '^Figure:1.2 $', True),
|
"span[@class='caption-number']", '^Figure:1.2 $', True),
|
||||||
(".//div[@class='figure align-center']/p[@class='caption']/"
|
(".//div[@class='figure align-default']/p[@class='caption']/"
|
||||||
"span[@class='caption-number']", '^Figure:1.3 $', True),
|
"span[@class='caption-number']", '^Figure:1.3 $', True),
|
||||||
(".//div[@class='figure align-center']/p[@class='caption']/"
|
(".//div[@class='figure align-default']/p[@class='caption']/"
|
||||||
"span[@class='caption-number']", '^Figure:1.4 $', True),
|
"span[@class='caption-number']", '^Figure:1.4 $', True),
|
||||||
(".//table/caption/span[@class='caption-number']",
|
(".//table/caption/span[@class='caption-number']",
|
||||||
'^Tab_1.1 $', True),
|
'^Tab_1.1 $', True),
|
||||||
@ -896,11 +896,11 @@ def test_numfig_with_prefix_warn(app, warning):
|
|||||||
"span[@class='caption-number']", '^Code-1.4 $', True),
|
"span[@class='caption-number']", '^Code-1.4 $', True),
|
||||||
],
|
],
|
||||||
'bar.html': [
|
'bar.html': [
|
||||||
(".//div[@class='figure align-center']/p[@class='caption']/"
|
(".//div[@class='figure align-default']/p[@class='caption']/"
|
||||||
"span[@class='caption-number']", '^Figure:2.1 $', True),
|
"span[@class='caption-number']", '^Figure:2.1 $', True),
|
||||||
(".//div[@class='figure align-center']/p[@class='caption']/"
|
(".//div[@class='figure align-default']/p[@class='caption']/"
|
||||||
"span[@class='caption-number']", '^Figure:2.3 $', True),
|
"span[@class='caption-number']", '^Figure:2.3 $', True),
|
||||||
(".//div[@class='figure align-center']/p[@class='caption']/"
|
(".//div[@class='figure align-default']/p[@class='caption']/"
|
||||||
"span[@class='caption-number']", '^Figure:2.4 $', True),
|
"span[@class='caption-number']", '^Figure:2.4 $', True),
|
||||||
(".//table/caption/span[@class='caption-number']",
|
(".//table/caption/span[@class='caption-number']",
|
||||||
'^Tab_2.1 $', True),
|
'^Tab_2.1 $', True),
|
||||||
@ -916,7 +916,7 @@ def test_numfig_with_prefix_warn(app, warning):
|
|||||||
"span[@class='caption-number']", '^Code-2.4 $', True),
|
"span[@class='caption-number']", '^Code-2.4 $', True),
|
||||||
],
|
],
|
||||||
'baz.html': [
|
'baz.html': [
|
||||||
(".//div[@class='figure align-center']/p[@class='caption']/"
|
(".//div[@class='figure align-default']/p[@class='caption']/"
|
||||||
"span[@class='caption-number']", '^Figure:2.2 $', True),
|
"span[@class='caption-number']", '^Figure:2.2 $', True),
|
||||||
(".//table/caption/span[@class='caption-number']",
|
(".//table/caption/span[@class='caption-number']",
|
||||||
'^Tab_2.2 $', True),
|
'^Tab_2.2 $', True),
|
||||||
@ -952,9 +952,9 @@ def test_numfig_with_secnum_depth_warn(app, warning):
|
|||||||
|
|
||||||
@pytest.mark.parametrize("fname,expect", flat_dict({
|
@pytest.mark.parametrize("fname,expect", flat_dict({
|
||||||
'index.html': [
|
'index.html': [
|
||||||
(".//div[@class='figure align-center']/p[@class='caption']/"
|
(".//div[@class='figure align-default']/p[@class='caption']/"
|
||||||
"span[@class='caption-number']", '^Fig. 1 $', True),
|
"span[@class='caption-number']", '^Fig. 1 $', True),
|
||||||
(".//div[@class='figure align-center']/p[@class='caption']/"
|
(".//div[@class='figure align-default']/p[@class='caption']/"
|
||||||
"span[@class='caption-number']", '^Fig. 2 $', True),
|
"span[@class='caption-number']", '^Fig. 2 $', True),
|
||||||
(".//table/caption/span[@class='caption-number']",
|
(".//table/caption/span[@class='caption-number']",
|
||||||
'^Table 1 $', True),
|
'^Table 1 $', True),
|
||||||
@ -976,13 +976,13 @@ def test_numfig_with_secnum_depth_warn(app, warning):
|
|||||||
(".//li/p/a/span", '^Sect.1 Foo$', True),
|
(".//li/p/a/span", '^Sect.1 Foo$', True),
|
||||||
],
|
],
|
||||||
'foo.html': [
|
'foo.html': [
|
||||||
(".//div[@class='figure align-center']/p[@class='caption']/"
|
(".//div[@class='figure align-default']/p[@class='caption']/"
|
||||||
"span[@class='caption-number']", '^Fig. 1.1 $', True),
|
"span[@class='caption-number']", '^Fig. 1.1 $', True),
|
||||||
(".//div[@class='figure align-center']/p[@class='caption']/"
|
(".//div[@class='figure align-default']/p[@class='caption']/"
|
||||||
"span[@class='caption-number']", '^Fig. 1.1.1 $', True),
|
"span[@class='caption-number']", '^Fig. 1.1.1 $', True),
|
||||||
(".//div[@class='figure align-center']/p[@class='caption']/"
|
(".//div[@class='figure align-default']/p[@class='caption']/"
|
||||||
"span[@class='caption-number']", '^Fig. 1.1.2 $', True),
|
"span[@class='caption-number']", '^Fig. 1.1.2 $', True),
|
||||||
(".//div[@class='figure align-center']/p[@class='caption']/"
|
(".//div[@class='figure align-default']/p[@class='caption']/"
|
||||||
"span[@class='caption-number']", '^Fig. 1.2.1 $', True),
|
"span[@class='caption-number']", '^Fig. 1.2.1 $', True),
|
||||||
(".//table/caption/span[@class='caption-number']",
|
(".//table/caption/span[@class='caption-number']",
|
||||||
'^Table 1.1 $', True),
|
'^Table 1.1 $', True),
|
||||||
@ -1002,11 +1002,11 @@ def test_numfig_with_secnum_depth_warn(app, warning):
|
|||||||
"span[@class='caption-number']", '^Listing 1.2.1 $', True),
|
"span[@class='caption-number']", '^Listing 1.2.1 $', True),
|
||||||
],
|
],
|
||||||
'bar.html': [
|
'bar.html': [
|
||||||
(".//div[@class='figure align-center']/p[@class='caption']/"
|
(".//div[@class='figure align-default']/p[@class='caption']/"
|
||||||
"span[@class='caption-number']", '^Fig. 2.1.1 $', True),
|
"span[@class='caption-number']", '^Fig. 2.1.1 $', True),
|
||||||
(".//div[@class='figure align-center']/p[@class='caption']/"
|
(".//div[@class='figure align-default']/p[@class='caption']/"
|
||||||
"span[@class='caption-number']", '^Fig. 2.1.3 $', True),
|
"span[@class='caption-number']", '^Fig. 2.1.3 $', True),
|
||||||
(".//div[@class='figure align-center']/p[@class='caption']/"
|
(".//div[@class='figure align-default']/p[@class='caption']/"
|
||||||
"span[@class='caption-number']", '^Fig. 2.2.1 $', True),
|
"span[@class='caption-number']", '^Fig. 2.2.1 $', True),
|
||||||
(".//table/caption/span[@class='caption-number']",
|
(".//table/caption/span[@class='caption-number']",
|
||||||
'^Table 2.1.1 $', True),
|
'^Table 2.1.1 $', True),
|
||||||
@ -1022,7 +1022,7 @@ def test_numfig_with_secnum_depth_warn(app, warning):
|
|||||||
"span[@class='caption-number']", '^Listing 2.2.1 $', True),
|
"span[@class='caption-number']", '^Listing 2.2.1 $', True),
|
||||||
],
|
],
|
||||||
'baz.html': [
|
'baz.html': [
|
||||||
(".//div[@class='figure align-center']/p[@class='caption']/"
|
(".//div[@class='figure align-default']/p[@class='caption']/"
|
||||||
"span[@class='caption-number']", '^Fig. 2.1.2 $', True),
|
"span[@class='caption-number']", '^Fig. 2.1.2 $', True),
|
||||||
(".//table/caption/span[@class='caption-number']",
|
(".//table/caption/span[@class='caption-number']",
|
||||||
'^Table 2.1.2 $', True),
|
'^Table 2.1.2 $', True),
|
||||||
@ -1043,9 +1043,9 @@ def test_numfig_with_secnum_depth(app, cached_etree_parse, fname, expect):
|
|||||||
|
|
||||||
@pytest.mark.parametrize("fname,expect", flat_dict({
|
@pytest.mark.parametrize("fname,expect", flat_dict({
|
||||||
'index.html': [
|
'index.html': [
|
||||||
(".//div[@class='figure align-center']/p[@class='caption']/"
|
(".//div[@class='figure align-default']/p[@class='caption']/"
|
||||||
"span[@class='caption-number']", '^Fig. 1 $', True),
|
"span[@class='caption-number']", '^Fig. 1 $', True),
|
||||||
(".//div[@class='figure align-center']/p[@class='caption']/"
|
(".//div[@class='figure align-default']/p[@class='caption']/"
|
||||||
"span[@class='caption-number']", '^Fig. 2 $', True),
|
"span[@class='caption-number']", '^Fig. 2 $', True),
|
||||||
(".//table/caption/span[@class='caption-number']",
|
(".//table/caption/span[@class='caption-number']",
|
||||||
'^Table 1 $', True),
|
'^Table 1 $', True),
|
||||||
@ -1065,13 +1065,13 @@ def test_numfig_with_secnum_depth(app, cached_etree_parse, fname, expect):
|
|||||||
(".//li/p/a/span", '^Section.2.1$', True),
|
(".//li/p/a/span", '^Section.2.1$', True),
|
||||||
(".//li/p/a/span", '^Fig.1 should be Fig.1$', True),
|
(".//li/p/a/span", '^Fig.1 should be Fig.1$', True),
|
||||||
(".//li/p/a/span", '^Sect.1 Foo$', True),
|
(".//li/p/a/span", '^Sect.1 Foo$', True),
|
||||||
(".//div[@class='figure align-center']/p[@class='caption']/"
|
(".//div[@class='figure align-default']/p[@class='caption']/"
|
||||||
"span[@class='caption-number']", '^Fig. 1.1 $', True),
|
"span[@class='caption-number']", '^Fig. 1.1 $', True),
|
||||||
(".//div[@class='figure align-center']/p[@class='caption']/"
|
(".//div[@class='figure align-default']/p[@class='caption']/"
|
||||||
"span[@class='caption-number']", '^Fig. 1.2 $', True),
|
"span[@class='caption-number']", '^Fig. 1.2 $', True),
|
||||||
(".//div[@class='figure align-center']/p[@class='caption']/"
|
(".//div[@class='figure align-default']/p[@class='caption']/"
|
||||||
"span[@class='caption-number']", '^Fig. 1.3 $', True),
|
"span[@class='caption-number']", '^Fig. 1.3 $', True),
|
||||||
(".//div[@class='figure align-center']/p[@class='caption']/"
|
(".//div[@class='figure align-default']/p[@class='caption']/"
|
||||||
"span[@class='caption-number']", '^Fig. 1.4 $', True),
|
"span[@class='caption-number']", '^Fig. 1.4 $', True),
|
||||||
(".//table/caption/span[@class='caption-number']",
|
(".//table/caption/span[@class='caption-number']",
|
||||||
'^Table 1.1 $', True),
|
'^Table 1.1 $', True),
|
||||||
@ -1089,11 +1089,11 @@ def test_numfig_with_secnum_depth(app, cached_etree_parse, fname, expect):
|
|||||||
"span[@class='caption-number']", '^Listing 1.3 $', True),
|
"span[@class='caption-number']", '^Listing 1.3 $', True),
|
||||||
(".//div[@class='code-block-caption']/"
|
(".//div[@class='code-block-caption']/"
|
||||||
"span[@class='caption-number']", '^Listing 1.4 $', True),
|
"span[@class='caption-number']", '^Listing 1.4 $', True),
|
||||||
(".//div[@class='figure align-center']/p[@class='caption']/"
|
(".//div[@class='figure align-default']/p[@class='caption']/"
|
||||||
"span[@class='caption-number']", '^Fig. 2.1 $', True),
|
"span[@class='caption-number']", '^Fig. 2.1 $', True),
|
||||||
(".//div[@class='figure align-center']/p[@class='caption']/"
|
(".//div[@class='figure align-default']/p[@class='caption']/"
|
||||||
"span[@class='caption-number']", '^Fig. 2.3 $', True),
|
"span[@class='caption-number']", '^Fig. 2.3 $', True),
|
||||||
(".//div[@class='figure align-center']/p[@class='caption']/"
|
(".//div[@class='figure align-default']/p[@class='caption']/"
|
||||||
"span[@class='caption-number']", '^Fig. 2.4 $', True),
|
"span[@class='caption-number']", '^Fig. 2.4 $', True),
|
||||||
(".//table/caption/span[@class='caption-number']",
|
(".//table/caption/span[@class='caption-number']",
|
||||||
'^Table 2.1 $', True),
|
'^Table 2.1 $', True),
|
||||||
@ -1107,7 +1107,7 @@ def test_numfig_with_secnum_depth(app, cached_etree_parse, fname, expect):
|
|||||||
"span[@class='caption-number']", '^Listing 2.3 $', True),
|
"span[@class='caption-number']", '^Listing 2.3 $', True),
|
||||||
(".//div[@class='code-block-caption']/"
|
(".//div[@class='code-block-caption']/"
|
||||||
"span[@class='caption-number']", '^Listing 2.4 $', True),
|
"span[@class='caption-number']", '^Listing 2.4 $', True),
|
||||||
(".//div[@class='figure align-center']/p[@class='caption']/"
|
(".//div[@class='figure align-default']/p[@class='caption']/"
|
||||||
"span[@class='caption-number']", '^Fig. 2.2 $', True),
|
"span[@class='caption-number']", '^Fig. 2.2 $', True),
|
||||||
(".//table/caption/span[@class='caption-number']",
|
(".//table/caption/span[@class='caption-number']",
|
||||||
'^Table 2.2 $', True),
|
'^Table 2.2 $', True),
|
||||||
@ -1126,11 +1126,11 @@ def test_numfig_with_singlehtml(app, cached_etree_parse, fname, expect):
|
|||||||
|
|
||||||
@pytest.mark.parametrize("fname,expect", flat_dict({
|
@pytest.mark.parametrize("fname,expect", flat_dict({
|
||||||
'index.html': [
|
'index.html': [
|
||||||
(".//div[@class='figure align-center']/p[@class='caption']"
|
(".//div[@class='figure align-default']/p[@class='caption']"
|
||||||
"/span[@class='caption-number']", "Fig. 1", True),
|
"/span[@class='caption-number']", "Fig. 1", True),
|
||||||
(".//div[@class='figure align-center']/p[@class='caption']"
|
(".//div[@class='figure align-default']/p[@class='caption']"
|
||||||
"/span[@class='caption-number']", "Fig. 2", True),
|
"/span[@class='caption-number']", "Fig. 2", True),
|
||||||
(".//div[@class='figure align-center']/p[@class='caption']"
|
(".//div[@class='figure align-default']/p[@class='caption']"
|
||||||
"/span[@class='caption-number']", "Fig. 3", True),
|
"/span[@class='caption-number']", "Fig. 3", True),
|
||||||
(".//div//span[@class='caption-number']", "No.1 ", True),
|
(".//div//span[@class='caption-number']", "No.1 ", True),
|
||||||
(".//div//span[@class='caption-number']", "No.2 ", True),
|
(".//div//span[@class='caption-number']", "No.2 ", True),
|
||||||
@ -1338,7 +1338,7 @@ def test_html_sidebar(app, status, warning):
|
|||||||
assert '<h1 class="logo"><a href="#">Python</a></h1>' in result
|
assert '<h1 class="logo"><a href="#">Python</a></h1>' in result
|
||||||
assert '<h3>Navigation</h3>' in result
|
assert '<h3>Navigation</h3>' in result
|
||||||
assert '<h3>Related Topics</h3>' in result
|
assert '<h3>Related Topics</h3>' in result
|
||||||
assert '<h3>Quick search</h3>' in result
|
assert '<h3 id="searchlabel">Quick search</h3>' in result
|
||||||
|
|
||||||
app.builder.add_sidebars('index', ctx)
|
app.builder.add_sidebars('index', ctx)
|
||||||
assert ctx['sidebars'] == ['about.html', 'navigation.html', 'relations.html',
|
assert ctx['sidebars'] == ['about.html', 'navigation.html', 'relations.html',
|
||||||
@ -1353,7 +1353,7 @@ def test_html_sidebar(app, status, warning):
|
|||||||
assert '<h1 class="logo"><a href="#">Python</a></h1>' not in result
|
assert '<h1 class="logo"><a href="#">Python</a></h1>' not in result
|
||||||
assert '<h3>Navigation</h3>' not in result
|
assert '<h3>Navigation</h3>' not in result
|
||||||
assert '<h3>Related Topics</h3>' in result
|
assert '<h3>Related Topics</h3>' in result
|
||||||
assert '<h3>Quick search</h3>' not in result
|
assert '<h3 id="searchlabel">Quick search</h3>' not in result
|
||||||
|
|
||||||
app.builder.add_sidebars('index', ctx)
|
app.builder.add_sidebars('index', ctx)
|
||||||
assert ctx['sidebars'] == ['relations.html']
|
assert ctx['sidebars'] == ['relations.html']
|
||||||
@ -1367,7 +1367,7 @@ def test_html_sidebar(app, status, warning):
|
|||||||
assert '<h1 class="logo"><a href="#">Python</a></h1>' not in result
|
assert '<h1 class="logo"><a href="#">Python</a></h1>' not in result
|
||||||
assert '<h3>Navigation</h3>' not in result
|
assert '<h3>Navigation</h3>' not in result
|
||||||
assert '<h3>Related Topics</h3>' not in result
|
assert '<h3>Related Topics</h3>' not in result
|
||||||
assert '<h3>Quick search</h3>' not in result
|
assert '<h3 id="searchlabel">Quick search</h3>' not in result
|
||||||
|
|
||||||
app.builder.add_sidebars('index', ctx)
|
app.builder.add_sidebars('index', ctx)
|
||||||
assert ctx['sidebars'] == []
|
assert ctx['sidebars'] == []
|
||||||
|
@ -333,7 +333,9 @@ def test_pymethod_options(app):
|
|||||||
" .. py:method:: meth3\n"
|
" .. py:method:: meth3\n"
|
||||||
" :staticmethod:\n"
|
" :staticmethod:\n"
|
||||||
" .. py:method:: meth4\n"
|
" .. py:method:: meth4\n"
|
||||||
" :async:\n")
|
" :async:\n"
|
||||||
|
" .. py:method:: meth5\n"
|
||||||
|
" :property:\n")
|
||||||
domain = app.env.get_domain('py')
|
domain = app.env.get_domain('py')
|
||||||
doctree = restructuredtext.parse(app, text)
|
doctree = restructuredtext.parse(app, text)
|
||||||
assert_node(doctree, (addnodes.index,
|
assert_node(doctree, (addnodes.index,
|
||||||
@ -346,6 +348,8 @@ def test_pymethod_options(app):
|
|||||||
addnodes.index,
|
addnodes.index,
|
||||||
desc,
|
desc,
|
||||||
addnodes.index,
|
addnodes.index,
|
||||||
|
desc,
|
||||||
|
addnodes.index,
|
||||||
desc)])]))
|
desc)])]))
|
||||||
|
|
||||||
# method
|
# method
|
||||||
@ -387,6 +391,15 @@ def test_pymethod_options(app):
|
|||||||
assert 'Class.meth4' in domain.objects
|
assert 'Class.meth4' in domain.objects
|
||||||
assert domain.objects['Class.meth4'] == ('index', 'method')
|
assert domain.objects['Class.meth4'] == ('index', 'method')
|
||||||
|
|
||||||
|
# :property:
|
||||||
|
assert_node(doctree[1][1][8], addnodes.index,
|
||||||
|
entries=[('single', 'meth5() (Class property)', 'Class.meth5', '', None)])
|
||||||
|
assert_node(doctree[1][1][9], ([desc_signature, ([desc_annotation, "property "],
|
||||||
|
[desc_name, "meth5"])],
|
||||||
|
[desc_content, ()]))
|
||||||
|
assert 'Class.meth5' in domain.objects
|
||||||
|
assert domain.objects['Class.meth5'] == ('index', 'method')
|
||||||
|
|
||||||
|
|
||||||
def test_pyclassmethod(app):
|
def test_pyclassmethod(app):
|
||||||
text = (".. py:class:: Class\n"
|
text = (".. py:class:: Class\n"
|
||||||
|
@ -10,8 +10,7 @@
|
|||||||
|
|
||||||
from sphinx import addnodes
|
from sphinx import addnodes
|
||||||
from sphinx.addnodes import (
|
from sphinx.addnodes import (
|
||||||
desc, desc_addname, desc_content, desc_name, desc_optional, desc_parameter,
|
desc, desc_addname, desc_annotation, desc_content, desc_name, desc_signature
|
||||||
desc_parameterlist, desc_returns, desc_signature
|
|
||||||
)
|
)
|
||||||
from sphinx.domains.rst import parse_directive
|
from sphinx.domains.rst import parse_directive
|
||||||
from sphinx.testing import restructuredtext
|
from sphinx.testing import restructuredtext
|
||||||
@ -69,6 +68,66 @@ def test_rst_directive_with_argument(app):
|
|||||||
domain="rst", objtype="directive", noindex=False)
|
domain="rst", objtype="directive", noindex=False)
|
||||||
|
|
||||||
|
|
||||||
|
def test_rst_directive_option(app):
|
||||||
|
text = ".. rst:directive:option:: foo"
|
||||||
|
doctree = restructuredtext.parse(app, text)
|
||||||
|
assert_node(doctree, (addnodes.index,
|
||||||
|
[desc, ([desc_signature, desc_name, ":foo:"],
|
||||||
|
[desc_content, ()])]))
|
||||||
|
assert_node(doctree[0],
|
||||||
|
entries=[("single", ":foo: (directive option)",
|
||||||
|
"directive:option--foo", "", "F")])
|
||||||
|
assert_node(doctree[1], addnodes.desc, desctype="directive:option",
|
||||||
|
domain="rst", objtype="directive:option", noindex=False)
|
||||||
|
|
||||||
|
|
||||||
|
def test_rst_directive_option_with_argument(app):
|
||||||
|
text = ".. rst:directive:option:: foo: bar baz"
|
||||||
|
doctree = restructuredtext.parse(app, text)
|
||||||
|
assert_node(doctree, (addnodes.index,
|
||||||
|
[desc, ([desc_signature, ([desc_name, ":foo:"],
|
||||||
|
[desc_annotation, " bar baz"])],
|
||||||
|
[desc_content, ()])]))
|
||||||
|
assert_node(doctree[0],
|
||||||
|
entries=[("single", ":foo: (directive option)",
|
||||||
|
"directive:option--foo", "", "F")])
|
||||||
|
assert_node(doctree[1], addnodes.desc, desctype="directive:option",
|
||||||
|
domain="rst", objtype="directive:option", noindex=False)
|
||||||
|
|
||||||
|
|
||||||
|
def test_rst_directive_option_type(app):
|
||||||
|
text = (".. rst:directive:option:: foo\n"
|
||||||
|
" :type: directives.flags\n")
|
||||||
|
doctree = restructuredtext.parse(app, text)
|
||||||
|
assert_node(doctree, (addnodes.index,
|
||||||
|
[desc, ([desc_signature, ([desc_name, ":foo:"],
|
||||||
|
[desc_annotation, " (directives.flags)"])],
|
||||||
|
[desc_content, ()])]))
|
||||||
|
assert_node(doctree[0],
|
||||||
|
entries=[("single", ":foo: (directive option)",
|
||||||
|
"directive:option--foo", "", "F")])
|
||||||
|
assert_node(doctree[1], addnodes.desc, desctype="directive:option",
|
||||||
|
domain="rst", objtype="directive:option", noindex=False)
|
||||||
|
|
||||||
|
|
||||||
|
def test_rst_directive_and_directive_option(app):
|
||||||
|
text = (".. rst:directive:: foo\n"
|
||||||
|
"\n"
|
||||||
|
" .. rst:directive:option:: bar\n")
|
||||||
|
doctree = restructuredtext.parse(app, text)
|
||||||
|
assert_node(doctree, (addnodes.index,
|
||||||
|
[desc, ([desc_signature, desc_name, ".. foo::"],
|
||||||
|
[desc_content, (addnodes.index,
|
||||||
|
desc)])]))
|
||||||
|
assert_node(doctree[1][1][0],
|
||||||
|
entries=[("pair", "foo (directive); :bar: (directive option)",
|
||||||
|
"directive:option-foo-bar", "", "B")])
|
||||||
|
assert_node(doctree[1][1][1], ([desc_signature, desc_name, ":bar:"],
|
||||||
|
[desc_content, ()]))
|
||||||
|
assert_node(doctree[1][1][1], addnodes.desc, desctype="directive:option",
|
||||||
|
domain="rst", objtype="directive:option", noindex=False)
|
||||||
|
|
||||||
|
|
||||||
def test_rst_role(app):
|
def test_rst_role(app):
|
||||||
text = ".. rst:role:: ref"
|
text = ".. rst:role:: ref"
|
||||||
doctree = restructuredtext.parse(app, text)
|
doctree = restructuredtext.parse(app, text)
|
||||||
|
@ -21,7 +21,7 @@ def test_graphviz_png_html(app, status, warning):
|
|||||||
app.builder.build_all()
|
app.builder.build_all()
|
||||||
|
|
||||||
content = (app.outdir / 'index.html').text()
|
content = (app.outdir / 'index.html').text()
|
||||||
html = (r'<div class="figure align-center" .*?>\s*'
|
html = (r'<div class="figure align-default" .*?>\s*'
|
||||||
r'<div class="graphviz"><img .*?/></div>\s*<p class="caption">'
|
r'<div class="graphviz"><img .*?/></div>\s*<p class="caption">'
|
||||||
r'<span class="caption-text">caption of graph</span>.*</p>\s*</div>')
|
r'<span class="caption-text">caption of graph</span>.*</p>\s*</div>')
|
||||||
assert re.search(html, content, re.S)
|
assert re.search(html, content, re.S)
|
||||||
@ -52,7 +52,7 @@ def test_graphviz_svg_html(app, status, warning):
|
|||||||
|
|
||||||
content = (app.outdir / 'index.html').text()
|
content = (app.outdir / 'index.html').text()
|
||||||
|
|
||||||
html = (r'<div class=\"figure align-center\" .*?>\n'
|
html = (r'<div class=\"figure align-default\" .*?>\n'
|
||||||
r'<div class="graphviz"><object data=\".*\.svg\".*>\n'
|
r'<div class="graphviz"><object data=\".*\.svg\".*>\n'
|
||||||
r'\s*<p class=\"warning\">digraph foo {\n'
|
r'\s*<p class=\"warning\">digraph foo {\n'
|
||||||
r'bar -> baz\n'
|
r'bar -> baz\n'
|
||||||
|
@ -140,7 +140,7 @@ def test_inheritance_diagram_png_html(app, status, warning):
|
|||||||
|
|
||||||
content = (app.outdir / 'index.html').text()
|
content = (app.outdir / 'index.html').text()
|
||||||
|
|
||||||
pattern = ('<div class="figure align-center" id="id1">\n'
|
pattern = ('<div class="figure align-default" id="id1">\n'
|
||||||
'<div class="graphviz">'
|
'<div class="graphviz">'
|
||||||
'<img src="_images/inheritance-\\w+.png" alt="Inheritance diagram of test.Foo" '
|
'<img src="_images/inheritance-\\w+.png" alt="Inheritance diagram of test.Foo" '
|
||||||
'class="inheritance graphviz" /></div>\n<p class="caption">'
|
'class="inheritance graphviz" /></div>\n<p class="caption">'
|
||||||
@ -157,7 +157,7 @@ def test_inheritance_diagram_svg_html(app, status, warning):
|
|||||||
|
|
||||||
content = (app.outdir / 'index.html').text()
|
content = (app.outdir / 'index.html').text()
|
||||||
|
|
||||||
pattern = ('<div class="figure align-center" id="id1">\n'
|
pattern = ('<div class="figure align-default" id="id1">\n'
|
||||||
'<div class="graphviz">'
|
'<div class="graphviz">'
|
||||||
'<object data="_images/inheritance-\\w+.svg" '
|
'<object data="_images/inheritance-\\w+.svg" '
|
||||||
'type="image/svg\\+xml" class="inheritance graphviz">\n'
|
'type="image/svg\\+xml" class="inheritance graphviz">\n'
|
||||||
@ -197,7 +197,7 @@ def test_inheritance_diagram_latex_alias(app, status, warning):
|
|||||||
|
|
||||||
content = (app.outdir / 'index.html').text()
|
content = (app.outdir / 'index.html').text()
|
||||||
|
|
||||||
pattern = ('<div class="figure align-center" id="id1">\n'
|
pattern = ('<div class="figure align-default" id="id1">\n'
|
||||||
'<div class="graphviz">'
|
'<div class="graphviz">'
|
||||||
'<img src="_images/inheritance-\\w+.png" alt="Inheritance diagram of test.Foo" '
|
'<img src="_images/inheritance-\\w+.png" alt="Inheritance diagram of test.Foo" '
|
||||||
'class="inheritance graphviz" /></div>\n<p class="caption">'
|
'class="inheritance graphviz" /></div>\n<p class="caption">'
|
||||||
|
@ -126,4 +126,4 @@ def test_theme_sidebars(app, status, warning):
|
|||||||
assert '<h3><a href="#">Table of Contents</a></h3>' in result
|
assert '<h3><a href="#">Table of Contents</a></h3>' in result
|
||||||
assert '<h3>Related Topics</h3>' not in result
|
assert '<h3>Related Topics</h3>' not in result
|
||||||
assert '<h3>This Page</h3>' not in result
|
assert '<h3>This Page</h3>' not in result
|
||||||
assert '<h3>Quick search</h3>' in result
|
assert '<h3 id="searchlabel">Quick search</h3>' in result
|
||||||
|
@ -475,3 +475,14 @@ def test_isattributedescriptor(app):
|
|||||||
assert inspect.isattributedescriptor(types.FrameType.f_locals) is True # GetSetDescriptorType # NOQA
|
assert inspect.isattributedescriptor(types.FrameType.f_locals) is True # GetSetDescriptorType # NOQA
|
||||||
assert inspect.isattributedescriptor(datetime.timedelta.days) is True # MemberDescriptorType # NOQA
|
assert inspect.isattributedescriptor(datetime.timedelta.days) is True # MemberDescriptorType # NOQA
|
||||||
assert inspect.isattributedescriptor(testinstancemethod) is False # instancemethod (C-API) # NOQA
|
assert inspect.isattributedescriptor(testinstancemethod) is False # instancemethod (C-API) # NOQA
|
||||||
|
|
||||||
|
|
||||||
|
def test_isproperty(app):
|
||||||
|
from target.functions import func
|
||||||
|
from target.methods import Base
|
||||||
|
|
||||||
|
assert inspect.isproperty(Base.prop) is True # property of class
|
||||||
|
assert inspect.isproperty(Base().prop) is False # property of instance
|
||||||
|
assert inspect.isproperty(Base.meth) is False # method of class
|
||||||
|
assert inspect.isproperty(Base().meth) is False # method of instance
|
||||||
|
assert inspect.isproperty(func) is False # function
|
||||||
|
9
tox.ini
9
tox.ini
@ -66,6 +66,15 @@ extras =
|
|||||||
commands =
|
commands =
|
||||||
python setup.py build_sphinx {posargs}
|
python setup.py build_sphinx {posargs}
|
||||||
|
|
||||||
|
[testenv:docslint]
|
||||||
|
basepython = python3
|
||||||
|
description =
|
||||||
|
Lint documentation.
|
||||||
|
extras =
|
||||||
|
docs
|
||||||
|
commands =
|
||||||
|
python utils/doclinter.py CHANGES CONTRIBUTING.rst README.rst doc/
|
||||||
|
|
||||||
[testenv:bindep]
|
[testenv:bindep]
|
||||||
description =
|
description =
|
||||||
Install binary dependencies.
|
Install binary dependencies.
|
||||||
|
59
utils/doclinter.py
Normal file
59
utils/doclinter.py
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
"""
|
||||||
|
utils.doclinter
|
||||||
|
~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
A linter for Sphinx docs
|
||||||
|
|
||||||
|
:copyright: Copyright 2007-2019 by the Sphinx team, see AUTHORS.
|
||||||
|
:license: BSD, see LICENSE for details.
|
||||||
|
"""
|
||||||
|
|
||||||
|
import os
|
||||||
|
import re
|
||||||
|
import sys
|
||||||
|
from typing import List
|
||||||
|
|
||||||
|
|
||||||
|
MAX_LINE_LENGTH = 100
|
||||||
|
|
||||||
|
|
||||||
|
def lint(path: str) -> int:
|
||||||
|
with open(path) as f:
|
||||||
|
document = f.readlines()
|
||||||
|
|
||||||
|
errors = 0
|
||||||
|
for i, line in enumerate(document):
|
||||||
|
if line.endswith(' '):
|
||||||
|
print('%s:%d: the line ends with whitespace.' %
|
||||||
|
(path, i + 1))
|
||||||
|
errors += 1
|
||||||
|
|
||||||
|
if len(line) > MAX_LINE_LENGTH:
|
||||||
|
if re.match(r'^\s*\.\. ', line):
|
||||||
|
# ignore directives and hyperlink targets
|
||||||
|
pass
|
||||||
|
else:
|
||||||
|
print('%s:%d: the line is too long (%d > %d).' %
|
||||||
|
(path, i + 1, len(line), MAX_LINE_LENGTH))
|
||||||
|
errors += 1
|
||||||
|
|
||||||
|
return errors
|
||||||
|
|
||||||
|
|
||||||
|
def main(args: List[str]) -> int:
|
||||||
|
errors = 0
|
||||||
|
for directory in args:
|
||||||
|
for root, dirs, files in os.walk(directory):
|
||||||
|
for filename in files:
|
||||||
|
if filename.endswith('.rst'):
|
||||||
|
path = os.path.join(root, filename)
|
||||||
|
errors += lint(path)
|
||||||
|
|
||||||
|
if errors:
|
||||||
|
return 1
|
||||||
|
else:
|
||||||
|
return 0
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
sys.exit(main(sys.argv[1:]))
|
Loading…
Reference in New Issue
Block a user