Skip to content

Commit d8da586

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 d8da586

File tree

1 file changed

+21
-11
lines changed

1 file changed

+21
-11
lines changed

shared/runtime/pyexec.c

Lines changed: 21 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -59,12 +59,13 @@ static bool repl_display_debugging_info = 0;
5959
#define EXEC_FLAG_SOURCE_IS_READER (1 << 6)
6060
#define EXEC_FLAG_NO_INTERRUPT (1 << 7)
6161

62+
6263
// parses, compiles and executes the code in the lexer
6364
// frees the lexer before returning
6465
// EXEC_FLAG_PRINT_EOF prints 2 EOF chars: 1 after normal output, 1 after exception output
6566
// EXEC_FLAG_ALLOW_DEBUGGING allows debugging info to be printed after executing the code
6667
// 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) {
68+
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) {
6869
int ret = 0;
6970
#if MICROPY_REPL_INFO
7071
uint32_t start = 0;
@@ -86,6 +87,14 @@ static int parse_compile_execute(const void *source, mp_parse_input_kind_t input
8687
ctx->module.globals = mp_globals_get();
8788
ctx->constants = frozen->constants;
8889
module_fun = mp_make_function_from_proto_fun(frozen->proto_fun, ctx, NULL);
90+
91+
#if MICROPY_PY___FILE__
92+
// Set __file__ for frozen MPY modules
93+
if (input_kind == MP_PARSE_FILE_INPUT && frozen_module_name != NULL) {
94+
qstr source_name = qstr_from_str(frozen_module_name);
95+
mp_store_global(MP_QSTR___file__, MP_OBJ_NEW_QSTR(source_name));
96+
}
97+
#endif
8998
} else
9099
#endif
91100
{
@@ -161,6 +170,7 @@ static int parse_compile_execute(const void *source, mp_parse_input_kind_t input
161170
// check for SystemExit
162171
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))) {
163172
// Extract SystemExit value
173+
// None is an exit value of 0; an int is its value; anything else is 1
164174
mp_obj_t exit_val = mp_obj_exception_get_value(MP_OBJ_FROM_PTR(nlr.ret_val));
165175
mp_int_t val = 0;
166176
if (exit_val != mp_const_none && !mp_obj_get_int_maybe(exit_val, &val)) {
@@ -297,7 +307,7 @@ static int do_reader_stdin(int c) {
297307
mp_reader_stdin_t reader_stdin;
298308
mp_reader_new_stdin(&reader, &reader_stdin, MICROPY_REPL_STDIN_BUFFER_MAX);
299309
int exec_flags = EXEC_FLAG_PRINT_EOF | EXEC_FLAG_SOURCE_IS_READER;
300-
return parse_compile_execute(&reader, MP_PARSE_FILE_INPUT, exec_flags);
310+
return parse_compile_execute(&reader, MP_PARSE_FILE_INPUT, exec_flags, NULL);
301311
}
302312

303313
#if MICROPY_REPL_EVENT_DRIVEN
@@ -372,7 +382,7 @@ static int pyexec_raw_repl_process_char(int c) {
372382
return PYEXEC_FORCED_EXIT;
373383
}
374384

375-
int ret = parse_compile_execute(MP_STATE_VM(repl_line), MP_PARSE_FILE_INPUT, EXEC_FLAG_PRINT_EOF | EXEC_FLAG_SOURCE_IS_VSTR);
385+
int ret = parse_compile_execute(MP_STATE_VM(repl_line), MP_PARSE_FILE_INPUT, EXEC_FLAG_PRINT_EOF | EXEC_FLAG_SOURCE_IS_VSTR, NULL);
376386
if (ret & PYEXEC_FORCED_EXIT) {
377387
return ret;
378388
}
@@ -393,7 +403,7 @@ static int pyexec_friendly_repl_process_char(int c) {
393403
} else if (c == CHAR_CTRL_D) {
394404
// end of input
395405
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);
406+
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);
397407
if (ret & PYEXEC_FORCED_EXIT) {
398408
return ret;
399409
}
@@ -484,7 +494,7 @@ static int pyexec_friendly_repl_process_char(int c) {
484494
}
485495

486496
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);
497+
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);
488498
if (ret & PYEXEC_FORCED_EXIT) {
489499
return ret;
490500
}
@@ -567,7 +577,7 @@ int pyexec_raw_repl(void) {
567577
return PYEXEC_FORCED_EXIT;
568578
}
569579

570-
int ret = parse_compile_execute(&line, MP_PARSE_FILE_INPUT, EXEC_FLAG_PRINT_EOF | EXEC_FLAG_SOURCE_IS_VSTR);
580+
int ret = parse_compile_execute(&line, MP_PARSE_FILE_INPUT, EXEC_FLAG_PRINT_EOF | EXEC_FLAG_SOURCE_IS_VSTR, NULL);
571581
if (ret & PYEXEC_FORCED_EXIT) {
572582
return ret;
573583
}
@@ -692,7 +702,7 @@ int pyexec_friendly_repl(void) {
692702
}
693703
}
694704

695-
ret = parse_compile_execute(&line, parse_input_kind, EXEC_FLAG_ALLOW_DEBUGGING | EXEC_FLAG_IS_REPL | EXEC_FLAG_SOURCE_IS_VSTR);
705+
ret = parse_compile_execute(&line, parse_input_kind, EXEC_FLAG_ALLOW_DEBUGGING | EXEC_FLAG_IS_REPL | EXEC_FLAG_SOURCE_IS_VSTR, NULL);
696706
if (ret & PYEXEC_FORCED_EXIT) {
697707
return ret;
698708
}
@@ -703,7 +713,7 @@ int pyexec_friendly_repl(void) {
703713
#endif // MICROPY_ENABLE_COMPILER
704714

705715
int pyexec_file(const char *filename) {
706-
return parse_compile_execute(filename, MP_PARSE_FILE_INPUT, EXEC_FLAG_SOURCE_IS_FILENAME);
716+
return parse_compile_execute(filename, MP_PARSE_FILE_INPUT, EXEC_FLAG_SOURCE_IS_FILENAME, NULL);
707717
}
708718

709719

@@ -729,13 +739,13 @@ int pyexec_frozen_module(const char *name, bool allow_keyboard_interrupt) {
729739
switch (frozen_type) {
730740
#if MICROPY_MODULE_FROZEN_STR
731741
case MP_FROZEN_STR:
732-
return parse_compile_execute(frozen_data, MP_PARSE_FILE_INPUT, exec_flags);
742+
return parse_compile_execute(frozen_data, MP_PARSE_FILE_INPUT, exec_flags, NULL);
733743
#endif
734744

735745
#if MICROPY_MODULE_FROZEN_MPY
736746
case MP_FROZEN_MPY:
737747
return parse_compile_execute(frozen_data, MP_PARSE_FILE_INPUT, exec_flags |
738-
EXEC_FLAG_SOURCE_IS_RAW_CODE);
748+
EXEC_FLAG_SOURCE_IS_RAW_CODE, name);
739749
#endif
740750

741751
default:
@@ -747,7 +757,7 @@ int pyexec_frozen_module(const char *name, bool allow_keyboard_interrupt) {
747757

748758
int pyexec_vstr(vstr_t *str, bool allow_keyboard_interrupt) {
749759
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);
760+
return parse_compile_execute(str, MP_PARSE_FILE_INPUT, exec_flags | EXEC_FLAG_SOURCE_IS_VSTR, NULL);
751761
}
752762

753763
#if MICROPY_REPL_INFO

0 commit comments

Comments
 (0)