diff options
Diffstat (limited to 'Python/ceval.c')
-rw-r--r-- | Python/ceval.c | 39 |
1 files changed, 29 insertions, 10 deletions
diff --git a/Python/ceval.c b/Python/ceval.c index df3fa79..d777a3a 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -3779,13 +3779,31 @@ ext_do_call(PyObject *func, PyObject ***pp_stack, int flags, int na, int nk) if (flags & CALL_FLAG_KW) { kwdict = EXT_POP(*pp_stack); - if (!(kwdict && PyDict_Check(kwdict))) { - PyErr_Format(PyExc_TypeError, - "%s%s argument after ** " - "must be a dictionary", - PyEval_GetFuncName(func), - PyEval_GetFuncDesc(func)); - goto ext_call_fail; + if (!PyDict_Check(kwdict)) { + PyObject *d; + d = PyDict_New(); + if (d == NULL) + goto ext_call_fail; + if (PyDict_Update(d, kwdict) != 0) { + Py_DECREF(d); + /* PyDict_Update raises attribute + * error (percolated from an attempt + * to get 'keys' attribute) instead of + * a type error if its second argument + * is not a mapping. + */ + if (PyErr_ExceptionMatches(PyExc_AttributeError)) { + PyErr_Format(PyExc_TypeError, + "%.200s%.200s argument after ** " + "must be a mapping, not %.200s", + PyEval_GetFuncName(func), + PyEval_GetFuncDesc(func), + kwdict->ob_type->tp_name); + } + goto ext_call_fail; + } + Py_DECREF(kwdict); + kwdict = d; } } if (flags & CALL_FLAG_VAR) { @@ -3796,10 +3814,11 @@ ext_do_call(PyObject *func, PyObject ***pp_stack, int flags, int na, int nk) if (t == NULL) { if (PyErr_ExceptionMatches(PyExc_TypeError)) { PyErr_Format(PyExc_TypeError, - "%s%s argument after * " - "must be a sequence", + "%.200s%.200s argument after * " + "must be a sequence, not %200s", PyEval_GetFuncName(func), - PyEval_GetFuncDesc(func)); + PyEval_GetFuncDesc(func), + stararg->ob_type->tp_name); } goto ext_call_fail; } |