autodoc: Support TypeVar (refs: #7722)

This commit is contained in:
Takeshi KOMIYA 2020-05-30 21:17:20 +09:00
parent cb5e094c0a
commit 8bd5f8b214
4 changed files with 100 additions and 1 deletions

View File

@ -52,6 +52,7 @@ Features added
* #2106: autodoc: Support multiple signatures on docstring
* #4422: autodoc: Support GenericAlias in Python 3.7 or above
* #3610: autodoc: Support overloaded functions
* #7722: autodoc: Support TypeVar
* #7466: autosummary: headings in generated documents are not translated
* #7490: autosummary: Add ``:caption:`` option to autosummary directive to set a
caption to the toctree

View File

@ -16,7 +16,7 @@ import warnings
from inspect import Parameter, Signature
from types import ModuleType
from typing import (
Any, Callable, Dict, Iterator, List, Optional, Sequence, Set, Tuple, Type, Union
Any, Callable, Dict, Iterator, List, Optional, Sequence, Set, Tuple, Type, TypeVar, Union
)
from docutils.statemachine import StringList
@ -1644,6 +1644,48 @@ class GenericAliasDocumenter(DataDocumenter):
super().add_content(content)
class TypeVarDocumenter(DataDocumenter):
"""
Specialized Documenter subclass for TypeVars.
"""
objtype = 'typevar'
directivetype = 'data'
priority = DataDocumenter.priority + 1
@classmethod
def can_document_member(cls, member: Any, membername: str, isattr: bool, parent: Any
) -> bool:
return isinstance(member, TypeVar) and isattr # type: ignore
def add_directive_header(self, sig: str) -> None:
self.options.annotation = SUPPRESS # type: ignore
super().add_directive_header(sig)
def get_doc(self, encoding: str = None, ignore: int = None) -> List[List[str]]:
if ignore is not None:
warnings.warn("The 'ignore' argument to autodoc.%s.get_doc() is deprecated."
% self.__class__.__name__,
RemovedInSphinx50Warning, stacklevel=2)
if self.object.__doc__ != TypeVar.__doc__:
return super().get_doc()
else:
return []
def add_content(self, more_content: Any, no_docstring: bool = False) -> None:
attrs = [repr(self.object.__name__)]
for constraint in self.object.__constraints__:
attrs.append(stringify_typehint(constraint))
if self.object.__covariant__:
attrs.append("covariant=True")
if self.object.__contravariant__:
attrs.append("contravariant=True")
content = StringList([_('alias of TypeVar(%s)') % ", ".join(attrs)], source='')
super().add_content(content)
class MethodDocumenter(DocstringSignatureMixin, ClassLevelDocumenter): # type: ignore
"""
Specialized Documenter subclass for methods (normal, static and class).
@ -2017,6 +2059,7 @@ def setup(app: Sphinx) -> Dict[str, Any]:
app.add_autodocumenter(DataDocumenter)
app.add_autodocumenter(DataDeclarationDocumenter)
app.add_autodocumenter(GenericAliasDocumenter)
app.add_autodocumenter(TypeVarDocumenter)
app.add_autodocumenter(FunctionDocumenter)
app.add_autodocumenter(DecoratorDocumenter)
app.add_autodocumenter(MethodDocumenter)

View File

@ -0,0 +1,15 @@
from typing import TypeVar
#: T1
T1 = TypeVar("T1")
T2 = TypeVar("T2") # A TypeVar not having doc comment
#: T3
T3 = TypeVar("T3", int, str)
#: T4
T4 = TypeVar("T4", covariant=True)
#: T5
T5 = TypeVar("T5", contravariant=True)

View File

@ -1618,6 +1618,46 @@ def test_autodoc_GenericAlias(app):
]
@pytest.mark.sphinx('html', testroot='ext-autodoc')
def test_autodoc_TypeVar(app):
options = {"members": None,
"undoc-members": None}
actual = do_autodoc(app, 'module', 'target.typevar', options)
assert list(actual) == [
'',
'.. py:module:: target.typevar',
'',
'',
'.. py:data:: T1',
' :module: target.typevar',
'',
' T1',
'',
" alias of TypeVar('T1')",
'',
'.. py:data:: T3',
' :module: target.typevar',
'',
' T3',
'',
" alias of TypeVar('T3', int, str)",
'',
'.. py:data:: T4',
' :module: target.typevar',
'',
' T4',
'',
" alias of TypeVar('T4', covariant=True)",
'',
'.. py:data:: T5',
' :module: target.typevar',
'',
' T5',
'',
" alias of TypeVar('T5', contravariant=True)",
]
@pytest.mark.skipif(sys.version_info < (3, 9), reason='py39+ is required.')
@pytest.mark.sphinx('html', testroot='ext-autodoc')
def test_autodoc_Annotated(app):