Skip to content

Commit fb742cd

Browse files
committed
py/{builtinimport,frozenmod}: Rework frozen modules support to support packages.
Now frozen modules is treated just as a kind of VFS, and all operations performed on it correspond to operations on normal filesystem. This allows to support packages properly, and potentially also data files. This change also have changes to rework frozen bytecode modules support to use the same framework, but it's not finished (and actually may not work, as older adhox handling of any type of frozen modules is removed).
1 parent b580958 commit fb742cd

3 files changed

Lines changed: 45 additions & 33 deletions

File tree

py/builtinimport.c

Lines changed: 26 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -60,22 +60,32 @@ bool mp_obj_is_package(mp_obj_t module) {
6060
return dest[0] != MP_OBJ_NULL;
6161
}
6262

63+
// Stat either frozen or normal module by a given path
64+
// (whatever is available, if at all).
65+
STATIC mp_import_stat_t mp_import_stat_any(const char *path) {
66+
mp_import_stat_t st = mp_frozen_stat(path);
67+
if (st != MP_IMPORT_STAT_NO_EXIST) {
68+
return st;
69+
}
70+
return mp_import_stat(path);
71+
}
72+
6373
STATIC mp_import_stat_t stat_dir_or_file(vstr_t *path) {
64-
mp_import_stat_t stat = mp_import_stat(vstr_null_terminated_str(path));
74+
mp_import_stat_t stat = mp_import_stat_any(vstr_null_terminated_str(path));
6575
DEBUG_printf("stat %s: %d\n", vstr_str(path), stat);
6676
if (stat == MP_IMPORT_STAT_DIR) {
6777
return stat;
6878
}
6979

7080
vstr_add_str(path, ".py");
71-
stat = mp_import_stat(vstr_null_terminated_str(path));
81+
stat = mp_import_stat_any(vstr_null_terminated_str(path));
7282
if (stat == MP_IMPORT_STAT_FILE) {
7383
return stat;
7484
}
7585

7686
#if MICROPY_PERSISTENT_CODE_LOAD
7787
vstr_ins_byte(path, path->len - 2, 'm');
78-
stat = mp_import_stat(vstr_null_terminated_str(path));
88+
stat = mp_import_stat_any(vstr_null_terminated_str(path));
7989
if (stat == MP_IMPORT_STAT_FILE) {
8090
return stat;
8191
}
@@ -196,8 +206,18 @@ STATIC void do_load(mp_obj_t module_obj, vstr_t *file) {
196206

197207
#if MICROPY_ENABLE_COMPILER
198208
{
199-
mp_lexer_t *lex = mp_lexer_new_from_file(file_str);
200-
do_load_from_lexer(module_obj, lex, file_str);
209+
void *modref;
210+
int frozen_type = mp_find_frozen_module(file_str, file->len, &modref);
211+
#if MICROPY_PERSISTENT_CODE_LOAD
212+
if (frozen_type == MP_FROZEN_MPY) {
213+
do_execute_raw_code(module_obj, modref);
214+
return;
215+
}
216+
#endif
217+
if (frozen_type == MP_FROZEN_NONE) {
218+
modref = mp_lexer_new_from_file(file_str);
219+
}
220+
do_load_from_lexer(module_obj, modref, file_str);
201221
}
202222
#else
203223
nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ImportError,
@@ -340,33 +360,6 @@ mp_obj_t mp_builtin___import__(size_t n_args, const mp_obj_t *args) {
340360
}
341361
DEBUG_printf("Module not yet loaded\n");
342362

343-
#if MICROPY_MODULE_FROZEN
344-
void *frozen_data;
345-
int frozen_type = mp_find_frozen_module(mod_str, mod_len, &frozen_data);
346-
if (frozen_type != MP_FROZEN_NONE) {
347-
module_obj = mp_obj_new_module(module_name_qstr);
348-
// if args[3] (fromtuple) has magic value False, set up
349-
// this module for command-line "-m" option (set module's
350-
// name to __main__ instead of real name).
351-
// TODO: Duplicated below too.
352-
if (fromtuple == mp_const_false) {
353-
mp_obj_module_t *o = MP_OBJ_TO_PTR(module_obj);
354-
mp_obj_dict_store(MP_OBJ_FROM_PTR(o->globals), MP_OBJ_NEW_QSTR(MP_QSTR___name__), MP_OBJ_NEW_QSTR(MP_QSTR___main__));
355-
}
356-
#if MICROPY_MODULE_FROZEN_STR
357-
if (frozen_type == MP_FROZEN_STR) {
358-
do_load_from_lexer(module_obj, frozen_data, mod_str);
359-
}
360-
#endif
361-
#if MICROPY_MODULE_FROZEN_MPY
362-
if (frozen_type == MP_FROZEN_MPY) {
363-
do_execute_raw_code(module_obj, frozen_data);
364-
}
365-
#endif
366-
return module_obj;
367-
}
368-
#endif
369-
370363
uint last = 0;
371364
VSTR_FIXED(path, MICROPY_ALLOC_PATH_MAX)
372365
module_obj = MP_OBJ_NULL;
@@ -445,7 +438,7 @@ mp_obj_t mp_builtin___import__(size_t n_args, const mp_obj_t *args) {
445438
mp_store_attr(module_obj, MP_QSTR___path__, mp_obj_new_str(vstr_str(&path), vstr_len(&path), false));
446439
vstr_add_char(&path, PATH_SEP_CHAR);
447440
vstr_add_str(&path, "__init__.py");
448-
if (mp_import_stat(vstr_null_terminated_str(&path)) != MP_IMPORT_STAT_FILE) {
441+
if (mp_import_stat_any(vstr_null_terminated_str(&path)) != MP_IMPORT_STAT_FILE) {
449442
vstr_cut_tail_bytes(&path, sizeof("/__init__.py") - 1); // cut off /__init__.py
450443
mp_warning("%s is imported as namespace package", vstr_str(&path));
451444
} else {

py/frozenmod.c

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,24 @@ extern const char mp_frozen_str_names[];
4343
extern const uint32_t mp_frozen_str_sizes[];
4444
extern const char mp_frozen_str_content[];
4545

46+
mp_import_stat_t mp_frozen_stat(const char *str) {
47+
size_t len = strlen(str);
48+
const char *name = mp_frozen_str_names;
49+
50+
for (int i = 0; *name != 0; i++) {
51+
size_t l = strlen(name);
52+
if (l >= len && !memcmp(str, name, len)) {
53+
if (name[len] == 0) {
54+
return MP_IMPORT_STAT_FILE;
55+
} else if (name[len] == '/') {
56+
return MP_IMPORT_STAT_DIR;
57+
}
58+
}
59+
name += l + 1;
60+
}
61+
return MP_IMPORT_STAT_NO_EXIST;
62+
}
63+
4664
STATIC mp_lexer_t *mp_find_frozen_str(const char *str, size_t len) {
4765
const char *name = mp_frozen_str_names;
4866

py/frozenmod.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,3 +31,4 @@ enum {
3131
};
3232

3333
int mp_find_frozen_module(const char *str, size_t len, void **data);
34+
mp_import_stat_t mp_frozen_stat(const char *str);

0 commit comments

Comments
 (0)