diff options
Diffstat (limited to 'Python/errors.c')
-rw-r--r-- | Python/errors.c | 215 |
1 files changed, 154 insertions, 61 deletions
diff --git a/Python/errors.c b/Python/errors.c index 626b16e..1832b5b 100644 --- a/Python/errors.c +++ b/Python/errors.c @@ -71,6 +71,11 @@ PyErr_SetObject(PyObject *exception, PyObject *value) if (value == NULL || !PyExceptionInstance_Check(value)) { /* We must normalize the value right now */ PyObject *args, *fixed_value; +#ifdef Py_DEBUG + /* in debug mode, PyEval_EvalFrameEx() fails with an assertion + error if an exception is set when it is called */ + PyErr_Clear(); +#endif if (value == NULL || value == Py_None) args = PyTuple_New(0); else if (PyTuple_Check(value)) { @@ -112,6 +117,20 @@ PyErr_SetObject(PyObject *exception, PyObject *value) PyErr_Restore(exception, value, tb); } +/* Set a key error with the specified argument, wrapping it in a + * tuple automatically so that tuple keys are not unpacked as the + * exception arguments. */ +void +_PyErr_SetKeyError(PyObject *arg) +{ + PyObject *tup; + tup = PyTuple_Pack(1, arg); + if (!tup) + return; /* caller will expect error to be set anyway */ + PyErr_SetObject(PyExc_KeyError, tup); + Py_DECREF(tup); +} + void PyErr_SetNone(PyObject *exception) { @@ -227,12 +246,21 @@ PyErr_NormalizeException(PyObject **exc, PyObject **val, PyObject **tb) value will be an instance. */ if (PyExceptionClass_Check(type)) { + int is_subclass; + if (inclass) { + is_subclass = PyObject_IsSubclass(inclass, type); + if (is_subclass < 0) + goto finally; + } + else + is_subclass = 0; + /* if the value was not an instance, or is not an instance whose class is (or is derived from) type, then use the value as an argument to instantiation of the type class. */ - if (!inclass || !PyObject_IsSubclass(inclass, type)) { + if (!inclass || !is_subclass) { PyObject *args, *res; if (value == Py_None) @@ -366,6 +394,12 @@ PyErr_BadArgument(void) PyObject * PyErr_NoMemory(void) { + if (Py_TYPE(PyExc_MemoryError) == NULL) { + /* PyErr_NoMemory() has been called before PyExc_MemoryError has been + initialized by _PyExc_Init() */ + Py_FatalError("Out of memory and PyExc_MemoryError is not " + "initialized yet"); + } PyErr_SetNone(PyExc_MemoryError); return NULL; } @@ -588,7 +622,7 @@ PyObject *PyErr_SetExcFromWindowsErr(PyObject *exc, int ierr) PyObject *PyErr_SetFromWindowsErr(int ierr) { - return PyErr_SetExcFromWindowsErrWithFilename(PyExc_WindowsError, + return PyErr_SetExcFromWindowsErrWithFilename(PyExc_OSError, ierr, NULL); } PyObject *PyErr_SetFromWindowsErrWithFilename( @@ -597,7 +631,7 @@ PyObject *PyErr_SetFromWindowsErrWithFilename( { PyObject *name = filename ? PyUnicode_DecodeFSDefault(filename) : NULL; PyObject *result = PyErr_SetExcFromWindowsErrWithFilenameObject( - PyExc_WindowsError, + PyExc_OSError, ierr, name); Py_XDECREF(name); return result; @@ -611,7 +645,7 @@ PyObject *PyErr_SetFromWindowsErrWithUnicodeFilename( PyUnicode_FromUnicode(filename, wcslen(filename)) : NULL; PyObject *result = PyErr_SetExcFromWindowsErrWithFilenameObject( - PyExc_WindowsError, + PyExc_OSError, ierr, name); Py_XDECREF(name); return result; @@ -646,8 +680,11 @@ PyErr_SetImportError(PyObject *msg, PyObject *name, PyObject *path) Py_INCREF(msg); PyTuple_SET_ITEM(args, 0, msg); - PyDict_SetItemString(kwargs, "name", name); - PyDict_SetItemString(kwargs, "path", path); + + if (PyDict_SetItemString(kwargs, "name", name) < 0) + return NULL; + if (PyDict_SetItemString(kwargs, "path", path) < 0) + return NULL; error = PyObject_Call(PyExc_ImportError, args, kwargs); if (error != NULL) { @@ -675,6 +712,7 @@ _PyErr_BadInternalCall(const char *filename, int lineno) void PyErr_BadInternalCall(void) { + assert(0 && "bad argument to internal function"); PyErr_Format(PyExc_SystemError, "bad argument to internal function"); } @@ -694,6 +732,12 @@ PyErr_Format(PyObject *exception, const char *format, ...) va_start(vargs); #endif +#ifdef Py_DEBUG + /* in debug mode, PyEval_EvalFrameEx() fails with an assertion error + if an exception is set when it is called */ + PyErr_Clear(); +#endif + string = PyUnicode_FromFormatV(format, vargs); PyErr_SetObject(exception, string); Py_XDECREF(string); @@ -795,60 +839,84 @@ PyErr_WriteUnraisable(PyObject *obj) { _Py_IDENTIFIER(__module__); PyObject *f, *t, *v, *tb; + PyObject *moduleName = NULL; + char* className; + PyErr_Fetch(&t, &v, &tb); + f = PySys_GetObject("stderr"); - if (f != NULL && f != Py_None) { - PyFile_WriteString("Exception ", f); - if (t) { - PyObject* moduleName; - char* className; - assert(PyExceptionClass_Check(t)); - className = PyExceptionClass_Name(t); - if (className != NULL) { - char *dot = strrchr(className, '.'); - if (dot != NULL) - className = dot+1; - } + if (f == NULL || f == Py_None) + goto done; + + if (obj) { + if (PyFile_WriteString("Exception ignored in: ", f) < 0) + goto done; + if (PyFile_WriteObject(obj, f, 0) < 0) + goto done; + if (PyFile_WriteString("\n", f) < 0) + goto done; + } - moduleName = _PyObject_GetAttrId(t, &PyId___module__); - if (moduleName == NULL) - PyFile_WriteString("<unknown>", f); - else { - char* modstr = _PyUnicode_AsString(moduleName); - if (modstr && - strcmp(modstr, "builtins") != 0) - { - PyFile_WriteString(modstr, f); - PyFile_WriteString(".", f); - } - } - if (className == NULL) - PyFile_WriteString("<unknown>", f); - else - PyFile_WriteString(className, f); - if (v && v != Py_None) { - PyFile_WriteString(": ", f); - PyFile_WriteObject(v, f, 0); - } - Py_XDECREF(moduleName); - } - if (obj) { - PyFile_WriteString(" in ", f); - PyFile_WriteObject(obj, f, 0); + if (PyTraceBack_Print(tb, f) < 0) + goto done; + + if (!t) + goto done; + + assert(PyExceptionClass_Check(t)); + className = PyExceptionClass_Name(t); + if (className != NULL) { + char *dot = strrchr(className, '.'); + if (dot != NULL) + className = dot+1; + } + + moduleName = _PyObject_GetAttrId(t, &PyId___module__); + if (moduleName == NULL) { + PyErr_Clear(); + if (PyFile_WriteString("<unknown>", f) < 0) + goto done; + } + else { + if (PyUnicode_CompareWithASCIIString(moduleName, "builtins") != 0) { + if (PyFile_WriteObject(moduleName, f, Py_PRINT_RAW) < 0) + goto done; + if (PyFile_WriteString(".", f) < 0) + goto done; } - PyFile_WriteString(" ignored\n", f); - PyErr_Clear(); /* Just in case */ } + if (className == NULL) { + if (PyFile_WriteString("<unknown>", f) < 0) + goto done; + } + else { + if (PyFile_WriteString(className, f) < 0) + goto done; + } + + if (v && v != Py_None) { + if (PyFile_WriteString(": ", f) < 0) + goto done; + if (PyFile_WriteObject(v, f, Py_PRINT_RAW) < 0) + goto done; + } + if (PyFile_WriteString("\n", f) < 0) + goto done; + +done: + Py_XDECREF(moduleName); Py_XDECREF(t); Py_XDECREF(v); Py_XDECREF(tb); + PyErr_Clear(); /* Just in case */ } extern PyObject *PyModule_GetWarningsModule(void); void -PyErr_SyntaxLocation(const char *filename, int lineno) { +PyErr_SyntaxLocation(const char *filename, int lineno) +{ PyErr_SyntaxLocationEx(filename, lineno, -1); } @@ -858,7 +926,7 @@ PyErr_SyntaxLocation(const char *filename, int lineno) { to make printing of exceptions believe it is a syntax error. */ void -PyErr_SyntaxLocationEx(const char *filename, int lineno, int col_offset) +PyErr_SyntaxLocationObject(PyObject *filename, int lineno, int col_offset) { PyObject *exc, *v, *tb, *tmp; _Py_IDENTIFIER(filename); @@ -892,16 +960,10 @@ PyErr_SyntaxLocationEx(const char *filename, int lineno, int col_offset) } } if (filename != NULL) { - tmp = PyUnicode_DecodeFSDefault(filename); - if (tmp == NULL) + if (_PyObject_SetAttrId(v, &PyId_filename, filename)) PyErr_Clear(); - else { - if (_PyObject_SetAttrId(v, &PyId_filename, tmp)) - PyErr_Clear(); - Py_DECREF(tmp); - } - tmp = PyErr_ProgramText(filename, lineno); + tmp = PyErr_ProgramTextObject(filename, lineno); if (tmp) { if (_PyObject_SetAttrId(v, &PyId_text, tmp)) PyErr_Clear(); @@ -931,22 +993,33 @@ PyErr_SyntaxLocationEx(const char *filename, int lineno, int col_offset) PyErr_Restore(exc, v, tb); } +void +PyErr_SyntaxLocationEx(const char *filename, int lineno, int col_offset) +{ + PyObject *fileobj; + if (filename != NULL) { + fileobj = PyUnicode_DecodeFSDefault(filename); + if (fileobj == NULL) + PyErr_Clear(); + } + else + fileobj = NULL; + PyErr_SyntaxLocationObject(fileobj, lineno, col_offset); + Py_XDECREF(fileobj); +} + /* Attempt to load the line of text that the exception refers to. If it fails, it will return NULL but will not set an exception. XXX The functionality of this function is quite similar to the functionality in tb_displayline() in traceback.c. */ -PyObject * -PyErr_ProgramText(const char *filename, int lineno) +static PyObject * +err_programtext(FILE *fp, int lineno) { - FILE *fp; int i; char linebuf[1000]; - if (filename == NULL || *filename == '\0' || lineno <= 0) - return NULL; - fp = fopen(filename, "r" PY_STDIOTEXTMODE); if (fp == NULL) return NULL; for (i = 0; i < lineno; i++) { @@ -977,6 +1050,26 @@ PyErr_ProgramText(const char *filename, int lineno) return NULL; } +PyObject * +PyErr_ProgramText(const char *filename, int lineno) +{ + FILE *fp; + if (filename == NULL || *filename == '\0' || lineno <= 0) + return NULL; + fp = _Py_fopen(filename, "r" PY_STDIOTEXTMODE); + return err_programtext(fp, lineno); +} + +PyObject * +PyErr_ProgramTextObject(PyObject *filename, int lineno) +{ + FILE *fp; + if (filename == NULL || lineno <= 0) + return NULL; + fp = _Py_fopen_obj(filename, "r" PY_STDIOTEXTMODE); + return err_programtext(fp, lineno); +} + #ifdef __cplusplus } #endif |