Skip to content

Commit 8b776e0

Browse files
gh-85294: Handle missing arguments to @singledispatchmethod gracefully (GH-21471)
Co-authored-by: Serhiy Storchaka <[email protected]>
1 parent 5903190 commit 8b776e0

File tree

3 files changed

+23
-2
lines changed

3 files changed

+23
-2
lines changed

Lib/functools.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -918,7 +918,6 @@ def wrapper(*args, **kw):
918918
if not args:
919919
raise TypeError(f'{funcname} requires at least '
920920
'1 positional argument')
921-
922921
return dispatch(args[0].__class__)(*args, **kw)
923922

924923
funcname = getattr(func, '__name__', 'singledispatch function')
@@ -968,7 +967,11 @@ def __get__(self, obj, cls=None):
968967
return _method
969968

970969
dispatch = self.dispatcher.dispatch
970+
funcname = getattr(self.func, '__name__', 'singledispatchmethod method')
971971
def _method(*args, **kwargs):
972+
if not args:
973+
raise TypeError(f'{funcname} requires at least '
974+
'1 positional argument')
972975
return dispatch(args[0].__class__).__get__(obj, cls)(*args, **kwargs)
973976

974977
_method.__isabstractmethod__ = self.__isabstractmethod__

Lib/test/test_functools.py

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2867,11 +2867,26 @@ def _(arg: typing.Union[int, typing.Iterable[str]]):
28672867

28682868
def test_invalid_positional_argument(self):
28692869
@functools.singledispatch
2870-
def f(*args):
2870+
def f(*args, **kwargs):
28712871
pass
28722872
msg = 'f requires at least 1 positional argument'
28732873
with self.assertRaisesRegex(TypeError, msg):
28742874
f()
2875+
msg = 'f requires at least 1 positional argument'
2876+
with self.assertRaisesRegex(TypeError, msg):
2877+
f(a=1)
2878+
2879+
def test_invalid_positional_argument_singledispatchmethod(self):
2880+
class A:
2881+
@functools.singledispatchmethod
2882+
def t(self, *args, **kwargs):
2883+
pass
2884+
msg = 't requires at least 1 positional argument'
2885+
with self.assertRaisesRegex(TypeError, msg):
2886+
A().t()
2887+
msg = 't requires at least 1 positional argument'
2888+
with self.assertRaisesRegex(TypeError, msg):
2889+
A().t(a=1)
28752890

28762891
def test_union(self):
28772892
@functools.singledispatch
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
Failing to pass arguments properly to :func:`functools.singledispatchmethod`
2+
now throws a TypeError instead of hitting an index out of bounds
3+
internally.

0 commit comments

Comments
 (0)