mirror of
https://github.com/python/cpython.git
synced 2025-08-04 08:59:19 +00:00
bpo-45678: Add more `singledispatchmethod
` tests (GH-29412)
In order to fix a bug in the 3.9 branch in #29394, more tests were added to ``test_functools.py`` to ensure that ``singledispatchmethod`` still correctly wrapped a target method, even if the target method had already been wrapped by multiple other decorators. This PR brings the new tests into the 3.11 and 3.10 branches as well.
This commit is contained in:
parent
3509b26c91
commit
32f55d1a5d
2 changed files with 102 additions and 0 deletions
|
@ -2519,6 +2519,105 @@ class TestSingleDispatch(unittest.TestCase):
|
|||
self.assertEqual(A.static_func.__name__, 'static_func')
|
||||
self.assertEqual(A().static_func.__name__, 'static_func')
|
||||
|
||||
def test_double_wrapped_methods(self):
|
||||
def classmethod_friendly_decorator(func):
|
||||
wrapped = func.__func__
|
||||
@classmethod
|
||||
@functools.wraps(wrapped)
|
||||
def wrapper(*args, **kwargs):
|
||||
return wrapped(*args, **kwargs)
|
||||
return wrapper
|
||||
|
||||
class WithoutSingleDispatch:
|
||||
@classmethod
|
||||
@contextlib.contextmanager
|
||||
def cls_context_manager(cls, arg: int) -> str:
|
||||
try:
|
||||
yield str(arg)
|
||||
finally:
|
||||
return 'Done'
|
||||
|
||||
@classmethod_friendly_decorator
|
||||
@classmethod
|
||||
def decorated_classmethod(cls, arg: int) -> str:
|
||||
return str(arg)
|
||||
|
||||
class WithSingleDispatch:
|
||||
@functools.singledispatchmethod
|
||||
@classmethod
|
||||
@contextlib.contextmanager
|
||||
def cls_context_manager(cls, arg: int) -> str:
|
||||
"""My function docstring"""
|
||||
try:
|
||||
yield str(arg)
|
||||
finally:
|
||||
return 'Done'
|
||||
|
||||
@functools.singledispatchmethod
|
||||
@classmethod_friendly_decorator
|
||||
@classmethod
|
||||
def decorated_classmethod(cls, arg: int) -> str:
|
||||
"""My function docstring"""
|
||||
return str(arg)
|
||||
|
||||
# These are sanity checks
|
||||
# to test the test itself is working as expected
|
||||
with WithoutSingleDispatch.cls_context_manager(5) as foo:
|
||||
without_single_dispatch_foo = foo
|
||||
|
||||
with WithSingleDispatch.cls_context_manager(5) as foo:
|
||||
single_dispatch_foo = foo
|
||||
|
||||
self.assertEqual(without_single_dispatch_foo, single_dispatch_foo)
|
||||
self.assertEqual(single_dispatch_foo, '5')
|
||||
|
||||
self.assertEqual(
|
||||
WithoutSingleDispatch.decorated_classmethod(5),
|
||||
WithSingleDispatch.decorated_classmethod(5)
|
||||
)
|
||||
|
||||
self.assertEqual(WithSingleDispatch.decorated_classmethod(5), '5')
|
||||
|
||||
# Behavioural checks now follow
|
||||
for method_name in ('cls_context_manager', 'decorated_classmethod'):
|
||||
with self.subTest(method=method_name):
|
||||
self.assertEqual(
|
||||
getattr(WithSingleDispatch, method_name).__name__,
|
||||
getattr(WithoutSingleDispatch, method_name).__name__
|
||||
)
|
||||
|
||||
self.assertEqual(
|
||||
getattr(WithSingleDispatch(), method_name).__name__,
|
||||
getattr(WithoutSingleDispatch(), method_name).__name__
|
||||
)
|
||||
|
||||
for meth in (
|
||||
WithSingleDispatch.cls_context_manager,
|
||||
WithSingleDispatch().cls_context_manager,
|
||||
WithSingleDispatch.decorated_classmethod,
|
||||
WithSingleDispatch().decorated_classmethod
|
||||
):
|
||||
with self.subTest(meth=meth):
|
||||
self.assertEqual(meth.__doc__, 'My function docstring')
|
||||
self.assertEqual(meth.__annotations__['arg'], int)
|
||||
|
||||
self.assertEqual(
|
||||
WithSingleDispatch.cls_context_manager.__name__,
|
||||
'cls_context_manager'
|
||||
)
|
||||
self.assertEqual(
|
||||
WithSingleDispatch().cls_context_manager.__name__,
|
||||
'cls_context_manager'
|
||||
)
|
||||
self.assertEqual(
|
||||
WithSingleDispatch.decorated_classmethod.__name__,
|
||||
'decorated_classmethod'
|
||||
)
|
||||
self.assertEqual(
|
||||
WithSingleDispatch().decorated_classmethod.__name__,
|
||||
'decorated_classmethod'
|
||||
)
|
||||
|
||||
def test_invalid_registrations(self):
|
||||
msg_prefix = "Invalid first argument to `register()`: "
|
||||
msg_suffix = (
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue