mirror of
https://github.com/sphinx-doc/sphinx.git
synced 2025-02-25 18:55:22 -06:00
Support overloaded constructors (__call__, __init__ and __new__)
This commit is contained in:
parent
fb2f777079
commit
49de4ab1a1
@ -1279,6 +1279,9 @@ class ClassDocumenter(DocstringSignatureMixin, ModuleLevelDocumenter): # type:
|
||||
'private-members': bool_option, 'special-members': members_option,
|
||||
} # type: Dict[str, Callable]
|
||||
|
||||
_signature_class = None # type: Any
|
||||
_signature_method_name = None # type: str
|
||||
|
||||
def __init__(self, *args: Any) -> None:
|
||||
super().__init__(*args)
|
||||
merge_special_members_option(self.options)
|
||||
@ -1299,7 +1302,7 @@ class ClassDocumenter(DocstringSignatureMixin, ModuleLevelDocumenter): # type:
|
||||
self.doc_as_attr = True
|
||||
return ret
|
||||
|
||||
def _get_signature(self) -> Optional[Signature]:
|
||||
def _get_signature(self) -> Tuple[Optional[Any], Optional[str], Optional[Signature]]:
|
||||
def get_user_defined_function_or_method(obj: Any, attr: str) -> Any:
|
||||
""" Get the `attr` function or method from `obj`, if it is user-defined. """
|
||||
if inspect.is_builtin_class_method(obj, attr):
|
||||
@ -1323,7 +1326,8 @@ class ClassDocumenter(DocstringSignatureMixin, ModuleLevelDocumenter): # type:
|
||||
if call is not None:
|
||||
self.env.app.emit('autodoc-before-process-signature', call, True)
|
||||
try:
|
||||
return inspect.signature(call, bound_method=True)
|
||||
sig = inspect.signature(call, bound_method=True)
|
||||
return type(self.object), '__call__', sig
|
||||
except ValueError:
|
||||
pass
|
||||
|
||||
@ -1332,7 +1336,8 @@ class ClassDocumenter(DocstringSignatureMixin, ModuleLevelDocumenter): # type:
|
||||
if new is not None:
|
||||
self.env.app.emit('autodoc-before-process-signature', new, True)
|
||||
try:
|
||||
return inspect.signature(new, bound_method=True)
|
||||
sig = inspect.signature(new, bound_method=True)
|
||||
return self.object, '__new__', sig
|
||||
except ValueError:
|
||||
pass
|
||||
|
||||
@ -1341,7 +1346,8 @@ class ClassDocumenter(DocstringSignatureMixin, ModuleLevelDocumenter): # type:
|
||||
if init is not None:
|
||||
self.env.app.emit('autodoc-before-process-signature', init, True)
|
||||
try:
|
||||
return inspect.signature(init, bound_method=True)
|
||||
sig = inspect.signature(init, bound_method=True)
|
||||
return self.object, '__init__', sig
|
||||
except ValueError:
|
||||
pass
|
||||
|
||||
@ -1351,20 +1357,21 @@ class ClassDocumenter(DocstringSignatureMixin, ModuleLevelDocumenter): # type:
|
||||
# the signature from, so just pass the object itself to our hook.
|
||||
self.env.app.emit('autodoc-before-process-signature', self.object, False)
|
||||
try:
|
||||
return inspect.signature(self.object, bound_method=False)
|
||||
sig = inspect.signature(self.object, bound_method=False)
|
||||
return None, None, sig
|
||||
except ValueError:
|
||||
pass
|
||||
|
||||
# Still no signature: happens e.g. for old-style classes
|
||||
# with __init__ in C and no `__text_signature__`.
|
||||
return None
|
||||
return None, None, None
|
||||
|
||||
def format_args(self, **kwargs: Any) -> str:
|
||||
if self.env.config.autodoc_typehints in ('none', 'description'):
|
||||
kwargs.setdefault('show_annotation', False)
|
||||
|
||||
try:
|
||||
sig = self._get_signature()
|
||||
self._signature_class, self._signature_method_name, sig = self._get_signature()
|
||||
except TypeError as exc:
|
||||
# __signature__ attribute contained junk
|
||||
logger.warning(__("Failed to get a constructor signature for %s: %s"),
|
||||
@ -1380,7 +1387,30 @@ class ClassDocumenter(DocstringSignatureMixin, ModuleLevelDocumenter): # type:
|
||||
if self.doc_as_attr:
|
||||
return ''
|
||||
|
||||
return super().format_signature(**kwargs)
|
||||
sig = super().format_signature()
|
||||
|
||||
overloaded = False
|
||||
qualname = None
|
||||
# TODO: recreate analyzer for the module of class (To be clear, owner of the method)
|
||||
if self._signature_class and self._signature_method_name and self.analyzer:
|
||||
qualname = '.'.join([self._signature_class.__qualname__,
|
||||
self._signature_method_name])
|
||||
if qualname in self.analyzer.overloads:
|
||||
overloaded = True
|
||||
|
||||
sigs = []
|
||||
if overloaded:
|
||||
# Use signatures for overloaded methods instead of the implementation method.
|
||||
for overload in self.analyzer.overloads.get(qualname):
|
||||
parameters = list(overload.parameters.values())
|
||||
overload = overload.replace(parameters=parameters[1:],
|
||||
return_annotation=Parameter.empty)
|
||||
sig = stringify_signature(overload, **kwargs)
|
||||
sigs.append(sig)
|
||||
else:
|
||||
sigs.append(sig)
|
||||
|
||||
return "\n".join(sigs)
|
||||
|
||||
def add_directive_header(self, sig: str) -> None:
|
||||
sourcename = self.get_sourcename()
|
||||
|
@ -1,4 +1,4 @@
|
||||
from typing import overload
|
||||
from typing import Any, overload
|
||||
|
||||
|
||||
@overload
|
||||
@ -39,3 +39,50 @@ class Math:
|
||||
def sum(self, x, y):
|
||||
"""docstring"""
|
||||
return x + y
|
||||
|
||||
|
||||
class Foo:
|
||||
"""docstring"""
|
||||
|
||||
@overload
|
||||
def __new__(cls, x: int, y: int) -> "Foo":
|
||||
...
|
||||
|
||||
@overload
|
||||
def __new__(cls, x: str, y: str) -> "Foo":
|
||||
...
|
||||
|
||||
def __new__(cls, x, y):
|
||||
pass
|
||||
|
||||
|
||||
class Bar:
|
||||
"""docstring"""
|
||||
|
||||
@overload
|
||||
def __init__(cls, x: int, y: int) -> None:
|
||||
...
|
||||
|
||||
@overload
|
||||
def __init__(cls, x: str, y: str) -> None:
|
||||
...
|
||||
|
||||
def __init__(cls, x, y):
|
||||
pass
|
||||
|
||||
|
||||
class Meta(type):
|
||||
@overload
|
||||
def __call__(cls, x: int, y: int) -> Any:
|
||||
...
|
||||
|
||||
@overload
|
||||
def __call__(cls, x: str, y: str) -> Any:
|
||||
...
|
||||
|
||||
def __call__(cls, x, y):
|
||||
pass
|
||||
|
||||
|
||||
class Baz(metaclass=Meta):
|
||||
"""docstring"""
|
||||
|
@ -1796,6 +1796,27 @@ def test_overload(app):
|
||||
'.. py:module:: target.overload',
|
||||
'',
|
||||
'',
|
||||
'.. py:class:: Bar(x: int, y: int)',
|
||||
' Bar(x: str, y: str)',
|
||||
' :module: target.overload',
|
||||
'',
|
||||
' docstring',
|
||||
'',
|
||||
'',
|
||||
'.. py:class:: Baz(x: int, y: int)',
|
||||
' Baz(x: str, y: str)',
|
||||
' :module: target.overload',
|
||||
'',
|
||||
' docstring',
|
||||
'',
|
||||
'',
|
||||
'.. py:class:: Foo(x: int, y: int)',
|
||||
' Foo(x: str, y: str)',
|
||||
' :module: target.overload',
|
||||
'',
|
||||
' docstring',
|
||||
'',
|
||||
'',
|
||||
'.. py:class:: Math()',
|
||||
' :module: target.overload',
|
||||
'',
|
||||
|
Loading…
Reference in New Issue
Block a user