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:
|
def add_directive_header(self, sig: str) -> None:
|
||||||
sourcename = self.get_sourcename()
|
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):
|
if inspect.iscoroutinefunction(self.object):
|
||||||
self.add_line(' :async:', sourcename)
|
self.add_line(' :async:', sourcename)
|
||||||
|
|
||||||
|
def add_singledispatch_directive_header(self, sig: str) -> None:
|
||||||
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:
|
|
||||||
sourcename = self.get_sourcename()
|
sourcename = self.get_sourcename()
|
||||||
|
|
||||||
# intercept generated directive headers
|
# intercept generated directive headers
|
||||||
@ -1125,6 +1110,26 @@ class SingledispatchFunctionDocumenter(FunctionDocumenter):
|
|||||||
func.__signature__ = sig.replace(parameters=params) # type: ignore
|
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):
|
class DecoratorDocumenter(FunctionDocumenter):
|
||||||
"""
|
"""
|
||||||
Specialized Documenter subclass for decorator functions.
|
Specialized Documenter subclass for decorator functions.
|
||||||
@ -1455,7 +1460,11 @@ class MethodDocumenter(DocstringSignatureMixin, ClassLevelDocumenter): # type:
|
|||||||
return args
|
return args
|
||||||
|
|
||||||
def add_directive_header(self, sig: str) -> None:
|
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()
|
sourcename = self.get_sourcename()
|
||||||
obj = self.parent.__dict__.get(self.object_name, self.object)
|
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:
|
def document_members(self, all_members: bool = False) -> None:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
def add_singledispatch_directive_header(self, sig: str) -> None:
|
||||||
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:
|
|
||||||
sourcename = self.get_sourcename()
|
sourcename = self.get_sourcename()
|
||||||
|
|
||||||
# intercept generated directive headers
|
# intercept generated directive headers
|
||||||
@ -1533,6 +1521,29 @@ class SingledispatchMethodDocumenter(MethodDocumenter):
|
|||||||
func.__signature__ = sig.replace(parameters=params) # type: ignore
|
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
|
class AttributeDocumenter(DocstringStripSignatureMixin, ClassLevelDocumenter): # type: ignore
|
||||||
"""
|
"""
|
||||||
Specialized Documenter subclass for attributes.
|
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),
|
@pytest.mark.skipif(sys.version_info < (3, 8),
|
||||||
reason='singledispatchmethod is available since python3.8')
|
reason='singledispatchmethod is available since python3.8')
|
||||||
@pytest.mark.usefixtures('setup_test')
|
@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.usefixtures('setup_test')
|
||||||
@pytest.mark.skipif(pyximport is None, reason='cython is not installed')
|
@pytest.mark.skipif(pyximport is None, reason='cython is not installed')
|
||||||
def test_cython():
|
def test_cython():
|
||||||
|
Loading…
Reference in New Issue
Block a user