From: Ammar Askar Date: Fri, 16 Feb 2024 21:17:30 +0000 (-0500) Subject: gh-85294: Handle missing arguments to @singledispatchmethod gracefully (GH-21471) X-Git-Tag: v3.13.0a5~375 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=8b776e0f41d7711f3e2be2435bf85f2d5fa6e009;p=thirdparty%2FPython%2Fcpython.git gh-85294: Handle missing arguments to @singledispatchmethod gracefully (GH-21471) Co-authored-by: Serhiy Storchaka --- diff --git a/Lib/functools.py b/Lib/functools.py index ee4197b38617..7045be551c8c 100644 --- a/Lib/functools.py +++ b/Lib/functools.py @@ -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__ diff --git a/Lib/test/test_functools.py b/Lib/test/test_functools.py index 7c66b906d308..2c814d5e8888 100644 --- a/Lib/test/test_functools.py +++ b/Lib/test/test_functools.py @@ -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 index 000000000000..76568d407449 --- /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.