summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTakeshi KOMIYA <i.tkomiya@gmail.com>2020-04-27 22:48:02 +0900
committerGitHub <noreply@github.com>2020-04-27 22:48:02 +0900
commit1cffff2a3024a8aeb4a7f9af9a10198d1d97c76c (patch)
tree293c037149d690b57fdefe2ac37c4569957a5610
parent7a40ed0f271057b668076593db1d9a9d68baf8d3 (diff)
parent65c9df83033ef248c57e1405d99a35a3751f2ed8 (diff)
downloadsphinx-git-1cffff2a3024a8aeb4a7f9af9a10198d1d97c76c.tar.gz
Merge pull request #7487 from thomascobb/singledispatch_autofunction
Support singledispatch autodoc directives
-rw-r--r--sphinx/ext/autodoc/__init__.py72
-rw-r--r--tests/test_autodoc.py32
2 files changed, 59 insertions, 45 deletions
diff --git a/sphinx/ext/autodoc/__init__.py b/sphinx/ext/autodoc/__init__.py
index 7b3028b12..3e8b2d765 100644
--- a/sphinx/ext/autodoc/__init__.py
+++ b/sphinx/ext/autodoc/__init__.py
@@ -1078,30 +1078,15 @@ class FunctionDocumenter(DocstringSignatureMixin, ModuleLevelDocumenter): # typ
def add_directive_header(self, sig: str) -> None:
sourcename = self.get_sourcename()
- super().add_directive_header(sig)
+ if inspect.is_singledispatch_function(self.object):
+ self.add_singledispatch_directive_header(sig)
+ else:
+ super().add_directive_header(sig)
if inspect.iscoroutinefunction(self.object):
self.add_line(' :async:', sourcename)
-
-class SingledispatchFunctionDocumenter(FunctionDocumenter):
- """
- Specialized Documenter subclass for singledispatch'ed functions.
- """
- objtype = 'singledispatch_function'
- directivetype = 'function'
- member_order = 30
-
- # before FunctionDocumenter
- priority = FunctionDocumenter.priority + 1
-
- @classmethod
- def can_document_member(cls, member: Any, membername: str, isattr: bool, parent: Any
- ) -> bool:
- return (super().can_document_member(member, membername, isattr, parent) and
- inspect.is_singledispatch_function(member))
-
- def add_directive_header(self, sig: str) -> None:
+ def add_singledispatch_directive_header(self, sig: str) -> None:
sourcename = self.get_sourcename()
# intercept generated directive headers
@@ -1141,6 +1126,14 @@ class SingledispatchFunctionDocumenter(FunctionDocumenter):
func.__signature__ = sig.replace(parameters=params) # type: ignore
+class SingledispatchFunctionDocumenter(FunctionDocumenter):
+ """
+ Used to be a specialized Documenter subclass for singledispatch'ed functions.
+
+ Retained for backwards compatibility, now does the same as the FunctionDocumenter
+ """
+
+
class DecoratorDocumenter(FunctionDocumenter):
"""
Specialized Documenter subclass for decorator functions.
@@ -1475,7 +1468,11 @@ class MethodDocumenter(DocstringSignatureMixin, ClassLevelDocumenter): # type:
return args
def add_directive_header(self, sig: str) -> None:
- super().add_directive_header(sig)
+ meth = self.parent.__dict__.get(self.objpath[-1])
+ if inspect.is_singledispatch_method(meth):
+ self.add_singledispatch_directive_header(sig)
+ else:
+ super().add_directive_header(sig)
sourcename = self.get_sourcename()
obj = self.parent.__dict__.get(self.object_name, self.object)
@@ -1491,28 +1488,7 @@ class MethodDocumenter(DocstringSignatureMixin, ClassLevelDocumenter): # type:
def document_members(self, all_members: bool = False) -> None:
pass
-
-class SingledispatchMethodDocumenter(MethodDocumenter):
- """
- Specialized Documenter subclass for singledispatch'ed methods.
- """
- objtype = 'singledispatch_method'
- directivetype = 'method'
- member_order = 50
-
- # before MethodDocumenter
- priority = MethodDocumenter.priority + 1
-
- @classmethod
- def can_document_member(cls, member: Any, membername: str, isattr: bool, parent: Any
- ) -> bool:
- if super().can_document_member(member, membername, isattr, parent) and parent.object:
- meth = parent.object.__dict__.get(membername)
- return inspect.is_singledispatch_method(meth)
- else:
- return False
-
- def add_directive_header(self, sig: str) -> None:
+ def add_singledispatch_directive_header(self, sig: str) -> None:
sourcename = self.get_sourcename()
# intercept generated directive headers
@@ -1553,6 +1529,14 @@ class SingledispatchMethodDocumenter(MethodDocumenter):
func.__signature__ = sig.replace(parameters=params) # type: ignore
+class SingledispatchMethodDocumenter(MethodDocumenter):
+ """
+ Used to be a specialized Documenter subclass for singledispatch'ed methods.
+
+ Retained for backwards compatibility, now does the same as the MethodDocumenter
+ """
+
+
class AttributeDocumenter(DocstringStripSignatureMixin, ClassLevelDocumenter): # type: ignore
"""
Specialized Documenter subclass for attributes.
@@ -1771,10 +1755,8 @@ def setup(app: Sphinx) -> Dict[str, Any]:
app.add_autodocumenter(DataDocumenter)
app.add_autodocumenter(DataDeclarationDocumenter)
app.add_autodocumenter(FunctionDocumenter)
- app.add_autodocumenter(SingledispatchFunctionDocumenter)
app.add_autodocumenter(DecoratorDocumenter)
app.add_autodocumenter(MethodDocumenter)
- app.add_autodocumenter(SingledispatchMethodDocumenter)
app.add_autodocumenter(AttributeDocumenter)
app.add_autodocumenter(PropertyDocumenter)
app.add_autodocumenter(InstanceAttributeDocumenter)
diff --git a/tests/test_autodoc.py b/tests/test_autodoc.py
index 7cdb074d2..51ae3ddc3 100644
--- a/tests/test_autodoc.py
+++ b/tests/test_autodoc.py
@@ -1603,6 +1603,21 @@ def test_singledispatch():
]
+@pytest.mark.usefixtures('setup_test')
+def test_singledispatch_autofunction():
+ options = {}
+ actual = do_autodoc(app, 'function', 'target.singledispatch.func', options)
+ assert list(actual) == [
+ '',
+ '.. py:function:: func(arg, kwarg=None)',
+ ' func(arg: int, kwarg=None)',
+ ' func(arg: str, kwarg=None)',
+ ' :module: target.singledispatch',
+ '',
+ ' A function for general use.',
+ '',
+ ]
+
@pytest.mark.skipif(sys.version_info < (3, 8),
reason='singledispatchmethod is available since python3.8')
@pytest.mark.usefixtures('setup_test')
@@ -1630,6 +1645,23 @@ def test_singledispatchmethod():
]
+@pytest.mark.skipif(sys.version_info < (3, 8),
+ reason='singledispatchmethod is available since python3.8')
+@pytest.mark.usefixtures('setup_test')
+def test_singledispatchmethod_automethod():
+ options = {}
+ actual = do_autodoc(app, 'method', 'target.singledispatchmethod.Foo.meth', options)
+ assert list(actual) == [
+ '',
+ '.. py:method:: Foo.meth(arg, kwarg=None)',
+ ' Foo.meth(arg: int, kwarg=None)',
+ ' Foo.meth(arg: str, kwarg=None)',
+ ' :module: target.singledispatchmethod',
+ '',
+ ' A method for general use.',
+ '',
+ ]
+
@pytest.mark.usefixtures('setup_test')
@pytest.mark.skipif(pyximport is None, reason='cython is not installed')
def test_cython():