diff --git a/Lib/test/output/test_exceptions b/Lib/test/output/test_exceptions index e1e146ab361..28a7aa8390f 100644 --- a/Lib/test/output/test_exceptions +++ b/Lib/test/output/test_exceptions @@ -10,7 +10,7 @@ spam ImportError spam IndexError -spam +'spam' KeyError spam KeyboardInterrupt diff --git a/Python/exceptions.c b/Python/exceptions.c index 24ea25ddee0..3f07089641b 100644 --- a/Python/exceptions.c +++ b/Python/exceptions.c @@ -785,7 +785,7 @@ SyntaxError__str__(PyObject *self, PyObject *args) /* XXX -- do all the additional formatting with filename and lineno here */ - if (PyString_Check(str)) { + if (str != NULL && PyString_Check(str)) { int have_filename = 0; int have_lineno = 0; char *buffer = NULL; @@ -844,6 +844,44 @@ static PyMethodDef SyntaxError_methods[] = { }; +static PyObject * +KeyError__str__(PyObject *self, PyObject *args) +{ + PyObject *argsattr; + PyObject *result; + + if (!PyArg_ParseTuple(args, "O:__str__", &self)) + return NULL; + + if (!(argsattr = PyObject_GetAttrString(self, "args"))) + return NULL; + + /* If args is a tuple of exactly one item, apply repr to args[0]. + This is done so that e.g. the exception raised by {}[''] prints + KeyError: '' + rather than the confusing + KeyError + alone. The downside is that if KeyError is raised with an explanatory + string, that string will be displayed in quotes. Too bad. + If args is anything else, use the default Exception__str__(). + */ + if (PyTuple_Check(argsattr) && PyTuple_GET_SIZE(argsattr) == 1) { + PyObject *key = PyTuple_GET_ITEM(argsattr, 0); + result = PyObject_Repr(key); + } + else + result = Exception__str__(self, args); + + Py_DECREF(argsattr); + return result; +} + +static PyMethodDef KeyError_methods[] = { + {"__str__", KeyError__str__, METH_VARARGS}, + {NULL, NULL} +}; + + static int get_int(PyObject *exc, const char *name, int *value) { @@ -1617,7 +1655,7 @@ static struct { {"IndexError", &PyExc_IndexError, &PyExc_LookupError, IndexError__doc__}, {"KeyError", &PyExc_KeyError, &PyExc_LookupError, - KeyError__doc__}, + KeyError__doc__, KeyError_methods}, {"ArithmeticError", &PyExc_ArithmeticError, 0, ArithmeticError__doc__}, {"OverflowError", &PyExc_OverflowError, &PyExc_ArithmeticError, OverflowError__doc__},