Commits

Georg Brandl committed a3c61c6

Patch #1507676: improve exception messages in abstract.c, object.c and typeobject.c.

Comments (0)

Files changed (4)

Lib/test/test_genexps.py

     Traceback (most recent call last):
       File "<pyshell#4>", line 1, in -toplevel-
         (i for i in 6)
-    TypeError: iteration over non-sequence
+    TypeError: 'int' object is not iterable
 
 Verify late binding for the outermost if-expression
 

Objects/abstract.c

 /* Shorthands to return certain errors */
 
 static PyObject *
-type_error(const char *msg)
+type_error(const char *msg, PyObject *obj)
 {
-	PyErr_SetString(PyExc_TypeError, msg);
+	PyErr_Format(PyExc_TypeError, msg, obj->ob_type->tp_name);
 	return NULL;
 }
 
 			return PySequence_GetItem(o, key_value);
 		}
 		else if (o->ob_type->tp_as_sequence->sq_item)
-			return type_error("sequence index must be integer");
+			return type_error("sequence index must "
+					  "be integer, not '%.200s'", key);
 	}
 
-	return type_error("unsubscriptable object");
+	return type_error("'%.200s' object is unsubscriptable", o);
 }
 
 int
 			return PySequence_SetItem(o, key_value, value);
 		}
 		else if (o->ob_type->tp_as_sequence->sq_ass_item) {
-			type_error("sequence index must be integer");
+			type_error("sequence index must be "
+				   "integer, not '%.200s'", key);
 			return -1;
 		}
 	}
 
-	type_error("object does not support item assignment");
+	type_error("'%.200s' object does not support item assignment", o);
 	return -1;
 }
 
 			return PySequence_DelItem(o, key_value);
 		}
 		else if (o->ob_type->tp_as_sequence->sq_ass_item) {
-			type_error("sequence index must be integer");
+			type_error("sequence index must be "
+				   "integer, not '%.200s'", key);
 			return -1;
 		}
 	}
 
-	type_error("object does not support item deletion");
+	type_error("'%.200s' object does not support item deletion", o);
 	return -1;
 }
 
 binop_type_error(PyObject *v, PyObject *w, const char *op_name)
 {
 	PyErr_Format(PyExc_TypeError,
-		     "unsupported operand type(s) for %s: '%s' and '%s'",
+		     "unsupported operand type(s) for %.100s: "
+		     "'%.100s' and '%.100s'",
 		     op_name,
 		     v->ob_type->tp_name,
 		     w->ob_type->tp_name);
 		PyErr_Format(
 			PyExc_TypeError,
 			"unsupported operand type(s) for ** or pow(): "
-			"'%s' and '%s'",
+			"'%.100s' and '%.100s'",
 			v->ob_type->tp_name,
 			w->ob_type->tp_name);
 	else
 		PyErr_Format(
 			PyExc_TypeError,
 			"unsupported operand type(s) for pow(): "
-			"'%s', '%s', '%s'",
+			"'%.100s', '%.100s', '%.100s'",
 			v->ob_type->tp_name,
 			w->ob_type->tp_name,
 			z->ob_type->tp_name);
 			return NULL;
 	}
 	else {
-		return type_error(
-			"can't multiply sequence by non-int");
+		return type_error("can't multiply sequence by "
+				  "non-int of type '%.200s'", n);
 	}
 	return (*repeatfunc)(seq, count);
 }
 	if (m && m->nb_negative)
 		return (*m->nb_negative)(o);
 
-	return type_error("bad operand type for unary -");
+	return type_error("bad operand type for unary -: '%.200s'", o);
 }
 
 PyObject *
 	if (m && m->nb_positive)
 		return (*m->nb_positive)(o);
 
-	return type_error("bad operand type for unary +");
+	return type_error("bad operand type for unary +: '%.200s'", o);
 }
 
 PyObject *
 	if (m && m->nb_invert)
 		return (*m->nb_invert)(o);
 
-	return type_error("bad operand type for unary ~");
+	return type_error("bad operand type for unary ~: '%.200s'", o);
 }
 
 PyObject *
 	if (m && m->nb_absolute)
 		return m->nb_absolute(o);
 
-	return type_error("bad operand type for abs()");
+	return type_error("bad operand type for abs(): '%.200s'", o);
 }
 
 /* Add a check for embedded NULL-bytes in the argument. */
 	if (!PyObject_AsCharBuffer(o, &buffer, &buffer_len))
 		return int_from_string((char*)buffer, buffer_len);
 
-	return type_error("int() argument must be a string or a number");
+	return type_error("int() argument must be a string or a "
+			  "number, not '%.200s'", o);
 }
 
 /* Add a check for embedded NULL-bytes in the argument. */
 	if (!PyObject_AsCharBuffer(o, &buffer, &buffer_len))
 		return long_from_string(buffer, buffer_len);
 
-	return type_error("long() argument must be a string or a number");
+	return type_error("long() argument must be a string or a "
+			  "number, not '%.200s'", o);
 }
 
 PyObject *
 	if (m && m->sq_length)
 		return m->sq_length(s);
 
-	type_error("len() of unsized object");
+	type_error("non-sequence object of type '%.200s' has no len()", s);
 	return -1;
 }
 
 			return result;
 		Py_DECREF(result);
 	}
-	return type_error("object can't be concatenated");
+	return type_error("'%.200s' object can't be concatenated", s);
 }
 
 PyObject *
 			return result;
 		Py_DECREF(result);
 	}
-	return type_error("object can't be repeated");
+	return type_error("'%.200s' object can't be repeated", o);
 }
 
 PyObject *
 			return result;
 		Py_DECREF(result);
 	}
-	return type_error("object can't be concatenated");
+	return type_error("'%.200s' object can't be concatenated", s);
 }
 
 PyObject *
 			return result;
 		Py_DECREF(result);
 	}
-	return type_error("object can't be repeated");
+	return type_error("'%.200s' object can't be repeated", o);
 }
 
 PyObject *
 		return m->sq_item(s, i);
 	}
 
-	return type_error("unindexable object");
+	return type_error("'%.200s' object is unindexable", s);
 }
 
 PyObject *
 		return res;
 	}
 
-	return type_error("unsliceable object");
+	return type_error("'%.200s' object is unsliceable", s);
 }
 
 int
 		return m->sq_ass_item(s, i, o);
 	}
 
-	type_error("object does not support item assignment");
+	type_error("'%.200s' object does not support item assignment", s);
 	return -1;
 }
 
 		return m->sq_ass_item(s, i, (PyObject *)NULL);
 	}
 
-	type_error("object doesn't support item deletion");
+	type_error("'%.200s' object doesn't support item deletion", s);
 	return -1;
 }
 
 		return res;
 	}
 
-	type_error("object doesn't support slice assignment");
+	type_error("'%.200s' object doesn't support slice assignment", s);
 	return -1;
 }
 
 		}
 		return m->sq_ass_slice(s, i1, i2, (PyObject *)NULL);
 	}
-	type_error("object doesn't support slice deletion");
+	type_error("'%.200s' object doesn't support slice deletion", s);
 	return -1;
 }
 
  	it = PyObject_GetIter(v);
 	if (it == NULL) {
 		if (PyErr_ExceptionMatches(PyExc_TypeError))
-			return type_error(m);
+			PyErr_SetString(PyExc_TypeError, m);
 		return NULL;
 	}
 
 
 	it = PyObject_GetIter(seq);
 	if (it == NULL) {
-		type_error("iterable argument required");
+		type_error("argument of type '%.200s' is not iterable", seq);
 		return -1;
 	}
 
 	if (m && m->mp_length)
 		return m->mp_length(o);
 
-	type_error("len() of unsized object");
+	type_error("non-mapping object of type '%.200s' has no len()", o);
 	return -1;
 }
 
 				"NULL result without error in PyObject_Call");
 		return result;
 	}
-	PyErr_Format(PyExc_TypeError, "'%s' object is not callable",
+	PyErr_Format(PyExc_TypeError, "'%.200s' object is not callable",
 		     func->ob_type->tp_name);
 	return NULL;
 }
 	}
 
 	if (!PyCallable_Check(func)) {
-		type_error("call of non-callable attribute"); 
+		type_error("attribute of type '%.200s' is not callable", func); 
 		goto exit;
 	}
 
 	}
 
 	if (!PyCallable_Check(func)) {
-		type_error("call of non-callable attribute"); 
+		type_error("attribute of type '%.200s' is not callable", func); 
 		goto exit;
 	}
 
 	if (f == NULL) {
 		if (PySequence_Check(o))
 			return PySeqIter_New(o);
-		PyErr_SetString(PyExc_TypeError,
-				"iteration over non-sequence");
-		return NULL;
+		return type_error("'%.200s' object is not iterable", o);
 	}
 	else {
 		PyObject *res = (*f)(o);
 		return _Py_HashPointer(v); /* Use address as hash value */
 	}
 	/* If there's a cmp but no hash defined, the object can't be hashed */
-	PyErr_SetString(PyExc_TypeError, "unhashable type");
+	PyErr_Format(PyExc_TypeError, "unhashable type: '%.200s'",
+		     v->ob_type->tp_name);
 	return -1;
 }
 
 		else
 #endif
 		{
-			PyErr_SetString(PyExc_TypeError,
-					"attribute name must be string");
+			PyErr_Format(PyExc_TypeError,
+				     "attribute name must be string, not '%.200s'",
+				     name->ob_type->tp_name);
 			return NULL;
 		}
 	}
 		else
 #endif
 		{
-			PyErr_SetString(PyExc_TypeError,
-					"attribute name must be string");
+			PyErr_Format(PyExc_TypeError,
+				     "attribute name must be string, not '%.200s'",
+				     name->ob_type->tp_name);
 			return -1;
 		}
 	}
 		else
 #endif
 		{
-			PyErr_SetString(PyExc_TypeError,
-					"attribute name must be string");
+			PyErr_Format(PyExc_TypeError,
+				     "attribute name must be string, not '%.200s'",
+				     name->ob_type->tp_name);
 			return NULL;
 		}
 	}
 		else
 #endif
 		{
-			PyErr_SetString(PyExc_TypeError,
-					"attribute name must be string");
+			PyErr_Format(PyExc_TypeError,
+				     "attribute name must be string, not '%.200s'",
+				     name->ob_type->tp_name);
 			return -1;
 		}
 	}
 
 	if (descr == NULL) {
 		PyErr_Format(PyExc_AttributeError,
-			     "'%.50s' object has no attribute '%.400s'",
+			     "'%.100s' object has no attribute '%.200s'",
 			     tp->tp_name, PyString_AS_STRING(name));
 		goto done;
 	}
 
 	assert(result);
 	if (!PyList_Check(result)) {
-		PyErr_SetString(PyExc_TypeError,
-			"Expected keys() to be a list.");
+		PyErr_Format(PyExc_TypeError,
+			"Expected keys() to be a list, not '%.200s'",
+			result->ob_type->tp_name);
 		goto error;
 	}
 	if (PyList_Sort(result) != 0)

Objects/typeobject.c

 		return -1;
 	}
 	if (value != NULL && !PyDict_Check(value)) {
-		PyErr_SetString(PyExc_TypeError,
-				"__dict__ must be set to a dictionary");
+		PyErr_Format(PyExc_TypeError,
+			     "__dict__ must be set to a dictionary, "
+			     "not a '%.200s'", value->ob_type->tp_name);
 		return -1;
 	}
 	dict = *dictptr;
 	Py_ssize_t i, n;
 
 	if (!PyString_Check(s)) {
-		PyErr_SetString(PyExc_TypeError,
-				"__slots__ must be strings");
+		PyErr_Format(PyExc_TypeError,
+			     "__slots__ items must be strings, not '%.200s'",
+			     s->ob_type->tp_name);
 		return 0;
 	}
 	p = (unsigned char *) PyString_AS_STRING(s);
 		args = PyObject_CallObject(getnewargs, NULL);
 		Py_DECREF(getnewargs);
 		if (args != NULL && !PyTuple_Check(args)) {
-			PyErr_SetString(PyExc_TypeError,
-				"__getnewargs__ should return a tuple");
+			PyErr_Format(PyExc_TypeError,
+				"__getnewargs__ should return a tuple, "
+				"not '%.200s'", args->ob_type->tp_name);
 			goto end;
 		}
 	}
 		result = temp->ob_type->tp_as_number->nb_index(temp);
 	}
 	else {
-		PyErr_SetString(PyExc_TypeError, 
-				"__index__ must return an int or a long");
+		PyErr_Format(PyExc_TypeError, 
+			     "__index__ must return an int or a long, "
+			     "not '%.200s'", temp->ob_type->tp_name);
 		result = -1;
 	}
 	Py_DECREF(temp);
 			func = lookup_method(self, "__cmp__", &cmp_str);
 		}
 		if (func != NULL) {
+			PyErr_Format(PyExc_TypeError, "unhashable type: '%.200s'",
+				     self->ob_type->tp_name);
 			Py_DECREF(func);
-			PyErr_SetString(PyExc_TypeError, "unhashable type");
 			return -1;
 		}
 		PyErr_Clear();
 	PyErr_Clear();
 	func = lookup_method(self, "__getitem__", &getitem_str);
 	if (func == NULL) {
-		PyErr_SetString(PyExc_TypeError,
-				"iteration over non-sequence");
+		PyErr_Format(PyExc_TypeError,
+			     "'%.200s' object is not iterable",
+			     self->ob_type->tp_name);
 		return NULL;
 	}
 	Py_DECREF(func);
 	if (res == NULL)
 		return -1;
 	if (res != Py_None) {
-		PyErr_SetString(PyExc_TypeError,
-			   "__init__() should return None");
+		PyErr_Format(PyExc_TypeError,
+			     "__init__() should return None, not '%.200s'",
+			     res->ob_type->tp_name);
 		Py_DECREF(res);
 		return -1;
 	}
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.