[Python-checkins] cpython (3.6): Issue #28410: Added _PyErr_FormatFromCause() -- the helper for raising
serhiy.storchaka
python-checkins at python.org
Fri Oct 21 10:15:58 EDT 2016
https://hg.python.org/cpython/rev/969c8bfe8872
changeset: 104608:969c8bfe8872
branch: 3.6
parent: 104606:23a1d9ec35d5
user: Serhiy Storchaka <storchaka at gmail.com>
date: Fri Oct 21 17:09:17 2016 +0300
summary:
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]
files:
Include/pyerrors.h | 11 +++++++
Lib/test/test_capi.py | 4 +-
Modules/zipimport.c | 6 +--
Objects/abstract.c | 22 +++++++--------
Objects/genobject.c | 32 +---------------------
Objects/unicodeobject.c | 7 +---
Python/errors.c | 41 +++++++++++++++++++++++++++++
7 files changed, 70 insertions(+), 53 deletions(-)
diff --git a/Include/pyerrors.h b/Include/pyerrors.h
--- a/Include/pyerrors.h
+++ b/Include/pyerrors.h
@@ -255,6 +255,17 @@
va_list vargs);
#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
PyAPI_FUNC(PyObject *) PyErr_SetFromWindowsErrWithFilename(
int ierr,
diff --git a/Lib/test/test_capi.py b/Lib/test/test_capi.py
--- a/Lib/test/test_capi.py
+++ b/Lib/test/test_capi.py
@@ -222,8 +222,8 @@
br'result with an error set\n'
br'ValueError\n'
br'\n'
- br'During handling of the above exception, '
- br'another exception occurred:\n'
+ br'The above exception was the direct cause '
+ br'of the following exception:\n'
br'\n'
br'SystemError: <built-in '
br'function return_result_with_error> '
diff --git a/Modules/zipimport.c b/Modules/zipimport.c
--- a/Modules/zipimport.c
+++ b/Modules/zipimport.c
@@ -907,10 +907,8 @@
fp = _Py_fopen_obj(archive, "rb");
if (fp == NULL) {
if (PyErr_ExceptionMatches(PyExc_OSError)) {
- PyObject *exc, *val, *tb;
- PyErr_Fetch(&exc, &val, &tb);
- PyErr_Format(ZipImportError, "can't open Zip file: %R", archive);
- _PyErr_ChainExceptions(exc, val, tb);
+ _PyErr_FormatFromCause(ZipImportError,
+ "can't open Zip file: %R", archive);
}
return NULL;
}
diff --git a/Objects/abstract.c b/Objects/abstract.c
--- a/Objects/abstract.c
+++ b/Objects/abstract.c
@@ -2198,20 +2198,18 @@
}
else {
if (err_occurred) {
- PyObject *exc, *val, *tb;
- PyErr_Fetch(&exc, &val, &tb);
-
Py_DECREF(result);
- if (func)
- PyErr_Format(PyExc_SystemError,
- "%R returned a result with an error set",
- func);
- else
- PyErr_Format(PyExc_SystemError,
- "%s returned a result with an error set",
- where);
- _PyErr_ChainExceptions(exc, val, tb);
+ if (func) {
+ _PyErr_FormatFromCause(PyExc_SystemError,
+ "%R returned a result with an error set",
+ func);
+ }
+ else {
+ _PyErr_FormatFromCause(PyExc_SystemError,
+ "%s returned a result with an error set",
+ where);
+ }
#ifdef Py_DEBUG
/* Ensure that the bug is caught in debug mode */
Py_FatalError("a function returned a result with an error set");
diff --git a/Objects/genobject.c b/Objects/genobject.c
--- a/Objects/genobject.c
+++ b/Objects/genobject.c
@@ -118,33 +118,6 @@
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 *
gen_send_ex(PyGenObject *gen, PyObject *arg, int exc, int closing)
{
@@ -276,8 +249,7 @@
else if PyAsyncGen_CheckExact(gen) {
msg = "async generator raised StopIteration";
}
- /* Raise a RuntimeError */
- gen_chain_runtime_error(msg);
+ _PyErr_FormatFromCause(PyExc_RuntimeError, "%s", msg);
}
else {
/* `gen` is an ordinary generator without
@@ -309,7 +281,7 @@
raise a RuntimeError.
*/
const char *msg = "async generator raised StopAsyncIteration";
- gen_chain_runtime_error(msg);
+ _PyErr_FormatFromCause(PyExc_RuntimeError, "%s", msg);
}
if (!result || f->f_stacktop == NULL) {
diff --git a/Objects/unicodeobject.c b/Objects/unicodeobject.c
--- a/Objects/unicodeobject.c
+++ b/Objects/unicodeobject.c
@@ -3835,13 +3835,10 @@
Py_FileSystemDefaultEncodeErrors);
#ifdef MS_WINDOWS
if (!res && PyErr_ExceptionMatches(PyExc_UnicodeDecodeError)) {
- PyObject *exc, *val, *tb;
- PyErr_Fetch(&exc, &val, &tb);
- PyErr_Format(PyExc_RuntimeError,
- "filesystem path bytes were not correctly encoded with '%s'. " \
+ _PyErr_FormatFromCause(PyExc_RuntimeError,
+ "filesystem path bytes were not correctly encoded with '%s'. "
"Please report this at http://bugs.python.org/issue27781",
Py_FileSystemDefaultEncoding);
- _PyErr_ChainExceptions(exc, val, tb);
}
#endif
return res;
diff --git a/Python/errors.c b/Python/errors.c
--- a/Python/errors.c
+++ b/Python/errors.c
@@ -401,6 +401,47 @@
}
}
+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 */
int
--
Repository URL: https://hg.python.org/cpython
More information about the Python-checkins
mailing list