diff --git a/py/objexcept.c b/py/objexcept.c index a10bd2c187..b4f5018c06 100644 --- a/py/objexcept.c +++ b/py/objexcept.c @@ -111,6 +111,15 @@ mp_obj_t mp_alloc_emergency_exception_buf(mp_obj_t size_in) { #endif #endif // MICROPY_ENABLE_EMERGENCY_EXCEPTION_BUF +STATIC mp_obj_exception_t *get_native_exception(mp_obj_t self_in) { + assert(mp_obj_is_exception_instance(self_in)); + if (mp_obj_is_native_exception_instance(self_in)) { + return MP_OBJ_TO_PTR(self_in); + } else { + return MP_OBJ_TO_PTR(((mp_obj_instance_t *)MP_OBJ_TO_PTR(self_in))->subobj[0]); + } +} + STATIC void decompress_error_text_maybe(mp_obj_exception_t *o) { #if MICROPY_ROM_TEXT_COMPRESSION if (o->args->len == 1 && mp_obj_is_type(o->args->items[0], &mp_type_str)) { @@ -240,7 +249,7 @@ mp_obj_t mp_obj_exception_make_new(const mp_obj_type_t *type, size_t n_args, siz // Get exception "value" - that is, first argument, or None mp_obj_t mp_obj_exception_get_value(mp_obj_t self_in) { - mp_obj_exception_t *self = MP_OBJ_TO_PTR(self_in); + mp_obj_exception_t *self = get_native_exception(self_in); if (self->args->len == 0) { return mp_const_none; } else { @@ -559,25 +568,15 @@ bool mp_obj_exception_match(mp_obj_t exc, mp_const_obj_t exc_type) { // traceback handling functions -#define GET_NATIVE_EXCEPTION(self, self_in) \ - /* make sure self_in is an exception instance */ \ - assert(mp_obj_is_exception_instance(self_in)); \ - mp_obj_exception_t *self; \ - if (mp_obj_is_native_exception_instance(self_in)) { \ - self = MP_OBJ_TO_PTR(self_in); \ - } else { \ - self = MP_OBJ_TO_PTR(((mp_obj_instance_t *)MP_OBJ_TO_PTR(self_in))->subobj[0]); \ - } - void mp_obj_exception_clear_traceback(mp_obj_t self_in) { - GET_NATIVE_EXCEPTION(self, self_in); + mp_obj_exception_t *self = get_native_exception(self_in); // just set the traceback to the null object // we don't want to call any memory management functions here self->traceback_data = NULL; } void mp_obj_exception_add_traceback(mp_obj_t self_in, qstr file, size_t line, qstr block) { - GET_NATIVE_EXCEPTION(self, self_in); + mp_obj_exception_t *self = get_native_exception(self_in); // append this traceback info to traceback data // if memory allocation fails (eg because gc is locked), just return @@ -630,7 +629,7 @@ void mp_obj_exception_add_traceback(mp_obj_t self_in, qstr file, size_t line, qs } void mp_obj_exception_get_traceback(mp_obj_t self_in, size_t *n, size_t **values) { - GET_NATIVE_EXCEPTION(self, self_in); + mp_obj_exception_t *self = get_native_exception(self_in); if (self->traceback_data == NULL) { *n = 0; diff --git a/tests/basics/subclass_native3.py b/tests/basics/subclass_native3.py index ac5aabfed7..0c45c4924f 100644 --- a/tests/basics/subclass_native3.py +++ b/tests/basics/subclass_native3.py @@ -34,6 +34,26 @@ print(MyStopIteration().value) print(MyStopIteration(1).value) +class Iter: + def __iter__(self): + return self + + def __next__(self): + # This exception will stop the "yield from", with a value of 3 + raise MyStopIteration(3) + + +def gen(): + print((yield from Iter())) + return 4 + + +try: + next(gen()) +except StopIteration as er: + print(er.args) + + class MyOSError(OSError): pass