diff options
| author | Jim Mussared <jim.mussared@gmail.com> | 2023-06-05 16:52:29 +1000 |
|---|---|---|
| committer | Jim Mussared <jim.mussared@gmail.com> | 2023-06-08 17:54:24 +1000 |
| commit | 5e50975a6dd9466afafbcd012c00078093fe1f57 (patch) | |
| tree | 92e29c7c944b69ed94c3f161c6c8519d5e7bed15 /ports/unix/main.c | |
| parent | 7d2ee8aed0cc5ba1a0041ac4cc7631898aaf252f (diff) | |
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>
Diffstat (limited to 'ports/unix/main.c')
| -rw-r--r-- | ports/unix/main.c | 66 |
1 files changed, 35 insertions, 31 deletions
diff --git a/ports/unix/main.c b/ports/unix/main.c index 16f663de1..b065706ba 100644 --- a/ports/unix/main.c +++ b/ports/unix/main.c @@ -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); |
