Handle singledispatch functions with rewritten signatures.

If a singledispatch function has its `__signature__` rewritten, autodoc
fails to annotate that signature because `func.__annotations__` is not
consulted.  Instead, directly assign to `__signature__` instead.
This commit is contained in:
Antony Lee 2020-03-10 10:58:18 +01:00
parent 5caaa5534b
commit f9048cf18e
2 changed files with 19 additions and 8 deletions

View File

@ -13,6 +13,7 @@
import importlib
import re
import warnings
from inspect import Parameter
from types import ModuleType
from typing import Any, Callable, Dict, Iterator, List, Sequence, Set, Tuple, Type, Union
from unittest.mock import patch
@ -1108,9 +1109,10 @@ class SingledispatchFunctionDocumenter(FunctionDocumenter):
if len(sig.parameters) == 0:
return
name = list(sig.parameters)[0]
if name not in func.__annotations__:
func.__annotations__[name] = typ
params = list(sig.parameters.values())
if params[0].annotation is Parameter.empty:
params[0] = params[0].replace(annotation=typ)
func.__signature__ = sig.replace(parameters=params) # type: ignore
class DecoratorDocumenter(FunctionDocumenter):
@ -1508,13 +1510,14 @@ class SingledispatchMethodDocumenter(MethodDocumenter):
def annotate_to_first_argument(self, func: Callable, typ: Type) -> None:
"""Annotate type hint to the first argument of function if needed."""
sig = inspect.signature(func, bound_method=True)
if len(sig.parameters) == 0:
sig = inspect.signature(func)
if len(sig.parameters) == 1:
return
name = list(sig.parameters)[0]
if name not in func.__annotations__:
func.__annotations__[name] = typ
params = list(sig.parameters.values())
if params[1].annotation is Parameter.empty:
params[1] = params[1].replace(annotation=typ)
func.__signature__ = sig.replace(parameters=params) # type: ignore
class AttributeDocumenter(DocstringStripSignatureMixin, ClassLevelDocumenter): # type: ignore

View File

@ -1,4 +1,11 @@
from functools import singledispatch
import inspect
def assign_signature(func):
# This is intended to cover more complex signature-rewriting decorators.
func.__signature__ = inspect.signature(func)
return func
@singledispatch
@ -14,6 +21,7 @@ def _func_int(arg, kwarg=None):
@func.register(str)
@assign_signature
def _func_str(arg, kwarg=None):
"""A function for str."""
pass