Merge pull request #10313 from GutiCW/feature-support_mocked_decorator_for_class_methods

Support mocked decorator for class methods
This commit is contained in:
Takeshi KOMIYA
2022-04-03 17:16:39 +09:00
committed by GitHub
3 changed files with 21 additions and 4 deletions

View File

@@ -5,11 +5,11 @@ import os
import sys
from importlib.abc import Loader, MetaPathFinder
from importlib.machinery import ModuleSpec
from types import ModuleType
from types import MethodType, ModuleType
from typing import Any, Generator, Iterator, List, Optional, Sequence, Tuple, Union
from sphinx.util import logging
from sphinx.util.inspect import safe_getattr
from sphinx.util.inspect import isboundmethod, safe_getattr
logger = logging.getLogger(__name__)
@@ -164,9 +164,15 @@ def ismock(subject: Any) -> bool:
if isinstance(subject, _MockModule):
return True
# check the object is bound method
if isinstance(subject, MethodType) and isboundmethod(subject):
tmp_subject = subject.__func__
else:
tmp_subject = subject
try:
# check the object is mocked object
__mro__ = safe_getattr(type(subject), '__mro__', [])
__mro__ = safe_getattr(type(tmp_subject), '__mro__', [])
if len(__mro__) > 2 and __mro__[-2] is _MockObject:
# A mocked object has a MRO that ends with (..., _MockObject, object).
return True

View File

@@ -12,7 +12,7 @@ from functools import partial, partialmethod
from importlib import import_module
from inspect import Parameter, isclass, ismethod, ismethoddescriptor, ismodule # NOQA
from io import StringIO
from types import ModuleType
from types import MethodType, ModuleType
from typing import Any, Callable, Dict, Mapping, Optional, Sequence, Tuple, Type, cast
from sphinx.pycode.ast import ast # for py36-37
@@ -238,6 +238,11 @@ def isabstractmethod(obj: Any) -> bool:
return safe_getattr(obj, '__isabstractmethod__', False) is True
def isboundmethod(method: MethodType) -> bool:
"""Check if the method is a bound method."""
return safe_getattr(method, '__self__', None) is not None
def is_cython_function_or_method(obj: Any) -> bool:
"""Check if the object is a function or method in cython."""
try:

View File

@@ -114,6 +114,11 @@ def test_mock_decorator():
def meth(self):
pass
@classmethod
@mock.method_deco
def class_meth(cls):
pass
@mock.class_deco
class Bar:
pass
@@ -124,6 +129,7 @@ def test_mock_decorator():
assert undecorate(func).__name__ == "func"
assert undecorate(Foo.meth).__name__ == "meth"
assert undecorate(Foo.class_meth).__name__ == "class_meth"
assert undecorate(Bar).__name__ == "Bar"
assert undecorate(Baz).__name__ == "Baz"