summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlex Waygood <Alex.Waygood@Gmail.com>2021-10-19 20:30:27 (GMT)
committerGitHub <noreply@github.com>2021-10-19 20:30:27 (GMT)
commitad6d162e518963711d24c80f1b7d6079bd437584 (patch)
tree04d24b5533d5527c06707048881a8ce3d719e311
parentf4b12440cf24d7636755aac5b2645e47713557c7 (diff)
downloadcpython-ad6d162e518963711d24c80f1b7d6079bd437584.zip
cpython-ad6d162e518963711d24c80f1b7d6079bd437584.tar.gz
cpython-ad6d162e518963711d24c80f1b7d6079bd437584.tar.bz2
bpo-39679: Add tests for classmethod/staticmethod singledispatchmethods (GH-29034)
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.
-rw-r--r--Lib/test/test_functools.py42
-rw-r--r--Misc/NEWS.d/next/Tests/2021-10-18-16-18-41.bpo-39679.F18qcE.rst2
2 files changed, 44 insertions, 0 deletions
diff --git a/Lib/test/test_functools.py b/Lib/test/test_functools.py
index fece825..bdb4ddc 100644
--- a/Lib/test/test_functools.py
+++ b/Lib/test/test_functools.py
@@ -2437,6 +2437,48 @@ class TestSingleDispatch(unittest.TestCase):
self.assertEqual(a.t(''), "str")
self.assertEqual(a.t(0.0), "base")
+ def test_staticmethod_type_ann_register(self):
+ class A:
+ @functools.singledispatchmethod
+ @staticmethod
+ def t(arg):
+ return arg
+ @t.register
+ @staticmethod
+ def _(arg: int):
+ return isinstance(arg, int)
+ @t.register
+ @staticmethod
+ def _(arg: str):
+ return isinstance(arg, str)
+ a = A()
+
+ self.assertTrue(A.t(0))
+ self.assertTrue(A.t(''))
+ self.assertEqual(A.t(0.0), 0.0)
+
+ def test_classmethod_type_ann_register(self):
+ class A:
+ def __init__(self, arg):
+ self.arg = arg
+
+ @functools.singledispatchmethod
+ @classmethod
+ def t(cls, arg):
+ return cls("base")
+ @t.register
+ @classmethod
+ def _(cls, arg: int):
+ return cls("int")
+ @t.register
+ @classmethod
+ def _(cls, arg: str):
+ return cls("str")
+
+ self.assertEqual(A.t(0).arg, "int")
+ self.assertEqual(A.t('').arg, "str")
+ self.assertEqual(A.t(0.0).arg, "base")
+
def test_invalid_registrations(self):
msg_prefix = "Invalid first argument to `register()`: "
msg_suffix = (
diff --git a/Misc/NEWS.d/next/Tests/2021-10-18-16-18-41.bpo-39679.F18qcE.rst b/Misc/NEWS.d/next/Tests/2021-10-18-16-18-41.bpo-39679.F18qcE.rst
new file mode 100644
index 0000000..b0d1b68
--- /dev/null
+++ b/Misc/NEWS.d/next/Tests/2021-10-18-16-18-41.bpo-39679.F18qcE.rst
@@ -0,0 +1,2 @@
+Add more test cases for `@functools.singledispatchmethod` when combined with
+`@classmethod` or `@staticmethod`.