Skip to content

Commit

Permalink
Merge pull request #9266 from jepler/improve-exception-chaining
Browse files Browse the repository at this point in the history
Fix exception chaining for non-built-in exceptions
  • Loading branch information
dhalbert authored May 21, 2024
2 parents 0de50aa + 94db02f commit 1a3c471
Show file tree
Hide file tree
Showing 3 changed files with 149 additions and 5 deletions.
22 changes: 17 additions & 5 deletions py/obj.c
Original file line number Diff line number Diff line change
Expand Up @@ -143,18 +143,30 @@ void mp_obj_print(mp_obj_t o_in, mp_print_kind_t kind) {
mp_obj_print_helper(MP_PYTHON_PRINTER, o_in, kind);
}

// CIRCUITPY-CHANGE
#if MICROPY_CPYTHON_EXCEPTION_CHAIN
static mp_obj_t mp_load_attr_or_none(mp_obj_t base, qstr attr) {
mp_obj_t dest[2];
mp_load_method_protected(base, attr, dest, true);
return dest[0] == MP_OBJ_NULL ? mp_const_none : dest[0];
}
#endif

// CIRCUITPY-CHANGE
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);
mp_rom_error_text_t msg = MP_ERROR_TEXT("During handling of the above exception, another exception occurred:");
mp_obj_exception_t *inner = NULL;
if (self->cause) {
mp_obj_t inner_obj = mp_const_none;
if (!self->suppress_context) {
inner_obj = mp_load_attr_or_none(self_in, MP_QSTR___context__);
}
if (inner_obj == mp_const_none) {
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;
inner_obj = mp_load_attr_or_none(self_in, MP_QSTR___cause__);
}
mp_obj_exception_t *inner = mp_obj_is_exception_instance(inner_obj) ?
mp_obj_exception_get_native(inner_obj) : NULL;
if (inner && !inner->marked) {
inner->marked = true;
mp_obj_print_exception_with_limit(print, MP_OBJ_FROM_PTR(inner), limit);
Expand Down
57 changes: 57 additions & 0 deletions tests/circuitpython/traceback_test_chained.py
Original file line number Diff line number Diff line change
Expand Up @@ -72,3 +72,60 @@ def print_exc_info(e, chain=True):
print_exc_info(e, chain=False)
print_exc_info(e)
print()

class SomeException(RuntimeError):
pass

try:
try:
raise Exception("inner")
except Exception as inner:
raise SomeException("outer") from inner
except Exception as e:
print_exc_info(e)

try:
try:
raise Exception("inner")
except Exception as inner:
l = inner
raise SomeException("outer") from l
except Exception as e:
print_exc_info(e)
print()

try:
try:
raise SomeException("inner")
except Exception as inner:
raise Exception("outer") from inner
except Exception as e:
print_exc_info(e)

try:
try:
raise SomeException("inner")
except Exception as inner:
l = inner
raise Exception("outer") from l
except Exception as e:
print_exc_info(e)
print()

try:
try:
raise SomeException("inner")
except Exception as inner:
raise SomeException("outer") from inner
except Exception as e:
print_exc_info(e)

try:
try:
raise SomeException("inner")
except Exception as inner:
l = inner
raise SomeException("outer") from l
except Exception as e:
print_exc_info(e)
print()
75 changes: 75 additions & 0 deletions tests/circuitpython/traceback_test_chained.py.exp
Original file line number Diff line number Diff line change
Expand Up @@ -74,3 +74,78 @@ ZeroDivisionError: division by zero
------------------------------------------------------------------------


------------------------------------------------------------------------
Traceback (most recent call last):
File "circuitpython/traceback_test_chained.py", line 81, in <module>
Exception: inner

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
File "circuitpython/traceback_test_chained.py", line 83, in <module>
SomeException: outer
------------------------------------------------------------------------

------------------------------------------------------------------------
Traceback (most recent call last):
File "circuitpython/traceback_test_chained.py", line 89, in <module>
Exception: inner

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
File "circuitpython/traceback_test_chained.py", line 92, in <module>
SomeException: outer
------------------------------------------------------------------------


------------------------------------------------------------------------
Traceback (most recent call last):
File "circuitpython/traceback_test_chained.py", line 99, in <module>
RuntimeError: inner

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
File "circuitpython/traceback_test_chained.py", line 101, in <module>
Exception: outer
------------------------------------------------------------------------

------------------------------------------------------------------------
Traceback (most recent call last):
File "circuitpython/traceback_test_chained.py", line 107, in <module>
RuntimeError: inner

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
File "circuitpython/traceback_test_chained.py", line 110, in <module>
Exception: outer
------------------------------------------------------------------------


------------------------------------------------------------------------
Traceback (most recent call last):
File "circuitpython/traceback_test_chained.py", line 117, in <module>
RuntimeError: inner

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
File "circuitpython/traceback_test_chained.py", line 119, in <module>
SomeException: outer
------------------------------------------------------------------------

------------------------------------------------------------------------
Traceback (most recent call last):
File "circuitpython/traceback_test_chained.py", line 125, in <module>
RuntimeError: inner

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
File "circuitpython/traceback_test_chained.py", line 128, in <module>
SomeException: outer
------------------------------------------------------------------------


0 comments on commit 1a3c471

Please sign in to comment.