diff --git a/CHANGES b/CHANGES index 87b134488..7a06cef75 100644 --- a/CHANGES +++ b/CHANGES @@ -27,6 +27,7 @@ Bugs fixed (escaped) line breaks are present. * C++, properly use ``desc_addname`` nodes for prefixes of names. * #4915, #4916: links on search page are broken when using dirhtml builder +* #4969: autodoc: constructor method should not have return annotation Testing -------- diff --git a/sphinx/ext/autodoc/__init__.py b/sphinx/ext/autodoc/__init__.py index d516146bf..eabe487e3 100644 --- a/sphinx/ext/autodoc/__init__.py +++ b/sphinx/ext/autodoc/__init__.py @@ -1035,9 +1035,11 @@ class FunctionDocumenter(DocstringSignatureMixin, ModuleLevelDocumenter): # typ # typing) we try to use the constructor signature as function # signature without the first argument. try: - args = Signature(self.object.__new__, bound_method=True).format_args() + sig = Signature(self.object.__new__, bound_method=True, has_retval=False) + args = sig.format_args() except TypeError: - args = Signature(self.object.__init__, bound_method=True).format_args() + sig = Signature(self.object.__init__, bound_method=True, has_retval=False) + args = sig.format_args() # escape backslashes for reST args = args.replace('\\', '\\\\') @@ -1090,7 +1092,7 @@ class ClassDocumenter(DocstringSignatureMixin, ModuleLevelDocumenter): # type: not(inspect.ismethod(initmeth) or inspect.isfunction(initmeth)): return None try: - return Signature(initmeth, bound_method=True).format_args() + return Signature(initmeth, bound_method=True, has_retval=False).format_args() except TypeError: # still not possible: happens e.g. for old-style classes # with __init__ in C diff --git a/sphinx/util/inspect.py b/sphinx/util/inspect.py index 492db8700..72c3065bc 100644 --- a/sphinx/util/inspect.py +++ b/sphinx/util/inspect.py @@ -298,8 +298,8 @@ class Signature(object): its return annotation. """ - def __init__(self, subject, bound_method=False): - # type: (Callable, bool) -> None + def __init__(self, subject, bound_method=False, has_retval=True): + # type: (Callable, bool, bool) -> None # check subject is not a built-in class (ex. int, str) if (isinstance(subject, type) and is_builtin_class_method(subject, "__new__") and @@ -307,6 +307,7 @@ class Signature(object): raise TypeError("can't compute signature for built-in type {}".format(subject)) self.subject = subject + self.has_retval = has_retval self.partialmethod_with_noargs = False if PY3: @@ -375,7 +376,10 @@ class Signature(object): def return_annotation(self): # type: () -> Any if PY3 and self.signature: - return self.signature.return_annotation + if self.has_retval: + return self.signature.return_annotation + else: + return inspect.Parameter.empty else: return None diff --git a/tests/test_util_inspect.py b/tests/test_util_inspect.py index 6a3e25b6e..76f21a5e1 100644 --- a/tests/test_util_inspect.py +++ b/tests/test_util_inspect.py @@ -280,6 +280,10 @@ def test_Signature_annotations(): sig = inspect.Signature(f11).format_args() assert sig == '(x: CustomAnnotation, y: 123) -> None' + # has_retval=False + sig = inspect.Signature(f11, has_retval=False).format_args() + assert sig == '(x: CustomAnnotation, y: 123)' + def test_safe_getattr_with_default(): class Foo(object):