Skip to content

Commit b1917e3

Browse files
committed
shared/runtime/pyexec: Add __file__ support for frozen modules.
Set __file__ attribute for frozen boot.py/main.py modules during execution. Uses temporary storage to provide the module name to frozen MPY modules which bypass normal lexer-based __file__ setting. Signed-off-by: Andrew Leech <andrew.leech@planetinnovation.com.au>
1 parent 11241da commit b1917e3

File tree

1 file changed

+20
-11
lines changed

1 file changed

+20
-11
lines changed

shared/runtime/pyexec.c

Lines changed: 20 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ static bool repl_display_debugging_info = 0;
6464
// EXEC_FLAG_PRINT_EOF prints 2 EOF chars: 1 after normal output, 1 after exception output
6565
// EXEC_FLAG_ALLOW_DEBUGGING allows debugging info to be printed after executing the code
6666
// EXEC_FLAG_IS_REPL is used for REPL inputs (flag passed on to mp_compile)
67-
static int parse_compile_execute(const void *source, mp_parse_input_kind_t input_kind, mp_uint_t exec_flags) {
67+
static int parse_compile_execute(const void *source, mp_parse_input_kind_t input_kind, mp_uint_t exec_flags, const char *frozen_module_name) {
6868
int ret = 0;
6969
#if MICROPY_REPL_INFO
7070
uint32_t start = 0;
@@ -86,6 +86,14 @@ static int parse_compile_execute(const void *source, mp_parse_input_kind_t input
8686
ctx->module.globals = mp_globals_get();
8787
ctx->constants = frozen->constants;
8888
module_fun = mp_make_function_from_proto_fun(frozen->proto_fun, ctx, NULL);
89+
90+
#if MICROPY_PY___FILE__
91+
// Set __file__ for frozen MPY modules
92+
if (input_kind == MP_PARSE_FILE_INPUT && frozen_module_name != NULL) {
93+
qstr source_name = qstr_from_str(frozen_module_name);
94+
mp_store_global(MP_QSTR___file__, MP_OBJ_NEW_QSTR(source_name));
95+
}
96+
#endif
8997
} else
9098
#endif
9199
{
@@ -161,6 +169,7 @@ static int parse_compile_execute(const void *source, mp_parse_input_kind_t input
161169
// check for SystemExit
162170
if (mp_obj_is_subclass_fast(MP_OBJ_FROM_PTR(((mp_obj_base_t *)nlr.ret_val)->type), MP_OBJ_FROM_PTR(&mp_type_SystemExit))) {
163171
// Extract SystemExit value
172+
// None is an exit value of 0; an int is its value; anything else is 1
164173
mp_obj_t exit_val = mp_obj_exception_get_value(MP_OBJ_FROM_PTR(nlr.ret_val));
165174
mp_int_t val = 0;
166175
if (exit_val != mp_const_none && !mp_obj_get_int_maybe(exit_val, &val)) {
@@ -297,7 +306,7 @@ static int do_reader_stdin(int c) {
297306
mp_reader_stdin_t reader_stdin;
298307
mp_reader_new_stdin(&reader, &reader_stdin, MICROPY_REPL_STDIN_BUFFER_MAX);
299308
int exec_flags = EXEC_FLAG_PRINT_EOF | EXEC_FLAG_SOURCE_IS_READER;
300-
return parse_compile_execute(&reader, MP_PARSE_FILE_INPUT, exec_flags);
309+
return parse_compile_execute(&reader, MP_PARSE_FILE_INPUT, exec_flags, NULL);
301310
}
302311

303312
#if MICROPY_REPL_EVENT_DRIVEN
@@ -372,7 +381,7 @@ static int pyexec_raw_repl_process_char(int c) {
372381
return PYEXEC_FORCED_EXIT;
373382
}
374383

375-
int ret = parse_compile_execute(MP_STATE_VM(repl_line), MP_PARSE_FILE_INPUT, EXEC_FLAG_PRINT_EOF | EXEC_FLAG_SOURCE_IS_VSTR);
384+
int ret = parse_compile_execute(MP_STATE_VM(repl_line), MP_PARSE_FILE_INPUT, EXEC_FLAG_PRINT_EOF | EXEC_FLAG_SOURCE_IS_VSTR, NULL);
376385
if (ret & PYEXEC_FORCED_EXIT) {
377386
return ret;
378387
}
@@ -393,7 +402,7 @@ static int pyexec_friendly_repl_process_char(int c) {
393402
} else if (c == CHAR_CTRL_D) {
394403
// end of input
395404
mp_hal_stdout_tx_str("\r\n");
396-
int ret = parse_compile_execute(MP_STATE_VM(repl_line), MP_PARSE_FILE_INPUT, EXEC_FLAG_ALLOW_DEBUGGING | EXEC_FLAG_IS_REPL | EXEC_FLAG_SOURCE_IS_VSTR);
405+
int ret = parse_compile_execute(MP_STATE_VM(repl_line), MP_PARSE_FILE_INPUT, EXEC_FLAG_ALLOW_DEBUGGING | EXEC_FLAG_IS_REPL | EXEC_FLAG_SOURCE_IS_VSTR, NULL);
397406
if (ret & PYEXEC_FORCED_EXIT) {
398407
return ret;
399408
}
@@ -484,7 +493,7 @@ static int pyexec_friendly_repl_process_char(int c) {
484493
}
485494

486495
exec:;
487-
int ret = parse_compile_execute(MP_STATE_VM(repl_line), MP_PARSE_SINGLE_INPUT, EXEC_FLAG_ALLOW_DEBUGGING | EXEC_FLAG_IS_REPL | EXEC_FLAG_SOURCE_IS_VSTR);
496+
int ret = parse_compile_execute(MP_STATE_VM(repl_line), MP_PARSE_SINGLE_INPUT, EXEC_FLAG_ALLOW_DEBUGGING | EXEC_FLAG_IS_REPL | EXEC_FLAG_SOURCE_IS_VSTR, NULL);
488497
if (ret & PYEXEC_FORCED_EXIT) {
489498
return ret;
490499
}
@@ -567,7 +576,7 @@ int pyexec_raw_repl(void) {
567576
return PYEXEC_FORCED_EXIT;
568577
}
569578

570-
int ret = parse_compile_execute(&line, MP_PARSE_FILE_INPUT, EXEC_FLAG_PRINT_EOF | EXEC_FLAG_SOURCE_IS_VSTR);
579+
int ret = parse_compile_execute(&line, MP_PARSE_FILE_INPUT, EXEC_FLAG_PRINT_EOF | EXEC_FLAG_SOURCE_IS_VSTR, NULL);
571580
if (ret & PYEXEC_FORCED_EXIT) {
572581
return ret;
573582
}
@@ -692,7 +701,7 @@ int pyexec_friendly_repl(void) {
692701
}
693702
}
694703

695-
ret = parse_compile_execute(&line, parse_input_kind, EXEC_FLAG_ALLOW_DEBUGGING | EXEC_FLAG_IS_REPL | EXEC_FLAG_SOURCE_IS_VSTR);
704+
ret = parse_compile_execute(&line, parse_input_kind, EXEC_FLAG_ALLOW_DEBUGGING | EXEC_FLAG_IS_REPL | EXEC_FLAG_SOURCE_IS_VSTR, NULL);
696705
if (ret & PYEXEC_FORCED_EXIT) {
697706
return ret;
698707
}
@@ -703,7 +712,7 @@ int pyexec_friendly_repl(void) {
703712
#endif // MICROPY_ENABLE_COMPILER
704713

705714
int pyexec_file(const char *filename) {
706-
return parse_compile_execute(filename, MP_PARSE_FILE_INPUT, EXEC_FLAG_SOURCE_IS_FILENAME);
715+
return parse_compile_execute(filename, MP_PARSE_FILE_INPUT, EXEC_FLAG_SOURCE_IS_FILENAME, NULL);
707716
}
708717

709718

@@ -729,13 +738,13 @@ int pyexec_frozen_module(const char *name, bool allow_keyboard_interrupt) {
729738
switch (frozen_type) {
730739
#if MICROPY_MODULE_FROZEN_STR
731740
case MP_FROZEN_STR:
732-
return parse_compile_execute(frozen_data, MP_PARSE_FILE_INPUT, exec_flags);
741+
return parse_compile_execute(frozen_data, MP_PARSE_FILE_INPUT, exec_flags, NULL);
733742
#endif
734743

735744
#if MICROPY_MODULE_FROZEN_MPY
736745
case MP_FROZEN_MPY:
737746
return parse_compile_execute(frozen_data, MP_PARSE_FILE_INPUT, exec_flags |
738-
EXEC_FLAG_SOURCE_IS_RAW_CODE);
747+
EXEC_FLAG_SOURCE_IS_RAW_CODE, name);
739748
#endif
740749

741750
default:
@@ -747,7 +756,7 @@ int pyexec_frozen_module(const char *name, bool allow_keyboard_interrupt) {
747756

748757
int pyexec_vstr(vstr_t *str, bool allow_keyboard_interrupt) {
749758
mp_uint_t exec_flags = allow_keyboard_interrupt ? 0 : EXEC_FLAG_NO_INTERRUPT;
750-
return parse_compile_execute(str, MP_PARSE_FILE_INPUT, exec_flags | EXEC_FLAG_SOURCE_IS_VSTR);
759+
return parse_compile_execute(str, MP_PARSE_FILE_INPUT, exec_flags | EXEC_FLAG_SOURCE_IS_VSTR, NULL);
751760
}
752761

753762
#if MICROPY_REPL_INFO

0 commit comments

Comments
 (0)