py/objexcept: Make mp_obj_exception_get_value support subclassed excs.

Signed-off-by: Damien George <damien@micropython.org>
This commit is contained in:
Damien George 2021-06-29 17:32:18 +10:00
parent b8255dd2e0
commit e3825e28e6
2 changed files with 33 additions and 14 deletions

View File

@ -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;

View File

@ -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