mirror of
https://github.com/python/cpython.git
synced 2025-11-03 03:22:27 +00:00
Fix exception handling for non-PyFunction objects, SF bug 414743.
Fix based on patch #414750 by Michael Hudson. New functions get_func_name() and get_func_desc() return reasonable names and descriptions for all objects. XXX Even objects that aren't actually callable.
This commit is contained in:
parent
7667680d70
commit
512a237725
1 changed files with 54 additions and 16 deletions
|
|
@ -40,6 +40,8 @@ static PyObject *eval_code2(PyCodeObject *,
|
||||||
PyObject **, int,
|
PyObject **, int,
|
||||||
PyObject *);
|
PyObject *);
|
||||||
|
|
||||||
|
static char *get_func_name(PyObject *);
|
||||||
|
static char *get_func_desc(PyObject *);
|
||||||
static PyObject *call_object(PyObject *, PyObject *, PyObject *);
|
static PyObject *call_object(PyObject *, PyObject *, PyObject *);
|
||||||
static PyObject *call_cfunction(PyObject *, PyObject *, PyObject *);
|
static PyObject *call_cfunction(PyObject *, PyObject *, PyObject *);
|
||||||
static PyObject *call_instance(PyObject *, PyObject *, PyObject *);
|
static PyObject *call_instance(PyObject *, PyObject *, PyObject *);
|
||||||
|
|
@ -2741,6 +2743,43 @@ PyEval_CallObjectWithKeywords(PyObject *func, PyObject *arg, PyObject *kw)
|
||||||
most common, but not by such a large margin.
|
most common, but not by such a large margin.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
static char *
|
||||||
|
get_func_name(PyObject *func)
|
||||||
|
{
|
||||||
|
if (PyMethod_Check(func))
|
||||||
|
return get_func_name(PyMethod_GET_FUNCTION(func));
|
||||||
|
else if (PyFunction_Check(func))
|
||||||
|
return PyString_AsString(((PyFunctionObject*)func)->func_name);
|
||||||
|
else if (PyCFunction_Check(func))
|
||||||
|
return ((PyCFunctionObject*)func)->m_ml->ml_name;
|
||||||
|
else if (PyClass_Check(func))
|
||||||
|
return PyString_AsString(((PyClassObject*)func)->cl_name);
|
||||||
|
else if (PyInstance_Check(func)) {
|
||||||
|
return PyString_AsString(
|
||||||
|
((PyInstanceObject*)func)->in_class->cl_name);
|
||||||
|
} else {
|
||||||
|
return func->ob_type->tp_name;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static char *
|
||||||
|
get_func_desc(PyObject *func)
|
||||||
|
{
|
||||||
|
if (PyMethod_Check(func))
|
||||||
|
return "()";
|
||||||
|
else if (PyFunction_Check(func))
|
||||||
|
return "()";
|
||||||
|
else if (PyCFunction_Check(func))
|
||||||
|
return "()";
|
||||||
|
else if (PyClass_Check(func))
|
||||||
|
return " constructor";
|
||||||
|
else if (PyInstance_Check(func)) {
|
||||||
|
return " instance";
|
||||||
|
} else {
|
||||||
|
return " object";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static PyObject *
|
static PyObject *
|
||||||
call_object(PyObject *func, PyObject *arg, PyObject *kw)
|
call_object(PyObject *func, PyObject *arg, PyObject *kw)
|
||||||
{
|
{
|
||||||
|
|
@ -2992,12 +3031,12 @@ update_keyword_args(PyObject *orig_kwdict, int nk, PyObject ***pp_stack,
|
||||||
PyObject *value = EXT_POP(*pp_stack);
|
PyObject *value = EXT_POP(*pp_stack);
|
||||||
PyObject *key = EXT_POP(*pp_stack);
|
PyObject *key = EXT_POP(*pp_stack);
|
||||||
if (PyDict_GetItem(kwdict, key) != NULL) {
|
if (PyDict_GetItem(kwdict, key) != NULL) {
|
||||||
PyObject* fn = ((PyFunctionObject*) func)->func_name;
|
|
||||||
PyErr_Format(PyExc_TypeError,
|
PyErr_Format(PyExc_TypeError,
|
||||||
"%.200s%s got multiple values "
|
"%.200s%s got multiple values "
|
||||||
"for keyword argument '%.400s'",
|
"for keyword argument '%.200s'",
|
||||||
fn ? PyString_AsString(fn) : "function",
|
get_func_name(func),
|
||||||
fn ? "()" : "", PyString_AsString(key));
|
get_func_desc(func),
|
||||||
|
PyString_AsString(key));
|
||||||
Py_DECREF(key);
|
Py_DECREF(key);
|
||||||
Py_DECREF(value);
|
Py_DECREF(value);
|
||||||
Py_DECREF(kwdict);
|
Py_DECREF(kwdict);
|
||||||
|
|
@ -3088,11 +3127,11 @@ ext_do_call(PyObject *func, PyObject ***pp_stack, int flags, int na, int nk)
|
||||||
if (flags & CALL_FLAG_KW) {
|
if (flags & CALL_FLAG_KW) {
|
||||||
kwdict = EXT_POP(*pp_stack);
|
kwdict = EXT_POP(*pp_stack);
|
||||||
if (!(kwdict && PyDict_Check(kwdict))) {
|
if (!(kwdict && PyDict_Check(kwdict))) {
|
||||||
PyObject* fn = ((PyFunctionObject*) func)->func_name;
|
|
||||||
PyErr_Format(PyExc_TypeError,
|
PyErr_Format(PyExc_TypeError,
|
||||||
"%s%s argument after ** must be a dictionary",
|
"%s%s argument after ** "
|
||||||
fn ? PyString_AsString(fn) : "function",
|
"must be a dictionary",
|
||||||
fn ? "()" : "");
|
get_func_name(func),
|
||||||
|
get_func_desc(func));
|
||||||
goto ext_call_fail;
|
goto ext_call_fail;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -3102,14 +3141,13 @@ ext_do_call(PyObject *func, PyObject ***pp_stack, int flags, int na, int nk)
|
||||||
PyObject *t = NULL;
|
PyObject *t = NULL;
|
||||||
t = PySequence_Tuple(stararg);
|
t = PySequence_Tuple(stararg);
|
||||||
if (t == NULL) {
|
if (t == NULL) {
|
||||||
if (PyErr_ExceptionMatches(PyExc_TypeError)) {
|
if (PyErr_ExceptionMatches(PyExc_TypeError)) {
|
||||||
PyObject* fn =
|
PyErr_Format(PyExc_TypeError,
|
||||||
((PyFunctionObject*) func)->func_name;
|
"%s%s argument after * "
|
||||||
PyErr_Format(PyExc_TypeError,
|
"must be a sequence",
|
||||||
"%s%s argument after * must be a sequence",
|
get_func_name(func),
|
||||||
fn ? PyString_AsString(fn) : "function",
|
get_func_desc(func));
|
||||||
fn ? "()" : "");
|
}
|
||||||
}
|
|
||||||
goto ext_call_fail;
|
goto ext_call_fail;
|
||||||
}
|
}
|
||||||
Py_DECREF(stararg);
|
Py_DECREF(stararg);
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue