mirror of
https://github.com/sphinx-doc/sphinx.git
synced 2025-02-25 18:55:22 -06:00
Merge pull request #7190 from tk0miya/7189_async_classmethod
Fix #7189: autodoc: classmethod coroutines are not detected
This commit is contained in:
commit
404b507dec
1
CHANGES
1
CHANGES
@ -18,6 +18,7 @@ Bugs fixed
|
|||||||
|
|
||||||
* #7184: autodoc: ``*args`` and ``**kwarg`` in type comments are not handled
|
* #7184: autodoc: ``*args`` and ``**kwarg`` in type comments are not handled
|
||||||
properly
|
properly
|
||||||
|
* #7189: autodoc: classmethod coroutines are not detected
|
||||||
|
|
||||||
Testing
|
Testing
|
||||||
--------
|
--------
|
||||||
|
@ -111,6 +111,19 @@ def getargspec(func):
|
|||||||
kwonlyargs, kwdefaults, annotations)
|
kwonlyargs, kwdefaults, annotations)
|
||||||
|
|
||||||
|
|
||||||
|
def unwrap(obj: Any) -> Any:
|
||||||
|
"""Get an original object from wrapped object."""
|
||||||
|
while True:
|
||||||
|
if ispartial(obj):
|
||||||
|
obj = unpartial(obj)
|
||||||
|
elif isclassmethod(obj):
|
||||||
|
obj = obj.__func__
|
||||||
|
elif isstaticmethod(obj):
|
||||||
|
obj = obj.__func__
|
||||||
|
else:
|
||||||
|
return obj
|
||||||
|
|
||||||
|
|
||||||
def isenumclass(x: Any) -> bool:
|
def isenumclass(x: Any) -> bool:
|
||||||
"""Check if the object is subclass of enum."""
|
"""Check if the object is subclass of enum."""
|
||||||
return inspect.isclass(x) and issubclass(x, enum.Enum)
|
return inspect.isclass(x) and issubclass(x, enum.Enum)
|
||||||
@ -141,7 +154,7 @@ def isclassmethod(obj: Any) -> bool:
|
|||||||
"""Check if the object is classmethod."""
|
"""Check if the object is classmethod."""
|
||||||
if isinstance(obj, classmethod):
|
if isinstance(obj, classmethod):
|
||||||
return True
|
return True
|
||||||
elif inspect.ismethod(obj) and obj.__self__ is not None:
|
elif inspect.ismethod(obj) and obj.__self__ is not None and isclass(obj.__self__):
|
||||||
return True
|
return True
|
||||||
|
|
||||||
return False
|
return False
|
||||||
@ -208,17 +221,17 @@ def isattributedescriptor(obj: Any) -> bool:
|
|||||||
|
|
||||||
def isfunction(obj: Any) -> bool:
|
def isfunction(obj: Any) -> bool:
|
||||||
"""Check if the object is function."""
|
"""Check if the object is function."""
|
||||||
return inspect.isfunction(unpartial(obj))
|
return inspect.isfunction(unwrap(obj))
|
||||||
|
|
||||||
|
|
||||||
def isbuiltin(obj: Any) -> bool:
|
def isbuiltin(obj: Any) -> bool:
|
||||||
"""Check if the object is builtin."""
|
"""Check if the object is builtin."""
|
||||||
return inspect.isbuiltin(unpartial(obj))
|
return inspect.isbuiltin(unwrap(obj))
|
||||||
|
|
||||||
|
|
||||||
def iscoroutinefunction(obj: Any) -> bool:
|
def iscoroutinefunction(obj: Any) -> bool:
|
||||||
"""Check if the object is coroutine-function."""
|
"""Check if the object is coroutine-function."""
|
||||||
obj = unpartial(obj)
|
obj = unwrap(obj)
|
||||||
if hasattr(obj, '__code__') and inspect.iscoroutinefunction(obj):
|
if hasattr(obj, '__code__') and inspect.iscoroutinefunction(obj):
|
||||||
# check obj.__code__ because iscoroutinefunction() crashes for custom method-like
|
# check obj.__code__ because iscoroutinefunction() crashes for custom method-like
|
||||||
# objects (see https://github.com/sphinx-doc/sphinx/issues/6605)
|
# objects (see https://github.com/sphinx-doc/sphinx/issues/6605)
|
||||||
|
@ -3,6 +3,16 @@ class AsyncClass:
|
|||||||
"""A documented coroutine function"""
|
"""A documented coroutine function"""
|
||||||
attr_coro_result = await _other_coro_func() # NOQA
|
attr_coro_result = await _other_coro_func() # NOQA
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
async def do_coroutine2(cls):
|
||||||
|
"""A documented coroutine classmethod"""
|
||||||
|
pass
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
async def do_coroutine3():
|
||||||
|
"""A documented coroutine staticmethod"""
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
async def _other_coro_func():
|
async def _other_coro_func():
|
||||||
return "run"
|
return "run"
|
||||||
|
@ -1319,7 +1319,23 @@ def test_coroutine():
|
|||||||
' :async:',
|
' :async:',
|
||||||
' ',
|
' ',
|
||||||
' A documented coroutine function',
|
' A documented coroutine function',
|
||||||
' '
|
' ',
|
||||||
|
' ',
|
||||||
|
' .. py:method:: AsyncClass.do_coroutine2()',
|
||||||
|
' :module: target.coroutine',
|
||||||
|
' :async:',
|
||||||
|
' :classmethod:',
|
||||||
|
' ',
|
||||||
|
' A documented coroutine classmethod',
|
||||||
|
' ',
|
||||||
|
' ',
|
||||||
|
' .. py:method:: AsyncClass.do_coroutine3()',
|
||||||
|
' :module: target.coroutine',
|
||||||
|
' :async:',
|
||||||
|
' :staticmethod:',
|
||||||
|
' ',
|
||||||
|
' A documented coroutine staticmethod',
|
||||||
|
' ',
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
|
@ -419,6 +419,16 @@ def test_dict_customtype():
|
|||||||
assert "<CustomType(2)>: 2" in description
|
assert "<CustomType(2)>: 2" in description
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.sphinx(testroot='ext-autodoc')
|
||||||
|
def test_isclassmethod(app):
|
||||||
|
from target.methods import Base, Inherited
|
||||||
|
|
||||||
|
assert inspect.isclassmethod(Base.classmeth) is True
|
||||||
|
assert inspect.isclassmethod(Base.meth) is False
|
||||||
|
assert inspect.isclassmethod(Inherited.classmeth) is True
|
||||||
|
assert inspect.isclassmethod(Inherited.meth) is False
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.sphinx(testroot='ext-autodoc')
|
@pytest.mark.sphinx(testroot='ext-autodoc')
|
||||||
def test_isstaticmethod(app):
|
def test_isstaticmethod(app):
|
||||||
from target.methods import Base, Inherited
|
from target.methods import Base, Inherited
|
||||||
|
Loading…
Reference in New Issue
Block a user