Fix #4415: autodoc classifies inherited classmethods as regular methods

This commit is contained in:
Takeshi KOMIYA 2018-01-19 09:47:22 +09:00
parent a9f949e858
commit cbb10d61f7
5 changed files with 26 additions and 2 deletions

View File

@ -16,6 +16,8 @@ Features added
Bugs fixed
----------
* #4415: autodoc classifies inherited classmethods as regular methods
Testing
--------

View File

@ -32,7 +32,7 @@ from sphinx.application import ExtensionError
from sphinx.util import logging
from sphinx.util.inspect import Signature, isdescriptor, safe_getmembers, \
safe_getattr, object_description, is_builtin_class_method, \
isenumattribute, getdoc
isenumattribute, isclassmethod, getdoc
from sphinx.util.docstrings import prepare_docstring
if False:
@ -1261,8 +1261,10 @@ class MethodDocumenter(DocstringSignatureMixin, ClassLevelDocumenter): # type:
# to distinguish classmethod/staticmethod
obj = self.parent.__dict__.get(self.object_name)
if obj is None:
obj = self.object
if isinstance(obj, classmethod):
if isclassmethod(obj):
self.directivetype = 'classmethod'
# document class and static members before ordinary ones
self.member_order = self.member_order - 1

View File

@ -154,6 +154,20 @@ def isenumattribute(x):
return isinstance(x, enum.Enum)
def isclassmethod(obj):
# type: (Any) -> bool
"""Check if the object is classmethod."""
if isinstance(obj, classmethod):
return True
elif inspect.ismethod(obj):
if getattr(obj, 'im_self', None): # py2
return True
elif getattr(obj, '__self__', None): # py3
return True
return False
def isdescriptor(x):
# type: (Any) -> bool
"""Check if the object is some kind of descriptor."""

View File

@ -64,6 +64,10 @@ class Base(object):
def inheritedmeth(self):
"""Inherited function."""
@classmethod
def inheritedclassmeth(cls):
"""Inherited class method."""
class Derived(Base):
def inheritedmeth(self):

View File

@ -715,6 +715,7 @@ def test_generate():
assert_processes(should, 'class', 'Class')
options.inherited_members = True
should.append(('method', 'target.Class.inheritedmeth'))
should.append(('method', 'target.Class.inheritedclassmeth'))
assert_processes(should, 'class', 'Class')
# test special members
@ -798,6 +799,7 @@ def test_generate():
' .. py:attribute:: Class.inst_attr_comment',
' .. py:attribute:: Class.inst_attr_string',
' .. py:attribute:: Class._private_inst_attr',
' .. py:classmethod:: Class.inheritedclassmeth()',
' .. py:method:: Class.inheritedmeth()',
],
'class', 'Class', member_order='bysource', all_members=True)