mirror of
https://github.com/sphinx-doc/sphinx.git
synced 2025-02-25 18:55:22 -06:00
Merge branch '3.x'
This commit is contained in:
commit
e116613a3a
@ -1,8 +1,6 @@
|
|||||||
|
comment: false
|
||||||
coverage:
|
coverage:
|
||||||
status:
|
status:
|
||||||
project:
|
project:
|
||||||
default:
|
default:
|
||||||
enabled: no
|
enabled: no
|
||||||
patch:
|
|
||||||
default:
|
|
||||||
enabled: no
|
|
||||||
|
13
.travis.yml
13
.travis.yml
@ -1,6 +1,6 @@
|
|||||||
language: python
|
os: linux
|
||||||
sudo: false
|
|
||||||
dist: xenial
|
dist: xenial
|
||||||
|
language: python
|
||||||
cache: pip
|
cache: pip
|
||||||
|
|
||||||
env:
|
env:
|
||||||
@ -9,7 +9,7 @@ env:
|
|||||||
- SKIP_LATEX_BUILD=1
|
- SKIP_LATEX_BUILD=1
|
||||||
- IS_PYTHON=true
|
- IS_PYTHON=true
|
||||||
|
|
||||||
matrix:
|
jobs:
|
||||||
include:
|
include:
|
||||||
- python: '3.6'
|
- python: '3.6'
|
||||||
env:
|
env:
|
||||||
@ -20,7 +20,9 @@ matrix:
|
|||||||
- python: '3.8'
|
- python: '3.8'
|
||||||
env:
|
env:
|
||||||
- TOXENV=du16
|
- TOXENV=du16
|
||||||
- PYTEST_ADDOPTS="--cov ./ --cov-append --cov-config setup.cfg"
|
# Disable codecov temporarily
|
||||||
|
# refs: https://github.com/sphinx-doc/sphinx/pull/7286#issuecomment-596617853
|
||||||
|
# - PYTEST_ADDOPTS="--cov ./ --cov-append --cov-config setup.cfg"
|
||||||
- python: 'nightly'
|
- python: 'nightly'
|
||||||
env:
|
env:
|
||||||
- TOXENV=py39
|
- TOXENV=py39
|
||||||
@ -34,8 +36,7 @@ matrix:
|
|||||||
env: TOXENV=flake8
|
env: TOXENV=flake8
|
||||||
|
|
||||||
- language: node_js
|
- language: node_js
|
||||||
node_js:
|
node_js: '10.7'
|
||||||
- 10.7
|
|
||||||
env: IS_PYTHON=false
|
env: IS_PYTHON=false
|
||||||
services: xvfb
|
services: xvfb
|
||||||
|
|
||||||
|
18
CHANGES
18
CHANGES
@ -52,18 +52,17 @@ Incompatible changes
|
|||||||
* Due to the scoping changes for :rst:dir:`productionlist` some uses of
|
* Due to the scoping changes for :rst:dir:`productionlist` some uses of
|
||||||
:rst:role:`token` must be modified to include the scope which was previously
|
:rst:role:`token` must be modified to include the scope which was previously
|
||||||
ignored.
|
ignored.
|
||||||
* #6903: js domain: Internal data structure has changed. Both objects and
|
* #6903: Internal data structure of Python, reST and standard domains have
|
||||||
modules have node_id for cross reference
|
changed. The node_id is added to the index of objects and modules. Now they
|
||||||
|
contains a pair of docname and node_id for cross reference.
|
||||||
* #7210: js domain: Non intended behavior is removed such as ``parseInt_`` links
|
* #7210: js domain: Non intended behavior is removed such as ``parseInt_`` links
|
||||||
to ``.. js:function:: parseInt``
|
to ``.. js:function:: parseInt``
|
||||||
* #6903: rst domain: Internal data structure has changed. Now objects have
|
|
||||||
node_id for cross reference
|
|
||||||
* #7229: rst domain: Non intended behavior is removed such as ``numref_`` links
|
* #7229: rst domain: Non intended behavior is removed such as ``numref_`` links
|
||||||
to ``.. rst:role:: numref``
|
to ``.. rst:role:: numref``
|
||||||
* #6903: py domain: Internal data structure has changed. Both objects and
|
|
||||||
modules have node_id for cross reference
|
|
||||||
* #6903: py domain: Non intended behavior is removed such as ``say_hello_``
|
* #6903: py domain: Non intended behavior is removed such as ``say_hello_``
|
||||||
links to ``.. py:function:: say_hello()``
|
links to ``.. py:function:: say_hello()``
|
||||||
|
* #7246: py domain: Drop special cross reference helper for exceptions,
|
||||||
|
functions and methods
|
||||||
|
|
||||||
Deprecated
|
Deprecated
|
||||||
----------
|
----------
|
||||||
@ -71,6 +70,7 @@ Deprecated
|
|||||||
* ``desc_signature['first']``
|
* ``desc_signature['first']``
|
||||||
* ``sphinx.directives.DescDirective``
|
* ``sphinx.directives.DescDirective``
|
||||||
* ``sphinx.domains.std.StandardDomain.add_object()``
|
* ``sphinx.domains.std.StandardDomain.add_object()``
|
||||||
|
* ``sphinx.domains.python.PyDecoratorMixin``
|
||||||
* ``sphinx.parsers.Parser.app``
|
* ``sphinx.parsers.Parser.app``
|
||||||
* ``sphinx.testing.path.Path.text()``
|
* ``sphinx.testing.path.Path.text()``
|
||||||
* ``sphinx.testing.path.Path.bytes()``
|
* ``sphinx.testing.path.Path.bytes()``
|
||||||
@ -87,6 +87,9 @@ Features added
|
|||||||
* #6830: autodoc: consider a member private if docstring contains
|
* #6830: autodoc: consider a member private if docstring contains
|
||||||
``:meta private:`` in info-field-list
|
``:meta private:`` in info-field-list
|
||||||
* #7165: autodoc: Support Annotated type (PEP-593)
|
* #7165: autodoc: Support Annotated type (PEP-593)
|
||||||
|
* #2815: autodoc: Support singledispatch functions and methods
|
||||||
|
* #7079: autodoc: :confval:`autodoc_typehints` accepts ``"description"``
|
||||||
|
configuration. It shows typehints as object description
|
||||||
* #6558: glossary: emit a warning for duplicated glossary entry
|
* #6558: glossary: emit a warning for duplicated glossary entry
|
||||||
* #3106: domain: Register hyperlink target for index page automatically
|
* #3106: domain: Register hyperlink target for index page automatically
|
||||||
* #6558: std domain: emit a warning for duplicated generic objects
|
* #6558: std domain: emit a warning for duplicated generic objects
|
||||||
@ -120,8 +123,11 @@ Bugs fixed
|
|||||||
* C++, suppress warnings for directly dependent typenames in cross references
|
* C++, suppress warnings for directly dependent typenames in cross references
|
||||||
generated automatically in signatures.
|
generated automatically in signatures.
|
||||||
* #5637: autodoc: Incorrect handling of nested class names on show-inheritance
|
* #5637: autodoc: Incorrect handling of nested class names on show-inheritance
|
||||||
|
* #7267: autodoc: error message for invalid directive options has wrong location
|
||||||
* #5637: inheritance_diagram: Incorrect handling of nested class names
|
* #5637: inheritance_diagram: Incorrect handling of nested class names
|
||||||
* #7139: ``code-block:: guess`` does not work
|
* #7139: ``code-block:: guess`` does not work
|
||||||
|
* #7278: html search: Fix use of ``html_file_suffix`` instead of
|
||||||
|
``html_link_suffix`` in search results
|
||||||
|
|
||||||
Testing
|
Testing
|
||||||
--------
|
--------
|
||||||
|
@ -5,7 +5,6 @@ PYTHON ?= python3
|
|||||||
# You can set these variables from the command line.
|
# You can set these variables from the command line.
|
||||||
SPHINXOPTS =
|
SPHINXOPTS =
|
||||||
SPHINXBUILD = $(PYTHON) ../sphinx/cmd/build.py
|
SPHINXBUILD = $(PYTHON) ../sphinx/cmd/build.py
|
||||||
SPHINXPROJ = sphinx
|
|
||||||
SOURCEDIR = .
|
SOURCEDIR = .
|
||||||
BUILDDIR = _build
|
BUILDDIR = _build
|
||||||
|
|
||||||
|
@ -7,6 +7,7 @@ import sphinx
|
|||||||
|
|
||||||
extensions = ['sphinx.ext.autodoc', 'sphinx.ext.doctest', 'sphinx.ext.todo',
|
extensions = ['sphinx.ext.autodoc', 'sphinx.ext.doctest', 'sphinx.ext.todo',
|
||||||
'sphinx.ext.autosummary', 'sphinx.ext.extlinks',
|
'sphinx.ext.autosummary', 'sphinx.ext.extlinks',
|
||||||
|
'sphinx.ext.intersphinx',
|
||||||
'sphinx.ext.viewcode', 'sphinx.ext.inheritance_diagram']
|
'sphinx.ext.viewcode', 'sphinx.ext.inheritance_diagram']
|
||||||
|
|
||||||
master_doc = 'contents'
|
master_doc = 'contents'
|
||||||
|
@ -61,6 +61,11 @@ The following is a list of deprecated interfaces.
|
|||||||
- 5.0
|
- 5.0
|
||||||
- ``sphinx.domains.std.StandardDomain.note_object()``
|
- ``sphinx.domains.std.StandardDomain.note_object()``
|
||||||
|
|
||||||
|
* - ``sphinx.domains.python.PyDecoratorMixin``
|
||||||
|
- 3.0
|
||||||
|
- 5.0
|
||||||
|
- N/A
|
||||||
|
|
||||||
* - ``sphinx.parsers.Parser.app``
|
* - ``sphinx.parsers.Parser.app``
|
||||||
- 3.0
|
- 3.0
|
||||||
- 5.0
|
- 5.0
|
||||||
|
@ -7,7 +7,6 @@ if "%SPHINXBUILD%" == "" (
|
|||||||
)
|
)
|
||||||
set SOURCEDIR=.
|
set SOURCEDIR=.
|
||||||
set BUILDDIR=_build
|
set BUILDDIR=_build
|
||||||
set SPHINXPROJ=sphinx-doc
|
|
||||||
|
|
||||||
if "%1" == "" goto help
|
if "%1" == "" goto help
|
||||||
|
|
||||||
|
@ -466,9 +466,13 @@ There are also config values that you can set:
|
|||||||
following values:
|
following values:
|
||||||
|
|
||||||
* ``'signature'`` -- Show typehints as its signature (default)
|
* ``'signature'`` -- Show typehints as its signature (default)
|
||||||
|
* ``'description'`` -- Show typehints as content of function or method
|
||||||
* ``'none'`` -- Do not show typehints
|
* ``'none'`` -- Do not show typehints
|
||||||
|
|
||||||
.. versionadded:: 2.1
|
.. versionadded:: 2.1
|
||||||
|
.. versionadded:: 3.0
|
||||||
|
|
||||||
|
New option ``'description'`` is added.
|
||||||
|
|
||||||
.. confval:: autodoc_warningiserror
|
.. confval:: autodoc_warningiserror
|
||||||
|
|
||||||
@ -596,24 +600,3 @@ member should be included in the documentation by using the following event:
|
|||||||
``inherited_members``, ``undoc_members``, ``show_inheritance`` and
|
``inherited_members``, ``undoc_members``, ``show_inheritance`` and
|
||||||
``noindex`` that are true if the flag option of same name was given to the
|
``noindex`` that are true if the flag option of same name was given to the
|
||||||
auto directive
|
auto directive
|
||||||
|
|
||||||
Generating documents from type annotations
|
|
||||||
------------------------------------------
|
|
||||||
|
|
||||||
As an experimental feature, autodoc provides ``sphinx.ext.autodoc.typehints`` as
|
|
||||||
an additional extension. It extends autodoc itself to generate function document
|
|
||||||
from its type annotations.
|
|
||||||
|
|
||||||
To enable the feature, please add ``sphinx.ext.autodoc.typehints`` to list of
|
|
||||||
extensions and set `'description'` to :confval:`autodoc_typehints`:
|
|
||||||
|
|
||||||
.. code-block:: python
|
|
||||||
|
|
||||||
extensions = ['sphinx.ext.autodoc', 'sphinx.ext.autodoc.typehints']
|
|
||||||
|
|
||||||
autodoc_typehints = 'description'
|
|
||||||
|
|
||||||
.. versionadded:: 2.4
|
|
||||||
|
|
||||||
Added as an experimental feature. This will be integrated into autodoc core
|
|
||||||
in Sphinx-3.0.
|
|
||||||
|
2
setup.py
2
setup.py
@ -48,7 +48,7 @@ extras_require = {
|
|||||||
'docutils-stubs',
|
'docutils-stubs',
|
||||||
],
|
],
|
||||||
'test': [
|
'test': [
|
||||||
'pytest < 5.3.3',
|
'pytest',
|
||||||
'pytest-cov',
|
'pytest-cov',
|
||||||
'html5lib',
|
'html5lib',
|
||||||
'typed_ast', # for py35-37
|
'typed_ast', # for py35-37
|
||||||
|
@ -469,6 +469,7 @@ class StandaloneHTMLBuilder(Builder):
|
|||||||
'show_source': self.config.html_show_sourcelink,
|
'show_source': self.config.html_show_sourcelink,
|
||||||
'sourcelink_suffix': self.config.html_sourcelink_suffix,
|
'sourcelink_suffix': self.config.html_sourcelink_suffix,
|
||||||
'file_suffix': self.out_suffix,
|
'file_suffix': self.out_suffix,
|
||||||
|
'link_suffix': self.link_suffix,
|
||||||
'script_files': self.script_files,
|
'script_files': self.script_files,
|
||||||
'language': self.config.language,
|
'language': self.config.language,
|
||||||
'css_files': self.css_files,
|
'css_files': self.css_files,
|
||||||
|
@ -25,7 +25,7 @@ from sphinx import addnodes
|
|||||||
from sphinx.addnodes import pending_xref, desc_signature
|
from sphinx.addnodes import pending_xref, desc_signature
|
||||||
from sphinx.application import Sphinx
|
from sphinx.application import Sphinx
|
||||||
from sphinx.builders import Builder
|
from sphinx.builders import Builder
|
||||||
from sphinx.deprecation import RemovedInSphinx40Warning
|
from sphinx.deprecation import RemovedInSphinx40Warning, RemovedInSphinx50Warning
|
||||||
from sphinx.directives import ObjectDescription
|
from sphinx.directives import ObjectDescription
|
||||||
from sphinx.domains import Domain, ObjType, Index, IndexEntry
|
from sphinx.domains import Domain, ObjType, Index, IndexEntry
|
||||||
from sphinx.environment import BuildEnvironment
|
from sphinx.environment import BuildEnvironment
|
||||||
@ -439,8 +439,14 @@ class PyModulelevel(PyObject):
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
def run(self) -> List[Node]:
|
def run(self) -> List[Node]:
|
||||||
warnings.warn('PyModulelevel is deprecated.',
|
for cls in self.__class__.__mro__:
|
||||||
RemovedInSphinx40Warning)
|
if cls.__name__ != 'DirectiveAdapter':
|
||||||
|
warnings.warn('PyModulelevel is deprecated. '
|
||||||
|
'Please check the implementation of %s' % cls,
|
||||||
|
RemovedInSphinx40Warning)
|
||||||
|
break
|
||||||
|
else:
|
||||||
|
warnings.warn('PyModulelevel is deprecated', RemovedInSphinx40Warning)
|
||||||
|
|
||||||
return super().run()
|
return super().run()
|
||||||
|
|
||||||
@ -485,6 +491,23 @@ class PyFunction(PyObject):
|
|||||||
return _('%s() (built-in function)') % name
|
return _('%s() (built-in function)') % name
|
||||||
|
|
||||||
|
|
||||||
|
class PyDecoratorFunction(PyFunction):
|
||||||
|
"""Description of a decorator."""
|
||||||
|
|
||||||
|
def run(self) -> List[Node]:
|
||||||
|
# a decorator function is a function after all
|
||||||
|
self.name = 'py:function'
|
||||||
|
return super().run()
|
||||||
|
|
||||||
|
def handle_signature(self, sig: str, signode: desc_signature) -> Tuple[str, str]:
|
||||||
|
ret = super().handle_signature(sig, signode)
|
||||||
|
signode.insert(0, addnodes.desc_addname('@', '@'))
|
||||||
|
return ret
|
||||||
|
|
||||||
|
def needs_arglist(self) -> bool:
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
class PyVariable(PyObject):
|
class PyVariable(PyObject):
|
||||||
"""Description of a variable."""
|
"""Description of a variable."""
|
||||||
|
|
||||||
@ -542,8 +565,14 @@ class PyClassmember(PyObject):
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
def run(self) -> List[Node]:
|
def run(self) -> List[Node]:
|
||||||
warnings.warn('PyClassmember is deprecated.',
|
for cls in self.__class__.__mro__:
|
||||||
RemovedInSphinx40Warning)
|
if cls.__name__ != 'DirectiveAdapter':
|
||||||
|
warnings.warn('PyClassmember is deprecated. '
|
||||||
|
'Please check the implementation of %s' % cls,
|
||||||
|
RemovedInSphinx40Warning)
|
||||||
|
break
|
||||||
|
else:
|
||||||
|
warnings.warn('PyClassmember is deprecated', RemovedInSphinx40Warning)
|
||||||
|
|
||||||
return super().run()
|
return super().run()
|
||||||
|
|
||||||
@ -696,6 +725,22 @@ class PyStaticMethod(PyMethod):
|
|||||||
return super().run()
|
return super().run()
|
||||||
|
|
||||||
|
|
||||||
|
class PyDecoratorMethod(PyMethod):
|
||||||
|
"""Description of a decoratormethod."""
|
||||||
|
|
||||||
|
def run(self) -> List[Node]:
|
||||||
|
self.name = 'py:method'
|
||||||
|
return super().run()
|
||||||
|
|
||||||
|
def handle_signature(self, sig: str, signode: desc_signature) -> Tuple[str, str]:
|
||||||
|
ret = super().handle_signature(sig, signode)
|
||||||
|
signode.insert(0, addnodes.desc_addname('@', '@'))
|
||||||
|
return ret
|
||||||
|
|
||||||
|
def needs_arglist(self) -> bool:
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
class PyAttribute(PyObject):
|
class PyAttribute(PyObject):
|
||||||
"""Description of an attribute."""
|
"""Description of an attribute."""
|
||||||
|
|
||||||
@ -738,6 +783,15 @@ class PyDecoratorMixin:
|
|||||||
Mixin for decorator directives.
|
Mixin for decorator directives.
|
||||||
"""
|
"""
|
||||||
def handle_signature(self, sig: str, signode: desc_signature) -> Tuple[str, str]:
|
def handle_signature(self, sig: str, signode: desc_signature) -> Tuple[str, str]:
|
||||||
|
for cls in self.__class__.__mro__:
|
||||||
|
if cls.__name__ != 'DirectiveAdapter':
|
||||||
|
warnings.warn('PyDecoratorMixin is deprecated. '
|
||||||
|
'Please check the implementation of %s' % cls,
|
||||||
|
RemovedInSphinx50Warning)
|
||||||
|
break
|
||||||
|
else:
|
||||||
|
warnings.warn('PyDecoratorMixin is deprecated', RemovedInSphinx50Warning)
|
||||||
|
|
||||||
ret = super().handle_signature(sig, signode) # type: ignore
|
ret = super().handle_signature(sig, signode) # type: ignore
|
||||||
signode.insert(0, addnodes.desc_addname('@', '@'))
|
signode.insert(0, addnodes.desc_addname('@', '@'))
|
||||||
return ret
|
return ret
|
||||||
@ -746,25 +800,6 @@ class PyDecoratorMixin:
|
|||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
class PyDecoratorFunction(PyDecoratorMixin, PyModulelevel):
|
|
||||||
"""
|
|
||||||
Directive to mark functions meant to be used as decorators.
|
|
||||||
"""
|
|
||||||
def run(self) -> List[Node]:
|
|
||||||
# a decorator function is a function after all
|
|
||||||
self.name = 'py:function'
|
|
||||||
return super().run()
|
|
||||||
|
|
||||||
|
|
||||||
class PyDecoratorMethod(PyDecoratorMixin, PyClassmember):
|
|
||||||
"""
|
|
||||||
Directive to mark methods meant to be used as decorators.
|
|
||||||
"""
|
|
||||||
def run(self) -> List[Node]:
|
|
||||||
self.name = 'py:method'
|
|
||||||
return super().run()
|
|
||||||
|
|
||||||
|
|
||||||
class PyModule(SphinxDirective):
|
class PyModule(SphinxDirective):
|
||||||
"""
|
"""
|
||||||
Directive to mark description of a new module.
|
Directive to mark description of a new module.
|
||||||
@ -1106,14 +1141,6 @@ class PythonDomain(Domain):
|
|||||||
elif modname and classname and \
|
elif modname and classname and \
|
||||||
modname + '.' + classname + '.' + name in self.objects:
|
modname + '.' + classname + '.' + name in self.objects:
|
||||||
newname = modname + '.' + classname + '.' + name
|
newname = modname + '.' + classname + '.' + name
|
||||||
# special case: builtin exceptions have module "exceptions" set
|
|
||||||
elif type == 'exc' and '.' not in name and \
|
|
||||||
'exceptions.' + name in self.objects:
|
|
||||||
newname = 'exceptions.' + name
|
|
||||||
# special case: object methods
|
|
||||||
elif type in ('func', 'meth') and '.' not in name and \
|
|
||||||
'object.' + name in self.objects:
|
|
||||||
newname = 'object.' + name
|
|
||||||
if newname is not None:
|
if newname is not None:
|
||||||
matches.append((newname, self.objects[newname]))
|
matches.append((newname, self.objects[newname]))
|
||||||
return matches
|
return matches
|
||||||
|
@ -16,6 +16,7 @@ import warnings
|
|||||||
from types import ModuleType
|
from types import ModuleType
|
||||||
from typing import Any, Callable, Dict, Iterator, List, Sequence, Set, Tuple, Type, Union
|
from typing import Any, Callable, Dict, Iterator, List, Sequence, Set, Tuple, Type, Union
|
||||||
from typing import TYPE_CHECKING
|
from typing import TYPE_CHECKING
|
||||||
|
from unittest.mock import patch
|
||||||
|
|
||||||
from docutils.statemachine import StringList
|
from docutils.statemachine import StringList
|
||||||
|
|
||||||
@ -1002,7 +1003,7 @@ class FunctionDocumenter(DocstringSignatureMixin, ModuleLevelDocumenter): # typ
|
|||||||
(inspect.isroutine(member) and isinstance(parent, ModuleDocumenter)))
|
(inspect.isroutine(member) and isinstance(parent, ModuleDocumenter)))
|
||||||
|
|
||||||
def format_args(self, **kwargs: Any) -> str:
|
def format_args(self, **kwargs: Any) -> str:
|
||||||
if self.env.config.autodoc_typehints == 'none':
|
if self.env.config.autodoc_typehints in ('none', 'description'):
|
||||||
kwargs.setdefault('show_annotation', False)
|
kwargs.setdefault('show_annotation', False)
|
||||||
|
|
||||||
if inspect.isbuiltin(self.object) or inspect.ismethoddescriptor(self.object):
|
if inspect.isbuiltin(self.object) or inspect.ismethoddescriptor(self.object):
|
||||||
@ -1055,6 +1056,62 @@ class FunctionDocumenter(DocstringSignatureMixin, ModuleLevelDocumenter): # typ
|
|||||||
self.add_line(' :async:', sourcename)
|
self.add_line(' :async:', sourcename)
|
||||||
|
|
||||||
|
|
||||||
|
class SingledispatchFunctionDocumenter(FunctionDocumenter):
|
||||||
|
"""
|
||||||
|
Specialized Documenter subclass for singledispatch'ed functions.
|
||||||
|
"""
|
||||||
|
objtype = 'singledispatch_function'
|
||||||
|
directivetype = 'function'
|
||||||
|
member_order = 30
|
||||||
|
|
||||||
|
# before FunctionDocumenter
|
||||||
|
priority = FunctionDocumenter.priority + 1
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def can_document_member(cls, member: Any, membername: str, isattr: bool, parent: Any
|
||||||
|
) -> bool:
|
||||||
|
return (super().can_document_member(member, membername, isattr, parent) and
|
||||||
|
inspect.is_singledispatch_function(member))
|
||||||
|
|
||||||
|
def add_directive_header(self, sig: str) -> None:
|
||||||
|
sourcename = self.get_sourcename()
|
||||||
|
|
||||||
|
# intercept generated directive headers
|
||||||
|
# TODO: It is very hacky to use mock to intercept header generation
|
||||||
|
with patch.object(self, 'add_line') as add_line:
|
||||||
|
super().add_directive_header(sig)
|
||||||
|
|
||||||
|
# output first line of header
|
||||||
|
self.add_line(*add_line.call_args_list[0][0])
|
||||||
|
|
||||||
|
# inserts signature of singledispatch'ed functions
|
||||||
|
for typ, func in self.object.registry.items():
|
||||||
|
if typ is object:
|
||||||
|
pass # default implementation. skipped.
|
||||||
|
else:
|
||||||
|
self.annotate_to_first_argument(func, typ)
|
||||||
|
|
||||||
|
documenter = FunctionDocumenter(self.directive, '')
|
||||||
|
documenter.object = func
|
||||||
|
self.add_line(' %s%s' % (self.format_name(),
|
||||||
|
documenter.format_signature()),
|
||||||
|
sourcename)
|
||||||
|
|
||||||
|
# output remains of directive header
|
||||||
|
for call in add_line.call_args_list[1:]:
|
||||||
|
self.add_line(*call[0])
|
||||||
|
|
||||||
|
def annotate_to_first_argument(self, func: Callable, typ: Type) -> None:
|
||||||
|
"""Annotate type hint to the first argument of function if needed."""
|
||||||
|
sig = inspect.signature(func)
|
||||||
|
if len(sig.parameters) == 0:
|
||||||
|
return
|
||||||
|
|
||||||
|
name = list(sig.parameters)[0]
|
||||||
|
if name not in func.__annotations__:
|
||||||
|
func.__annotations__[name] = typ
|
||||||
|
|
||||||
|
|
||||||
class DecoratorDocumenter(FunctionDocumenter):
|
class DecoratorDocumenter(FunctionDocumenter):
|
||||||
"""
|
"""
|
||||||
Specialized Documenter subclass for decorator functions.
|
Specialized Documenter subclass for decorator functions.
|
||||||
@ -1399,6 +1456,66 @@ class MethodDocumenter(DocstringSignatureMixin, ClassLevelDocumenter): # type:
|
|||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class SingledispatchMethodDocumenter(MethodDocumenter):
|
||||||
|
"""
|
||||||
|
Specialized Documenter subclass for singledispatch'ed methods.
|
||||||
|
"""
|
||||||
|
objtype = 'singledispatch_method'
|
||||||
|
directivetype = 'method'
|
||||||
|
member_order = 50
|
||||||
|
|
||||||
|
# before MethodDocumenter
|
||||||
|
priority = MethodDocumenter.priority + 1
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def can_document_member(cls, member: Any, membername: str, isattr: bool, parent: Any
|
||||||
|
) -> bool:
|
||||||
|
if super().can_document_member(member, membername, isattr, parent) and parent.object:
|
||||||
|
meth = parent.object.__dict__.get(membername)
|
||||||
|
return inspect.is_singledispatch_method(meth)
|
||||||
|
else:
|
||||||
|
return False
|
||||||
|
|
||||||
|
def add_directive_header(self, sig: str) -> None:
|
||||||
|
sourcename = self.get_sourcename()
|
||||||
|
|
||||||
|
# intercept generated directive headers
|
||||||
|
# TODO: It is very hacky to use mock to intercept header generation
|
||||||
|
with patch.object(self, 'add_line') as add_line:
|
||||||
|
super().add_directive_header(sig)
|
||||||
|
|
||||||
|
# output first line of header
|
||||||
|
self.add_line(*add_line.call_args_list[0][0])
|
||||||
|
|
||||||
|
# inserts signature of singledispatch'ed functions
|
||||||
|
meth = self.parent.__dict__.get(self.objpath[-1])
|
||||||
|
for typ, func in meth.dispatcher.registry.items():
|
||||||
|
if typ is object:
|
||||||
|
pass # default implementation. skipped.
|
||||||
|
else:
|
||||||
|
self.annotate_to_first_argument(func, typ)
|
||||||
|
|
||||||
|
documenter = MethodDocumenter(self.directive, '')
|
||||||
|
documenter.object = func
|
||||||
|
self.add_line(' %s%s' % (self.format_name(),
|
||||||
|
documenter.format_signature()),
|
||||||
|
sourcename)
|
||||||
|
|
||||||
|
# output remains of directive header
|
||||||
|
for call in add_line.call_args_list[1:]:
|
||||||
|
self.add_line(*call[0])
|
||||||
|
|
||||||
|
def annotate_to_first_argument(self, func: Callable, typ: Type) -> None:
|
||||||
|
"""Annotate type hint to the first argument of function if needed."""
|
||||||
|
sig = inspect.signature(func, bound_method=True)
|
||||||
|
if len(sig.parameters) == 0:
|
||||||
|
return
|
||||||
|
|
||||||
|
name = list(sig.parameters)[0]
|
||||||
|
if name not in func.__annotations__:
|
||||||
|
func.__annotations__[name] = typ
|
||||||
|
|
||||||
|
|
||||||
class AttributeDocumenter(DocstringStripSignatureMixin, ClassLevelDocumenter): # type: ignore
|
class AttributeDocumenter(DocstringStripSignatureMixin, ClassLevelDocumenter): # type: ignore
|
||||||
"""
|
"""
|
||||||
Specialized Documenter subclass for attributes.
|
Specialized Documenter subclass for attributes.
|
||||||
@ -1611,8 +1728,10 @@ def setup(app: Sphinx) -> Dict[str, Any]:
|
|||||||
app.add_autodocumenter(DataDocumenter)
|
app.add_autodocumenter(DataDocumenter)
|
||||||
app.add_autodocumenter(DataDeclarationDocumenter)
|
app.add_autodocumenter(DataDeclarationDocumenter)
|
||||||
app.add_autodocumenter(FunctionDocumenter)
|
app.add_autodocumenter(FunctionDocumenter)
|
||||||
|
app.add_autodocumenter(SingledispatchFunctionDocumenter)
|
||||||
app.add_autodocumenter(DecoratorDocumenter)
|
app.add_autodocumenter(DecoratorDocumenter)
|
||||||
app.add_autodocumenter(MethodDocumenter)
|
app.add_autodocumenter(MethodDocumenter)
|
||||||
|
app.add_autodocumenter(SingledispatchMethodDocumenter)
|
||||||
app.add_autodocumenter(AttributeDocumenter)
|
app.add_autodocumenter(AttributeDocumenter)
|
||||||
app.add_autodocumenter(PropertyDocumenter)
|
app.add_autodocumenter(PropertyDocumenter)
|
||||||
app.add_autodocumenter(InstanceAttributeDocumenter)
|
app.add_autodocumenter(InstanceAttributeDocumenter)
|
||||||
@ -1624,7 +1743,8 @@ def setup(app: Sphinx) -> Dict[str, Any]:
|
|||||||
app.add_config_value('autodoc_default_options', {}, True)
|
app.add_config_value('autodoc_default_options', {}, True)
|
||||||
app.add_config_value('autodoc_docstring_signature', True, True)
|
app.add_config_value('autodoc_docstring_signature', True, True)
|
||||||
app.add_config_value('autodoc_mock_imports', [], True)
|
app.add_config_value('autodoc_mock_imports', [], True)
|
||||||
app.add_config_value('autodoc_typehints', "signature", True, ENUM("signature", "none"))
|
app.add_config_value('autodoc_typehints', "signature", True,
|
||||||
|
ENUM("signature", "description", "none"))
|
||||||
app.add_config_value('autodoc_warningiserror', True, True)
|
app.add_config_value('autodoc_warningiserror', True, True)
|
||||||
app.add_config_value('autodoc_inherit_docstrings', True, True)
|
app.add_config_value('autodoc_inherit_docstrings', True, True)
|
||||||
app.add_event('autodoc-before-process-signature')
|
app.add_event('autodoc-before-process-signature')
|
||||||
@ -1633,5 +1753,6 @@ def setup(app: Sphinx) -> Dict[str, Any]:
|
|||||||
app.add_event('autodoc-skip-member')
|
app.add_event('autodoc-skip-member')
|
||||||
|
|
||||||
app.setup_extension('sphinx.ext.autodoc.type_comment')
|
app.setup_extension('sphinx.ext.autodoc.type_comment')
|
||||||
|
app.setup_extension('sphinx.ext.autodoc.typehints')
|
||||||
|
|
||||||
return {'version': sphinx.__display_version__, 'parallel_read_safe': True}
|
return {'version': sphinx.__display_version__, 'parallel_read_safe': True}
|
||||||
|
@ -133,7 +133,7 @@ class AutodocDirective(SphinxDirective):
|
|||||||
except (KeyError, ValueError, TypeError) as exc:
|
except (KeyError, ValueError, TypeError) as exc:
|
||||||
# an option is either unknown or has a wrong type
|
# an option is either unknown or has a wrong type
|
||||||
logger.error('An option to %s is either unknown or has an invalid value: %s' %
|
logger.error('An option to %s is either unknown or has an invalid value: %s' %
|
||||||
(self.name, exc), location=(source, lineno))
|
(self.name, exc), location=(self.env.docname, lineno))
|
||||||
return []
|
return []
|
||||||
|
|
||||||
# generate the output
|
# generate the output
|
||||||
|
@ -18,21 +18,9 @@ from docutils.nodes import Element
|
|||||||
|
|
||||||
from sphinx import addnodes
|
from sphinx import addnodes
|
||||||
from sphinx.application import Sphinx
|
from sphinx.application import Sphinx
|
||||||
from sphinx.config import Config, ENUM
|
|
||||||
from sphinx.util import inspect, typing
|
from sphinx.util import inspect, typing
|
||||||
|
|
||||||
|
|
||||||
def config_inited(app: Sphinx, config: Config) -> None:
|
|
||||||
if config.autodoc_typehints == 'description':
|
|
||||||
# HACK: override this to make autodoc suppressing typehints in signatures
|
|
||||||
config.autodoc_typehints = 'none' # type: ignore
|
|
||||||
|
|
||||||
# preserve user settings
|
|
||||||
app._autodoc_typehints_description = True # type: ignore
|
|
||||||
else:
|
|
||||||
app._autodoc_typehints_description = False # type: ignore
|
|
||||||
|
|
||||||
|
|
||||||
def record_typehints(app: Sphinx, objtype: str, name: str, obj: Any,
|
def record_typehints(app: Sphinx, objtype: str, name: str, obj: Any,
|
||||||
options: Dict, args: str, retann: str) -> None:
|
options: Dict, args: str, retann: str) -> None:
|
||||||
"""Record type hints to env object."""
|
"""Record type hints to env object."""
|
||||||
@ -53,7 +41,7 @@ def record_typehints(app: Sphinx, objtype: str, name: str, obj: Any,
|
|||||||
def merge_typehints(app: Sphinx, domain: str, objtype: str, contentnode: Element) -> None:
|
def merge_typehints(app: Sphinx, domain: str, objtype: str, contentnode: Element) -> None:
|
||||||
if domain != 'py':
|
if domain != 'py':
|
||||||
return
|
return
|
||||||
if app._autodoc_typehints_description is False: # type: ignore
|
if app.config.autodoc_typehints != 'description':
|
||||||
return
|
return
|
||||||
|
|
||||||
signature = cast(addnodes.desc_signature, contentnode.parent[0])
|
signature = cast(addnodes.desc_signature, contentnode.parent[0])
|
||||||
@ -141,10 +129,6 @@ def modify_field_list(node: nodes.field_list, annotations: Dict[str, str]) -> No
|
|||||||
|
|
||||||
|
|
||||||
def setup(app: Sphinx) -> Dict[str, Any]:
|
def setup(app: Sphinx) -> Dict[str, Any]:
|
||||||
app.setup_extension('sphinx.ext.autodoc')
|
|
||||||
app.config.values['autodoc_typehints'] = ('signature', True,
|
|
||||||
ENUM("signature", "description", "none"))
|
|
||||||
app.connect('config-inited', config_inited)
|
|
||||||
app.connect('autodoc-process-signature', record_typehints)
|
app.connect('autodoc-process-signature', record_typehints)
|
||||||
app.connect('object-description-transform', merge_typehints)
|
app.connect('object-description-transform', merge_typehints)
|
||||||
|
|
||||||
|
@ -68,12 +68,14 @@ def setup_documenters(app: Any) -> None:
|
|||||||
FunctionDocumenter, MethodDocumenter, AttributeDocumenter,
|
FunctionDocumenter, MethodDocumenter, AttributeDocumenter,
|
||||||
InstanceAttributeDocumenter, DecoratorDocumenter, PropertyDocumenter,
|
InstanceAttributeDocumenter, DecoratorDocumenter, PropertyDocumenter,
|
||||||
SlotsAttributeDocumenter, DataDeclarationDocumenter,
|
SlotsAttributeDocumenter, DataDeclarationDocumenter,
|
||||||
|
SingledispatchFunctionDocumenter,
|
||||||
)
|
)
|
||||||
documenters = [
|
documenters = [
|
||||||
ModuleDocumenter, ClassDocumenter, ExceptionDocumenter, DataDocumenter,
|
ModuleDocumenter, ClassDocumenter, ExceptionDocumenter, DataDocumenter,
|
||||||
FunctionDocumenter, MethodDocumenter, AttributeDocumenter,
|
FunctionDocumenter, MethodDocumenter, AttributeDocumenter,
|
||||||
InstanceAttributeDocumenter, DecoratorDocumenter, PropertyDocumenter,
|
InstanceAttributeDocumenter, DecoratorDocumenter, PropertyDocumenter,
|
||||||
SlotsAttributeDocumenter, DataDeclarationDocumenter,
|
SlotsAttributeDocumenter, DataDeclarationDocumenter,
|
||||||
|
SingledispatchFunctionDocumenter,
|
||||||
] # type: List[Type[Documenter]]
|
] # type: List[Type[Documenter]]
|
||||||
for documenter in documenters:
|
for documenter in documenters:
|
||||||
app.registry.add_documenter(documenter.objtype, documenter)
|
app.registry.add_documenter(documenter.objtype, documenter)
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -5,6 +5,7 @@ var DOCUMENTATION_OPTIONS = {
|
|||||||
COLLAPSE_INDEX: false,
|
COLLAPSE_INDEX: false,
|
||||||
BUILDER: '{{ builder }}',
|
BUILDER: '{{ builder }}',
|
||||||
FILE_SUFFIX: '{{ file_suffix }}',
|
FILE_SUFFIX: '{{ file_suffix }}',
|
||||||
|
LINK_SUFFIX: '{{ link_suffix }}',
|
||||||
HAS_SOURCE: {{ has_source|lower }},
|
HAS_SOURCE: {{ has_source|lower }},
|
||||||
SOURCELINK_SUFFIX: '{{ sourcelink_suffix }}',
|
SOURCELINK_SUFFIX: '{{ sourcelink_suffix }}',
|
||||||
NAVIGATION_WITH_KEYS: {{ 'true' if theme_navigation_with_keys|tobool else 'false'}}
|
NAVIGATION_WITH_KEYS: {{ 'true' if theme_navigation_with_keys|tobool else 'false'}}
|
||||||
|
@ -251,6 +251,7 @@ var Search = {
|
|||||||
var item = results.pop();
|
var item = results.pop();
|
||||||
var listItem = $('<li style="display:none"></li>');
|
var listItem = $('<li style="display:none"></li>');
|
||||||
var requestUrl = "";
|
var requestUrl = "";
|
||||||
|
var linkUrl = "";
|
||||||
if (DOCUMENTATION_OPTIONS.BUILDER === 'dirhtml') {
|
if (DOCUMENTATION_OPTIONS.BUILDER === 'dirhtml') {
|
||||||
// dirhtml builder
|
// dirhtml builder
|
||||||
var dirname = item[0] + '/';
|
var dirname = item[0] + '/';
|
||||||
@ -260,13 +261,15 @@ var Search = {
|
|||||||
dirname = '';
|
dirname = '';
|
||||||
}
|
}
|
||||||
requestUrl = DOCUMENTATION_OPTIONS.URL_ROOT + dirname;
|
requestUrl = DOCUMENTATION_OPTIONS.URL_ROOT + dirname;
|
||||||
|
linkUrl = requestUrl;
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
// normal html builders
|
// normal html builders
|
||||||
requestUrl = DOCUMENTATION_OPTIONS.URL_ROOT + item[0] + DOCUMENTATION_OPTIONS.FILE_SUFFIX;
|
requestUrl = DOCUMENTATION_OPTIONS.URL_ROOT + item[0] + DOCUMENTATION_OPTIONS.FILE_SUFFIX;
|
||||||
|
linkUrl = item[0] + DOCUMENTATION_OPTIONS.LINK_SUFFIX;
|
||||||
}
|
}
|
||||||
listItem.append($('<a/>').attr('href',
|
listItem.append($('<a/>').attr('href',
|
||||||
requestUrl +
|
linkUrl +
|
||||||
highlightstring + item[2]).html(item[1]));
|
highlightstring + item[2]).html(item[1]));
|
||||||
if (item[3]) {
|
if (item[3]) {
|
||||||
listItem.append($('<span> (' + item[3] + ')</span>'));
|
listItem.append($('<span> (' + item[3] + ')</span>'));
|
||||||
|
@ -224,6 +224,26 @@ def isattributedescriptor(obj: Any) -> bool:
|
|||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
def is_singledispatch_function(obj: Any) -> bool:
|
||||||
|
"""Check if the object is singledispatch function."""
|
||||||
|
if (inspect.isfunction(obj) and
|
||||||
|
hasattr(obj, 'dispatch') and
|
||||||
|
hasattr(obj, 'register') and
|
||||||
|
obj.dispatch.__module__ == 'functools'):
|
||||||
|
return True
|
||||||
|
else:
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
def is_singledispatch_method(obj: Any) -> bool:
|
||||||
|
"""Check if the object is singledispatch method."""
|
||||||
|
try:
|
||||||
|
from functools import singledispatchmethod # type: ignore
|
||||||
|
return isinstance(obj, singledispatchmethod)
|
||||||
|
except ImportError: # py35-37
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
def isfunction(obj: Any) -> bool:
|
def isfunction(obj: Any) -> bool:
|
||||||
"""Check if the object is function."""
|
"""Check if the object is function."""
|
||||||
return inspect.isfunction(unwrap(obj))
|
return inspect.isfunction(unwrap(obj))
|
||||||
|
@ -51,3 +51,11 @@ module
|
|||||||
.. py:attribute:: attr2
|
.. py:attribute:: attr2
|
||||||
|
|
||||||
:type: :doc:`index`
|
:type: :doc:`index`
|
||||||
|
|
||||||
|
.. py:module:: exceptions
|
||||||
|
|
||||||
|
.. py:exception:: Exception
|
||||||
|
|
||||||
|
.. py:module:: object
|
||||||
|
|
||||||
|
.. py:function:: sum()
|
||||||
|
19
tests/roots/test-ext-autodoc/target/singledispatch.py
Normal file
19
tests/roots/test-ext-autodoc/target/singledispatch.py
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
from functools import singledispatch
|
||||||
|
|
||||||
|
|
||||||
|
@singledispatch
|
||||||
|
def func(arg, kwarg=None):
|
||||||
|
"""A function for general use."""
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
@func.register(int)
|
||||||
|
def _func_int(arg, kwarg=None):
|
||||||
|
"""A function for int."""
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
@func.register(str)
|
||||||
|
def _func_str(arg, kwarg=None):
|
||||||
|
"""A function for str."""
|
||||||
|
pass
|
20
tests/roots/test-ext-autodoc/target/singledispatchmethod.py
Normal file
20
tests/roots/test-ext-autodoc/target/singledispatchmethod.py
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
from functools import singledispatchmethod
|
||||||
|
|
||||||
|
|
||||||
|
class Foo:
|
||||||
|
"""docstring"""
|
||||||
|
|
||||||
|
@singledispatchmethod
|
||||||
|
def meth(self, arg, kwarg=None):
|
||||||
|
"""A method for general use."""
|
||||||
|
pass
|
||||||
|
|
||||||
|
@meth.register(int)
|
||||||
|
def _meth_int(self, arg, kwarg=None):
|
||||||
|
"""A method for int."""
|
||||||
|
pass
|
||||||
|
|
||||||
|
@meth.register(str)
|
||||||
|
def _meth_str(self, arg, kwarg=None):
|
||||||
|
"""A method for str."""
|
||||||
|
pass
|
@ -1563,3 +1563,49 @@ def test_autodoc_for_egged_code(app):
|
|||||||
' :module: sample',
|
' :module: sample',
|
||||||
''
|
''
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.usefixtures('setup_test')
|
||||||
|
def test_singledispatch():
|
||||||
|
options = {"members": None}
|
||||||
|
actual = do_autodoc(app, 'module', 'target.singledispatch', options)
|
||||||
|
assert list(actual) == [
|
||||||
|
'',
|
||||||
|
'.. py:module:: target.singledispatch',
|
||||||
|
'',
|
||||||
|
'',
|
||||||
|
'.. py:function:: func(arg, kwarg=None)',
|
||||||
|
' func(arg: int, kwarg=None)',
|
||||||
|
' func(arg: str, kwarg=None)',
|
||||||
|
' :module: target.singledispatch',
|
||||||
|
'',
|
||||||
|
' A function for general use.',
|
||||||
|
' '
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.skipif(sys.version_info < (3, 8),
|
||||||
|
reason='singledispatchmethod is available since python3.8')
|
||||||
|
@pytest.mark.usefixtures('setup_test')
|
||||||
|
def test_singledispatchmethod():
|
||||||
|
options = {"members": None}
|
||||||
|
actual = do_autodoc(app, 'module', 'target.singledispatchmethod', options)
|
||||||
|
assert list(actual) == [
|
||||||
|
'',
|
||||||
|
'.. py:module:: target.singledispatchmethod',
|
||||||
|
'',
|
||||||
|
'',
|
||||||
|
'.. py:class:: Foo',
|
||||||
|
' :module: target.singledispatchmethod',
|
||||||
|
'',
|
||||||
|
' docstring',
|
||||||
|
' ',
|
||||||
|
' ',
|
||||||
|
' .. py:method:: Foo.meth(arg, kwarg=None)',
|
||||||
|
' Foo.meth(arg: int, kwarg=None)',
|
||||||
|
' Foo.meth(arg: str, kwarg=None)',
|
||||||
|
' :module: target.singledispatchmethod',
|
||||||
|
' ',
|
||||||
|
' A method for general use.',
|
||||||
|
' '
|
||||||
|
]
|
||||||
|
@ -585,6 +585,36 @@ def test_pyattribute(app):
|
|||||||
assert domain.objects['Class.attr'] == ('index', 'class-attr', 'attribute')
|
assert domain.objects['Class.attr'] == ('index', 'class-attr', 'attribute')
|
||||||
|
|
||||||
|
|
||||||
|
def test_pydecorator_signature(app):
|
||||||
|
text = ".. py:decorator:: deco"
|
||||||
|
domain = app.env.get_domain('py')
|
||||||
|
doctree = restructuredtext.parse(app, text)
|
||||||
|
assert_node(doctree, (addnodes.index,
|
||||||
|
[desc, ([desc_signature, ([desc_addname, "@"],
|
||||||
|
[desc_name, "deco"])],
|
||||||
|
desc_content)]))
|
||||||
|
assert_node(doctree[1], addnodes.desc, desctype="function",
|
||||||
|
domain="py", objtype="function", noindex=False)
|
||||||
|
|
||||||
|
assert 'deco' in domain.objects
|
||||||
|
assert domain.objects['deco'] == ('index', 'deco', 'function')
|
||||||
|
|
||||||
|
|
||||||
|
def test_pydecoratormethod_signature(app):
|
||||||
|
text = ".. py:decoratormethod:: deco"
|
||||||
|
domain = app.env.get_domain('py')
|
||||||
|
doctree = restructuredtext.parse(app, text)
|
||||||
|
assert_node(doctree, (addnodes.index,
|
||||||
|
[desc, ([desc_signature, ([desc_addname, "@"],
|
||||||
|
[desc_name, "deco"])],
|
||||||
|
desc_content)]))
|
||||||
|
assert_node(doctree[1], addnodes.desc, desctype="method",
|
||||||
|
domain="py", objtype="method", noindex=False)
|
||||||
|
|
||||||
|
assert 'deco' in domain.objects
|
||||||
|
assert domain.objects['deco'] == ('index', 'deco', 'method')
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.sphinx(freshenv=True)
|
@pytest.mark.sphinx(freshenv=True)
|
||||||
def test_module_index(app):
|
def test_module_index(app):
|
||||||
text = (".. py:module:: docutils\n"
|
text = (".. py:module:: docutils\n"
|
||||||
|
@ -462,10 +462,9 @@ def test_mocked_module_imports(app, warning):
|
|||||||
assert warning.getvalue() == ''
|
assert warning.getvalue() == ''
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.sphinx('html', testroot='ext-autodoc')
|
@pytest.mark.sphinx('html', testroot='ext-autodoc',
|
||||||
|
confoverrides={'autodoc_typehints': "signature"})
|
||||||
def test_autodoc_typehints_signature(app):
|
def test_autodoc_typehints_signature(app):
|
||||||
app.config.autodoc_typehints = "signature"
|
|
||||||
|
|
||||||
options = {"members": None,
|
options = {"members": None,
|
||||||
"undoc-members": True}
|
"undoc-members": True}
|
||||||
actual = do_autodoc(app, 'module', 'target.typehints', options)
|
actual = do_autodoc(app, 'module', 'target.typehints', options)
|
||||||
@ -513,10 +512,9 @@ def test_autodoc_typehints_signature(app):
|
|||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.sphinx('html', testroot='ext-autodoc')
|
@pytest.mark.sphinx('html', testroot='ext-autodoc',
|
||||||
|
confoverrides={'autodoc_typehints': "none"})
|
||||||
def test_autodoc_typehints_none(app):
|
def test_autodoc_typehints_none(app):
|
||||||
app.config.autodoc_typehints = "none"
|
|
||||||
|
|
||||||
options = {"members": None,
|
options = {"members": None,
|
||||||
"undoc-members": True}
|
"undoc-members": True}
|
||||||
actual = do_autodoc(app, 'module', 'target.typehints', options)
|
actual = do_autodoc(app, 'module', 'target.typehints', options)
|
||||||
@ -564,8 +562,7 @@ def test_autodoc_typehints_none(app):
|
|||||||
|
|
||||||
|
|
||||||
@pytest.mark.sphinx('text', testroot='ext-autodoc',
|
@pytest.mark.sphinx('text', testroot='ext-autodoc',
|
||||||
confoverrides={'extensions': ['sphinx.ext.autodoc.typehints'],
|
confoverrides={'autodoc_typehints': "description"})
|
||||||
'autodoc_typehints': 'description'})
|
|
||||||
def test_autodoc_typehints_description(app):
|
def test_autodoc_typehints_description(app):
|
||||||
app.build()
|
app.build()
|
||||||
context = (app.outdir / 'index.txt').read_text()
|
context = (app.outdir / 'index.txt').read_text()
|
||||||
|
Loading…
Reference in New Issue
Block a user