diff --git a/sphinx/ext/autodoc/__init__.py b/sphinx/ext/autodoc/__init__.py index 79ad1ee94..171a3e7b0 100644 --- a/sphinx/ext/autodoc/__init__.py +++ b/sphinx/ext/autodoc/__init__.py @@ -2270,8 +2270,8 @@ class SlotsAttributeDocumenter(AttributeDocumenter): % self.__class__.__name__, RemovedInSphinx50Warning, stacklevel=2) name = self.objpath[-1] - __slots__ = safe_getattr(self.parent, '__slots__', []) - if isinstance(__slots__, dict) and isinstance(__slots__.get(name), str): + __slots__ = inspect.getslots(self.parent) + if __slots__ and isinstance(__slots__.get(name, None), str): docstring = prepare_docstring(__slots__[name]) return [docstring] else: diff --git a/sphinx/ext/autodoc/importer.py b/sphinx/ext/autodoc/importer.py index 29c56c54b..adfa6d05d 100644 --- a/sphinx/ext/autodoc/importer.py +++ b/sphinx/ext/autodoc/importer.py @@ -16,7 +16,7 @@ from typing import Any, Callable, Dict, List, Mapping, NamedTuple, Optional, Tup from sphinx.deprecation import RemovedInSphinx40Warning, deprecated_alias from sphinx.pycode import ModuleAnalyzer from sphinx.util import logging -from sphinx.util.inspect import isclass, isenumclass, safe_getattr +from sphinx.util.inspect import getslots, isclass, isenumclass, safe_getattr if False: # For type annotation @@ -203,14 +203,15 @@ def get_object_members(subject: Any, objpath: List[str], attrgetter: Callable, members[name] = Attribute(name, True, value) # members in __slots__ - if isclass(subject) and getattr(subject, '__slots__', None) is not None: - from sphinx.ext.autodoc import SLOTSATTR + try: + __slots__ = getslots(subject) + if __slots__: + from sphinx.ext.autodoc import SLOTSATTR - slots = subject.__slots__ - if isinstance(slots, str): - slots = [slots] - for name in slots: - members[name] = Attribute(name, True, SLOTSATTR) + for name in __slots__: + members[name] = Attribute(name, True, SLOTSATTR) + except (TypeError, ValueError): + pass # other members for name in dir(subject):