From bc87b862fd22afb38ed7392b69474286fa5fe19f Mon Sep 17 00:00:00 2001 From: Damien George Date: Thu, 10 May 2018 23:00:04 +1000 Subject: [PATCH] py/runtime: Add mp_load_method_protected helper which catches exceptions This new helper function acts like mp_load_method_maybe but is wrapped in an NLR handler so it can catch exceptions. It prevents AttributeError from propagating out, and optionally all other exceptions. This helper can be used to fully implement hasattr (see follow-up commit), and also for cases where mp_load_method_maybe is used but it must now raise an exception. --- py/runtime.c | 16 ++++++++++++++++ py/runtime.h | 1 + 2 files changed, 17 insertions(+) diff --git a/py/runtime.c b/py/runtime.c index 4efb29bec7..8f10630768 100644 --- a/py/runtime.c +++ b/py/runtime.c @@ -1086,6 +1086,22 @@ void mp_load_method(mp_obj_t base, qstr attr, mp_obj_t *dest) { } } +// Acts like mp_load_method_maybe but catches AttributeError, and all other exceptions if requested +void mp_load_method_protected(mp_obj_t obj, qstr attr, mp_obj_t *dest, bool catch_all_exc) { + nlr_buf_t nlr; + if (nlr_push(&nlr) == 0) { + mp_load_method_maybe(obj, attr, dest); + nlr_pop(); + } else { + if (!catch_all_exc + && !mp_obj_is_subclass_fast(MP_OBJ_FROM_PTR(((mp_obj_base_t*)nlr.ret_val)->type), + MP_OBJ_FROM_PTR(&mp_type_AttributeError))) { + // Re-raise the exception + nlr_raise(MP_OBJ_FROM_PTR(nlr.ret_val)); + } + } +} + void mp_store_attr(mp_obj_t base, qstr attr, mp_obj_t value) { DEBUG_OP_printf("store attr %p.%s <- %p\n", base, qstr_str(attr), value); mp_obj_type_t *type = mp_obj_get_type(base); diff --git a/py/runtime.h b/py/runtime.h index 6288e88367..ad65f3f46d 100644 --- a/py/runtime.h +++ b/py/runtime.h @@ -132,6 +132,7 @@ mp_obj_t mp_load_attr(mp_obj_t base, qstr attr); void mp_convert_member_lookup(mp_obj_t obj, const mp_obj_type_t *type, mp_obj_t member, mp_obj_t *dest); void mp_load_method(mp_obj_t base, qstr attr, mp_obj_t *dest); void mp_load_method_maybe(mp_obj_t base, qstr attr, mp_obj_t *dest); +void mp_load_method_protected(mp_obj_t obj, qstr attr, mp_obj_t *dest, bool catch_all_exc); void mp_load_super_method(qstr attr, mp_obj_t *dest); void mp_store_attr(mp_obj_t base, qstr attr, mp_obj_t val);