diff Python/ceval.c @ 17406:c9e07bc303a2 legacy-trunk

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.
author Jeremy Hylton <jeremy@alum.mit.edu>
date Wed, 11 Apr 2001 13:52:29 +0000
parents 2054cea38754
children 35139a9454d4
line wrap: on
line diff
--- a/Python/ceval.c	Wed Apr 11 07:44:53 2001 +0000
+++ b/Python/ceval.c	Wed Apr 11 13:52:29 2001 +0000
@@ -40,6 +40,8 @@
 			    PyObject **, int,
 			    PyObject *);
 
+static char *get_func_name(PyObject *);
+static char *get_func_desc(PyObject *);
 static PyObject *call_object(PyObject *, PyObject *, PyObject *);
 static PyObject *call_cfunction(PyObject *, PyObject *, PyObject *);
 static PyObject *call_instance(PyObject *, PyObject *, PyObject *);
@@ -2741,6 +2743,43 @@
     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 *
 call_object(PyObject *func, PyObject *arg, PyObject *kw)
 {
@@ -2992,12 +3031,12 @@
 		PyObject *value = EXT_POP(*pp_stack);
 		PyObject *key = EXT_POP(*pp_stack);
 		if (PyDict_GetItem(kwdict, key) != NULL) {
-                        PyObject* fn = ((PyFunctionObject*) func)->func_name;
                         PyErr_Format(PyExc_TypeError,
                                      "%.200s%s got multiple values "
-                                     "for keyword argument '%.400s'",
-                                     fn ? PyString_AsString(fn) : "function",
-                                     fn ? "()" : "", PyString_AsString(key));
+                                     "for keyword argument '%.200s'",
+				     get_func_name(func),
+				     get_func_desc(func),
+				     PyString_AsString(key));
 			Py_DECREF(key);
 			Py_DECREF(value);
 			Py_DECREF(kwdict);
@@ -3088,11 +3127,11 @@
 	if (flags & CALL_FLAG_KW) {
 		kwdict = EXT_POP(*pp_stack);
 		if (!(kwdict && PyDict_Check(kwdict))) {
-                        PyObject* fn = ((PyFunctionObject*) func)->func_name;
 			PyErr_Format(PyExc_TypeError,
-                            "%s%s argument after ** must be a dictionary",
-                            fn ? PyString_AsString(fn) : "function",
-                            fn ? "()" : "");
+				     "%s%s argument after ** "
+				     "must be a dictionary",
+				     get_func_name(func),
+				     get_func_desc(func));
 			goto ext_call_fail;
 		}
 	}
@@ -3102,14 +3141,13 @@
 			PyObject *t = NULL;
 			t = PySequence_Tuple(stararg);
 			if (t == NULL) {
-			    if (PyErr_ExceptionMatches(PyExc_TypeError)) {
-                                PyObject* fn =
-                                    ((PyFunctionObject*) func)->func_name;
-				PyErr_Format(PyExc_TypeError,
-                                    "%s%s argument after * must be a sequence",
-                                    fn ? PyString_AsString(fn) : "function",
-                                    fn ? "()" : "");
-			    }
+				if (PyErr_ExceptionMatches(PyExc_TypeError)) {
+					PyErr_Format(PyExc_TypeError,
+						     "%s%s argument after * "
+						     "must be a sequence",
+						     get_func_name(func),
+						     get_func_desc(func));
+				}
 				goto ext_call_fail;
 			}
 			Py_DECREF(stararg);