Commit 8de8c8a0 authored by Armin Rigo's avatar Armin Rigo

#492

Python 3.8 adds support for sys.unraisablehook(), but also a new
_PyErr_WriteUnraisableMsg() that calls it and is slightly more
flexible in displaying the error message.  Use that
parent e15fd37f19d0
......@@ -180,6 +180,10 @@
# define Py_SET_REFCNT(obj, val) (Py_REFCNT(obj) = (val))
#endif
#if PY_VERSION_HEX >= 0x03080000
# define USE_WRITEUNRAISABLEMSG
#endif
/************************************************************/
/* base type flag: exactly one of the following: */
......@@ -6066,6 +6070,43 @@ static void _my_PyErr_WriteUnraisable(PyObject *t, PyObject *v, PyObject *tb,
char *extra_error_line)
{
/* like PyErr_WriteUnraisable(), but write a full traceback */
#ifdef USE_WRITEUNRAISABLEMSG
/* PyErr_WriteUnraisable actually writes the full traceback anyway
from Python 3.4, but we can't really get the formatting of the
custom text to be what we want. We can do better from Python
3.8 by calling the new _PyErr_WriteUnraisableMsg().
Luckily it's also Python 3.8 that adds new functionality that
people might want: the new sys.unraisablehook().
*/
PyObject *s;
int first_char;
assert(objdescr != NULL && objdescr[0] != 0); /* non-empty */
first_char = objdescr[0];
if (first_char >= 'A' && first_char <= 'Z')
first_char += 'a' - 'A'; /* lower() the very first character */
if (extra_error_line == NULL)
extra_error_line = "";
if (obj != NULL)
s = PyUnicode_FromFormat("%c%s%R%s",
first_char, objdescr + 1, obj, extra_error_line);
else
s = PyUnicode_FromFormat("%c%s%s",
first_char, objdescr + 1, extra_error_line);
PyErr_Restore(t, v, tb);
if (s != NULL) {
_PyErr_WriteUnraisableMsg(PyText_AS_UTF8(s), NULL);
Py_DECREF(s);
}
else
PyErr_WriteUnraisable(obj); /* best effort */
PyErr_Clear();
#else
/* version for Python 2.7 and < 3.8 */
PyObject *f;
#if PY_MAJOR_VERSION >= 3
/* jump through hoops to ensure the tb is attached to v, on Python 3 */
......@@ -6090,6 +6131,8 @@ static void _my_PyErr_WriteUnraisable(PyObject *t, PyObject *v, PyObject *tb,
Py_XDECREF(t);
Py_XDECREF(v);
Py_XDECREF(tb);
#endif
}
static void general_invoke_callback(int decode_args_from_libffi,
......@@ -6139,7 +6182,11 @@ static void general_invoke_callback(int decode_args_from_libffi,
goto error;
if (convert_from_object_fficallback(result, SIGNATURE(1), py_res,
decode_args_from_libffi) < 0) {
#ifdef USE_WRITEUNRAISABLEMSG
extra_error_line = ", trying to convert the result back to C";
#else
extra_error_line = "Trying to convert the result back to C:\n";
#endif
goto error;
}
done:
......@@ -6191,10 +6238,16 @@ static void general_invoke_callback(int decode_args_from_libffi,
_my_PyErr_WriteUnraisable(exc1, val1, tb1,
"From cffi callback ", py_ob,
extra_error_line);
#ifdef USE_WRITEUNRAISABLEMSG
_my_PyErr_WriteUnraisable(exc2, val2, tb2,
"during handling of the above exception by 'onerror'",
NULL, NULL);
#else
extra_error_line = ("\nDuring the call to 'onerror', "
"another exception occurred:\n\n");
_my_PyErr_WriteUnraisable(exc2, val2, tb2,
NULL, NULL, extra_error_line);
#endif
_cffi_stop_error_capture(ecap);
}
}
......
......@@ -1331,7 +1331,9 @@ def test_callback_exception():
except ImportError:
import io as cStringIO # Python 3
import linecache
def matches(istr, ipattern):
def matches(istr, ipattern, ipattern38):
if sys.version_info >= (3, 8):
ipattern = ipattern38
str, pattern = istr, ipattern
while '$' in pattern:
i = pattern.index('$')
......@@ -1375,6 +1377,14 @@ Traceback (most recent call last):
File "$", line $, in check_value
$
ValueError: 42
""", """\
Exception ignored from cffi callback <function$Zcb1 at 0x$>:
Traceback (most recent call last):
File "$", line $, in Zcb1
$
File "$", line $, in check_value
$
ValueError: 42
""")
sys.stderr = cStringIO.StringIO()
bigvalue = 20000
......@@ -1383,6 +1393,12 @@ ValueError: 42
From cffi callback <function$Zcb1 at 0x$>:
Trying to convert the result back to C:
OverflowError: integer 60000 does not fit 'short'
""", """\
Exception ignored from cffi callback <function$Zcb1 at 0x$>, trying to convert the result back to C:
Traceback (most recent call last):
File "$", line $, in test_callback_exception
$
OverflowError: integer 60000 does not fit 'short'
""")
sys.stderr = cStringIO.StringIO()
bigvalue = 20000
......@@ -1419,6 +1435,17 @@ OverflowError: integer 60000 does not fit 'short'
During the call to 'onerror', another exception occurred:
TypeError: $integer$
""", """\
Exception ignored from cffi callback <function$Zcb1 at 0x$>, trying to convert the result back to C:
Traceback (most recent call last):
File "$", line $, in test_callback_exception
$
OverflowError: integer 60000 does not fit 'short'
Exception ignored during handling of the above exception by 'onerror':
Traceback (most recent call last):
File "$", line $, in test_callback_exception
$
TypeError: $integer$
""")
#
......@@ -1432,6 +1459,17 @@ OverflowError: integer 60000 does not fit 'short'
During the call to 'onerror', another exception occurred:
Traceback (most recent call last):
File "$", line $, in oops
$
AttributeError: 'str' object has no attribute 'append'
""", """\
Exception ignored from cffi callback <function$Zcb1 at 0x$>, trying to convert the result back to C:
Traceback (most recent call last):
File "$", line $, in test_callback_exception
$
OverflowError: integer 60000 does not fit 'short'
Exception ignored during handling of the above exception by 'onerror':
Traceback (most recent call last):
File "$", line $, in oops
$
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment