diff options
-rw-r--r-- | CHANGES | 1 | ||||
-rw-r--r-- | sphinx/ext/autodoc/__init__.py | 32 | ||||
-rw-r--r-- | tests/roots/test-ext-autodoc/target/overload.py | 41 | ||||
-rw-r--r-- | tests/test_ext_autodoc.py | 33 |
4 files changed, 103 insertions, 4 deletions
@@ -51,6 +51,7 @@ Features added builtin base classes * #2106: autodoc: Support multiple signatures on docstring * #4422: autodoc: Support GenericAlias in Python 3.7 or above +* #3610: autodoc: Support overloaded functions * #7466: autosummary: headings in generated documents are not translated * #7490: autosummary: Add ``:caption:`` option to autosummary directive to set a caption to the toctree diff --git a/sphinx/ext/autodoc/__init__.py b/sphinx/ext/autodoc/__init__.py index e247d3bd2..4fb6a4ce9 100644 --- a/sphinx/ext/autodoc/__init__.py +++ b/sphinx/ext/autodoc/__init__.py @@ -1192,8 +1192,14 @@ class FunctionDocumenter(DocstringSignatureMixin, ModuleLevelDocumenter): # typ self.add_line(' :async:', sourcename) def format_signature(self, **kwargs: Any) -> str: - sig = super().format_signature(**kwargs) - sigs = [sig] + sigs = [] + if self.analyzer and '.'.join(self.objpath) in self.analyzer.overloads: + # Use signatures for overloaded functions instead of the implementation function. + overloaded = True + else: + overloaded = False + sig = super().format_signature(**kwargs) + sigs.append(sig) if inspect.is_singledispatch_function(self.object): # append signature of singledispatch'ed functions @@ -1207,6 +1213,10 @@ class FunctionDocumenter(DocstringSignatureMixin, ModuleLevelDocumenter): # typ documenter.object = func documenter.objpath = [None] sigs.append(documenter.format_signature()) + if overloaded: + for overload in self.analyzer.overloads.get('.'.join(self.objpath)): + sig = stringify_signature(overload, **kwargs) + sigs.append(sig) return "\n".join(sigs) @@ -1693,8 +1703,14 @@ class MethodDocumenter(DocstringSignatureMixin, ClassLevelDocumenter): # type: pass def format_signature(self, **kwargs: Any) -> str: - sig = super().format_signature(**kwargs) - sigs = [sig] + sigs = [] + if self.analyzer and '.'.join(self.objpath) in self.analyzer.overloads: + # Use signatures for overloaded methods instead of the implementation method. + overloaded = True + else: + overloaded = False + sig = super().format_signature(**kwargs) + sigs.append(sig) meth = self.parent.__dict__.get(self.objpath[-1]) if inspect.is_singledispatch_method(meth): @@ -1710,6 +1726,14 @@ class MethodDocumenter(DocstringSignatureMixin, ClassLevelDocumenter): # type: documenter.object = func documenter.objpath = [None] sigs.append(documenter.format_signature()) + if overloaded: + for overload in self.analyzer.overloads.get('.'.join(self.objpath)): + if not inspect.isstaticmethod(self.object, cls=self.parent, + name=self.object_name): + parameters = list(overload.parameters.values()) + overload = overload.replace(parameters=parameters[1:]) + sig = stringify_signature(overload, **kwargs) + sigs.append(sig) return "\n".join(sigs) diff --git a/tests/roots/test-ext-autodoc/target/overload.py b/tests/roots/test-ext-autodoc/target/overload.py new file mode 100644 index 000000000..87d1c8533 --- /dev/null +++ b/tests/roots/test-ext-autodoc/target/overload.py @@ -0,0 +1,41 @@ +from typing import overload + + +@overload +def sum(x: int, y: int) -> int: + ... + + +@overload +def sum(x: float, y: float) -> float: + ... + + +@overload +def sum(x: str, y: str) -> str: + ... + + +def sum(x, y): + """docstring""" + return x + y + + +class Math: + """docstring""" + + @overload + def sum(self, x: int, y: int) -> int: + ... + + @overload + def sum(self, x: float, y: float) -> float: + ... + + @overload + def sum(self, x: str, y: str) -> str: + ... + + def sum(self, x, y): + """docstring""" + return x + y diff --git a/tests/test_ext_autodoc.py b/tests/test_ext_autodoc.py index 5cc1f3c22..0a651950b 100644 --- a/tests/test_ext_autodoc.py +++ b/tests/test_ext_autodoc.py @@ -1787,6 +1787,39 @@ def test_final(app): ] +@pytest.mark.sphinx('html', testroot='ext-autodoc') +def test_overload(app): + options = {"members": None} + actual = do_autodoc(app, 'module', 'target.overload', options) + assert list(actual) == [ + '', + '.. py:module:: target.overload', + '', + '', + '.. py:class:: Math()', + ' :module: target.overload', + '', + ' docstring', + '', + '', + ' .. py:method:: Math.sum(x: int, y: int) -> int', + ' Math.sum(x: float, y: float) -> float', + ' Math.sum(x: str, y: str) -> str', + ' :module: target.overload', + '', + ' docstring', + '', + '', + '.. py:function:: sum(x: int, y: int) -> int', + ' sum(x: float, y: float) -> float', + ' sum(x: str, y: str) -> str', + ' :module: target.overload', + '', + ' docstring', + '', + ] + + @pytest.mark.sphinx('dummy', testroot='ext-autodoc') def test_autodoc(app, status, warning): app.builder.build_all() |