Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 602d451

Browse files
committed
Add a custom __str__ method to KeyError that applies repr() to the
missing key. (Also added a guard to SyntaxError__str__ to prevent calling PyString_Check(NULL).)
1 parent 99dba27 commit 602d451

2 files changed

Lines changed: 41 additions & 3 deletions

File tree

Lib/test/output/test_exceptions

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ spam
1010
ImportError
1111
spam
1212
IndexError
13-
spam
13+
'spam'
1414
KeyError
1515
spam
1616
KeyboardInterrupt

Python/exceptions.c

Lines changed: 40 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -785,7 +785,7 @@ SyntaxError__str__(PyObject *self, PyObject *args)
785785
/* XXX -- do all the additional formatting with filename and
786786
lineno here */
787787

788-
if (PyString_Check(str)) {
788+
if (str != NULL && PyString_Check(str)) {
789789
int have_filename = 0;
790790
int have_lineno = 0;
791791
char *buffer = NULL;
@@ -844,6 +844,44 @@ static PyMethodDef SyntaxError_methods[] = {
844844
};
845845

846846

847+
static PyObject *
848+
KeyError__str__(PyObject *self, PyObject *args)
849+
{
850+
PyObject *argsattr;
851+
PyObject *result;
852+
853+
if (!PyArg_ParseTuple(args, "O:__str__", &self))
854+
return NULL;
855+
856+
if (!(argsattr = PyObject_GetAttrString(self, "args")))
857+
return NULL;
858+
859+
/* If args is a tuple of exactly one item, apply repr to args[0].
860+
This is done so that e.g. the exception raised by {}[''] prints
861+
KeyError: ''
862+
rather than the confusing
863+
KeyError
864+
alone. The downside is that if KeyError is raised with an explanatory
865+
string, that string will be displayed in quotes. Too bad.
866+
If args is anything else, use the default Exception__str__().
867+
*/
868+
if (PyTuple_Check(argsattr) && PyTuple_GET_SIZE(argsattr) == 1) {
869+
PyObject *key = PyTuple_GET_ITEM(argsattr, 0);
870+
result = PyObject_Repr(key);
871+
}
872+
else
873+
result = Exception__str__(self, args);
874+
875+
Py_DECREF(argsattr);
876+
return result;
877+
}
878+
879+
static PyMethodDef KeyError_methods[] = {
880+
{"__str__", KeyError__str__, METH_VARARGS},
881+
{NULL, NULL}
882+
};
883+
884+
847885
static
848886
int get_int(PyObject *exc, const char *name, int *value)
849887
{
@@ -1617,7 +1655,7 @@ static struct {
16171655
{"IndexError", &PyExc_IndexError, &PyExc_LookupError,
16181656
IndexError__doc__},
16191657
{"KeyError", &PyExc_KeyError, &PyExc_LookupError,
1620-
KeyError__doc__},
1658+
KeyError__doc__, KeyError_methods},
16211659
{"ArithmeticError", &PyExc_ArithmeticError, 0, ArithmeticError__doc__},
16221660
{"OverflowError", &PyExc_OverflowError, &PyExc_ArithmeticError,
16231661
OverflowError__doc__},

0 commit comments

Comments
 (0)