diff --git a/py/obj.h b/py/obj.h index 9fee0413ae..d96e4ec751 100644 --- a/py/obj.h +++ b/py/obj.h @@ -458,7 +458,7 @@ mp_int_t mp_obj_int_get_checked(mp_const_obj_t self_in); #define mp_obj_is_native_exception_instance(o) (mp_obj_get_type(o)->make_new == mp_obj_exception_make_new) bool mp_obj_is_exception_type(mp_obj_t self_in); bool mp_obj_is_exception_instance(mp_obj_t self_in); -bool mp_obj_exception_match(mp_obj_t exc, const mp_obj_type_t *exc_type); +bool mp_obj_exception_match(mp_obj_t exc, mp_const_obj_t exc_type); void mp_obj_exception_clear_traceback(mp_obj_t self_in); void mp_obj_exception_add_traceback(mp_obj_t self_in, qstr file, mp_uint_t line, qstr block); void mp_obj_exception_get_traceback(mp_obj_t self_in, mp_uint_t *n, mp_uint_t **values); diff --git a/py/objexcept.c b/py/objexcept.c index 6cf9cbc4b5..7f0736543a 100644 --- a/py/objexcept.c +++ b/py/objexcept.c @@ -403,11 +403,15 @@ bool mp_obj_is_exception_instance(mp_obj_t self_in) { return mp_obj_is_exception_type(mp_obj_get_type(self_in)); } -// return true if exception (type or instance) is a subclass of given -// exception type. -bool mp_obj_exception_match(mp_obj_t exc, const mp_obj_type_t *exc_type) { - // TODO: move implementation from RT_BINARY_OP_EXCEPTION_MATCH here. - return mp_binary_op(MP_BINARY_OP_EXCEPTION_MATCH, exc, (mp_obj_t)exc_type) == mp_const_true; +// Return true if exception (type or instance) is a subclass of given +// exception type. Assumes exc_type is a subclass of BaseException, as +// defined by mp_obj_is_exception_type(exc_type). +bool mp_obj_exception_match(mp_obj_t exc, mp_const_obj_t exc_type) { + // if exc is an instance of an exception, then extract and use its type + if (mp_obj_is_exception_instance(exc)) { + exc = mp_obj_get_type(exc); + } + return mp_obj_is_subclass_fast(exc, exc_type); } // traceback handling functions diff --git a/py/runtime.c b/py/runtime.c index 403e98c7c9..1600caa065 100644 --- a/py/runtime.c +++ b/py/runtime.c @@ -263,18 +263,25 @@ mp_obj_t mp_binary_op(mp_uint_t op, mp_obj_t lhs, mp_obj_t rhs) { if (op == MP_BINARY_OP_EXCEPTION_MATCH) { // rhs must be issubclass(rhs, BaseException) if (mp_obj_is_exception_type(rhs)) { - // if lhs is an instance of an exception, then extract and use its type - if (mp_obj_is_exception_instance(lhs)) { - lhs = mp_obj_get_type(lhs); - } - if (mp_obj_is_subclass_fast(lhs, rhs)) { + if (mp_obj_exception_match(lhs, rhs)) { return mp_const_true; } else { return mp_const_false; } + } else if (MP_OBJ_IS_TYPE(rhs, &mp_type_tuple)) { + mp_obj_tuple_t *tuple = rhs; + for (mp_uint_t i = 0; i < tuple->len; i++) { + rhs = tuple->items[i]; + if (!mp_obj_is_exception_type(rhs)) { + goto unsupported_op; + } + if (mp_obj_exception_match(lhs, rhs)) { + return mp_const_true; + } + } + return mp_const_false; } - assert(0); - return mp_const_false; + goto unsupported_op; } if (MP_OBJ_IS_SMALL_INT(lhs)) {