mirror of
https://github.com/sphinx-doc/sphinx.git
synced 2025-02-25 18:55:22 -06:00
Close #6325: autodoc: Support attributes in __slots__
This commit is contained in:
parent
3de408d2d9
commit
277aba935d
2
CHANGES
2
CHANGES
@ -83,6 +83,8 @@ Features added
|
|||||||
``imported-members`` option
|
``imported-members`` option
|
||||||
* #4777: autodoc: Support coroutine
|
* #4777: autodoc: Support coroutine
|
||||||
* #744: autodoc: Support abstractmethod
|
* #744: autodoc: Support abstractmethod
|
||||||
|
* #6325: autodoc: Support attributes in __slots__. For dict-style __slots__,
|
||||||
|
autodoc considers values as a docstring of the attribute
|
||||||
* #6212 autosummary: Add :confval:`autosummary_imported_members` to display
|
* #6212 autosummary: Add :confval:`autosummary_imported_members` to display
|
||||||
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 '.'
|
||||||
|
@ -67,6 +67,7 @@ def identity(x):
|
|||||||
|
|
||||||
ALL = object()
|
ALL = object()
|
||||||
INSTANCEATTR = object()
|
INSTANCEATTR = object()
|
||||||
|
SLOTSATTR = object()
|
||||||
|
|
||||||
|
|
||||||
def members_option(arg):
|
def members_option(arg):
|
||||||
@ -1493,6 +1494,55 @@ class InstanceAttributeDocumenter(AttributeDocumenter):
|
|||||||
super().add_content(more_content, no_docstring=True)
|
super().add_content(more_content, no_docstring=True)
|
||||||
|
|
||||||
|
|
||||||
|
class SlotsAttributeDocumenter(AttributeDocumenter):
|
||||||
|
"""
|
||||||
|
Specialized Documenter subclass for attributes that cannot be imported
|
||||||
|
because they are attributes in __slots__.
|
||||||
|
"""
|
||||||
|
objtype = 'slotsattribute'
|
||||||
|
directivetype = 'attribute'
|
||||||
|
member_order = 60
|
||||||
|
|
||||||
|
# must be higher than AttributeDocumenter
|
||||||
|
priority = 11
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def can_document_member(cls, member, membername, isattr, parent):
|
||||||
|
# type: (Any, str, bool, Any) -> bool
|
||||||
|
"""This documents only SLOTSATTR members."""
|
||||||
|
return member is SLOTSATTR
|
||||||
|
|
||||||
|
def import_object(self):
|
||||||
|
# type: () -> bool
|
||||||
|
"""Never import anything."""
|
||||||
|
# disguise as an attribute
|
||||||
|
self.objtype = 'attribute'
|
||||||
|
self._datadescriptor = True
|
||||||
|
|
||||||
|
with mock(self.env.config.autodoc_mock_imports):
|
||||||
|
try:
|
||||||
|
ret = import_object(self.modname, self.objpath[:-1], 'class',
|
||||||
|
attrgetter=self.get_attr,
|
||||||
|
warningiserror=self.env.config.autodoc_warningiserror)
|
||||||
|
self.module, _, _, self.parent = ret
|
||||||
|
return True
|
||||||
|
except ImportError as exc:
|
||||||
|
logger.warning(exc.args[0], type='autodoc', subtype='import_object')
|
||||||
|
self.env.note_reread()
|
||||||
|
return False
|
||||||
|
|
||||||
|
def get_doc(self, encoding=None, ignore=1):
|
||||||
|
# type: (str, int) -> List[List[str]]
|
||||||
|
"""Decode and return lines of the docstring(s) for the object."""
|
||||||
|
name = self.objpath[-1]
|
||||||
|
__slots__ = safe_getattr(self.parent, '__slots__', [])
|
||||||
|
if isinstance(__slots__, dict) and isinstance(__slots__.get(name), str):
|
||||||
|
docstring = prepare_docstring(__slots__[name])
|
||||||
|
return [docstring]
|
||||||
|
else:
|
||||||
|
return []
|
||||||
|
|
||||||
|
|
||||||
def get_documenters(app):
|
def get_documenters(app):
|
||||||
# type: (Sphinx) -> Dict[str, Type[Documenter]]
|
# type: (Sphinx) -> Dict[str, Type[Documenter]]
|
||||||
"""Returns registered Documenter classes"""
|
"""Returns registered Documenter classes"""
|
||||||
@ -1554,6 +1604,7 @@ def setup(app):
|
|||||||
app.add_autodocumenter(AttributeDocumenter)
|
app.add_autodocumenter(AttributeDocumenter)
|
||||||
app.add_autodocumenter(PropertyDocumenter)
|
app.add_autodocumenter(PropertyDocumenter)
|
||||||
app.add_autodocumenter(InstanceAttributeDocumenter)
|
app.add_autodocumenter(InstanceAttributeDocumenter)
|
||||||
|
app.add_autodocumenter(SlotsAttributeDocumenter)
|
||||||
|
|
||||||
app.add_config_value('autoclass_content', 'class', True)
|
app.add_config_value('autoclass_content', 'class', True)
|
||||||
app.add_config_value('autodoc_member_order', 'alphabetic', True)
|
app.add_config_value('autodoc_member_order', 'alphabetic', True)
|
||||||
|
@ -15,7 +15,7 @@ from collections import namedtuple
|
|||||||
|
|
||||||
from sphinx.deprecation import RemovedInSphinx40Warning, deprecated_alias
|
from sphinx.deprecation import RemovedInSphinx40Warning, deprecated_alias
|
||||||
from sphinx.util import logging
|
from sphinx.util import logging
|
||||||
from sphinx.util.inspect import isenumclass, safe_getattr
|
from sphinx.util.inspect import isclass, isenumclass, safe_getattr
|
||||||
|
|
||||||
if False:
|
if False:
|
||||||
# For type annotation
|
# For type annotation
|
||||||
@ -127,6 +127,13 @@ def get_object_members(subject, objpath, attrgetter, analyzer=None):
|
|||||||
if name not in superclass.__dict__:
|
if name not in superclass.__dict__:
|
||||||
members[name] = Attribute(name, True, value)
|
members[name] = Attribute(name, True, value)
|
||||||
|
|
||||||
|
# members in __slots__
|
||||||
|
if isclass(subject) and hasattr(subject, '__slots__'):
|
||||||
|
from sphinx.ext.autodoc import SLOTSATTR
|
||||||
|
|
||||||
|
for name in subject.__slots__:
|
||||||
|
members[name] = Attribute(name, True, SLOTSATTR)
|
||||||
|
|
||||||
# other members
|
# other members
|
||||||
for name in dir(subject):
|
for name in dir(subject):
|
||||||
try:
|
try:
|
||||||
|
11
tests/roots/test-ext-autodoc/target/slots.py
Normal file
11
tests/roots/test-ext-autodoc/target/slots.py
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
class Foo:
|
||||||
|
__slots__ = ['attr']
|
||||||
|
|
||||||
|
|
||||||
|
class Bar:
|
||||||
|
__slots__ = {'attr1': 'docstring of attr1',
|
||||||
|
'attr2': 'docstring of attr2',
|
||||||
|
'attr3': None}
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
self.attr2 = None #: docstring of instance attr2
|
@ -1320,6 +1320,46 @@ def test_instance_attributes(app):
|
|||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.sphinx('html', testroot='ext-autodoc')
|
||||||
|
def test_slots(app):
|
||||||
|
options = {"members": None,
|
||||||
|
"undoc-members": True}
|
||||||
|
actual = do_autodoc(app, 'module', 'target.slots', options)
|
||||||
|
assert list(actual) == [
|
||||||
|
'',
|
||||||
|
'.. py:module:: target.slots',
|
||||||
|
'',
|
||||||
|
'',
|
||||||
|
'.. py:class:: Bar()',
|
||||||
|
' :module: target.slots',
|
||||||
|
'',
|
||||||
|
' ',
|
||||||
|
' .. py:attribute:: Bar.attr1',
|
||||||
|
' :module: target.slots',
|
||||||
|
' ',
|
||||||
|
' docstring of attr1',
|
||||||
|
' ',
|
||||||
|
' ',
|
||||||
|
' .. py:attribute:: Bar.attr2',
|
||||||
|
' :module: target.slots',
|
||||||
|
' ',
|
||||||
|
' docstring of instance attr2',
|
||||||
|
' ',
|
||||||
|
' ',
|
||||||
|
' .. py:attribute:: Bar.attr3',
|
||||||
|
' :module: target.slots',
|
||||||
|
' ',
|
||||||
|
'',
|
||||||
|
'.. py:class:: Foo',
|
||||||
|
' :module: target.slots',
|
||||||
|
'',
|
||||||
|
' ',
|
||||||
|
' .. py:attribute:: Foo.attr',
|
||||||
|
' :module: target.slots',
|
||||||
|
' ',
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.sphinx('html', testroot='ext-autodoc')
|
@pytest.mark.sphinx('html', testroot='ext-autodoc')
|
||||||
def test_enum_class(app):
|
def test_enum_class(app):
|
||||||
options = {"members": None,
|
options = {"members": None,
|
||||||
|
Loading…
Reference in New Issue
Block a user