summaryrefslogtreecommitdiff
path: root/py
diff options
context:
space:
mode:
authorJim Mussared <jim.mussared@gmail.com>2023-05-10 13:02:09 +1000
committerDamien George <damien@micropython.org>2023-06-01 16:03:21 +1000
commit42f3f66431bb3131f5ee78f3e121491e9d0fb91d (patch)
treed645e0abf05402ff9123915dc0d840a8eb274da0 /py
parent69dd013919461272b3669a516ef98d60accd3165 (diff)
py/builtinimport: Handle empty sys.path correctly.
If sys.path is enabled, but empty, this will now no longer search the filesystem. Previously an empty sys.path was equivalent to having `sys.path=[""]`. This is a breaking change, but this behavior now matches CPython. This also provides an alternative mechanism to the u-prefix to force an import of a builtin module: ``` import sys _path = sys.path[:] sys.path.clear() import foo # Forces the built-in foo. sys.path.extend(_path) del _path ``` Code size diff is -32 bytes on PYBV11. This work was funded through GitHub Sponsors. Signed-off-by: Jim Mussared <jim.mussared@gmail.com>
Diffstat (limited to 'py')
-rw-r--r--py/builtinimport.c49
1 files changed, 26 insertions, 23 deletions
diff --git a/py/builtinimport.c b/py/builtinimport.c
index e620c0377..025fff928 100644
--- a/py/builtinimport.c
+++ b/py/builtinimport.c
@@ -117,8 +117,9 @@ STATIC mp_import_stat_t stat_dir_or_file(vstr_t *path) {
return stat_file_py_or_mpy(path);
}
-// Given a top-level module, try and find it in each of the sys.path entries
-// via stat_dir_or_file.
+// Given a top-level module name, try and find it in each of the sys.path
+// entries. Note: On success, the dest argument will be updated to the matching
+// path (i.e. "<entry>/mod_name(.py)").
STATIC mp_import_stat_t stat_top_level_dir_or_file(qstr mod_name, vstr_t *dest) {
DEBUG_printf("stat_top_level_dir_or_file: '%s'\n", qstr_str(mod_name));
#if MICROPY_PY_SYS
@@ -126,32 +127,34 @@ STATIC mp_import_stat_t stat_top_level_dir_or_file(qstr mod_name, vstr_t *dest)
mp_obj_t *path_items;
mp_obj_list_get(mp_sys_path, &path_num, &path_items);
- if (path_num > 0) {
- // go through each path looking for a directory or file
- for (size_t i = 0; i < path_num; i++) {
- vstr_reset(dest);
- size_t p_len;
- const char *p = mp_obj_str_get_data(path_items[i], &p_len);
- if (p_len > 0) {
- vstr_add_strn(dest, p, p_len);
- vstr_add_char(dest, PATH_SEP_CHAR[0]);
- }
- vstr_add_str(dest, qstr_str(mod_name));
- mp_import_stat_t stat = stat_dir_or_file(dest);
- if (stat != MP_IMPORT_STAT_NO_EXIST) {
- return stat;
- }
+ // go through each sys.path entry, trying to import "<entry>/<mod_name>".
+ for (size_t i = 0; i < path_num; i++) {
+ vstr_reset(dest);
+ size_t p_len;
+ const char *p = mp_obj_str_get_data(path_items[i], &p_len);
+ if (p_len > 0) {
+ // Add the path separator (unless the entry is "", i.e. cwd).
+ vstr_add_strn(dest, p, p_len);
+ vstr_add_char(dest, PATH_SEP_CHAR[0]);
+ }
+ vstr_add_str(dest, qstr_str(mod_name));
+ mp_import_stat_t stat = stat_dir_or_file(dest);
+ if (stat != MP_IMPORT_STAT_NO_EXIST) {
+ return stat;
}
-
- // could not find a directory or file
- return MP_IMPORT_STAT_NO_EXIST;
}
- #endif
- // mp_sys_path is empty (or not enabled), so just stat the given path
- // directly.
+ // sys.path was empty or no matches, do not search the filesystem or
+ // frozen code.
+ return MP_IMPORT_STAT_NO_EXIST;
+
+ #else
+
+ // mp_sys_path is not enabled, so just stat the given path directly.
vstr_add_str(dest, qstr_str(mod_name));
return stat_dir_or_file(dest);
+
+ #endif
}
#if MICROPY_MODULE_FROZEN_STR || MICROPY_ENABLE_COMPILER