summaryrefslogtreecommitdiff
path: root/ports/unix/main.c
diff options
context:
space:
mode:
authorJim Mussared <jim.mussared@gmail.com>2023-06-05 16:52:29 +1000
committerJim Mussared <jim.mussared@gmail.com>2023-06-08 17:54:24 +1000
commit5e50975a6dd9466afafbcd012c00078093fe1f57 (patch)
tree92e29c7c944b69ed94c3f161c6c8519d5e7bed15 /ports/unix/main.c
parent7d2ee8aed0cc5ba1a0041ac4cc7631898aaf252f (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.c66
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);