From e288cb35c3008a27ac5366501da6ca2d3a15a221 Mon Sep 17 00:00:00 2001 From: Andrew Leech Date: Wed, 22 Jun 2022 10:36:41 +1000 Subject: [PATCH 1/5] py/objfun: Add function.__code__ attribute. Only if MICROPY_PY_SYS_SETTRACE is enabled. This is used to provide introspection of attributes such as function name or source file & line. Signed-off-by: Andrew Leech --- py/objfun.c | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) 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 From a05fa05826df24fc41e1a3da6547344ef4d0bfb5 Mon Sep 17 00:00:00 2001 From: Andrew Leech Date: Mon, 21 Aug 2023 16:09:39 +0930 Subject: [PATCH 2/5] unix/standard: Enable sys.settrace() by default. Signed-off-by: Andrew Leech --- ports/unix/variants/standard/mpconfigvariant.h | 2 ++ 1 file changed, 2 insertions(+) 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" From 8d3dce03b90ae4d342b51463da5aa94b6c7d4e8e Mon Sep 17 00:00:00 2001 From: Andrew Leech Date: Thu, 16 Jun 2022 20:33:48 +1000 Subject: [PATCH 3/5] sys/settrace: Add sys._getframe() function. Refer to https://docs.python.org/3/library/sys.html#sys._getframe Signed-off-by: Andrew Leech --- py/modsys.c | 12 +++++++++ py/profile.c | 51 ++++++++++++++++++++++++++++++++++--- py/profile.h | 3 +++ tests/misc/sys__getframe.py | 27 ++++++++++++++++++++ 4 files changed, 89 insertions(+), 4 deletions(-) create mode 100644 tests/misc/sys__getframe.py diff --git a/py/modsys.c b/py/modsys.c index 9ab02293b9063..4b7cd0d22ff3d 100644 --- a/py/modsys.c +++ b/py/modsys.c @@ -238,6 +238,16 @@ 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); + +// _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 +332,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/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() From 872b5d9c5eded56550e4a5d8fbab0b18e9e27432 Mon Sep 17 00:00:00 2001 From: Andrew Leech Date: Wed, 11 Jun 2025 05:55:56 +1000 Subject: [PATCH 4/5] sys/gettrace: Add gettrace function to mirror settrace. Refer to https://docs.python.org/3/library/sys.html#sys.gettrace Signed-off-by: Andrew Leech --- py/modsys.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/py/modsys.c b/py/modsys.c index 4b7cd0d22ff3d..3ce14bf5d17ad 100644 --- a/py/modsys.c +++ b/py/modsys.c @@ -239,6 +239,11 @@ static mp_obj_t mp_sys_settrace(mp_obj_t 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; From a7ae5224c72c16b7853ea8d4e447e111aa75b7cf Mon Sep 17 00:00:00 2001 From: Andrew Leech Date: Wed, 11 Jun 2025 05:55:56 +1000 Subject: [PATCH 5/5] lib/micropython-lib: Update submodule to include debugpy support. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Updates micropython-lib submodule to include the new debugpy implementation that enables VS Code debugging support for MicroPython applications. The debugpy port provides: - Debug Adapter Protocol (DAP) compatibility with VS Code - Line breakpoints, stepping, and variable inspection - Integration with MicroPython's sys.settrace functionality - Network-based debugging via TCP socket connection This enables developers to debug MicroPython code using the familiar VS Code debugging interface, improving the development experience. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude --- lib/micropython-lib | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 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