mirror of
https://github.com/sphinx-doc/sphinx.git
synced 2025-02-25 18:55:22 -06:00
Merge pull request #7651 from tk0miya/7650_undecorated_signature
Fix #7650: autodoc: undecorated signature is shown for decorated functions
This commit is contained in:
commit
5ae622d48a
1
CHANGES
1
CHANGES
@ -92,6 +92,7 @@ Bugs fixed
|
|||||||
``Union[foo, bar, None]``
|
``Union[foo, bar, None]``
|
||||||
* #7629: autodoc: autofunction emits an unfriendly warning if an invalid object
|
* #7629: autodoc: autofunction emits an unfriendly warning if an invalid object
|
||||||
specified
|
specified
|
||||||
|
* #7650: autodoc: undecorated signature is shown for decorated functions
|
||||||
* #7551: autosummary: a nested class is indexed as non-nested class
|
* #7551: autosummary: a nested class is indexed as non-nested class
|
||||||
* #7535: sphinx-autogen: crashes when custom template uses inheritance
|
* #7535: sphinx-autogen: crashes when custom template uses inheritance
|
||||||
* #7536: sphinx-autogen: crashes when template uses i18n feature
|
* #7536: sphinx-autogen: crashes when template uses i18n feature
|
||||||
|
@ -1051,10 +1051,12 @@ class FunctionDocumenter(DocstringSignatureMixin, ModuleLevelDocumenter): # typ
|
|||||||
if self.env.config.autodoc_typehints in ('none', 'description'):
|
if self.env.config.autodoc_typehints in ('none', 'description'):
|
||||||
kwargs.setdefault('show_annotation', False)
|
kwargs.setdefault('show_annotation', False)
|
||||||
|
|
||||||
unwrapped = inspect.unwrap(self.object)
|
|
||||||
try:
|
try:
|
||||||
self.env.app.emit('autodoc-before-process-signature', unwrapped, False)
|
self.env.app.emit('autodoc-before-process-signature', self.object, False)
|
||||||
sig = inspect.signature(unwrapped)
|
if inspect.is_singledispatch_function(self.object):
|
||||||
|
sig = inspect.signature(self.object, follow_wrapped=True)
|
||||||
|
else:
|
||||||
|
sig = inspect.signature(self.object)
|
||||||
args = stringify_signature(sig, **kwargs)
|
args = stringify_signature(sig, **kwargs)
|
||||||
except TypeError as exc:
|
except TypeError as exc:
|
||||||
logger.warning(__("Failed to get a function signature for %s: %s"),
|
logger.warning(__("Failed to get a function signature for %s: %s"),
|
||||||
@ -1451,7 +1453,6 @@ class MethodDocumenter(DocstringSignatureMixin, ClassLevelDocumenter): # type:
|
|||||||
if self.env.config.autodoc_typehints in ('none', 'description'):
|
if self.env.config.autodoc_typehints in ('none', 'description'):
|
||||||
kwargs.setdefault('show_annotation', False)
|
kwargs.setdefault('show_annotation', False)
|
||||||
|
|
||||||
unwrapped = inspect.unwrap(self.object)
|
|
||||||
try:
|
try:
|
||||||
if self.object == object.__init__ and self.parent != object:
|
if self.object == object.__init__ and self.parent != object:
|
||||||
# Classes not having own __init__() method are shown as no arguments.
|
# Classes not having own __init__() method are shown as no arguments.
|
||||||
@ -1460,12 +1461,18 @@ class MethodDocumenter(DocstringSignatureMixin, ClassLevelDocumenter): # type:
|
|||||||
# But it makes users confused.
|
# But it makes users confused.
|
||||||
args = '()'
|
args = '()'
|
||||||
else:
|
else:
|
||||||
if inspect.isstaticmethod(unwrapped, cls=self.parent, name=self.object_name):
|
if inspect.isstaticmethod(self.object, cls=self.parent, name=self.object_name):
|
||||||
self.env.app.emit('autodoc-before-process-signature', unwrapped, False)
|
self.env.app.emit('autodoc-before-process-signature', self.object, False)
|
||||||
sig = inspect.signature(unwrapped, bound_method=False)
|
sig = inspect.signature(self.object, bound_method=False)
|
||||||
else:
|
else:
|
||||||
self.env.app.emit('autodoc-before-process-signature', unwrapped, True)
|
self.env.app.emit('autodoc-before-process-signature', self.object, True)
|
||||||
sig = inspect.signature(unwrapped, bound_method=True)
|
|
||||||
|
meth = self.parent.__dict__.get(self.objpath[-1], None)
|
||||||
|
if meth and inspect.is_singledispatch_method(meth):
|
||||||
|
sig = inspect.signature(self.object, bound_method=True,
|
||||||
|
follow_wrapped=True)
|
||||||
|
else:
|
||||||
|
sig = inspect.signature(self.object, bound_method=True)
|
||||||
args = stringify_signature(sig, **kwargs)
|
args = stringify_signature(sig, **kwargs)
|
||||||
except TypeError as exc:
|
except TypeError as exc:
|
||||||
logger.warning(__("Failed to get a method signature for %s: %s"),
|
logger.warning(__("Failed to get a method signature for %s: %s"),
|
||||||
@ -1522,7 +1529,9 @@ class MethodDocumenter(DocstringSignatureMixin, ClassLevelDocumenter): # type:
|
|||||||
self.annotate_to_first_argument(func, typ)
|
self.annotate_to_first_argument(func, typ)
|
||||||
|
|
||||||
documenter = MethodDocumenter(self.directive, '')
|
documenter = MethodDocumenter(self.directive, '')
|
||||||
|
documenter.parent = self.parent
|
||||||
documenter.object = func
|
documenter.object = func
|
||||||
|
documenter.objpath = self.objpath
|
||||||
self.add_line(' %s%s' % (self.format_name(),
|
self.add_line(' %s%s' % (self.format_name(),
|
||||||
documenter.format_signature()),
|
documenter.format_signature()),
|
||||||
sourcename)
|
sourcename)
|
||||||
|
@ -408,12 +408,19 @@ def is_builtin_class_method(obj: Any, attr_name: str) -> bool:
|
|||||||
return getattr(builtins, name, None) is cls
|
return getattr(builtins, name, None) is cls
|
||||||
|
|
||||||
|
|
||||||
def signature(subject: Callable, bound_method: bool = False) -> inspect.Signature:
|
def signature(subject: Callable, bound_method: bool = False, follow_wrapped: bool = False
|
||||||
|
) -> inspect.Signature:
|
||||||
"""Return a Signature object for the given *subject*.
|
"""Return a Signature object for the given *subject*.
|
||||||
|
|
||||||
:param bound_method: Specify *subject* is a bound method or not
|
:param bound_method: Specify *subject* is a bound method or not
|
||||||
|
:param follow_wrapped: Same as ``inspect.signature()``.
|
||||||
|
Defaults to ``False`` (get a signature of *subject*).
|
||||||
"""
|
"""
|
||||||
try:
|
try:
|
||||||
|
try:
|
||||||
|
signature = inspect.signature(subject, follow_wrapped=follow_wrapped)
|
||||||
|
except ValueError:
|
||||||
|
# follow built-in wrappers up (ex. functools.lru_cache)
|
||||||
signature = inspect.signature(subject)
|
signature = inspect.signature(subject)
|
||||||
parameters = list(signature.parameters.values())
|
parameters = list(signature.parameters.values())
|
||||||
return_annotation = signature.return_annotation
|
return_annotation = signature.return_annotation
|
||||||
|
@ -1,5 +1,9 @@
|
|||||||
|
from functools import wraps
|
||||||
|
|
||||||
|
|
||||||
def deco1(func):
|
def deco1(func):
|
||||||
"""docstring for deco1"""
|
"""docstring for deco1"""
|
||||||
|
@wraps(func)
|
||||||
def wrapper():
|
def wrapper():
|
||||||
return func()
|
return func()
|
||||||
|
|
||||||
@ -14,3 +18,14 @@ def deco2(condition, message):
|
|||||||
|
|
||||||
return wrapper
|
return wrapper
|
||||||
return decorator
|
return decorator
|
||||||
|
|
||||||
|
|
||||||
|
@deco1
|
||||||
|
def foo(name=None, age=None):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class Bar:
|
||||||
|
@deco1
|
||||||
|
def meth(self, name=None, age=None):
|
||||||
|
pass
|
||||||
|
@ -142,6 +142,7 @@ def test_format_signature(app):
|
|||||||
inst = app.registry.documenters[objtype](directive, name)
|
inst = app.registry.documenters[objtype](directive, name)
|
||||||
inst.fullname = name
|
inst.fullname = name
|
||||||
inst.doc_as_attr = False # for class objtype
|
inst.doc_as_attr = False # for class objtype
|
||||||
|
inst.parent = object # dummy
|
||||||
inst.object = obj
|
inst.object = obj
|
||||||
inst.objpath = [name]
|
inst.objpath = [name]
|
||||||
inst.args = args
|
inst.args = args
|
||||||
@ -1243,6 +1244,17 @@ def test_autofunction_for_methoddescriptor(app):
|
|||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.sphinx('html', testroot='ext-autodoc')
|
||||||
|
def test_autofunction_for_decorated(app):
|
||||||
|
actual = do_autodoc(app, 'function', 'target.decorator.foo')
|
||||||
|
assert list(actual) == [
|
||||||
|
'',
|
||||||
|
'.. py:function:: foo()',
|
||||||
|
' :module: target.decorator',
|
||||||
|
'',
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.sphinx('html', testroot='ext-autodoc')
|
@pytest.mark.sphinx('html', testroot='ext-autodoc')
|
||||||
def test_automethod_for_builtin(app):
|
def test_automethod_for_builtin(app):
|
||||||
actual = do_autodoc(app, 'method', 'builtins.int.__add__')
|
actual = do_autodoc(app, 'method', 'builtins.int.__add__')
|
||||||
@ -1256,6 +1268,17 @@ def test_automethod_for_builtin(app):
|
|||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.sphinx('html', testroot='ext-autodoc')
|
||||||
|
def test_automethod_for_decorated(app):
|
||||||
|
actual = do_autodoc(app, 'method', 'target.decorator.Bar.meth')
|
||||||
|
assert list(actual) == [
|
||||||
|
'',
|
||||||
|
'.. py:method:: Bar.meth()',
|
||||||
|
' :module: target.decorator',
|
||||||
|
'',
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.sphinx('html', testroot='ext-autodoc')
|
@pytest.mark.sphinx('html', testroot='ext-autodoc')
|
||||||
def test_abstractmethods(app):
|
def test_abstractmethods(app):
|
||||||
options = {"members": None,
|
options = {"members": None,
|
||||||
@ -1415,7 +1438,7 @@ def test_coroutine(app):
|
|||||||
actual = do_autodoc(app, 'function', 'target.coroutine.sync_func')
|
actual = do_autodoc(app, 'function', 'target.coroutine.sync_func')
|
||||||
assert list(actual) == [
|
assert list(actual) == [
|
||||||
'',
|
'',
|
||||||
'.. py:function:: sync_func()',
|
'.. py:function:: sync_func(*args, **kwargs)',
|
||||||
' :module: target.coroutine',
|
' :module: target.coroutine',
|
||||||
'',
|
'',
|
||||||
]
|
]
|
||||||
|
@ -97,7 +97,7 @@ def test_signature_methods():
|
|||||||
|
|
||||||
# wrapped bound method
|
# wrapped bound method
|
||||||
sig = inspect.signature(wrapped_bound_method)
|
sig = inspect.signature(wrapped_bound_method)
|
||||||
assert stringify_signature(sig) == '(arg1, **kwargs)'
|
assert stringify_signature(sig) == '(*args, **kwargs)'
|
||||||
|
|
||||||
|
|
||||||
def test_signature_partialmethod():
|
def test_signature_partialmethod():
|
||||||
|
Loading…
Reference in New Issue
Block a user