]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
gh-85294: Handle missing arguments to @singledispatchmethod gracefully (GH-21471)
authorAmmar Askar <ammar@ammaraskar.com>
Fri, 16 Feb 2024 21:17:30 +0000 (16:17 -0500)
committerGitHub <noreply@github.com>
Fri, 16 Feb 2024 21:17:30 +0000 (23:17 +0200)
Co-authored-by: Serhiy Storchaka <storchaka@gmail.com>
Lib/functools.py
Lib/test/test_functools.py
Misc/NEWS.d/next/Library/2020-07-13-23-59-42.bpo-41122.8P_Brh.rst [new file with mode: 0644]

index ee4197b386178d6a20be453568febe050fd3336e..7045be551c8c491e549e19c208c1a70445405db2 100644 (file)
@@ -918,7 +918,6 @@ def singledispatch(func):
         if not args:
             raise TypeError(f'{funcname} requires at least '
                             '1 positional argument')
-
         return dispatch(args[0].__class__)(*args, **kw)
 
     funcname = getattr(func, '__name__', 'singledispatch function')
@@ -968,7 +967,11 @@ class singledispatchmethod:
                 return _method
 
         dispatch = self.dispatcher.dispatch
+        funcname = getattr(self.func, '__name__', 'singledispatchmethod method')
         def _method(*args, **kwargs):
+            if not args:
+                raise TypeError(f'{funcname} requires at least '
+                                '1 positional argument')
             return dispatch(args[0].__class__).__get__(obj, cls)(*args, **kwargs)
 
         _method.__isabstractmethod__ = self.__isabstractmethod__
index 7c66b906d308baf70e5e7a82b2200391bacca1ba..2c814d5e888840384ab6809cab831e69aa1eb414 100644 (file)
@@ -2867,11 +2867,26 @@ class TestSingleDispatch(unittest.TestCase):
 
     def test_invalid_positional_argument(self):
         @functools.singledispatch
-        def f(*args):
+        def f(*args, **kwargs):
             pass
         msg = 'f requires at least 1 positional argument'
         with self.assertRaisesRegex(TypeError, msg):
             f()
+        msg = 'f requires at least 1 positional argument'
+        with self.assertRaisesRegex(TypeError, msg):
+            f(a=1)
+
+    def test_invalid_positional_argument_singledispatchmethod(self):
+        class A:
+            @functools.singledispatchmethod
+            def t(self, *args, **kwargs):
+                pass
+        msg = 't requires at least 1 positional argument'
+        with self.assertRaisesRegex(TypeError, msg):
+            A().t()
+        msg = 't requires at least 1 positional argument'
+        with self.assertRaisesRegex(TypeError, msg):
+            A().t(a=1)
 
     def test_union(self):
         @functools.singledispatch
diff --git a/Misc/NEWS.d/next/Library/2020-07-13-23-59-42.bpo-41122.8P_Brh.rst b/Misc/NEWS.d/next/Library/2020-07-13-23-59-42.bpo-41122.8P_Brh.rst
new file mode 100644 (file)
index 0000000..76568d4
--- /dev/null
@@ -0,0 +1,3 @@
+Failing to pass arguments properly to :func:`functools.singledispatchmethod`
+now throws a TypeError instead of hitting an index out of bounds
+internally.