Merge pull request #8615 from tk0miya/refactor_autodoc

refactor: autodoc: Replace ClassAttribute by ObjectMember
This commit is contained in:
Takeshi KOMIYA
2020-12-31 10:44:09 +09:00
committed by GitHub
2 changed files with 19 additions and 30 deletions

View File

@@ -25,8 +25,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 (ClassAttribute, get_class_members, get_object_members,
import_module, import_object)
from sphinx.ext.autodoc.importer import (get_class_members, get_object_members, import_module,
import_object)
from sphinx.ext.autodoc.mock import ismock, mock
from sphinx.locale import _, __
from sphinx.pycode import ModuleAnalyzer, PycodeError
@@ -1619,10 +1619,6 @@ class ClassDocumenter(DocstringSignatureMixin, ModuleLevelDocumenter): # type:
self.add_line(' ' + _('Bases: %s') % ', '.join(bases), sourcename)
def get_object_members(self, want_all: bool) -> Tuple[bool, ObjectMembers]:
def convert(m: ClassAttribute) -> ObjectMember:
"""Convert ClassAttribute object to ObjectMember."""
return ObjectMember(m.name, m.value, class_=m.class_, docstring=m.docstring)
members = get_class_members(self.object, self.objpath, self.get_attr)
if not want_all:
if not self.options.members:
@@ -1631,15 +1627,15 @@ class ClassDocumenter(DocstringSignatureMixin, ModuleLevelDocumenter): # type:
selected = []
for name in self.options.members: # type: str
if name in members:
selected.append(convert(members[name]))
selected.append(members[name])
else:
logger.warning(__('missing attribute %s in object %s') %
(name, self.fullname), type='autodoc')
return False, selected
elif self.options.inherited_members:
return False, [convert(m) for m in members.values()]
return False, list(members.values())
else:
return False, [convert(m) for m in members.values() if m.class_ == self.object]
return False, [m for m in members.values() if m.class_ == self.object]
def get_doc(self, encoding: str = None, ignore: int = None) -> Optional[List[List[str]]]:
if encoding is not None:

View File

@@ -24,6 +24,8 @@ if False:
# For type annotation
from typing import Type # NOQA
from sphinx.ext.autodoc import ObjectMember
logger = logging.getLogger(__name__)
@@ -245,37 +247,27 @@ def get_object_members(subject: Any, objpath: List[str], attrgetter: Callable,
return members
class ClassAttribute:
"""The attribute of the class."""
def __init__(self, cls: Any, name: str, value: Any, docstring: Optional[str] = None):
self.class_ = cls
self.name = name
self.value = value
self.docstring = docstring
def get_class_members(subject: Any, objpath: List[str], attrgetter: Callable
) -> Dict[str, ClassAttribute]:
) -> Dict[str, "ObjectMember"]:
"""Get members and attributes of target class."""
from sphinx.ext.autodoc import INSTANCEATTR
from sphinx.ext.autodoc import INSTANCEATTR, ObjectMember
# the members directly defined in the class
obj_dict = attrgetter(subject, '__dict__', {})
members = {} # type: Dict[str, ClassAttribute]
members = {} # type: Dict[str, ObjectMember]
# enum members
if isenumclass(subject):
for name, value in subject.__members__.items():
if name not in members:
members[name] = ClassAttribute(subject, name, value)
members[name] = ObjectMember(name, value, class_=subject)
superclass = subject.__mro__[1]
for name in obj_dict:
if name not in superclass.__dict__:
value = safe_getattr(subject, name)
members[name] = ClassAttribute(subject, name, value)
members[name] = ObjectMember(name, value, class_=subject)
# members in __slots__
try:
@@ -284,7 +276,8 @@ def get_class_members(subject: Any, objpath: List[str], attrgetter: Callable
from sphinx.ext.autodoc import SLOTSATTR
for name, docstring in __slots__.items():
members[name] = ClassAttribute(subject, name, SLOTSATTR, docstring)
members[name] = ObjectMember(name, SLOTSATTR, class_=subject,
docstring=docstring)
except (AttributeError, TypeError, ValueError):
pass
@@ -295,9 +288,9 @@ def get_class_members(subject: Any, objpath: List[str], attrgetter: Callable
unmangled = unmangle(subject, name)
if unmangled and unmangled not in members:
if name in obj_dict:
members[unmangled] = ClassAttribute(subject, unmangled, value)
members[unmangled] = ObjectMember(unmangled, value, class_=subject)
else:
members[unmangled] = ClassAttribute(None, unmangled, value)
members[unmangled] = ObjectMember(unmangled, value)
except AttributeError:
continue
@@ -308,7 +301,7 @@ def get_class_members(subject: Any, objpath: List[str], attrgetter: Callable
for name in getannotations(cls):
name = unmangle(cls, name)
if name and name not in members:
members[name] = ClassAttribute(cls, name, INSTANCEATTR)
members[name] = ObjectMember(name, INSTANCEATTR, class_=cls)
except AttributeError:
pass
@@ -320,8 +313,8 @@ def get_class_members(subject: Any, objpath: List[str], attrgetter: Callable
analyzer.analyze()
for (ns, name), docstring in analyzer.attr_docs.items():
if ns == qualname and name not in members:
members[name] = ClassAttribute(cls, name, INSTANCEATTR,
'\n'.join(docstring))
members[name] = ObjectMember(name, INSTANCEATTR, class_=cls,
docstring='\n'.join(docstring))
except (AttributeError, PycodeError):
pass
except AttributeError: