mirror of
https://github.com/sphinx-doc/sphinx.git
synced 2025-02-25 18:55:22 -06:00
Support singledispatch in autofunction/methodThis makes autofunction and automethod work standalone withsingledispatch functions and methods. Previously only automodule wouldsupport these
This commit is contained in:
parent
2fac698e76
commit
22fafb9773
@ -1062,30 +1062,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
|
||||
@ -1125,6 +1110,26 @@ class SingledispatchFunctionDocumenter(FunctionDocumenter):
|
||||
func.__signature__ = sig.replace(parameters=params) # type: ignore
|
||||
|
||||
|
||||
class SingledispatchFunctionDocumenter(FunctionDocumenter):
|
||||
"""
|
||||
Specialized Documenter subclass for singledispatch'ed functions.
|
||||
|
||||
Retained for backwards compatibility, does the same as the FunctionDocumenter
|
||||
"""
|
||||
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))
|
||||
|
||||
|
||||
class DecoratorDocumenter(FunctionDocumenter):
|
||||
"""
|
||||
Specialized Documenter subclass for decorator functions.
|
||||
@ -1455,7 +1460,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)
|
||||
@ -1471,28 +1480,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
|
||||
@ -1533,6 +1521,29 @@ class SingledispatchMethodDocumenter(MethodDocumenter):
|
||||
func.__signature__ = sig.replace(parameters=params) # type: ignore
|
||||
|
||||
|
||||
class SingledispatchMethodDocumenter(MethodDocumenter):
|
||||
"""
|
||||
Specialized Documenter subclass for singledispatch'ed methods.
|
||||
|
||||
Retained for backwards compatibility, does the same as the MethodDocumenter
|
||||
"""
|
||||
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
|
||||
|
||||
|
||||
class AttributeDocumenter(DocstringStripSignatureMixin, ClassLevelDocumenter): # type: ignore
|
||||
"""
|
||||
Specialized Documenter subclass for attributes.
|
||||
|
@ -1604,6 +1604,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')
|
||||
@ -1631,6 +1646,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():
|
||||
|
Loading…
Reference in New Issue
Block a user