diff --git a/lib/micropython-lib b/lib/micropython-lib index 5b496e944ec04..f345a0db99b9d 160000 --- a/lib/micropython-lib +++ b/lib/micropython-lib @@ -1 +1 @@ -Subproject commit 5b496e944ec045177afa1620920a168410b7f60b +Subproject commit f345a0db99b9dc454ffcbfb13bfb68978467018d diff --git a/ports/unix/variants/standard/mpconfigvariant.h b/ports/unix/variants/standard/mpconfigvariant.h index 75201e9abc8d6..447832a7656b6 100644 --- a/ports/unix/variants/standard/mpconfigvariant.h +++ b/ports/unix/variants/standard/mpconfigvariant.h @@ -27,5 +27,7 @@ // Set base feature level. #define MICROPY_CONFIG_ROM_LEVEL (MICROPY_CONFIG_ROM_LEVEL_EXTRA_FEATURES) +#define MICROPY_PY_SYS_SETTRACE (1) + // Enable extra Unix features. #include "../mpconfigvariant_common.h" diff --git a/py/modsys.c b/py/modsys.c index 9ab02293b9063..3ce14bf5d17ad 100644 --- a/py/modsys.c +++ b/py/modsys.c @@ -238,6 +238,21 @@ static mp_obj_t mp_sys_settrace(mp_obj_t obj) { return mp_prof_settrace(obj); } MP_DEFINE_CONST_FUN_OBJ_1(mp_sys_settrace_obj, mp_sys_settrace); + +static mp_obj_t mp_sys_gettrace() { + return mp_prof_gettrace(); +} +MP_DEFINE_CONST_FUN_OBJ_0(mp_sys_gettrace_obj, mp_sys_gettrace); + +// _getframe(): Return current frame object. +static mp_obj_t mp_sys__getframe(size_t n_args, const mp_obj_t *args) { + size_t depth = 0; + if (n_args == 1) { + depth = mp_obj_get_int(args[0]); + } + return mp_prof_get_frame(depth); +} +MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_sys_getframe_obj, 0, 1, mp_sys__getframe); #endif // MICROPY_PY_SYS_SETTRACE #if MICROPY_PY_SYS_PATH && !MICROPY_PY_SYS_ATTR_DELEGATION @@ -322,6 +337,8 @@ static const mp_rom_map_elem_t mp_module_sys_globals_table[] = { #if MICROPY_PY_SYS_SETTRACE { MP_ROM_QSTR(MP_QSTR_settrace), MP_ROM_PTR(&mp_sys_settrace_obj) }, + { MP_ROM_QSTR(MP_QSTR_gettrace), MP_ROM_PTR(&mp_sys_gettrace_obj) }, + { MP_ROM_QSTR(MP_QSTR__getframe), MP_ROM_PTR(&mp_sys_getframe_obj) }, #endif #if MICROPY_PY_SYS_STDFILES diff --git a/py/objfun.c b/py/objfun.c index a742c5267254c..f71f7c9ee32bb 100644 --- a/py/objfun.c +++ b/py/objfun.c @@ -34,7 +34,8 @@ #include "py/objfun.h" #include "py/runtime.h" #include "py/bc.h" -#include "py/cstack.h" +#include "py/stackctrl.h" +#include "py/profile.h" #if MICROPY_DEBUG_VERBOSE // print debugging info #define DEBUG_PRINT (1) @@ -366,17 +367,13 @@ void mp_obj_fun_bc_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) { mp_obj_fun_bc_t *self = MP_OBJ_TO_PTR(self_in); dest[0] = MP_OBJ_FROM_PTR(self->context->module.globals); } - #if MICROPY_PY_FUNCTION_ATTRS_CODE + + #if MICROPY_PY_SYS_SETTRACE if (attr == MP_QSTR___code__) { - const mp_obj_fun_bc_t *self = MP_OBJ_TO_PTR(self_in); - if ((self->base.type == &mp_type_fun_bc - || self->base.type == &mp_type_gen_wrap) - && self->child_table == NULL) { - #if MICROPY_PY_BUILTINS_CODE <= MICROPY_PY_BUILTINS_CODE_BASIC - dest[0] = mp_obj_new_code(self->context->constants, self->bytecode); - #else - dest[0] = mp_obj_new_code(self->context, self->rc, true); - #endif + mp_obj_fun_bc_t *self = MP_OBJ_TO_PTR(self_in); + mp_obj_t code_obj = mp_obj_new_code(self->context, self->rc, false); + if (code_obj != MP_OBJ_NULL) { + dest[0] = code_obj; } } #endif diff --git a/py/profile.c b/py/profile.c index 397d0291f9fad..4b813bb0d7b06 100644 --- a/py/profile.c +++ b/py/profile.c @@ -86,17 +86,26 @@ static void frame_print(const mp_print_t *print, mp_obj_t o_in, mp_print_kind_t } static void frame_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) { - if (dest[0] != MP_OBJ_NULL) { + mp_obj_frame_t *o = MP_OBJ_TO_PTR(self_in); + + if (dest[0] == MP_OBJ_SENTINEL) { + // store attr + switch (attr) { + case MP_QSTR_f_trace: + o->f_trace = dest[1]; + dest[0] = MP_OBJ_NULL; + break; + } + return; + } else if (dest[0] != MP_OBJ_NULL) { // not load attribute return; } - mp_obj_frame_t *o = MP_OBJ_TO_PTR(self_in); - switch (attr) { case MP_QSTR_f_back: dest[0] = mp_const_none; - if (o->code_state->prev_state) { + if (o->code_state->prev_state && o->code_state->prev_state->frame) { dest[0] = MP_OBJ_FROM_PTR(o->code_state->prev_state->frame); } break; @@ -112,6 +121,12 @@ static void frame_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) { case MP_QSTR_f_lineno: dest[0] = MP_OBJ_NEW_SMALL_INT(o->lineno); break; + case MP_QSTR_f_trace: + dest[0] = o->f_trace; + break; + case MP_QSTR_f_locals: + dest[0] = mp_obj_new_dict(0); + break; } } @@ -148,6 +163,7 @@ mp_obj_t mp_obj_new_frame(const mp_code_state_t *code_state) { o->lineno = mp_prof_bytecode_lineno(rc, o->lasti); o->trace_opcodes = false; o->callback = MP_OBJ_NULL; + o->f_trace = MP_OBJ_NULL; return MP_OBJ_FROM_PTR(o); } @@ -187,6 +203,33 @@ mp_obj_t mp_prof_settrace(mp_obj_t callback) { return mp_const_none; } +mp_obj_t mp_prof_gettrace(void) { + if (prof_trace_cb == MP_OBJ_NULL) { + return mp_const_none; + } + return prof_trace_cb; +} + +mp_obj_t mp_prof_get_frame(size_t depth) { + + mp_code_state_t *code_state = MP_STATE_THREAD(current_code_state); + + for (size_t i = 0; i < depth; i++) { + code_state = code_state->prev_state; + if (code_state == NULL) { + mp_raise_ValueError(MP_ERROR_TEXT("call stack is not deep enough")); + } + } + + mp_obj_frame_t *frame = MP_OBJ_TO_PTR(mp_obj_new_frame(code_state)); + if (frame == NULL) { + // Couldn't allocate a frame object + return MP_OBJ_NULL; + } + + return MP_OBJ_FROM_PTR(frame); +} + mp_obj_t mp_prof_frame_enter(mp_code_state_t *code_state) { assert(!mp_prof_is_executing); diff --git a/py/profile.h b/py/profile.h index db72b9f076818..352deb34e23bc 100644 --- a/py/profile.h +++ b/py/profile.h @@ -43,6 +43,7 @@ typedef struct _mp_obj_frame_t { mp_uint_t lasti; mp_uint_t lineno; bool trace_opcodes; + mp_obj_t f_trace; } mp_obj_frame_t; uint mp_prof_bytecode_lineno(const mp_raw_code_t *rc, size_t bc); @@ -52,7 +53,9 @@ mp_obj_t mp_obj_new_frame(const mp_code_state_t *code_state); // This is the implementation for the sys.settrace mp_obj_t mp_prof_settrace(mp_obj_t callback); +mp_obj_t mp_prof_gettrace(void); +mp_obj_t mp_prof_get_frame(size_t depth); mp_obj_t mp_prof_frame_enter(mp_code_state_t *code_state); mp_obj_t mp_prof_frame_update(const mp_code_state_t *code_state); diff --git a/tests/misc/sys__getframe.py b/tests/misc/sys__getframe.py new file mode 100644 index 0000000000000..800921a41d493 --- /dev/null +++ b/tests/misc/sys__getframe.py @@ -0,0 +1,27 @@ +import sys + +try: + sys._getframe +except AttributeError: + print("SKIP") + raise SystemExit + +top_frame = sys._getframe() + +print(top_frame.f_code.co_name == "") + + +def new_frame(): + curr_frame = sys._getframe() + prev_frame = sys._getframe(1) + + print(curr_frame.f_code.co_name == "new_frame") + + print(prev_frame.f_code.co_name == "") + print(curr_frame.f_back.f_code.co_name == "") + + print(prev_frame.f_lineno == curr_frame.f_back.f_lineno) + print(prev_frame.f_code.co_filename == curr_frame.f_back.f_code.co_filename) + + +new_frame() pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy