summaryrefslogtreecommitdiffstatshomepage
path: root/py
diff options
context:
space:
mode:
authorPaul Sokolovsky <pfalcon@users.sourceforge.net>2016-11-14 02:23:30 +0300
committerPaul Sokolovsky <pfalcon@users.sourceforge.net>2016-11-14 02:29:09 +0300
commitc3d96d387c461c25ca3298dfa73d2a4efb45f1e7 (patch)
tree1fa555956aee8a774ab4b6c3211f62d82faea11b /py
parentbf318801d2fafa2786e74693d19a3c2fdb50ddda (diff)
downloadmicropython-c3d96d387c461c25ca3298dfa73d2a4efb45f1e7.tar.gz
micropython-c3d96d387c461c25ca3298dfa73d2a4efb45f1e7.zip
py/objexcept: Allow clearing traceback with 'exc.__traceback__ = None'.
We allow 'exc.__traceback__ = None' assignment as a low-level optimization of pre-allocating exception instance and raising it repeatedly - this avoids memory allocation during raise. However, uPy will keep adding traceback entries to such exception instance, so before throwing it, traceback should be cleared like above. 'exc.__traceback__ = None' syntax is CPython compatible. However, unlike it, reading that attribute or setting it to any other value is not supported (and not intended to be supported, again, the only reason for adding this feature is to allow zero-memalloc exception raising).
Diffstat (limited to 'py')
-rw-r--r--py/objexcept.c14
1 files changed, 12 insertions, 2 deletions
diff --git a/py/objexcept.c b/py/objexcept.c
index 9ccc9288c9..c1b992d276 100644
--- a/py/objexcept.c
+++ b/py/objexcept.c
@@ -152,11 +152,21 @@ mp_obj_t mp_obj_exception_get_value(mp_obj_t self_in) {
}
STATIC void exception_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) {
+ mp_obj_exception_t *self = MP_OBJ_TO_PTR(self_in);
if (dest[0] != MP_OBJ_NULL) {
- // not load attribute
+ // store/delete attribute
+ if (attr == MP_QSTR___traceback__ && dest[1] == mp_const_none) {
+ // We allow 'exc.__traceback__ = None' assignment as low-level
+ // optimization of pre-allocating exception instance and raising
+ // it repeatedly - this avoids memory allocation during raise.
+ // However, uPy will keep adding traceback entries to such
+ // exception instance, so before throwing it, traceback should
+ // be cleared like above.
+ self->traceback_len = 0;
+ dest[0] = MP_OBJ_NULL; // indicate success
+ }
return;
}
- mp_obj_exception_t *self = MP_OBJ_TO_PTR(self_in);
if (attr == MP_QSTR_args) {
dest[0] = MP_OBJ_FROM_PTR(self->args);
} else if (self->base.type == &mp_type_StopIteration && attr == MP_QSTR_value) {