autodoc: Add PropertyDocumenter to detect properties

This commit is contained in:
Takeshi KOMIYA 2019-04-16 22:00:41 +09:00
parent c59f2d9545
commit b708f7b82f
3 changed files with 56 additions and 14 deletions

View File

@ -1415,6 +1415,37 @@ class AttributeDocumenter(DocstringStripSignatureMixin, ClassLevelDocumenter):
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):
"""
Specialized Documenter subclass for attributes that cannot be imported
@ -1506,6 +1537,7 @@ def setup(app):
app.add_autodocumenter(DecoratorDocumenter)
app.add_autodocumenter(MethodDocumenter)
app.add_autodocumenter(AttributeDocumenter)
app.add_autodocumenter(PropertyDocumenter)
app.add_autodocumenter(InstanceAttributeDocumenter)
app.add_config_value('autoclass_content', 'class', True)

View File

@ -40,7 +40,7 @@ from sphinx.util.rst import escape as rst_escape
if False:
# 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.ext.autodoc import Documenter # NOQA
@ -170,7 +170,12 @@ def generate_autosummary_docs(sources, output_dir=None, suffix='.rst',
template = template_env.get_template('autosummary/base.rst')
def get_members(obj, typ, include_public=[], imported=True):
# type: (Any, str, List[str], bool) -> Tuple[List[str], List[str]]
# type: (Any, Union[str, Set[str]], List[str], bool) -> Tuple[List[str], List[str]] # NOQA
if isinstance(typ, str):
types = {typ}
else:
types = typ
items = [] # type: List[str]
for name in dir(obj):
try:
@ -178,7 +183,7 @@ def generate_autosummary_docs(sources, output_dir=None, suffix='.rst',
except AttributeError:
continue
documenter = get_documenter(app, value, obj)
if documenter.objtype == typ:
if documenter.objtype in types:
if imported or getattr(value, '__module__', None) == obj.__name__:
# skip imported members if expected
items.append(name)
@ -203,7 +208,7 @@ def generate_autosummary_docs(sources, output_dir=None, suffix='.rst',
ns['methods'], ns['all_methods'] = \
get_members(obj, 'method', ['__init__'])
ns['attributes'], ns['all_attributes'] = \
get_members(obj, 'attribute')
get_members(obj, {'attribute', 'property'})
parts = name.split('.')
if doc.objtype in ('method', 'attribute'):

View File

@ -756,7 +756,7 @@ def test_autodoc_undoc_members(app):
' .. py:attribute:: Class.mdocattr',
' .. py:method:: Class.meth()',
' .. 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:attribute:: Class.skipattr',
' .. py:method:: Class.skipmeth()',
@ -777,6 +777,7 @@ def test_autodoc_inherited_members(app):
' .. py:method:: Class.inheritedstaticmeth(cls)',
' .. py:method:: Class.meth()',
' .. py:method:: Class.moore(a, e, f) -> happiness',
' .. py:method:: Class.prop',
' .. py:method:: Class.skipmeth()'
]
@ -836,7 +837,7 @@ def test_autodoc_special_members(app):
' .. py:attribute:: Class.mdocattr',
' .. py:method:: Class.meth()',
' .. 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:attribute:: Class.skipattr',
' .. py:method:: Class.skipmeth()',
@ -1028,7 +1029,7 @@ def test_autodoc_member_order(app):
' .. py:method:: Class.excludemeth()',
' .. py:attribute:: Class.skipattr',
' .. py:attribute:: Class.attr',
' .. py:attribute:: Class.prop',
' .. py:method:: Class.prop',
' .. py:attribute:: Class.docattr',
' .. py:attribute:: Class.udocattr',
' .. py:attribute:: Class.mdocattr',
@ -1062,7 +1063,7 @@ def test_autodoc_member_order(app):
' .. py:attribute:: Class.inst_attr_inline',
' .. py:attribute:: Class.inst_attr_string',
' .. py:attribute:: Class.mdocattr',
' .. py:attribute:: Class.prop',
' .. py:method:: Class.prop',
' .. py:attribute:: Class.skipattr',
' .. py:attribute:: Class.udocattr'
]
@ -1085,7 +1086,7 @@ def test_autodoc_member_order(app):
' .. py:attribute:: Class.mdocattr',
' .. py:method:: Class.meth()',
' .. 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:attribute:: Class.skipattr',
' .. py:method:: Class.skipmeth()',
@ -1152,14 +1153,16 @@ def test_autodoc_docstring_signature(app):
' indented line',
' ',
' ',
' .. py:attribute:: DocstringSig.prop1',
' .. py:method:: DocstringSig.prop1',
' :module: target',
' :property:',
' ',
' First line of docstring',
' ',
' ',
' .. py:attribute:: DocstringSig.prop2',
' .. py:method:: DocstringSig.prop2',
' :module: target',
' :property:',
' ',
' First line of docstring',
' Second line of docstring',
@ -1194,15 +1197,17 @@ def test_autodoc_docstring_signature(app):
' indented line',
' ',
' ',
' .. py:attribute:: DocstringSig.prop1',
' .. py:method:: DocstringSig.prop1',
' :module: target',
' :property:',
' ',
' DocstringSig.prop1(self)',
' First line of docstring',
' ',
' ',
' .. py:attribute:: DocstringSig.prop2',
' .. py:method:: DocstringSig.prop2',
' :module: target',
' :property:',
' ',
' First line of docstring',
' Second line of docstring',
@ -1717,7 +1722,7 @@ def test_autodoc_default_options_with_values(app):
' .. py:method:: Class.skipmeth()',
' .. py:method:: Class.excludemeth()',
' .. py:attribute:: Class.attr',
' .. py:attribute:: Class.prop',
' .. py:method:: Class.prop',
' .. py:attribute:: Class.docattr',
' .. py:attribute:: Class.udocattr',
' .. py:attribute:: Class.mdocattr',