refactor: autodoc: Add get_class_members()

To enhance ClassDocumenter, Add a new helper function get_class_members().
At this moment, it is a copy of get_object_members().  It will be
changed to return more detailed information of class members.
This commit is contained in:
Takeshi KOMIYA 2020-12-17 02:55:05 +09:00
parent beeab6ced4
commit 18973f6c1b
2 changed files with 67 additions and 2 deletions

View File

@ -26,7 +26,8 @@ from sphinx.config import ENUM, Config
from sphinx.deprecation import (RemovedInSphinx40Warning, RemovedInSphinx50Warning,
RemovedInSphinx60Warning)
from sphinx.environment import BuildEnvironment
from sphinx.ext.autodoc.importer import get_module_members, get_object_members, import_object
from sphinx.ext.autodoc.importer import (get_class_members, get_module_members,
get_object_members, import_object)
from sphinx.ext.autodoc.mock import mock
from sphinx.locale import _, __
from sphinx.pycode import ModuleAnalyzer, PycodeError
@ -1576,7 +1577,7 @@ class ClassDocumenter(DocstringSignatureMixin, ModuleLevelDocumenter): # type:
self.add_line(' ' + _('Bases: %s') % ', '.join(bases), sourcename)
def get_object_members(self, want_all: bool) -> Tuple[bool, ObjectMembers]:
members = get_object_members(self.object, self.objpath, self.get_attr, self.analyzer)
members = get_class_members(self.object, self.objpath, self.get_attr, self.analyzer)
if not want_all:
if not self.options.members:
return False, [] # type: ignore

View File

@ -241,6 +241,70 @@ def get_object_members(subject: Any, objpath: List[str], attrgetter: Callable,
return members
def get_class_members(subject: Any, objpath: List[str], attrgetter: Callable,
analyzer: ModuleAnalyzer = None) -> Dict[str, Attribute]:
"""Get members and attributes of target class."""
from sphinx.ext.autodoc import INSTANCEATTR
# the members directly defined in the class
obj_dict = attrgetter(subject, '__dict__', {})
members = {} # type: Dict[str, Attribute]
# enum members
if isenumclass(subject):
for name, value in subject.__members__.items():
if name not in members:
members[name] = Attribute(name, True, value)
superclass = subject.__mro__[1]
for name in obj_dict:
if name not in superclass.__dict__:
value = safe_getattr(subject, name)
members[name] = Attribute(name, True, value)
# members in __slots__
try:
__slots__ = getslots(subject)
if __slots__:
from sphinx.ext.autodoc import SLOTSATTR
for name in __slots__:
members[name] = Attribute(name, True, SLOTSATTR)
except (AttributeError, TypeError, ValueError):
pass
# other members
for name in dir(subject):
try:
value = attrgetter(subject, name)
directly_defined = name in obj_dict
name = unmangle(subject, name)
if name and name not in members:
members[name] = Attribute(name, directly_defined, value)
except AttributeError:
continue
# annotation only member (ex. attr: int)
for i, cls in enumerate(getmro(subject)):
try:
for name in getannotations(cls):
name = unmangle(cls, name)
if name and name not in members:
members[name] = Attribute(name, i == 0, INSTANCEATTR)
except AttributeError:
pass
if analyzer:
# append instance attributes (cf. self.attr1) if analyzer knows
namespace = '.'.join(objpath)
for (ns, name) in analyzer.find_attr_docs():
if namespace == ns and name not in members:
members[name] = Attribute(name, True, INSTANCEATTR)
return members
from sphinx.ext.autodoc.mock import (MockFinder, MockLoader, _MockModule, _MockObject, # NOQA
mock)