Merge pull request #10427 from tk0miya/10421_autodoc_preserve_defaults_for_classmethod

Fix #10421: autodoc_preserve_defaults doesn't work on class methods
This commit is contained in:
Takeshi KOMIYA 2022-05-08 23:19:10 +09:00 committed by GitHub
commit e770e2567f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 29 additions and 1 deletions

View File

@ -99,6 +99,8 @@ Bugs fixed
function function
* #10305: autodoc: Failed to extract optional forward-ref'ed typehints correctly * #10305: autodoc: Failed to extract optional forward-ref'ed typehints correctly
via :confval:`autodoc_type_aliases` via :confval:`autodoc_type_aliases`
* #10421: autodoc: :confval:`autodoc_preserve_defaults` doesn't work on class
methods
* #10214: html: invalid language tag was generated if :confval:`language` * #10214: html: invalid language tag was generated if :confval:`language`
contains a country code (ex. zh_CN) contains a country code (ex. zh_CN)
* #9974: html: Updated jQuery version from 3.5.1 to 3.6.0 * #9974: html: Updated jQuery version from 3.5.1 to 3.6.0

View File

@ -7,6 +7,7 @@ and keep them not evaluated for readability.
import ast import ast
import inspect import inspect
import sys import sys
from inspect import Parameter
from typing import Any, Dict, List, Optional from typing import Any, Dict, List, Optional
from sphinx.application import Sphinx from sphinx.application import Sphinx
@ -96,8 +97,18 @@ def update_defvalue(app: Sphinx, obj: Any, bound_method: bool) -> None:
if value is None: if value is None:
value = ast_unparse(default) # type: ignore value = ast_unparse(default) # type: ignore
parameters[i] = param.replace(default=DefaultValue(value)) parameters[i] = param.replace(default=DefaultValue(value))
if bound_method and inspect.ismethod(obj):
# classmethods
cls = inspect.Parameter('cls', Parameter.POSITIONAL_OR_KEYWORD)
parameters.insert(0, cls)
sig = sig.replace(parameters=parameters) sig = sig.replace(parameters=parameters)
obj.__signature__ = sig if bound_method and inspect.ismethod(obj):
# classmethods can't be assigned __signature__ attribute.
obj.__dict__['__signature__'] = sig
else:
obj.__signature__ = sig
except (AttributeError, TypeError): except (AttributeError, TypeError):
# failed to update signature (ex. built-in or extension types) # failed to update signature (ex. built-in or extension types)
pass pass

View File

@ -22,3 +22,9 @@ class Class:
now: datetime = datetime.now(), color: int = 0xFFFFFF, now: datetime = datetime.now(), color: int = 0xFFFFFF,
*, kwarg1, kwarg2 = 0xFFFFFF) -> None: *, kwarg1, kwarg2 = 0xFFFFFF) -> None:
"""docstring""" """docstring"""
@classmethod
def clsmeth(cls, name: str = CONSTANT, sentinel: Any = SENTINEL,
now: datetime = datetime.now(), color: int = 0xFFFFFF,
*, kwarg1, kwarg2 = 0xFFFFFF) -> None:
"""docstring"""

View File

@ -28,6 +28,15 @@ def test_preserve_defaults(app):
' docstring', ' docstring',
'', '',
'', '',
' .. py:method:: Class.clsmeth(name: str = CONSTANT, sentinel: ~typing.Any = '
'SENTINEL, now: ~datetime.datetime = datetime.now(), color: int = %s, *, '
'kwarg1, kwarg2=%s) -> None' % (color, color),
' :module: target.preserve_defaults',
' :classmethod:',
'',
' docstring',
'',
'',
' .. py:method:: Class.meth(name: str = CONSTANT, sentinel: ~typing.Any = ' ' .. py:method:: Class.meth(name: str = CONSTANT, sentinel: ~typing.Any = '
'SENTINEL, now: ~datetime.datetime = datetime.now(), color: int = %s, *, ' 'SENTINEL, now: ~datetime.datetime = datetime.now(), color: int = %s, *, '
'kwarg1, kwarg2=%s) -> None' % (color, color), 'kwarg1, kwarg2=%s) -> None' % (color, color),