Recursively print chained exceptions

This commit is contained in:
Jeff Epler 2022-10-16 16:21:48 -05:00
parent f3169246ba
commit b6f86e1e73
No known key found for this signature in database
GPG Key ID: D5BF15AB975AB4DE
5 changed files with 138 additions and 9 deletions

View File

@ -106,7 +106,7 @@ msgstr ""
msgid "%q in use"
msgstr ""
#: py/obj.c py/objstr.c py/objstrunicode.c
#: py/objstr.c py/objstrunicode.c
msgid "%q index out of range"
msgstr ""
@ -171,11 +171,11 @@ msgstr ""
msgid "%q must be an int"
msgstr ""
#: py/argcheck.c
#: py/argcheck.c py/obj.c
msgid "%q must be of type %q"
msgstr ""
#: shared-bindings/digitalio/Pull.c
#: py/objexcept.c shared-bindings/digitalio/Pull.c
msgid "%q must be of type %q or None"
msgstr ""
@ -894,6 +894,10 @@ msgstr ""
msgid "Drive mode not used when direction is input."
msgstr ""
#: py/obj.c
msgid "During handling of the above exception, another exception occurred:"
msgstr ""
#: shared-bindings/aesio/aes.c
msgid "ECB only operates on 16 bytes at a time"
msgstr ""
@ -2007,6 +2011,10 @@ msgid ""
"exit safe mode."
msgstr ""
#: py/obj.c
msgid "The above exception was the direct cause of the following exception:"
msgstr ""
#: ports/espressif/boards/m5stack_atom_lite/mpconfigboard.h
msgid "The central button was pressed at start up.\n"
msgstr ""
@ -3153,7 +3161,7 @@ msgid "index is out of bounds"
msgstr ""
#: extmod/ulab/code/numpy/numerical.c extmod/ulab/code/ulab_tools.c
#: ports/espressif/common-hal/pulseio/PulseIn.c py/obj.c
#: ports/espressif/common-hal/pulseio/PulseIn.c
#: shared-bindings/bitmaptools/__init__.c
msgid "index out of range"
msgstr ""
@ -3336,10 +3344,6 @@ msgstr ""
msgid "invalid syntax for number"
msgstr ""
#: py/objexcept.c
msgid "invalid traceback"
msgstr ""
#: py/objtype.c
msgid "issubclass() arg 1 must be a class"
msgstr ""

View File

@ -142,9 +142,33 @@ void mp_obj_print(mp_obj_t o_in, mp_print_kind_t kind) {
mp_obj_print_helper(MP_PYTHON_PRINTER, o_in, kind);
}
static void mp_obj_print_inner_exception(const mp_print_t *print, mp_obj_t self_in, mp_int_t limit) {
#if MICROPY_CPYTHON_EXCEPTION_CHAIN
mp_obj_exception_t *self = mp_obj_exception_get_native(self_in);
const compressed_string_t *msg = MP_ERROR_TEXT("During handling of the above exception, another exception occurred:");
mp_obj_exception_t *inner = NULL;
if (self->cause) {
msg = MP_ERROR_TEXT("The above exception was the direct cause of the following exception:");
inner = self->cause;
} else if (!self->suppress_context) {
inner = self->context;
}
if (inner && !inner->marked) {
inner->marked = true;
mp_obj_print_exception_with_limit(print, MP_OBJ_FROM_PTR(inner), limit);
inner->marked = false;
mp_printf(print, "\n");
mp_cprintf(print, msg);
mp_printf(print, "\n\n");
}
#endif
}
// helper function to print an exception with traceback
void mp_obj_print_exception_with_limit(const mp_print_t *print, mp_obj_t exc, mp_int_t limit) {
if (mp_obj_is_exception_instance(exc) && stack_ok()) {
mp_obj_print_inner_exception(print, exc, limit);
size_t n, *values;
mp_obj_exception_get_traceback(exc, &n, &values);
if (n > 0) {

View File

@ -34,8 +34,11 @@ typedef struct _mp_obj_exception_t {
mp_obj_base_t base;
mp_obj_tuple_t *args;
mp_obj_traceback_t *traceback;
mp_obj_t cause, context;
#if MICROPY_CPYTHON_EXCEPTION_CHAIN
struct _mp_obj_exception_t *cause, *context;
bool suppress_context;
bool marked;
#endif
} mp_obj_exception_t;
void mp_obj_exception_print(const mp_print_t *print, mp_obj_t o_in, mp_print_kind_t kind);

View File

@ -0,0 +1,55 @@
try:
Exception().__cause__
except AttributeError:
print("SKIP")
raise SystemExit
try:
import traceback
except:
print("SKIP")
raise SystemExit
def print_exc_info(e):
print("-" * 72)
traceback.print_exception(None, e, e.__traceback__)
print("-" * 72)
print()
try:
try:
1 / 0
except Exception as inner:
raise RuntimeError() from inner
except Exception as e:
print_exc_info(e)
print()
try:
try:
1 / 0
except Exception as inner:
raise RuntimeError() from OSError()
except Exception as e:
print_exc_info(e)
print()
try:
try:
1 / 0
except Exception as inner:
raise RuntimeError()
except Exception as e:
print_exc_info(e)
print()
try:
try:
1 / 0
except Exception as inner:
raise RuntimeError() from None
except Exception as e:
print_exc_info(e)

View File

@ -0,0 +1,43 @@
------------------------------------------------------------------------
Traceback (most recent call last):
File "circuitpython/traceback_test_chained.py", line 23, in <module>
ZeroDivisionError: division by zero
The above exception was the direct cause of the following exception:
Traceback (most recent call last):
File "circuitpython/traceback_test_chained.py", line 25, in <module>
RuntimeError:
------------------------------------------------------------------------
------------------------------------------------------------------------
OSError:
The above exception was the direct cause of the following exception:
Traceback (most recent call last):
File "circuitpython/traceback_test_chained.py", line 34, in <module>
RuntimeError:
------------------------------------------------------------------------
------------------------------------------------------------------------
Traceback (most recent call last):
File "circuitpython/traceback_test_chained.py", line 42, in <module>
ZeroDivisionError: division by zero
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "circuitpython/traceback_test_chained.py", line 44, in <module>
RuntimeError:
------------------------------------------------------------------------
------------------------------------------------------------------------
Traceback (most recent call last):
File "circuitpython/traceback_test_chained.py", line 53, in <module>
RuntimeError:
------------------------------------------------------------------------