Fix #8693: autodoc: Default values for overloads are rendered as string

The default values for overloaded functions are rendered as string
literal unexpectedly because autodoc extracts code snippets from
the source code, not actual value (ex. int, ellipsis, and so on).

This introduces a simple wrapper class; `DefaultValue` to render these
code snippets like actual values, not string literals.
This commit is contained in:
Takeshi KOMIYA 2021-01-17 01:50:31 +09:00
parent 7c340e1c1c
commit 425cd1af02
4 changed files with 28 additions and 14 deletions

View File

@ -45,6 +45,7 @@ Bugs fixed
* #8315: autodoc: Failed to resolve struct.Struct type annotation * #8315: autodoc: Failed to resolve struct.Struct type annotation
* #8652: autodoc: All variable comments in the module are ignored if the module * #8652: autodoc: All variable comments in the module are ignored if the module
contains invalid type comments contains invalid type comments
* #8693: autodoc: Default values for overloaded functions are rendered as string
* #8306: autosummary: mocked modules are documented as empty page when using * #8306: autosummary: mocked modules are documented as empty page when using
:recursive: option :recursive: option
* #8618: html: kbd role produces incorrect HTML when compound-key separators (-, * #8618: html: kbd role produces incorrect HTML when compound-key separators (-,

View File

@ -499,6 +499,19 @@ def is_builtin_class_method(obj: Any, attr_name: str) -> bool:
return getattr(builtins, name, None) is cls return getattr(builtins, name, None) is cls
class DefaultValue:
"""A simple wrapper for default value of the parameters of overload functions."""
def __init__(self, value: str) -> None:
self.value = value
def __eq__(self, other: object) -> bool:
return self.value == other
def __repr__(self) -> str:
return self.value
def _should_unwrap(subject: Callable) -> bool: def _should_unwrap(subject: Callable) -> bool:
"""Check the function should be unwrapped on getting signature.""" """Check the function should be unwrapped on getting signature."""
if (safe_getattr(subject, '__globals__', None) and if (safe_getattr(subject, '__globals__', None) and
@ -704,7 +717,7 @@ def signature_from_ast(node: ast.FunctionDef, code: str = '') -> inspect.Signatu
if defaults[i] is Parameter.empty: if defaults[i] is Parameter.empty:
default = Parameter.empty default = Parameter.empty
else: else:
default = ast_unparse(defaults[i], code) default = DefaultValue(ast_unparse(defaults[i], code))
annotation = ast_unparse(arg.annotation, code) or Parameter.empty annotation = ast_unparse(arg.annotation, code) or Parameter.empty
params.append(Parameter(arg.arg, Parameter.POSITIONAL_ONLY, params.append(Parameter(arg.arg, Parameter.POSITIONAL_ONLY,
@ -714,7 +727,7 @@ def signature_from_ast(node: ast.FunctionDef, code: str = '') -> inspect.Signatu
if defaults[i + posonlyargs] is Parameter.empty: if defaults[i + posonlyargs] is Parameter.empty:
default = Parameter.empty default = Parameter.empty
else: else:
default = ast_unparse(defaults[i + posonlyargs], code) default = DefaultValue(ast_unparse(defaults[i + posonlyargs], code))
annotation = ast_unparse(arg.annotation, code) or Parameter.empty annotation = ast_unparse(arg.annotation, code) or Parameter.empty
params.append(Parameter(arg.arg, Parameter.POSITIONAL_OR_KEYWORD, params.append(Parameter(arg.arg, Parameter.POSITIONAL_OR_KEYWORD,

View File

@ -2,17 +2,17 @@ from typing import Any, overload
@overload @overload
def sum(x: int, y: int) -> int: def sum(x: int, y: int = 0) -> int:
... ...
@overload @overload
def sum(x: "float", y: "float") -> "float": def sum(x: "float", y: "float" = 0.0) -> "float":
... ...
@overload @overload
def sum(x: str, y: str) -> str: def sum(x: str, y: str = ...) -> str:
... ...
@ -25,15 +25,15 @@ class Math:
"""docstring""" """docstring"""
@overload @overload
def sum(self, x: int, y: int) -> int: def sum(self, x: int, y: int = 0) -> int:
... ...
@overload @overload
def sum(self, x: "float", y: "float") -> "float": def sum(self, x: "float", y: "float" = 0.0) -> "float":
... ...
@overload @overload
def sum(self, x: str, y: str) -> str: def sum(self, x: str, y: str = ...) -> str:
... ...
def sum(self, x, y): def sum(self, x, y):

View File

@ -2078,17 +2078,17 @@ def test_overload(app):
' docstring', ' docstring',
'', '',
'', '',
' .. py:method:: Math.sum(x: int, y: int) -> int', ' .. py:method:: Math.sum(x: int, y: int = 0) -> int',
' Math.sum(x: float, y: float) -> float', ' Math.sum(x: float, y: float = 0.0) -> float',
' Math.sum(x: str, y: str) -> str', ' Math.sum(x: str, y: str = ...) -> str',
' :module: target.overload', ' :module: target.overload',
'', '',
' docstring', ' docstring',
'', '',
'', '',
'.. py:function:: sum(x: int, y: int) -> int', '.. py:function:: sum(x: int, y: int = 0) -> int',
' sum(x: float, y: float) -> float', ' sum(x: float, y: float = 0.0) -> float',
' sum(x: str, y: str) -> str', ' sum(x: str, y: str = ...) -> str',
' :module: target.overload', ' :module: target.overload',
'', '',
' docstring', ' docstring',