changeset: 104358:35676cd72352 branch: 3.5 parent: 104354:5c459b0f2b75 user: Serhiy Storchaka date: Fri Oct 07 23:32:41 2016 +0300 files: Lib/test/test_extcall.py Python/ceval.c description: Issue #28257: Improved error message when pass a non-mapping as a var-keyword argument. diff -r 5c459b0f2b75 -r 35676cd72352 Lib/test/test_extcall.py --- a/Lib/test/test_extcall.py Fri Oct 07 23:24:35 2016 +0300 +++ b/Lib/test/test_extcall.py Fri Oct 07 23:32:41 2016 +0300 @@ -269,6 +269,16 @@ ... TypeError: h() argument after ** must be a mapping, not list + >>> h(**{'a': 1}, **h) + Traceback (most recent call last): + ... + TypeError: h() argument after ** must be a mapping, not function + + >>> h(**{'a': 1}, **[]) + Traceback (most recent call last): + ... + TypeError: h() argument after ** must be a mapping, not list + >>> dir(**h) Traceback (most recent call last): ... diff -r 5c459b0f2b75 -r 35676cd72352 Python/ceval.c --- a/Python/ceval.c Fri Oct 07 23:24:35 2016 +0300 +++ b/Python/ceval.c Fri Oct 07 23:32:41 2016 +0300 @@ -2663,7 +2663,8 @@ PyObject *intersection = _PyDictView_Intersect(sum, arg); if (intersection == NULL) { - if (PyErr_ExceptionMatches(PyExc_AttributeError)) { + if (PyErr_ExceptionMatches(PyExc_AttributeError) || + !PyMapping_Check(arg)) { int function_location = (oparg>>8) & 0xff; PyObject *func = ( PEEK(function_location + num_maps)); @@ -2707,9 +2708,21 @@ if (PyDict_Update(sum, arg) < 0) { if (PyErr_ExceptionMatches(PyExc_AttributeError)) { - PyErr_Format(PyExc_TypeError, - "'%.200s' object is not a mapping", - arg->ob_type->tp_name); + if (with_call) { + int function_location = (oparg>>8) & 0xff; + PyObject *func = PEEK(function_location + num_maps); + PyErr_Format(PyExc_TypeError, + "%.200s%.200s argument after ** " + "must be a mapping, not %.200s", + PyEval_GetFuncName(func), + PyEval_GetFuncDesc(func), + arg->ob_type->tp_name); + } + else { + PyErr_Format(PyExc_TypeError, + "'%.200s' object is not a mapping", + arg->ob_type->tp_name); + } } Py_DECREF(sum); goto error;