mirror of https://github.com/python/cpython
Issue #28410: Added _PyErr_FormatFromCause() -- the helper for raising
new exception with setting current exception as __cause__. _PyErr_FormatFromCause(exception, format, args...) is equivalent to Python raise exception(format % args) from sys.exc_info()[1]
This commit is contained in:
parent
b0426cd8c4
commit
467ab194fc
|
@ -255,6 +255,17 @@ PyAPI_FUNC(PyObject *) PyErr_FormatV(
|
||||||
va_list vargs);
|
va_list vargs);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifndef Py_LIMITED_API
|
||||||
|
/* Like PyErr_Format(), but saves current exception as __context__ and
|
||||||
|
__cause__.
|
||||||
|
*/
|
||||||
|
PyAPI_FUNC(PyObject *) _PyErr_FormatFromCause(
|
||||||
|
PyObject *exception,
|
||||||
|
const char *format, /* ASCII-encoded string */
|
||||||
|
...
|
||||||
|
);
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef MS_WINDOWS
|
#ifdef MS_WINDOWS
|
||||||
PyAPI_FUNC(PyObject *) PyErr_SetFromWindowsErrWithFilename(
|
PyAPI_FUNC(PyObject *) PyErr_SetFromWindowsErrWithFilename(
|
||||||
int ierr,
|
int ierr,
|
||||||
|
|
|
@ -222,8 +222,8 @@ class CAPITest(unittest.TestCase):
|
||||||
br'result with an error set\n'
|
br'result with an error set\n'
|
||||||
br'ValueError\n'
|
br'ValueError\n'
|
||||||
br'\n'
|
br'\n'
|
||||||
br'During handling of the above exception, '
|
br'The above exception was the direct cause '
|
||||||
br'another exception occurred:\n'
|
br'of the following exception:\n'
|
||||||
br'\n'
|
br'\n'
|
||||||
br'SystemError: <built-in '
|
br'SystemError: <built-in '
|
||||||
br'function return_result_with_error> '
|
br'function return_result_with_error> '
|
||||||
|
|
|
@ -907,10 +907,8 @@ read_directory(PyObject *archive)
|
||||||
fp = _Py_fopen_obj(archive, "rb");
|
fp = _Py_fopen_obj(archive, "rb");
|
||||||
if (fp == NULL) {
|
if (fp == NULL) {
|
||||||
if (PyErr_ExceptionMatches(PyExc_OSError)) {
|
if (PyErr_ExceptionMatches(PyExc_OSError)) {
|
||||||
PyObject *exc, *val, *tb;
|
_PyErr_FormatFromCause(ZipImportError,
|
||||||
PyErr_Fetch(&exc, &val, &tb);
|
"can't open Zip file: %R", archive);
|
||||||
PyErr_Format(ZipImportError, "can't open Zip file: %R", archive);
|
|
||||||
_PyErr_ChainExceptions(exc, val, tb);
|
|
||||||
}
|
}
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
|
@ -2198,20 +2198,18 @@ _Py_CheckFunctionResult(PyObject *func, PyObject *result, const char *where)
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if (err_occurred) {
|
if (err_occurred) {
|
||||||
PyObject *exc, *val, *tb;
|
|
||||||
PyErr_Fetch(&exc, &val, &tb);
|
|
||||||
|
|
||||||
Py_DECREF(result);
|
Py_DECREF(result);
|
||||||
|
|
||||||
if (func)
|
if (func) {
|
||||||
PyErr_Format(PyExc_SystemError,
|
_PyErr_FormatFromCause(PyExc_SystemError,
|
||||||
"%R returned a result with an error set",
|
"%R returned a result with an error set",
|
||||||
func);
|
func);
|
||||||
else
|
}
|
||||||
PyErr_Format(PyExc_SystemError,
|
else {
|
||||||
"%s returned a result with an error set",
|
_PyErr_FormatFromCause(PyExc_SystemError,
|
||||||
where);
|
"%s returned a result with an error set",
|
||||||
_PyErr_ChainExceptions(exc, val, tb);
|
where);
|
||||||
|
}
|
||||||
#ifdef Py_DEBUG
|
#ifdef Py_DEBUG
|
||||||
/* Ensure that the bug is caught in debug mode */
|
/* Ensure that the bug is caught in debug mode */
|
||||||
Py_FatalError("a function returned a result with an error set");
|
Py_FatalError("a function returned a result with an error set");
|
||||||
|
|
|
@ -118,33 +118,6 @@ gen_dealloc(PyGenObject *gen)
|
||||||
PyObject_GC_Del(gen);
|
PyObject_GC_Del(gen);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
|
||||||
gen_chain_runtime_error(const char *msg)
|
|
||||||
{
|
|
||||||
PyObject *exc, *val, *val2, *tb;
|
|
||||||
|
|
||||||
/* TODO: This about rewriting using _PyErr_ChainExceptions. */
|
|
||||||
|
|
||||||
PyErr_Fetch(&exc, &val, &tb);
|
|
||||||
PyErr_NormalizeException(&exc, &val, &tb);
|
|
||||||
if (tb != NULL) {
|
|
||||||
PyException_SetTraceback(val, tb);
|
|
||||||
}
|
|
||||||
|
|
||||||
Py_DECREF(exc);
|
|
||||||
Py_XDECREF(tb);
|
|
||||||
|
|
||||||
PyErr_SetString(PyExc_RuntimeError, msg);
|
|
||||||
PyErr_Fetch(&exc, &val2, &tb);
|
|
||||||
PyErr_NormalizeException(&exc, &val2, &tb);
|
|
||||||
|
|
||||||
Py_INCREF(val);
|
|
||||||
PyException_SetCause(val2, val);
|
|
||||||
PyException_SetContext(val2, val);
|
|
||||||
|
|
||||||
PyErr_Restore(exc, val2, tb);
|
|
||||||
}
|
|
||||||
|
|
||||||
static PyObject *
|
static PyObject *
|
||||||
gen_send_ex(PyGenObject *gen, PyObject *arg, int exc, int closing)
|
gen_send_ex(PyGenObject *gen, PyObject *arg, int exc, int closing)
|
||||||
{
|
{
|
||||||
|
@ -276,8 +249,7 @@ gen_send_ex(PyGenObject *gen, PyObject *arg, int exc, int closing)
|
||||||
else if PyAsyncGen_CheckExact(gen) {
|
else if PyAsyncGen_CheckExact(gen) {
|
||||||
msg = "async generator raised StopIteration";
|
msg = "async generator raised StopIteration";
|
||||||
}
|
}
|
||||||
/* Raise a RuntimeError */
|
_PyErr_FormatFromCause(PyExc_RuntimeError, "%s", msg);
|
||||||
gen_chain_runtime_error(msg);
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
/* `gen` is an ordinary generator without
|
/* `gen` is an ordinary generator without
|
||||||
|
@ -309,7 +281,7 @@ gen_send_ex(PyGenObject *gen, PyObject *arg, int exc, int closing)
|
||||||
raise a RuntimeError.
|
raise a RuntimeError.
|
||||||
*/
|
*/
|
||||||
const char *msg = "async generator raised StopAsyncIteration";
|
const char *msg = "async generator raised StopAsyncIteration";
|
||||||
gen_chain_runtime_error(msg);
|
_PyErr_FormatFromCause(PyExc_RuntimeError, "%s", msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!result || f->f_stacktop == NULL) {
|
if (!result || f->f_stacktop == NULL) {
|
||||||
|
|
|
@ -3835,13 +3835,10 @@ PyUnicode_DecodeFSDefaultAndSize(const char *s, Py_ssize_t size)
|
||||||
Py_FileSystemDefaultEncodeErrors);
|
Py_FileSystemDefaultEncodeErrors);
|
||||||
#ifdef MS_WINDOWS
|
#ifdef MS_WINDOWS
|
||||||
if (!res && PyErr_ExceptionMatches(PyExc_UnicodeDecodeError)) {
|
if (!res && PyErr_ExceptionMatches(PyExc_UnicodeDecodeError)) {
|
||||||
PyObject *exc, *val, *tb;
|
_PyErr_FormatFromCause(PyExc_RuntimeError,
|
||||||
PyErr_Fetch(&exc, &val, &tb);
|
"filesystem path bytes were not correctly encoded with '%s'. "
|
||||||
PyErr_Format(PyExc_RuntimeError,
|
|
||||||
"filesystem path bytes were not correctly encoded with '%s'. " \
|
|
||||||
"Please report this at http://bugs.python.org/issue27781",
|
"Please report this at http://bugs.python.org/issue27781",
|
||||||
Py_FileSystemDefaultEncoding);
|
Py_FileSystemDefaultEncoding);
|
||||||
_PyErr_ChainExceptions(exc, val, tb);
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
return res;
|
return res;
|
||||||
|
|
|
@ -401,6 +401,47 @@ _PyErr_ChainExceptions(PyObject *exc, PyObject *val, PyObject *tb)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static PyObject *
|
||||||
|
_PyErr_FormatVFromCause(PyObject *exception, const char *format, va_list vargs)
|
||||||
|
{
|
||||||
|
PyObject *exc, *val, *val2, *tb;
|
||||||
|
|
||||||
|
assert(PyErr_Occurred());
|
||||||
|
PyErr_Fetch(&exc, &val, &tb);
|
||||||
|
PyErr_NormalizeException(&exc, &val, &tb);
|
||||||
|
if (tb != NULL) {
|
||||||
|
PyException_SetTraceback(val, tb);
|
||||||
|
Py_DECREF(tb);
|
||||||
|
}
|
||||||
|
Py_DECREF(exc);
|
||||||
|
assert(!PyErr_Occurred());
|
||||||
|
|
||||||
|
PyErr_FormatV(exception, format, vargs);
|
||||||
|
|
||||||
|
PyErr_Fetch(&exc, &val2, &tb);
|
||||||
|
PyErr_NormalizeException(&exc, &val2, &tb);
|
||||||
|
Py_INCREF(val);
|
||||||
|
PyException_SetCause(val2, val);
|
||||||
|
PyException_SetContext(val2, val);
|
||||||
|
PyErr_Restore(exc, val2, tb);
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
PyObject *
|
||||||
|
_PyErr_FormatFromCause(PyObject *exception, const char *format, ...)
|
||||||
|
{
|
||||||
|
va_list vargs;
|
||||||
|
#ifdef HAVE_STDARG_PROTOTYPES
|
||||||
|
va_start(vargs, format);
|
||||||
|
#else
|
||||||
|
va_start(vargs);
|
||||||
|
#endif
|
||||||
|
_PyErr_FormatVFromCause(exception, format, vargs);
|
||||||
|
va_end(vargs);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
/* Convenience functions to set a type error exception and return 0 */
|
/* Convenience functions to set a type error exception and return 0 */
|
||||||
|
|
||||||
int
|
int
|
||||||
|
|
Loading…
Reference in New Issue