py/modsys: Allow sys.path to be assigned to.
Previously sys.path could be modified by append/pop or slice assignment. This allows `sys.path = [...]`, which can be simpler in many cases, but also improves CPython compatibility. It also allows sys.path to be set to a tuple which means that you can clear sys.path (e.g. temporarily) with no allocations. This also makes sys.path (and sys.argv for consistency) able to be disabled via mpconfig. The unix port (and upytesthelper) require them, so they explicitly verify that they're enabled. This work was funded through GitHub Sponsors. Signed-off-by: Jim Mussared <jim.mussared@gmail.com>
This commit is contained in:
@@ -69,6 +69,14 @@ long heap_size = 1024 * 1024 * (sizeof(mp_uint_t) / 4);
|
||||
#define MICROPY_GC_SPLIT_HEAP_N_HEAPS (1)
|
||||
#endif
|
||||
|
||||
#if !MICROPY_PY_SYS_PATH
|
||||
#error "The unix port requires MICROPY_PY_SYS_PATH=1"
|
||||
#endif
|
||||
|
||||
#if !MICROPY_PY_SYS_ARGV
|
||||
#error "The unix port requires MICROPY_PY_SYS_ARGV=1"
|
||||
#endif
|
||||
|
||||
STATIC void stderr_print_strn(void *env, const char *str, size_t len) {
|
||||
(void)env;
|
||||
ssize_t ret;
|
||||
@@ -538,44 +546,40 @@ MP_NOINLINE int main_(int argc, char **argv) {
|
||||
}
|
||||
#endif
|
||||
|
||||
char *home = getenv("HOME");
|
||||
char *path = getenv("MICROPYPATH");
|
||||
if (path == NULL) {
|
||||
path = MICROPY_PY_SYS_PATH_DEFAULT;
|
||||
}
|
||||
size_t path_num = 1; // [0] is for current dir (or base dir of the script)
|
||||
if (*path == PATHLIST_SEP_CHAR) {
|
||||
path_num++;
|
||||
}
|
||||
for (char *p = path; p != NULL; p = strchr(p, PATHLIST_SEP_CHAR)) {
|
||||
path_num++;
|
||||
if (p != NULL) {
|
||||
p++;
|
||||
}
|
||||
}
|
||||
mp_obj_list_init(MP_OBJ_TO_PTR(mp_sys_path), path_num);
|
||||
mp_obj_t *path_items;
|
||||
mp_obj_list_get(mp_sys_path, &path_num, &path_items);
|
||||
path_items[0] = MP_OBJ_NEW_QSTR(MP_QSTR_);
|
||||
{
|
||||
char *p = path;
|
||||
for (mp_uint_t i = 1; i < path_num; i++) {
|
||||
char *p1 = strchr(p, PATHLIST_SEP_CHAR);
|
||||
if (p1 == NULL) {
|
||||
p1 = p + strlen(p);
|
||||
// sys.path starts as [""]
|
||||
mp_sys_path = mp_obj_new_list(0, NULL);
|
||||
mp_obj_list_append(mp_sys_path, MP_OBJ_NEW_QSTR(MP_QSTR_));
|
||||
|
||||
// Add colon-separated entries from MICROPYPATH.
|
||||
char *home = getenv("HOME");
|
||||
char *path = getenv("MICROPYPATH");
|
||||
if (path == NULL) {
|
||||
path = MICROPY_PY_SYS_PATH_DEFAULT;
|
||||
}
|
||||
if (*path == PATHLIST_SEP_CHAR) {
|
||||
// First entry is empty. We've already added an empty entry to sys.path, so skip it.
|
||||
++path;
|
||||
}
|
||||
bool path_remaining = *path;
|
||||
while (path_remaining) {
|
||||
char *path_entry_end = strchr(path, PATHLIST_SEP_CHAR);
|
||||
if (path_entry_end == NULL) {
|
||||
path_entry_end = path + strlen(path);
|
||||
path_remaining = false;
|
||||
}
|
||||
if (p[0] == '~' && p[1] == '/' && home != NULL) {
|
||||
if (path[0] == '~' && path[1] == '/' && home != NULL) {
|
||||
// Expand standalone ~ to $HOME
|
||||
int home_l = strlen(home);
|
||||
vstr_t vstr;
|
||||
vstr_init(&vstr, home_l + (p1 - p - 1) + 1);
|
||||
vstr_init(&vstr, home_l + (path_entry_end - path - 1) + 1);
|
||||
vstr_add_strn(&vstr, home, home_l);
|
||||
vstr_add_strn(&vstr, p + 1, p1 - p - 1);
|
||||
path_items[i] = mp_obj_new_str_from_vstr(&vstr);
|
||||
vstr_add_strn(&vstr, path + 1, path_entry_end - path - 1);
|
||||
mp_obj_list_append(mp_sys_path, mp_obj_new_str_from_vstr(&vstr));
|
||||
} else {
|
||||
path_items[i] = mp_obj_new_str_via_qstr(p, p1 - p);
|
||||
mp_obj_list_append(mp_sys_path, mp_obj_new_str_via_qstr(path, path_entry_end - path));
|
||||
}
|
||||
p = p1 + 1;
|
||||
path = path_entry_end + 1;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -710,7 +714,7 @@ MP_NOINLINE int main_(int argc, char **argv) {
|
||||
|
||||
// Set base dir of the script as first entry in sys.path.
|
||||
char *p = strrchr(basedir, '/');
|
||||
path_items[0] = mp_obj_new_str_via_qstr(basedir, p - basedir);
|
||||
mp_obj_list_store(mp_sys_path, MP_OBJ_NEW_SMALL_INT(0), mp_obj_new_str_via_qstr(basedir, p - basedir));
|
||||
free(pathbuf);
|
||||
|
||||
set_sys_argv(argv, argc, a);
|
||||
|
||||
@@ -154,7 +154,7 @@ typedef long mp_off_t;
|
||||
// Ensure builtinimport.c works with -m.
|
||||
#define MICROPY_MODULE_OVERRIDE_MAIN_IMPORT (1)
|
||||
|
||||
// Don't default sys.argv because we do that in main.
|
||||
// Don't default sys.argv and sys.path because we do that in main.
|
||||
#define MICROPY_PY_SYS_PATH_ARGV_DEFAULTS (0)
|
||||
|
||||
// Enable sys.executable.
|
||||
|
||||
Reference in New Issue
Block a user