Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
py/objexcept.c@2:c89e95946844, 2016-04-16 (annotated)
- Committer:
- Colin Hogben
- Date:
- Sat Apr 16 22:43:41 2016 +0100
- Revision:
- 2:c89e95946844
- Parent:
- 0:5868e8752d44
py: update to upstream master
Who changed what in which revision?
| User | Revision | Line number | New contents of line |
|---|---|---|---|
| pythontech | 0:5868e8752d44 | 1 | /* |
| pythontech | 0:5868e8752d44 | 2 | * This file is part of the Micro Python project, http://micropython.org/ |
| pythontech | 0:5868e8752d44 | 3 | * |
| pythontech | 0:5868e8752d44 | 4 | * The MIT License (MIT) |
| pythontech | 0:5868e8752d44 | 5 | * |
| pythontech | 0:5868e8752d44 | 6 | * Copyright (c) 2013, 2014 Damien P. George |
| pythontech | 0:5868e8752d44 | 7 | * |
| pythontech | 0:5868e8752d44 | 8 | * Permission is hereby granted, free of charge, to any person obtaining a copy |
| pythontech | 0:5868e8752d44 | 9 | * of this software and associated documentation files (the "Software"), to deal |
| pythontech | 0:5868e8752d44 | 10 | * in the Software without restriction, including without limitation the rights |
| pythontech | 0:5868e8752d44 | 11 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
| pythontech | 0:5868e8752d44 | 12 | * copies of the Software, and to permit persons to whom the Software is |
| pythontech | 0:5868e8752d44 | 13 | * furnished to do so, subject to the following conditions: |
| pythontech | 0:5868e8752d44 | 14 | * |
| pythontech | 0:5868e8752d44 | 15 | * The above copyright notice and this permission notice shall be included in |
| pythontech | 0:5868e8752d44 | 16 | * all copies or substantial portions of the Software. |
| pythontech | 0:5868e8752d44 | 17 | * |
| pythontech | 0:5868e8752d44 | 18 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
| pythontech | 0:5868e8752d44 | 19 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
| pythontech | 0:5868e8752d44 | 20 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
| pythontech | 0:5868e8752d44 | 21 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
| pythontech | 0:5868e8752d44 | 22 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
| pythontech | 0:5868e8752d44 | 23 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN |
| pythontech | 0:5868e8752d44 | 24 | * THE SOFTWARE. |
| pythontech | 0:5868e8752d44 | 25 | */ |
| pythontech | 0:5868e8752d44 | 26 | |
| pythontech | 0:5868e8752d44 | 27 | #include <string.h> |
| pythontech | 0:5868e8752d44 | 28 | #include <stdarg.h> |
| pythontech | 0:5868e8752d44 | 29 | #include <assert.h> |
| pythontech | 0:5868e8752d44 | 30 | #include <stdio.h> |
| pythontech | 0:5868e8752d44 | 31 | |
| pythontech | 0:5868e8752d44 | 32 | #include "py/mpstate.h" |
| pythontech | 0:5868e8752d44 | 33 | #include "py/objlist.h" |
| pythontech | 0:5868e8752d44 | 34 | #include "py/objstr.h" |
| pythontech | 0:5868e8752d44 | 35 | #include "py/objtuple.h" |
| pythontech | 0:5868e8752d44 | 36 | #include "py/objtype.h" |
| pythontech | 0:5868e8752d44 | 37 | #include "py/runtime.h" |
| pythontech | 0:5868e8752d44 | 38 | #include "py/gc.h" |
| pythontech | 0:5868e8752d44 | 39 | |
| pythontech | 0:5868e8752d44 | 40 | // Instance of MemoryError exception - needed by mp_malloc_fail |
| pythontech | 0:5868e8752d44 | 41 | const mp_obj_exception_t mp_const_MemoryError_obj = {{&mp_type_MemoryError}, 0, 0, NULL, (mp_obj_tuple_t*)&mp_const_empty_tuple_obj}; |
| pythontech | 0:5868e8752d44 | 42 | |
| pythontech | 0:5868e8752d44 | 43 | // Optionally allocated buffer for storing the first argument of an exception |
| pythontech | 0:5868e8752d44 | 44 | // allocated when the heap is locked. |
| pythontech | 0:5868e8752d44 | 45 | #if MICROPY_ENABLE_EMERGENCY_EXCEPTION_BUF |
| pythontech | 0:5868e8752d44 | 46 | # if MICROPY_EMERGENCY_EXCEPTION_BUF_SIZE > 0 |
| pythontech | 0:5868e8752d44 | 47 | #define mp_emergency_exception_buf_size MICROPY_EMERGENCY_EXCEPTION_BUF_SIZE |
| pythontech | 0:5868e8752d44 | 48 | |
| pythontech | 0:5868e8752d44 | 49 | void mp_init_emergency_exception_buf(void) { |
| pythontech | 0:5868e8752d44 | 50 | // Nothing to do since the buffer was declared statically. We put this |
| pythontech | 0:5868e8752d44 | 51 | // definition here so that the calling code can call this function |
| pythontech | 0:5868e8752d44 | 52 | // regardless of how its configured (makes the calling code a bit cleaner). |
| pythontech | 0:5868e8752d44 | 53 | } |
| pythontech | 0:5868e8752d44 | 54 | |
| pythontech | 0:5868e8752d44 | 55 | #else |
| pythontech | 0:5868e8752d44 | 56 | #define mp_emergency_exception_buf_size MP_STATE_VM(mp_emergency_exception_buf_size) |
| pythontech | 0:5868e8752d44 | 57 | |
| pythontech | 0:5868e8752d44 | 58 | void mp_init_emergency_exception_buf(void) { |
| pythontech | 0:5868e8752d44 | 59 | mp_emergency_exception_buf_size = 0; |
| pythontech | 0:5868e8752d44 | 60 | MP_STATE_VM(mp_emergency_exception_buf) = NULL; |
| pythontech | 0:5868e8752d44 | 61 | } |
| pythontech | 0:5868e8752d44 | 62 | |
| pythontech | 0:5868e8752d44 | 63 | mp_obj_t mp_alloc_emergency_exception_buf(mp_obj_t size_in) { |
| pythontech | 0:5868e8752d44 | 64 | mp_int_t size = mp_obj_get_int(size_in); |
| pythontech | 0:5868e8752d44 | 65 | void *buf = NULL; |
| pythontech | 0:5868e8752d44 | 66 | if (size > 0) { |
| pythontech | 0:5868e8752d44 | 67 | buf = m_new(byte, size); |
| pythontech | 0:5868e8752d44 | 68 | } |
| pythontech | 0:5868e8752d44 | 69 | |
| pythontech | 0:5868e8752d44 | 70 | int old_size = mp_emergency_exception_buf_size; |
| pythontech | 0:5868e8752d44 | 71 | void *old_buf = MP_STATE_VM(mp_emergency_exception_buf); |
| pythontech | 0:5868e8752d44 | 72 | |
| pythontech | 0:5868e8752d44 | 73 | // Update the 2 variables atomically so that an interrupt can't occur |
| pythontech | 0:5868e8752d44 | 74 | // between the assignments. |
| pythontech | 0:5868e8752d44 | 75 | mp_uint_t atomic_state = MICROPY_BEGIN_ATOMIC_SECTION(); |
| pythontech | 0:5868e8752d44 | 76 | mp_emergency_exception_buf_size = size; |
| pythontech | 0:5868e8752d44 | 77 | MP_STATE_VM(mp_emergency_exception_buf) = buf; |
| pythontech | 0:5868e8752d44 | 78 | MICROPY_END_ATOMIC_SECTION(atomic_state); |
| pythontech | 0:5868e8752d44 | 79 | |
| pythontech | 0:5868e8752d44 | 80 | if (old_buf != NULL) { |
| pythontech | 0:5868e8752d44 | 81 | m_del(byte, old_buf, old_size); |
| pythontech | 0:5868e8752d44 | 82 | } |
| pythontech | 0:5868e8752d44 | 83 | return mp_const_none; |
| pythontech | 0:5868e8752d44 | 84 | } |
| pythontech | 0:5868e8752d44 | 85 | #endif |
| pythontech | 0:5868e8752d44 | 86 | #endif // MICROPY_ENABLE_EMERGENCY_EXCEPTION_BUF |
| pythontech | 0:5868e8752d44 | 87 | |
| pythontech | 0:5868e8752d44 | 88 | // Instance of GeneratorExit exception - needed by generator.close() |
| pythontech | 0:5868e8752d44 | 89 | // This would belong to objgenerator.c, but to keep mp_obj_exception_t |
| pythontech | 0:5868e8752d44 | 90 | // definition module-private so far, have it here. |
| pythontech | 0:5868e8752d44 | 91 | const mp_obj_exception_t mp_const_GeneratorExit_obj = {{&mp_type_GeneratorExit}, 0, 0, NULL, (mp_obj_tuple_t*)&mp_const_empty_tuple_obj}; |
| pythontech | 0:5868e8752d44 | 92 | |
| pythontech | 0:5868e8752d44 | 93 | STATIC void mp_obj_exception_print(const mp_print_t *print, mp_obj_t o_in, mp_print_kind_t kind) { |
| pythontech | 0:5868e8752d44 | 94 | mp_obj_exception_t *o = MP_OBJ_TO_PTR(o_in); |
| pythontech | 0:5868e8752d44 | 95 | mp_print_kind_t k = kind & ~PRINT_EXC_SUBCLASS; |
| pythontech | 0:5868e8752d44 | 96 | bool is_subclass = kind & PRINT_EXC_SUBCLASS; |
| pythontech | 0:5868e8752d44 | 97 | if (!is_subclass && (k == PRINT_REPR || k == PRINT_EXC)) { |
| pythontech | 0:5868e8752d44 | 98 | mp_print_str(print, qstr_str(o->base.type->name)); |
| pythontech | 0:5868e8752d44 | 99 | } |
| pythontech | 0:5868e8752d44 | 100 | |
| pythontech | 0:5868e8752d44 | 101 | if (k == PRINT_EXC) { |
| pythontech | 0:5868e8752d44 | 102 | mp_print_str(print, ": "); |
| pythontech | 0:5868e8752d44 | 103 | } |
| pythontech | 0:5868e8752d44 | 104 | |
| pythontech | 0:5868e8752d44 | 105 | if (k == PRINT_STR || k == PRINT_EXC) { |
| pythontech | 0:5868e8752d44 | 106 | if (o->args == NULL || o->args->len == 0) { |
| pythontech | 0:5868e8752d44 | 107 | mp_print_str(print, ""); |
| pythontech | 0:5868e8752d44 | 108 | return; |
| pythontech | 0:5868e8752d44 | 109 | } else if (o->args->len == 1) { |
| pythontech | 0:5868e8752d44 | 110 | mp_obj_print_helper(print, o->args->items[0], PRINT_STR); |
| pythontech | 0:5868e8752d44 | 111 | return; |
| pythontech | 0:5868e8752d44 | 112 | } |
| pythontech | 0:5868e8752d44 | 113 | } |
| pythontech | 0:5868e8752d44 | 114 | mp_obj_tuple_print(print, MP_OBJ_FROM_PTR(o->args), kind); |
| pythontech | 0:5868e8752d44 | 115 | } |
| pythontech | 0:5868e8752d44 | 116 | |
| pythontech | 0:5868e8752d44 | 117 | mp_obj_t mp_obj_exception_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) { |
| pythontech | 0:5868e8752d44 | 118 | mp_arg_check_num(n_args, n_kw, 0, MP_OBJ_FUN_ARGS_MAX, false); |
| pythontech | 0:5868e8752d44 | 119 | mp_obj_exception_t *o = m_new_obj_var_maybe(mp_obj_exception_t, mp_obj_t, 0); |
| pythontech | 0:5868e8752d44 | 120 | if (o == NULL) { |
| pythontech | 0:5868e8752d44 | 121 | // Couldn't allocate heap memory; use local data instead. |
| pythontech | 0:5868e8752d44 | 122 | o = &MP_STATE_VM(mp_emergency_exception_obj); |
| pythontech | 0:5868e8752d44 | 123 | // We can't store any args. |
| pythontech | 0:5868e8752d44 | 124 | o->args = (mp_obj_tuple_t*)&mp_const_empty_tuple_obj; |
| pythontech | 0:5868e8752d44 | 125 | } else { |
| pythontech | 0:5868e8752d44 | 126 | o->args = MP_OBJ_TO_PTR(mp_obj_new_tuple(n_args, args)); |
| pythontech | 0:5868e8752d44 | 127 | } |
| pythontech | 0:5868e8752d44 | 128 | o->base.type = type; |
| pythontech | 0:5868e8752d44 | 129 | o->traceback_data = NULL; |
| pythontech | 0:5868e8752d44 | 130 | return MP_OBJ_FROM_PTR(o); |
| pythontech | 0:5868e8752d44 | 131 | } |
| pythontech | 0:5868e8752d44 | 132 | |
| pythontech | 0:5868e8752d44 | 133 | // Get exception "value" - that is, first argument, or None |
| pythontech | 0:5868e8752d44 | 134 | mp_obj_t mp_obj_exception_get_value(mp_obj_t self_in) { |
| pythontech | 0:5868e8752d44 | 135 | mp_obj_exception_t *self = MP_OBJ_TO_PTR(self_in); |
| pythontech | 0:5868e8752d44 | 136 | if (self->args->len == 0) { |
| pythontech | 0:5868e8752d44 | 137 | return mp_const_none; |
| pythontech | 0:5868e8752d44 | 138 | } else { |
| pythontech | 0:5868e8752d44 | 139 | return self->args->items[0]; |
| pythontech | 0:5868e8752d44 | 140 | } |
| pythontech | 0:5868e8752d44 | 141 | } |
| pythontech | 0:5868e8752d44 | 142 | |
| pythontech | 0:5868e8752d44 | 143 | STATIC void exception_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) { |
| pythontech | 0:5868e8752d44 | 144 | if (dest[0] != MP_OBJ_NULL) { |
| pythontech | 0:5868e8752d44 | 145 | // not load attribute |
| pythontech | 0:5868e8752d44 | 146 | return; |
| pythontech | 0:5868e8752d44 | 147 | } |
| pythontech | 0:5868e8752d44 | 148 | mp_obj_exception_t *self = MP_OBJ_TO_PTR(self_in); |
| pythontech | 0:5868e8752d44 | 149 | if (attr == MP_QSTR_args) { |
| pythontech | 0:5868e8752d44 | 150 | dest[0] = MP_OBJ_FROM_PTR(self->args); |
| pythontech | 0:5868e8752d44 | 151 | } else if (self->base.type == &mp_type_StopIteration && attr == MP_QSTR_value) { |
| pythontech | 0:5868e8752d44 | 152 | dest[0] = mp_obj_exception_get_value(self_in); |
| pythontech | 0:5868e8752d44 | 153 | } |
| pythontech | 0:5868e8752d44 | 154 | } |
| pythontech | 0:5868e8752d44 | 155 | |
| pythontech | 0:5868e8752d44 | 156 | STATIC mp_obj_t exc___init__(size_t n_args, const mp_obj_t *args) { |
| pythontech | 0:5868e8752d44 | 157 | mp_obj_exception_t *self = MP_OBJ_TO_PTR(args[0]); |
| pythontech | 0:5868e8752d44 | 158 | mp_obj_t argst = mp_obj_new_tuple(n_args - 1, args + 1); |
| pythontech | 0:5868e8752d44 | 159 | self->args = MP_OBJ_TO_PTR(argst); |
| pythontech | 0:5868e8752d44 | 160 | return mp_const_none; |
| pythontech | 0:5868e8752d44 | 161 | } |
| pythontech | 0:5868e8752d44 | 162 | STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(exc___init___obj, 1, MP_OBJ_FUN_ARGS_MAX, exc___init__); |
| pythontech | 0:5868e8752d44 | 163 | |
| pythontech | 0:5868e8752d44 | 164 | STATIC const mp_rom_map_elem_t exc_locals_dict_table[] = { |
| pythontech | 0:5868e8752d44 | 165 | { MP_ROM_QSTR(MP_QSTR___init__), MP_ROM_PTR(&exc___init___obj) }, |
| pythontech | 0:5868e8752d44 | 166 | }; |
| pythontech | 0:5868e8752d44 | 167 | |
| pythontech | 0:5868e8752d44 | 168 | STATIC MP_DEFINE_CONST_DICT(exc_locals_dict, exc_locals_dict_table); |
| pythontech | 0:5868e8752d44 | 169 | |
| pythontech | 0:5868e8752d44 | 170 | const mp_obj_type_t mp_type_BaseException = { |
| pythontech | 0:5868e8752d44 | 171 | { &mp_type_type }, |
| pythontech | 0:5868e8752d44 | 172 | .name = MP_QSTR_BaseException, |
| pythontech | 0:5868e8752d44 | 173 | .print = mp_obj_exception_print, |
| pythontech | 0:5868e8752d44 | 174 | .make_new = mp_obj_exception_make_new, |
| pythontech | 0:5868e8752d44 | 175 | .attr = exception_attr, |
| pythontech | 0:5868e8752d44 | 176 | .locals_dict = (mp_obj_dict_t*)&exc_locals_dict, |
| pythontech | 0:5868e8752d44 | 177 | }; |
| pythontech | 0:5868e8752d44 | 178 | |
| pythontech | 0:5868e8752d44 | 179 | #define MP_DEFINE_EXCEPTION_BASE(base_name) \ |
| pythontech | 0:5868e8752d44 | 180 | STATIC const mp_rom_obj_tuple_t mp_type_ ## base_name ## _base_tuple = {{&mp_type_tuple}, 1, {MP_ROM_PTR(&mp_type_ ## base_name)}};\ |
| pythontech | 0:5868e8752d44 | 181 | |
| pythontech | 0:5868e8752d44 | 182 | #define MP_DEFINE_EXCEPTION(exc_name, base_name) \ |
| pythontech | 0:5868e8752d44 | 183 | const mp_obj_type_t mp_type_ ## exc_name = { \ |
| pythontech | 0:5868e8752d44 | 184 | { &mp_type_type }, \ |
| pythontech | 0:5868e8752d44 | 185 | .name = MP_QSTR_ ## exc_name, \ |
| pythontech | 0:5868e8752d44 | 186 | .print = mp_obj_exception_print, \ |
| pythontech | 0:5868e8752d44 | 187 | .make_new = mp_obj_exception_make_new, \ |
| pythontech | 0:5868e8752d44 | 188 | .attr = exception_attr, \ |
| pythontech | 0:5868e8752d44 | 189 | .bases_tuple = (mp_obj_tuple_t*)(mp_rom_obj_tuple_t*)&mp_type_ ## base_name ## _base_tuple, \ |
| pythontech | 0:5868e8752d44 | 190 | }; |
| pythontech | 0:5868e8752d44 | 191 | |
| pythontech | 0:5868e8752d44 | 192 | // List of all exceptions, arranged as in the table at: |
| pythontech | 0:5868e8752d44 | 193 | // http://docs.python.org/3/library/exceptions.html |
| pythontech | 0:5868e8752d44 | 194 | MP_DEFINE_EXCEPTION_BASE(BaseException) |
| pythontech | 0:5868e8752d44 | 195 | MP_DEFINE_EXCEPTION(SystemExit, BaseException) |
| pythontech | 0:5868e8752d44 | 196 | MP_DEFINE_EXCEPTION(KeyboardInterrupt, BaseException) |
| pythontech | 0:5868e8752d44 | 197 | MP_DEFINE_EXCEPTION(GeneratorExit, BaseException) |
| pythontech | 0:5868e8752d44 | 198 | MP_DEFINE_EXCEPTION(Exception, BaseException) |
| pythontech | 0:5868e8752d44 | 199 | MP_DEFINE_EXCEPTION_BASE(Exception) |
| Colin Hogben |
2:c89e95946844 | 200 | #if MICROPY_PY_ASYNC_AWAIT |
| Colin Hogben |
2:c89e95946844 | 201 | MP_DEFINE_EXCEPTION(StopAsyncIteration, Exception) |
| Colin Hogben |
2:c89e95946844 | 202 | #endif |
| pythontech | 0:5868e8752d44 | 203 | MP_DEFINE_EXCEPTION(StopIteration, Exception) |
| pythontech | 0:5868e8752d44 | 204 | MP_DEFINE_EXCEPTION(ArithmeticError, Exception) |
| pythontech | 0:5868e8752d44 | 205 | MP_DEFINE_EXCEPTION_BASE(ArithmeticError) |
| pythontech | 0:5868e8752d44 | 206 | //MP_DEFINE_EXCEPTION(FloatingPointError, ArithmeticError) |
| pythontech | 0:5868e8752d44 | 207 | MP_DEFINE_EXCEPTION(OverflowError, ArithmeticError) |
| pythontech | 0:5868e8752d44 | 208 | MP_DEFINE_EXCEPTION(ZeroDivisionError, ArithmeticError) |
| pythontech | 0:5868e8752d44 | 209 | MP_DEFINE_EXCEPTION(AssertionError, Exception) |
| pythontech | 0:5868e8752d44 | 210 | MP_DEFINE_EXCEPTION(AttributeError, Exception) |
| pythontech | 0:5868e8752d44 | 211 | //MP_DEFINE_EXCEPTION(BufferError, Exception) |
| pythontech | 0:5868e8752d44 | 212 | //MP_DEFINE_EXCEPTION(EnvironmentError, Exception) use OSError instead |
| pythontech | 0:5868e8752d44 | 213 | MP_DEFINE_EXCEPTION(EOFError, Exception) |
| pythontech | 0:5868e8752d44 | 214 | MP_DEFINE_EXCEPTION(ImportError, Exception) |
| pythontech | 0:5868e8752d44 | 215 | //MP_DEFINE_EXCEPTION(IOError, Exception) use OSError instead |
| pythontech | 0:5868e8752d44 | 216 | MP_DEFINE_EXCEPTION(LookupError, Exception) |
| pythontech | 0:5868e8752d44 | 217 | MP_DEFINE_EXCEPTION_BASE(LookupError) |
| pythontech | 0:5868e8752d44 | 218 | MP_DEFINE_EXCEPTION(IndexError, LookupError) |
| pythontech | 0:5868e8752d44 | 219 | MP_DEFINE_EXCEPTION(KeyError, LookupError) |
| pythontech | 0:5868e8752d44 | 220 | MP_DEFINE_EXCEPTION(MemoryError, Exception) |
| pythontech | 0:5868e8752d44 | 221 | MP_DEFINE_EXCEPTION(NameError, Exception) |
| pythontech | 0:5868e8752d44 | 222 | /* |
| pythontech | 0:5868e8752d44 | 223 | MP_DEFINE_EXCEPTION_BASE(NameError) |
| pythontech | 0:5868e8752d44 | 224 | MP_DEFINE_EXCEPTION(UnboundLocalError, NameError) |
| pythontech | 0:5868e8752d44 | 225 | */ |
| pythontech | 0:5868e8752d44 | 226 | MP_DEFINE_EXCEPTION(OSError, Exception) |
| pythontech | 0:5868e8752d44 | 227 | #if MICROPY_PY_BUILTINS_TIMEOUTERROR |
| pythontech | 0:5868e8752d44 | 228 | MP_DEFINE_EXCEPTION_BASE(OSError) |
| pythontech | 0:5868e8752d44 | 229 | MP_DEFINE_EXCEPTION(TimeoutError, OSError) |
| pythontech | 0:5868e8752d44 | 230 | #endif |
| pythontech | 0:5868e8752d44 | 231 | /* |
| pythontech | 0:5868e8752d44 | 232 | MP_DEFINE_EXCEPTION(BlockingIOError, OSError) |
| pythontech | 0:5868e8752d44 | 233 | MP_DEFINE_EXCEPTION(ChildProcessError, OSError) |
| pythontech | 0:5868e8752d44 | 234 | MP_DEFINE_EXCEPTION(ConnectionError, OSError) |
| pythontech | 0:5868e8752d44 | 235 | MP_DEFINE_EXCEPTION(BrokenPipeError, ConnectionError) |
| pythontech | 0:5868e8752d44 | 236 | MP_DEFINE_EXCEPTION(ConnectionAbortedError, ConnectionError) |
| pythontech | 0:5868e8752d44 | 237 | MP_DEFINE_EXCEPTION(ConnectionRefusedError, ConnectionError) |
| pythontech | 0:5868e8752d44 | 238 | MP_DEFINE_EXCEPTION(ConnectionResetError, ConnectionError) |
| pythontech | 0:5868e8752d44 | 239 | MP_DEFINE_EXCEPTION(InterruptedError, OSError) |
| pythontech | 0:5868e8752d44 | 240 | MP_DEFINE_EXCEPTION(IsADirectoryError, OSError) |
| pythontech | 0:5868e8752d44 | 241 | MP_DEFINE_EXCEPTION(NotADirectoryError, OSError) |
| pythontech | 0:5868e8752d44 | 242 | MP_DEFINE_EXCEPTION(PermissionError, OSError) |
| pythontech | 0:5868e8752d44 | 243 | MP_DEFINE_EXCEPTION(ProcessLookupError, OSError) |
| pythontech | 0:5868e8752d44 | 244 | MP_DEFINE_EXCEPTION(FileExistsError, OSError) |
| pythontech | 0:5868e8752d44 | 245 | MP_DEFINE_EXCEPTION(FileNotFoundError, OSError) |
| pythontech | 0:5868e8752d44 | 246 | MP_DEFINE_EXCEPTION(ReferenceError, Exception) |
| pythontech | 0:5868e8752d44 | 247 | */ |
| pythontech | 0:5868e8752d44 | 248 | MP_DEFINE_EXCEPTION(RuntimeError, Exception) |
| pythontech | 0:5868e8752d44 | 249 | MP_DEFINE_EXCEPTION_BASE(RuntimeError) |
| pythontech | 0:5868e8752d44 | 250 | MP_DEFINE_EXCEPTION(NotImplementedError, RuntimeError) |
| pythontech | 0:5868e8752d44 | 251 | MP_DEFINE_EXCEPTION(SyntaxError, Exception) |
| pythontech | 0:5868e8752d44 | 252 | MP_DEFINE_EXCEPTION_BASE(SyntaxError) |
| pythontech | 0:5868e8752d44 | 253 | MP_DEFINE_EXCEPTION(IndentationError, SyntaxError) |
| pythontech | 0:5868e8752d44 | 254 | /* |
| pythontech | 0:5868e8752d44 | 255 | MP_DEFINE_EXCEPTION_BASE(IndentationError) |
| pythontech | 0:5868e8752d44 | 256 | MP_DEFINE_EXCEPTION(TabError, IndentationError) |
| pythontech | 0:5868e8752d44 | 257 | */ |
| pythontech | 0:5868e8752d44 | 258 | //MP_DEFINE_EXCEPTION(SystemError, Exception) |
| pythontech | 0:5868e8752d44 | 259 | MP_DEFINE_EXCEPTION(TypeError, Exception) |
| pythontech | 0:5868e8752d44 | 260 | #if MICROPY_EMIT_NATIVE |
| pythontech | 0:5868e8752d44 | 261 | MP_DEFINE_EXCEPTION_BASE(TypeError) |
| pythontech | 0:5868e8752d44 | 262 | MP_DEFINE_EXCEPTION(ViperTypeError, TypeError) |
| pythontech | 0:5868e8752d44 | 263 | #endif |
| pythontech | 0:5868e8752d44 | 264 | MP_DEFINE_EXCEPTION(ValueError, Exception) |
| pythontech | 0:5868e8752d44 | 265 | #if MICROPY_PY_BUILTINS_STR_UNICODE |
| pythontech | 0:5868e8752d44 | 266 | MP_DEFINE_EXCEPTION_BASE(ValueError) |
| pythontech | 0:5868e8752d44 | 267 | MP_DEFINE_EXCEPTION(UnicodeError, ValueError) |
| pythontech | 0:5868e8752d44 | 268 | //TODO: Implement more UnicodeError subclasses which take arguments |
| pythontech | 0:5868e8752d44 | 269 | #endif |
| pythontech | 0:5868e8752d44 | 270 | /* |
| pythontech | 0:5868e8752d44 | 271 | MP_DEFINE_EXCEPTION(Warning, Exception) |
| pythontech | 0:5868e8752d44 | 272 | MP_DEFINE_EXCEPTION_BASE(Warning) |
| pythontech | 0:5868e8752d44 | 273 | MP_DEFINE_EXCEPTION(DeprecationWarning, Warning) |
| pythontech | 0:5868e8752d44 | 274 | MP_DEFINE_EXCEPTION(PendingDeprecationWarning, Warning) |
| pythontech | 0:5868e8752d44 | 275 | MP_DEFINE_EXCEPTION(RuntimeWarning, Warning) |
| pythontech | 0:5868e8752d44 | 276 | MP_DEFINE_EXCEPTION(SyntaxWarning, Warning) |
| pythontech | 0:5868e8752d44 | 277 | MP_DEFINE_EXCEPTION(UserWarning, Warning) |
| pythontech | 0:5868e8752d44 | 278 | MP_DEFINE_EXCEPTION(FutureWarning, Warning) |
| pythontech | 0:5868e8752d44 | 279 | MP_DEFINE_EXCEPTION(ImportWarning, Warning) |
| pythontech | 0:5868e8752d44 | 280 | MP_DEFINE_EXCEPTION(UnicodeWarning, Warning) |
| pythontech | 0:5868e8752d44 | 281 | MP_DEFINE_EXCEPTION(BytesWarning, Warning) |
| pythontech | 0:5868e8752d44 | 282 | MP_DEFINE_EXCEPTION(ResourceWarning, Warning) |
| pythontech | 0:5868e8752d44 | 283 | */ |
| pythontech | 0:5868e8752d44 | 284 | |
| pythontech | 0:5868e8752d44 | 285 | mp_obj_t mp_obj_new_exception(const mp_obj_type_t *exc_type) { |
| pythontech | 0:5868e8752d44 | 286 | return mp_obj_new_exception_args(exc_type, 0, NULL); |
| pythontech | 0:5868e8752d44 | 287 | } |
| pythontech | 0:5868e8752d44 | 288 | |
| pythontech | 0:5868e8752d44 | 289 | // "Optimized" version for common(?) case of having 1 exception arg |
| pythontech | 0:5868e8752d44 | 290 | mp_obj_t mp_obj_new_exception_arg1(const mp_obj_type_t *exc_type, mp_obj_t arg) { |
| pythontech | 0:5868e8752d44 | 291 | return mp_obj_new_exception_args(exc_type, 1, &arg); |
| pythontech | 0:5868e8752d44 | 292 | } |
| pythontech | 0:5868e8752d44 | 293 | |
| pythontech | 0:5868e8752d44 | 294 | mp_obj_t mp_obj_new_exception_args(const mp_obj_type_t *exc_type, mp_uint_t n_args, const mp_obj_t *args) { |
| pythontech | 0:5868e8752d44 | 295 | assert(exc_type->make_new == mp_obj_exception_make_new); |
| pythontech | 0:5868e8752d44 | 296 | return exc_type->make_new(exc_type, n_args, 0, args); |
| pythontech | 0:5868e8752d44 | 297 | } |
| pythontech | 0:5868e8752d44 | 298 | |
| pythontech | 0:5868e8752d44 | 299 | mp_obj_t mp_obj_new_exception_msg(const mp_obj_type_t *exc_type, const char *msg) { |
| pythontech | 0:5868e8752d44 | 300 | return mp_obj_new_exception_msg_varg(exc_type, msg); |
| pythontech | 0:5868e8752d44 | 301 | } |
| pythontech | 0:5868e8752d44 | 302 | |
| pythontech | 0:5868e8752d44 | 303 | mp_obj_t mp_obj_new_exception_msg_varg(const mp_obj_type_t *exc_type, const char *fmt, ...) { |
| pythontech | 0:5868e8752d44 | 304 | // check that the given type is an exception type |
| pythontech | 0:5868e8752d44 | 305 | assert(exc_type->make_new == mp_obj_exception_make_new); |
| pythontech | 0:5868e8752d44 | 306 | |
| pythontech | 0:5868e8752d44 | 307 | // make exception object |
| pythontech | 0:5868e8752d44 | 308 | mp_obj_exception_t *o = m_new_obj_var_maybe(mp_obj_exception_t, mp_obj_t, 0); |
| pythontech | 0:5868e8752d44 | 309 | if (o == NULL) { |
| pythontech | 0:5868e8752d44 | 310 | // Couldn't allocate heap memory; use local data instead. |
| pythontech | 0:5868e8752d44 | 311 | // Unfortunately, we won't be able to format the string... |
| pythontech | 0:5868e8752d44 | 312 | o = &MP_STATE_VM(mp_emergency_exception_obj); |
| pythontech | 0:5868e8752d44 | 313 | o->base.type = exc_type; |
| pythontech | 0:5868e8752d44 | 314 | o->traceback_data = NULL; |
| pythontech | 0:5868e8752d44 | 315 | o->args = (mp_obj_tuple_t*)&mp_const_empty_tuple_obj; |
| pythontech | 0:5868e8752d44 | 316 | |
| pythontech | 0:5868e8752d44 | 317 | #if MICROPY_ENABLE_EMERGENCY_EXCEPTION_BUF |
| pythontech | 0:5868e8752d44 | 318 | // If the user has provided a buffer, then we try to create a tuple |
| pythontech | 0:5868e8752d44 | 319 | // of length 1, which has a string object and the string data. |
| pythontech | 0:5868e8752d44 | 320 | |
| pythontech | 0:5868e8752d44 | 321 | if (mp_emergency_exception_buf_size > (sizeof(mp_obj_tuple_t) + sizeof(mp_obj_str_t) + sizeof(mp_obj_t))) { |
| pythontech | 0:5868e8752d44 | 322 | mp_obj_tuple_t *tuple = (mp_obj_tuple_t *)MP_STATE_VM(mp_emergency_exception_buf); |
| pythontech | 0:5868e8752d44 | 323 | mp_obj_str_t *str = (mp_obj_str_t *)&tuple->items[1]; |
| pythontech | 0:5868e8752d44 | 324 | |
| pythontech | 0:5868e8752d44 | 325 | tuple->base.type = &mp_type_tuple; |
| pythontech | 0:5868e8752d44 | 326 | tuple->len = 1; |
| pythontech | 0:5868e8752d44 | 327 | tuple->items[0] = MP_OBJ_FROM_PTR(str); |
| pythontech | 0:5868e8752d44 | 328 | |
| pythontech | 0:5868e8752d44 | 329 | byte *str_data = (byte *)&str[1]; |
| pythontech | 0:5868e8752d44 | 330 | uint max_len = MP_STATE_VM(mp_emergency_exception_buf) + mp_emergency_exception_buf_size |
| pythontech | 0:5868e8752d44 | 331 | - str_data; |
| pythontech | 0:5868e8752d44 | 332 | |
| pythontech | 0:5868e8752d44 | 333 | vstr_t vstr; |
| pythontech | 0:5868e8752d44 | 334 | vstr_init_fixed_buf(&vstr, max_len, (char *)str_data); |
| pythontech | 0:5868e8752d44 | 335 | |
| pythontech | 0:5868e8752d44 | 336 | va_list ap; |
| pythontech | 0:5868e8752d44 | 337 | va_start(ap, fmt); |
| pythontech | 0:5868e8752d44 | 338 | vstr_vprintf(&vstr, fmt, ap); |
| pythontech | 0:5868e8752d44 | 339 | va_end(ap); |
| pythontech | 0:5868e8752d44 | 340 | |
| pythontech | 0:5868e8752d44 | 341 | str->base.type = &mp_type_str; |
| pythontech | 0:5868e8752d44 | 342 | str->hash = qstr_compute_hash(str_data, str->len); |
| pythontech | 0:5868e8752d44 | 343 | str->len = vstr.len; |
| pythontech | 0:5868e8752d44 | 344 | str->data = str_data; |
| pythontech | 0:5868e8752d44 | 345 | |
| pythontech | 0:5868e8752d44 | 346 | o->args = tuple; |
| pythontech | 0:5868e8752d44 | 347 | |
| pythontech | 0:5868e8752d44 | 348 | uint offset = &str_data[str->len] - MP_STATE_VM(mp_emergency_exception_buf); |
| pythontech | 0:5868e8752d44 | 349 | offset += sizeof(void *) - 1; |
| pythontech | 0:5868e8752d44 | 350 | offset &= ~(sizeof(void *) - 1); |
| pythontech | 0:5868e8752d44 | 351 | |
| pythontech | 0:5868e8752d44 | 352 | if ((mp_emergency_exception_buf_size - offset) > (sizeof(o->traceback_data[0]) * 3)) { |
| pythontech | 0:5868e8752d44 | 353 | // We have room to store some traceback. |
| pythontech | 0:5868e8752d44 | 354 | o->traceback_data = (size_t*)((byte *)MP_STATE_VM(mp_emergency_exception_buf) + offset); |
| pythontech | 0:5868e8752d44 | 355 | o->traceback_alloc = (MP_STATE_VM(mp_emergency_exception_buf) + mp_emergency_exception_buf_size - (byte *)o->traceback_data) / sizeof(o->traceback_data[0]); |
| pythontech | 0:5868e8752d44 | 356 | o->traceback_len = 0; |
| pythontech | 0:5868e8752d44 | 357 | } |
| pythontech | 0:5868e8752d44 | 358 | } |
| pythontech | 0:5868e8752d44 | 359 | #endif // MICROPY_ENABLE_EMERGENCY_EXCEPTION_BUF |
| pythontech | 0:5868e8752d44 | 360 | } else { |
| pythontech | 0:5868e8752d44 | 361 | o->base.type = exc_type; |
| pythontech | 0:5868e8752d44 | 362 | o->traceback_data = NULL; |
| pythontech | 0:5868e8752d44 | 363 | o->args = MP_OBJ_TO_PTR(mp_obj_new_tuple(1, NULL)); |
| pythontech | 0:5868e8752d44 | 364 | |
| pythontech | 0:5868e8752d44 | 365 | if (fmt == NULL) { |
| pythontech | 0:5868e8752d44 | 366 | // no message |
| pythontech | 0:5868e8752d44 | 367 | assert(0); |
| pythontech | 0:5868e8752d44 | 368 | } else { |
| pythontech | 0:5868e8752d44 | 369 | if (strchr(fmt, '%') == NULL) { |
| pythontech | 0:5868e8752d44 | 370 | // no formatting substitutions, avoid allocating vstr. |
| pythontech | 0:5868e8752d44 | 371 | o->args->items[0] = mp_obj_new_str(fmt, strlen(fmt), false); |
| pythontech | 0:5868e8752d44 | 372 | } else { |
| pythontech | 0:5868e8752d44 | 373 | // render exception message and store as .args[0] |
| pythontech | 0:5868e8752d44 | 374 | va_list ap; |
| pythontech | 0:5868e8752d44 | 375 | vstr_t vstr; |
| pythontech | 0:5868e8752d44 | 376 | vstr_init(&vstr, 16); |
| pythontech | 0:5868e8752d44 | 377 | va_start(ap, fmt); |
| pythontech | 0:5868e8752d44 | 378 | vstr_vprintf(&vstr, fmt, ap); |
| pythontech | 0:5868e8752d44 | 379 | va_end(ap); |
| pythontech | 0:5868e8752d44 | 380 | o->args->items[0] = mp_obj_new_str_from_vstr(&mp_type_str, &vstr); |
| pythontech | 0:5868e8752d44 | 381 | } |
| pythontech | 0:5868e8752d44 | 382 | } |
| pythontech | 0:5868e8752d44 | 383 | } |
| pythontech | 0:5868e8752d44 | 384 | |
| pythontech | 0:5868e8752d44 | 385 | return MP_OBJ_FROM_PTR(o); |
| pythontech | 0:5868e8752d44 | 386 | } |
| pythontech | 0:5868e8752d44 | 387 | |
| pythontech | 0:5868e8752d44 | 388 | // return true if the given object is an exception type |
| pythontech | 0:5868e8752d44 | 389 | bool mp_obj_is_exception_type(mp_obj_t self_in) { |
| pythontech | 0:5868e8752d44 | 390 | if (MP_OBJ_IS_TYPE(self_in, &mp_type_type)) { |
| pythontech | 0:5868e8752d44 | 391 | // optimisation when self_in is a builtin exception |
| pythontech | 0:5868e8752d44 | 392 | mp_obj_type_t *self = MP_OBJ_TO_PTR(self_in); |
| pythontech | 0:5868e8752d44 | 393 | if (self->make_new == mp_obj_exception_make_new) { |
| pythontech | 0:5868e8752d44 | 394 | return true; |
| pythontech | 0:5868e8752d44 | 395 | } |
| pythontech | 0:5868e8752d44 | 396 | } |
| pythontech | 0:5868e8752d44 | 397 | return mp_obj_is_subclass_fast(self_in, MP_OBJ_FROM_PTR(&mp_type_BaseException)); |
| pythontech | 0:5868e8752d44 | 398 | } |
| pythontech | 0:5868e8752d44 | 399 | |
| pythontech | 0:5868e8752d44 | 400 | // return true if the given object is an instance of an exception type |
| pythontech | 0:5868e8752d44 | 401 | bool mp_obj_is_exception_instance(mp_obj_t self_in) { |
| pythontech | 0:5868e8752d44 | 402 | return mp_obj_is_exception_type(MP_OBJ_FROM_PTR(mp_obj_get_type(self_in))); |
| pythontech | 0:5868e8752d44 | 403 | } |
| pythontech | 0:5868e8752d44 | 404 | |
| pythontech | 0:5868e8752d44 | 405 | // Return true if exception (type or instance) is a subclass of given |
| pythontech | 0:5868e8752d44 | 406 | // exception type. Assumes exc_type is a subclass of BaseException, as |
| pythontech | 0:5868e8752d44 | 407 | // defined by mp_obj_is_exception_type(exc_type). |
| pythontech | 0:5868e8752d44 | 408 | bool mp_obj_exception_match(mp_obj_t exc, mp_const_obj_t exc_type) { |
| pythontech | 0:5868e8752d44 | 409 | // if exc is an instance of an exception, then extract and use its type |
| pythontech | 0:5868e8752d44 | 410 | if (mp_obj_is_exception_instance(exc)) { |
| pythontech | 0:5868e8752d44 | 411 | exc = MP_OBJ_FROM_PTR(mp_obj_get_type(exc)); |
| pythontech | 0:5868e8752d44 | 412 | } |
| pythontech | 0:5868e8752d44 | 413 | return mp_obj_is_subclass_fast(exc, exc_type); |
| pythontech | 0:5868e8752d44 | 414 | } |
| pythontech | 0:5868e8752d44 | 415 | |
| pythontech | 0:5868e8752d44 | 416 | // traceback handling functions |
| pythontech | 0:5868e8752d44 | 417 | |
| pythontech | 0:5868e8752d44 | 418 | #define GET_NATIVE_EXCEPTION(self, self_in) \ |
| pythontech | 0:5868e8752d44 | 419 | /* make sure self_in is an exception instance */ \ |
| pythontech | 0:5868e8752d44 | 420 | assert(mp_obj_is_exception_instance(self_in)); \ |
| pythontech | 0:5868e8752d44 | 421 | mp_obj_exception_t *self; \ |
| pythontech | 0:5868e8752d44 | 422 | if (mp_obj_is_native_exception_instance(self_in)) { \ |
| pythontech | 0:5868e8752d44 | 423 | self = MP_OBJ_TO_PTR(self_in); \ |
| pythontech | 0:5868e8752d44 | 424 | } else { \ |
| pythontech | 0:5868e8752d44 | 425 | self = MP_OBJ_TO_PTR(((mp_obj_instance_t*)MP_OBJ_TO_PTR(self_in))->subobj[0]); \ |
| pythontech | 0:5868e8752d44 | 426 | } |
| pythontech | 0:5868e8752d44 | 427 | |
| pythontech | 0:5868e8752d44 | 428 | void mp_obj_exception_clear_traceback(mp_obj_t self_in) { |
| pythontech | 0:5868e8752d44 | 429 | GET_NATIVE_EXCEPTION(self, self_in); |
| pythontech | 0:5868e8752d44 | 430 | // just set the traceback to the null object |
| pythontech | 0:5868e8752d44 | 431 | // we don't want to call any memory management functions here |
| pythontech | 0:5868e8752d44 | 432 | self->traceback_data = NULL; |
| pythontech | 0:5868e8752d44 | 433 | } |
| pythontech | 0:5868e8752d44 | 434 | |
| pythontech | 0:5868e8752d44 | 435 | void mp_obj_exception_add_traceback(mp_obj_t self_in, qstr file, size_t line, qstr block) { |
| pythontech | 0:5868e8752d44 | 436 | GET_NATIVE_EXCEPTION(self, self_in); |
| pythontech | 0:5868e8752d44 | 437 | |
| pythontech | 0:5868e8752d44 | 438 | // append this traceback info to traceback data |
| pythontech | 0:5868e8752d44 | 439 | // if memory allocation fails (eg because gc is locked), just return |
| pythontech | 0:5868e8752d44 | 440 | |
| pythontech | 0:5868e8752d44 | 441 | if (self->traceback_data == NULL) { |
| pythontech | 0:5868e8752d44 | 442 | self->traceback_data = m_new_maybe(size_t, 3); |
| pythontech | 0:5868e8752d44 | 443 | if (self->traceback_data == NULL) { |
| pythontech | 0:5868e8752d44 | 444 | return; |
| pythontech | 0:5868e8752d44 | 445 | } |
| pythontech | 0:5868e8752d44 | 446 | self->traceback_alloc = 3; |
| pythontech | 0:5868e8752d44 | 447 | self->traceback_len = 0; |
| pythontech | 0:5868e8752d44 | 448 | } else if (self->traceback_len + 3 > self->traceback_alloc) { |
| pythontech | 0:5868e8752d44 | 449 | // be conservative with growing traceback data |
| pythontech | 0:5868e8752d44 | 450 | size_t *tb_data = m_renew_maybe(size_t, self->traceback_data, self->traceback_alloc, self->traceback_alloc + 3, true); |
| pythontech | 0:5868e8752d44 | 451 | if (tb_data == NULL) { |
| pythontech | 0:5868e8752d44 | 452 | return; |
| pythontech | 0:5868e8752d44 | 453 | } |
| pythontech | 0:5868e8752d44 | 454 | self->traceback_data = tb_data; |
| pythontech | 0:5868e8752d44 | 455 | self->traceback_alloc += 3; |
| pythontech | 0:5868e8752d44 | 456 | } |
| pythontech | 0:5868e8752d44 | 457 | |
| pythontech | 0:5868e8752d44 | 458 | size_t *tb_data = &self->traceback_data[self->traceback_len]; |
| pythontech | 0:5868e8752d44 | 459 | self->traceback_len += 3; |
| pythontech | 0:5868e8752d44 | 460 | tb_data[0] = file; |
| pythontech | 0:5868e8752d44 | 461 | tb_data[1] = line; |
| pythontech | 0:5868e8752d44 | 462 | tb_data[2] = block; |
| pythontech | 0:5868e8752d44 | 463 | } |
| pythontech | 0:5868e8752d44 | 464 | |
| pythontech | 0:5868e8752d44 | 465 | void mp_obj_exception_get_traceback(mp_obj_t self_in, size_t *n, size_t **values) { |
| pythontech | 0:5868e8752d44 | 466 | GET_NATIVE_EXCEPTION(self, self_in); |
| pythontech | 0:5868e8752d44 | 467 | |
| pythontech | 0:5868e8752d44 | 468 | if (self->traceback_data == NULL) { |
| pythontech | 0:5868e8752d44 | 469 | *n = 0; |
| pythontech | 0:5868e8752d44 | 470 | *values = NULL; |
| pythontech | 0:5868e8752d44 | 471 | } else { |
| pythontech | 0:5868e8752d44 | 472 | *n = self->traceback_len; |
| pythontech | 0:5868e8752d44 | 473 | *values = self->traceback_data; |
| pythontech | 0:5868e8752d44 | 474 | } |
| pythontech | 0:5868e8752d44 | 475 | } |