Skip to content
Snippets Groups Projects
Commit 8b85d14b authored by Paul Sokolovsky's avatar Paul Sokolovsky
Browse files

modsys: Add basic sys.exc_info() implementation.

The implementation is very basic and non-compliant and provided solely for
CPython compatibility. The function itself is bad Python2 heritage, its
usage is discouraged.
parent cf5b6f69
No related branches found
No related tags found
No related merge requests found
......@@ -121,6 +121,26 @@ STATIC mp_obj_t mp_sys_print_exception(mp_uint_t n_args, const mp_obj_t *args) {
}
MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_sys_print_exception_obj, 1, 2, mp_sys_print_exception);
#if MICROPY_PY_SYS_EXC_INFO
STATIC mp_obj_t mp_sys_exc_info(void) {
mp_obj_t cur_exc = MP_STATE_VM(cur_exception);
mp_obj_tuple_t *t = mp_obj_new_tuple(3, NULL);
if (cur_exc == MP_OBJ_NULL) {
t->items[0] = mp_const_none;
t->items[1] = mp_const_none;
t->items[2] = mp_const_none;
return t;
}
t->items[0] = mp_obj_get_type(cur_exc);
t->items[1] = cur_exc;
t->items[2] = mp_const_none;
return t;
}
MP_DEFINE_CONST_FUN_OBJ_0(mp_sys_exc_info_obj, mp_sys_exc_info);
#endif
STATIC const mp_map_elem_t mp_module_sys_globals_table[] = {
{ MP_OBJ_NEW_QSTR(MP_QSTR___name__), MP_OBJ_NEW_QSTR(MP_QSTR_sys) },
......@@ -163,6 +183,10 @@ STATIC const mp_map_elem_t mp_module_sys_globals_table[] = {
{ MP_OBJ_NEW_QSTR(MP_QSTR_stderr), (mp_obj_t)&mp_sys_stderr_obj },
#endif
#if MICROPY_PY_SYS_EXC_INFO
{ MP_OBJ_NEW_QSTR(MP_QSTR_exc_info), (mp_obj_t)&mp_sys_exc_info_obj },
#endif
/*
* Extensions to CPython
*/
......
......@@ -573,6 +573,12 @@ typedef double mp_float_t;
#define MICROPY_PY_SYS_MAXSIZE (0)
#endif
// Whether to provide "sys.exc_info" function
// Avoid enabling this, this function is Python2 heritage
#ifndef MICROPY_PY_SYS_EXC_INFO
#define MICROPY_PY_SYS_EXC_INFO (0)
#endif
// Whether to provide "sys.exit" function
#ifndef MICROPY_PY_SYS_EXIT
#define MICROPY_PY_SYS_EXIT (0)
......
......@@ -107,6 +107,11 @@ typedef struct _mp_state_vm_t {
// pending exception object (MP_OBJ_NULL if not pending)
mp_obj_t mp_pending_exception;
// current exception being handled, for sys.exc_info()
#if MICROPY_PY_SYS_EXC_INFO
mp_obj_t cur_exception;
#endif
// dictionary for the __main__ module
mp_obj_dict_t dict_main;
......
......@@ -457,6 +457,9 @@ Q(implementation)
#if MICROPY_PY_SYS_MAXSIZE
Q(maxsize)
#endif
#if MICROPY_PY_SYS_EXC_INFO
Q(exc_info)
#endif
Q(print_exception)
#endif
......
......@@ -1228,6 +1228,10 @@ pending_exception_check:
exception_handler:
// exception occurred
#if MICROPY_PY_SYS_EXC_INFO
MP_STATE_VM(cur_exception) = nlr.ret_val;
#endif
#if SELECTIVE_EXC_IP
// with selective ip, we store the ip 1 byte past the opcode, so move ptr back
code_state->ip -= 1;
......
import sys
try:
sys.exc_info
except:
print("SKIP")
sys.exit()
def f():
print(sys.exc_info()[0:2])
try:
1/0
except:
print(sys.exc_info()[0:2])
f()
# MicroPython currently doesn't reset sys.exc_info() value
# on exit from "except" block.
#f()
# Recursive except blocks are not handled either - just don't
# use exc_info() at all!
......@@ -171,6 +171,7 @@ def run_tests(pyb, tests, args):
skip_tests.add('misc/features.py') # requires raise_varargs
skip_tests.add('misc/rge_sm.py') # requires yield
skip_tests.add('misc/print_exception.py') # because native doesn't have proper traceback info
skip_tests.add('misc/sys_exc_info.py') # sys.exc_info() is not supported for native
for test_file in tests:
test_basename = os.path.basename(test_file)
......
......@@ -71,6 +71,7 @@
#define MICROPY_PY_SYS_PLATFORM "linux"
#define MICROPY_PY_SYS_MAXSIZE (1)
#define MICROPY_PY_SYS_STDFILES (1)
#define MICROPY_PY_SYS_EXC_INFO (1)
#define MICROPY_PY_COLLECTIONS_ORDEREDDICT (1)
#define MICROPY_PY_MATH_SPECIAL_FUNCTIONS (1)
#define MICROPY_PY_CMATH (1)
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment