Skip to content

Commit c15ba30

Browse files
bpo-39679: Add tests for classmethod/staticmethod singledispatchmethods (GH-29034) (GH-29072)
In Python 3.8 and 3.9, stacking `@functools.singledispatchmethod` on top of `@classmethod` or `@staticmethod` caused an exception to be raised if the method was registered using type-annotations rather than `@method.register(int)`. This was not caught by unit tests, however, as the tests only tested the `@method.register(int)` way of registering additional implementations. The bug is no longer present in Python 3.10+, but `test_functools.py` is still lacking regression tests for these cases. This commit adds these test cases. (cherry picked from commit ad6d162) Co-authored-by: Alex Waygood <[email protected]>
1 parent 5c9cab5 commit c15ba30

File tree

2 files changed

+44
-0
lines changed

2 files changed

+44
-0
lines changed

Lib/test/test_functools.py

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2437,6 +2437,48 @@ def _(self, arg: str):
24372437
self.assertEqual(a.t(''), "str")
24382438
self.assertEqual(a.t(0.0), "base")
24392439

2440+
def test_staticmethod_type_ann_register(self):
2441+
class A:
2442+
@functools.singledispatchmethod
2443+
@staticmethod
2444+
def t(arg):
2445+
return arg
2446+
@t.register
2447+
@staticmethod
2448+
def _(arg: int):
2449+
return isinstance(arg, int)
2450+
@t.register
2451+
@staticmethod
2452+
def _(arg: str):
2453+
return isinstance(arg, str)
2454+
a = A()
2455+
2456+
self.assertTrue(A.t(0))
2457+
self.assertTrue(A.t(''))
2458+
self.assertEqual(A.t(0.0), 0.0)
2459+
2460+
def test_classmethod_type_ann_register(self):
2461+
class A:
2462+
def __init__(self, arg):
2463+
self.arg = arg
2464+
2465+
@functools.singledispatchmethod
2466+
@classmethod
2467+
def t(cls, arg):
2468+
return cls("base")
2469+
@t.register
2470+
@classmethod
2471+
def _(cls, arg: int):
2472+
return cls("int")
2473+
@t.register
2474+
@classmethod
2475+
def _(cls, arg: str):
2476+
return cls("str")
2477+
2478+
self.assertEqual(A.t(0).arg, "int")
2479+
self.assertEqual(A.t('').arg, "str")
2480+
self.assertEqual(A.t(0.0).arg, "base")
2481+
24402482
def test_invalid_registrations(self):
24412483
msg_prefix = "Invalid first argument to `register()`: "
24422484
msg_suffix = (
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Add more test cases for `@functools.singledispatchmethod` when combined with
2+
`@classmethod` or `@staticmethod`.

0 commit comments

Comments
 (0)