From: Tapeline Date: Fri, 24 Oct 2025 19:12:49 +0000 (+0500) Subject: gh-136327: Fix inconsistent ``TypeError`` messages regarding invalid values after... X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=4f8e7b5ac59f578d8b328d1238b5e1fee00601bc;p=thirdparty%2FPython%2Fcpython.git gh-136327: Fix inconsistent ``TypeError`` messages regarding invalid values after * and ** (#136395) --- diff --git a/Lib/test/pickletester.py b/Lib/test/pickletester.py index 1a7658b13fa5..e3663e44546d 100644 --- a/Lib/test/pickletester.py +++ b/Lib/test/pickletester.py @@ -1882,7 +1882,7 @@ class AbstractPicklingErrorTests: with self.assertRaises(TypeError) as cm: self.dumps(obj, proto) self.assertEqual(str(cm.exception), - 'functools.partial() argument after ** must be a mapping, not list') + 'Value after ** must be a mapping, not list') self.assertEqual(cm.exception.__notes__, [ 'when serializing test.pickletester.REX object']) else: diff --git a/Lib/test/test_extcall.py b/Lib/test/test_extcall.py index d9d85fe79af8..f003a5837ae0 100644 --- a/Lib/test/test_extcall.py +++ b/Lib/test/test_extcall.py @@ -137,7 +137,7 @@ Verify clearing of SF bug #733667 >>> g(*Nothing()) Traceback (most recent call last): ... - TypeError: test.test_extcall.g() argument after * must be an iterable, not Nothing + TypeError: Value after * must be an iterable, not Nothing >>> class Nothing: ... def __len__(self): return 5 @@ -146,7 +146,7 @@ Verify clearing of SF bug #733667 >>> g(*Nothing()) Traceback (most recent call last): ... - TypeError: test.test_extcall.g() argument after * must be an iterable, not Nothing + TypeError: Value after * must be an iterable, not Nothing >>> class Nothing(): ... def __len__(self): return 5 @@ -266,7 +266,7 @@ What about willful misconduct? >>> h(*h) Traceback (most recent call last): ... - TypeError: test.test_extcall.h() argument after * must be an iterable, not function + TypeError: Value after * must be an iterable, not function >>> h(1, *h) Traceback (most recent call last): @@ -281,55 +281,53 @@ What about willful misconduct? >>> dir(*h) Traceback (most recent call last): ... - TypeError: dir() argument after * must be an iterable, not function + TypeError: Value after * must be an iterable, not function >>> nothing = None >>> nothing(*h) Traceback (most recent call last): ... - TypeError: None argument after * must be an iterable, \ -not function + TypeError: Value after * must be an iterable, not function >>> h(**h) Traceback (most recent call last): ... - TypeError: test.test_extcall.h() argument after ** must be a mapping, not function + TypeError: Value after ** must be a mapping, not function >>> h(**[]) Traceback (most recent call last): ... - TypeError: test.test_extcall.h() argument after ** must be a mapping, not list + TypeError: Value after ** must be a mapping, not list >>> h(a=1, **h) Traceback (most recent call last): ... - TypeError: test.test_extcall.h() argument after ** must be a mapping, not function + TypeError: Value after ** must be a mapping, not function >>> h(a=1, **[]) Traceback (most recent call last): ... - TypeError: test.test_extcall.h() argument after ** must be a mapping, not list + TypeError: Value after ** must be a mapping, not list >>> h(**{'a': 1}, **h) Traceback (most recent call last): ... - TypeError: test.test_extcall.h() argument after ** must be a mapping, not function + TypeError: Value after ** must be a mapping, not function >>> h(**{'a': 1}, **[]) Traceback (most recent call last): ... - TypeError: test.test_extcall.h() argument after ** must be a mapping, not list + TypeError: Value after ** must be a mapping, not list >>> dir(**h) Traceback (most recent call last): ... - TypeError: dir() argument after ** must be a mapping, not function + TypeError: Value after ** must be a mapping, not function >>> nothing(**h) Traceback (most recent call last): ... - TypeError: None argument after ** must be a mapping, \ -not function + TypeError: Value after ** must be a mapping, not function >>> dir(b=1, **{'b': 1}) Traceback (most recent call last): diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2025-07-08-00-41-46.gh-issue-136327.7AiTb_.rst b/Misc/NEWS.d/next/Core_and_Builtins/2025-07-08-00-41-46.gh-issue-136327.7AiTb_.rst new file mode 100644 index 000000000000..3798e956c95a --- /dev/null +++ b/Misc/NEWS.d/next/Core_and_Builtins/2025-07-08-00-41-46.gh-issue-136327.7AiTb_.rst @@ -0,0 +1,2 @@ +Errors when calling functions with invalid values after ``*`` and ``**`` now do not +include the function name. Patch by Ilia Solin. diff --git a/Python/ceval.c b/Python/ceval.c index defd084db9a4..7ec5abf5a76b 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -3272,17 +3272,9 @@ int _Py_Check_ArgsIterable(PyThreadState *tstate, PyObject *func, PyObject *args) { if (Py_TYPE(args)->tp_iter == NULL && !PySequence_Check(args)) { - /* _Py_Check_ArgsIterable() may be called with a live exception: - * clear it to prevent calling _PyObject_FunctionStr() with an - * exception set. */ - _PyErr_Clear(tstate); - PyObject *funcstr = _PyObject_FunctionStr(func); - if (funcstr != NULL) { - _PyErr_Format(tstate, PyExc_TypeError, - "%U argument after * must be an iterable, not %.200s", - funcstr, Py_TYPE(args)->tp_name); - Py_DECREF(funcstr); - } + _PyErr_Format(tstate, PyExc_TypeError, + "Value after * must be an iterable, not %.200s", + Py_TYPE(args)->tp_name); return -1; } return 0; @@ -3298,15 +3290,10 @@ _PyEval_FormatKwargsError(PyThreadState *tstate, PyObject *func, PyObject *kwarg * is not a mapping. */ if (_PyErr_ExceptionMatches(tstate, PyExc_AttributeError)) { - _PyErr_Clear(tstate); - PyObject *funcstr = _PyObject_FunctionStr(func); - if (funcstr != NULL) { - _PyErr_Format( - tstate, PyExc_TypeError, - "%U argument after ** must be a mapping, not %.200s", - funcstr, Py_TYPE(kwargs)->tp_name); - Py_DECREF(funcstr); - } + _PyErr_Format( + tstate, PyExc_TypeError, + "Value after ** must be a mapping, not %.200s", + Py_TYPE(kwargs)->tp_name); } else if (_PyErr_ExceptionMatches(tstate, PyExc_KeyError)) { PyObject *exc = _PyErr_GetRaisedException(tstate);