https://github.com/python/cpython/commit/8b776e0f41d7711f3e2be2435bf85f2d5fa6e009
commit: 8b776e0f41d7711f3e2be2435bf85f2d5fa6e009
branch: main
author: Ammar Askar <[email protected]>
committer: serhiy-storchaka <[email protected]>
date: 2024-02-16T23:17:30+02:00
summary:

gh-85294: Handle missing arguments to @singledispatchmethod gracefully 
(GH-21471)

Co-authored-by: Serhiy Storchaka <[email protected]>

files:
A Misc/NEWS.d/next/Library/2020-07-13-23-59-42.bpo-41122.8P_Brh.rst
M Lib/functools.py
M Lib/test/test_functools.py

diff --git a/Lib/functools.py b/Lib/functools.py
index ee4197b386178d..7045be551c8c49 100644
--- a/Lib/functools.py
+++ b/Lib/functools.py
@@ -918,7 +918,6 @@ def wrapper(*args, **kw):
         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 @@ def __get__(self, obj, cls=None):
                 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__
diff --git a/Lib/test/test_functools.py b/Lib/test/test_functools.py
index 7c66b906d308ba..2c814d5e888840 100644
--- a/Lib/test/test_functools.py
+++ b/Lib/test/test_functools.py
@@ -2867,11 +2867,26 @@ def _(arg: typing.Union[int, typing.Iterable[str]]):
 
     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
index 00000000000000..76568d407449f5
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2020-07-13-23-59-42.bpo-41122.8P_Brh.rst
@@ -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.

_______________________________________________
Python-checkins mailing list -- [email protected]
To unsubscribe send an email to [email protected]
https://mail.python.org/mailman3/lists/python-checkins.python.org/
Member address: [email protected]

Reply via email to