Skip to content

Commit 3377765

Browse files
committed
Add working_directory for subsequent code file
This allows subfolders to be treated similar to / for multiple apps within different folders. Also, fix up the internal current working directory so it doesn't depend on volumes. Fixes #9045 and fixes #8409.
1 parent 443f829 commit 3377765

File tree

13 files changed

+189
-27
lines changed

13 files changed

+189
-27
lines changed

.gitmodules

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -173,7 +173,7 @@
173173
[submodule "ports/raspberrypi/sdk"]
174174
path = ports/raspberrypi/sdk
175175
url = https://github.com/adafruit/pico-sdk.git
176-
branch = force_inline_critical_section
176+
branch = force_inline_critical_section_2.1.1
177177
[submodule "data/nvm.toml"]
178178
path = data/nvm.toml
179179
url = https://github.com/adafruit/nvm.toml.git

extmod/vfs_fat.c

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@
3838

3939
// CIRCUITPY-CHANGE: extra includes
4040
#include <string.h>
41+
#include "py/gc.h"
4142
#include "py/obj.h"
4243
#include "py/objproperty.h"
4344
#include "py/runtime.h"
@@ -342,7 +343,10 @@ static mp_obj_t fat_vfs_stat(mp_obj_t vfs_in, mp_obj_t path_in) {
342343
FRESULT res = f_stat(&self->fatfs, path, &fno);
343344
if (res != FR_OK) {
344345
// CIRCUITPY-CHANGE
345-
mp_raise_OSError_fresult(res);
346+
if (gc_alloc_possible()) {
347+
mp_raise_OSError_fresult(res);
348+
}
349+
return mp_const_none;
346350
}
347351
}
348352

main.c

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -457,14 +457,19 @@ static bool __attribute__((noinline)) run_code_py(safe_mode_t safe_mode, bool *s
457457
usb_setup_with_vm();
458458
#endif
459459

460+
// Always return to root before trying to run files.
461+
common_hal_os_chdir("/");
460462
// Check if a different run file has been allocated
461463
if (next_code_configuration != NULL) {
462464
next_code_configuration->options &= ~SUPERVISOR_NEXT_CODE_OPT_NEWLY_SET;
463465
next_code_options = next_code_configuration->options;
464466
if (next_code_configuration->filename[0] != '\0') {
467+
if (next_code_configuration->working_directory != NULL) {
468+
common_hal_os_chdir(next_code_configuration->working_directory);
469+
}
465470
// This is where the user's python code is actually executed:
466471
const char *const filenames[] = { next_code_configuration->filename };
467-
found_main = maybe_run_list(filenames, MP_ARRAY_SIZE(filenames));
472+
found_main = maybe_run_list(filenames, 1);
468473
if (!found_main) {
469474
serial_write(next_code_configuration->filename);
470475
serial_write_compressed(MP_ERROR_TEXT(" not found.\n"));
@@ -1105,9 +1110,6 @@ int __attribute__((used)) main(void) {
11051110
}
11061111
simulate_reset = false;
11071112

1108-
// Always return to root before trying to run files.
1109-
common_hal_os_chdir("/");
1110-
11111113
if (pyexec_mode_kind == PYEXEC_MODE_FRIENDLY_REPL) {
11121114
// If code.py did a fake deep sleep, pretend that we
11131115
// are running code.py for the first time after a hard

ports/atmel-samd/boards/circuitbrains_basic_m0/mpconfigboard.mk

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,4 +10,5 @@ SPI_FLASH_FILESYSTEM = 1
1010
EXTERNAL_FLASH_DEVICES = "W25Q32JVxQ"
1111
LONGINT_IMPL = MPZ
1212

13+
CIRCUITPY_CODEOP = 0
1314
CIRCUITPY_JPEGIO = 0

ports/atmel-samd/boards/feather_m0_supersized/mpconfigboard.mk

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,3 +9,5 @@ CHIP_FAMILY = samd21
99
SPI_FLASH_FILESYSTEM = 1
1010
EXTERNAL_FLASH_DEVICES = "S25FL064L"
1111
LONGINT_IMPL = MPZ
12+
13+
CIRCUITPY_CODEOP = 0

shared-bindings/os/__init__.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
#include <stdbool.h>
1111

1212
#include "py/objtuple.h"
13+
#include "shared-module/os/__init__.h"
1314

1415
void common_hal_os_chdir(const char *path);
1516
mp_obj_t common_hal_os_getcwd(void);

shared-bindings/supervisor/__init__.c

Lines changed: 46 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
// SPDX-FileCopyrightText: Copyright (c) 2016-2017 Scott Shawcroft for Adafruit Industries
44
//
55
// SPDX-License-Identifier: MIT
6+
#include <stddef.h>
67
#include <string.h>
78

89
#include "py/obj.h"
@@ -25,6 +26,7 @@
2526
#include "shared-bindings/time/__init__.h"
2627
#include "shared-bindings/supervisor/Runtime.h"
2728
#include "shared-bindings/supervisor/StatusBar.h"
29+
#include "shared-bindings/util.h"
2830

2931
//| """Supervisor settings"""
3032
//|
@@ -57,6 +59,7 @@ MP_DEFINE_CONST_FUN_OBJ_0(supervisor_reload_obj, supervisor_reload);
5759
//| def set_next_code_file(
5860
//| filename: Optional[str],
5961
//| *,
62+
//| working_directory: Optional[str] = None,
6063
//| reload_on_success: bool = False,
6164
//| reload_on_error: bool = False,
6265
//| sticky_on_success: bool = False,
@@ -99,6 +102,7 @@ MP_DEFINE_CONST_FUN_OBJ_0(supervisor_reload_obj, supervisor_reload);
99102
static mp_obj_t supervisor_set_next_code_file(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
100103
static const mp_arg_t allowed_args[] = {
101104
{ MP_QSTR_filename, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_rom_obj = mp_const_none} },
105+
{ MP_QSTR_working_directory, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_rom_obj = mp_const_none} },
102106
{ MP_QSTR_reload_on_success, MP_ARG_KW_ONLY | MP_ARG_BOOL, {.u_bool = false} },
103107
{ MP_QSTR_reload_on_error, MP_ARG_KW_ONLY | MP_ARG_BOOL, {.u_bool = false} },
104108
{ MP_QSTR_sticky_on_success, MP_ARG_KW_ONLY | MP_ARG_BOOL, {.u_bool = false} },
@@ -107,6 +111,7 @@ static mp_obj_t supervisor_set_next_code_file(size_t n_args, const mp_obj_t *pos
107111
};
108112
struct {
109113
mp_arg_val_t filename;
114+
mp_arg_val_t working_directory;
110115
mp_arg_val_t reload_on_success;
111116
mp_arg_val_t reload_on_error;
112117
mp_arg_val_t sticky_on_success;
@@ -118,6 +123,11 @@ static mp_obj_t supervisor_set_next_code_file(size_t n_args, const mp_obj_t *pos
118123
if (!mp_obj_is_str_or_bytes(filename_obj) && filename_obj != mp_const_none) {
119124
mp_raise_TypeError_varg(MP_ERROR_TEXT("%q must be of type %q or %q, not %q"), MP_QSTR_filename, MP_QSTR_str, MP_QSTR_None, mp_obj_get_type(filename_obj)->name);
120125
}
126+
127+
mp_obj_t working_directory_obj = args.working_directory.u_obj;
128+
if (!mp_obj_is_str_or_bytes(working_directory_obj) && working_directory_obj != mp_const_none) {
129+
mp_raise_TypeError_varg(MP_ERROR_TEXT("%q must be of type %q or %q, not %q"), MP_QSTR_working_directory, MP_QSTR_str, MP_QSTR_None, mp_obj_get_type(working_directory_obj)->name);
130+
}
121131
if (filename_obj == mp_const_none) {
122132
filename_obj = mp_const_empty_bytes;
123133
}
@@ -139,18 +149,50 @@ static mp_obj_t supervisor_set_next_code_file(size_t n_args, const mp_obj_t *pos
139149
}
140150
size_t len;
141151
const char *filename = mp_obj_str_get_data(filename_obj, &len);
152+
if (!path_exists(filename)) {
153+
mp_raise_ValueError(MP_ERROR_TEXT("File not found"));
154+
}
155+
156+
size_t working_directory_len = 0;
157+
const char *working_directory = NULL;
158+
if (working_directory_obj != mp_const_none) {
159+
working_directory = mp_obj_str_get_data(working_directory_obj, &working_directory_len);
160+
if (!path_exists(working_directory)) {
161+
mp_raise_ValueError_varg(MP_ERROR_TEXT("Invalid %q"), MP_QSTR_working_directory);
162+
}
163+
}
142164
if (next_code_configuration != NULL) {
143165
port_free(next_code_configuration);
144166
next_code_configuration = NULL;
145167
}
146168
if (options != 0 || len != 0) {
147-
next_code_configuration = port_malloc(sizeof(supervisor_next_code_info_t) + len + 1, false);
169+
170+
size_t next_code_size = sizeof(supervisor_next_code_info_t) + len + 1;
171+
if (working_directory_len > 0) {
172+
next_code_size += working_directory_len + 1;
173+
}
174+
next_code_configuration = port_malloc(next_code_size, false);
148175
if (next_code_configuration == NULL) {
149-
m_malloc_fail(sizeof(supervisor_next_code_info_t) + len + 1);
176+
m_malloc_fail(next_code_size);
177+
}
178+
char *filename_ptr = (char *)next_code_configuration + sizeof(supervisor_next_code_info_t);
179+
180+
// Copy filename
181+
memcpy(filename_ptr, filename, len);
182+
filename_ptr[len] = '\0';
183+
184+
char *working_directory_ptr = NULL;
185+
// Copy working directory after filename if present
186+
if (working_directory_len > 0) {
187+
working_directory_ptr = filename_ptr + len + 1;
188+
memcpy(working_directory_ptr, working_directory, working_directory_len);
189+
working_directory_ptr[working_directory_len] = '\0';
150190
}
191+
// Set everything up last. We may have raised an exception early and we
192+
// don't want to free the memory if we failed.
193+
next_code_configuration->filename = filename_ptr;
194+
next_code_configuration->working_directory = working_directory_ptr;
151195
next_code_configuration->options = options | SUPERVISOR_NEXT_CODE_OPT_NEWLY_SET;
152-
memcpy(&next_code_configuration->filename, filename, len);
153-
next_code_configuration->filename[len] = '\0';
154196
}
155197
return mp_const_none;
156198
}

shared-bindings/supervisor/__init__.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@
66

77
#pragma once
88

9+
#include <stddef.h>
10+
#include <stdint.h>
911
// #include "py/mpconfig.h"
1012
#include "py/obj.h"
1113

@@ -18,7 +20,8 @@
1820

1921
typedef struct {
2022
uint8_t options;
21-
char filename[];
23+
const char *working_directory;
24+
const char *filename;
2225
} supervisor_next_code_info_t;
2326

2427
extern const super_runtime_obj_t common_hal_supervisor_runtime_obj;

shared-bindings/util.c

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@
88

99
#include "shared-bindings/util.h"
1010

11+
#include "shared-bindings/os/__init__.h"
12+
1113
// If so, deinit() has already been called on the object, so complain.
1214
void raise_deinited_error(void) {
1315
mp_raise_ValueError(MP_ERROR_TEXT("Object has been deinitialized and can no longer be used. Create a new object."));
@@ -33,3 +35,16 @@ void properties_construct_helper(mp_obj_t self_in, const mp_arg_t *args, const m
3335
}
3436
}
3537
}
38+
39+
bool path_exists(const char *path) {
40+
// Use common_hal_os_stat to check if path exists
41+
nlr_buf_t nlr;
42+
if (nlr_push(&nlr) == 0) {
43+
common_hal_os_stat(path);
44+
nlr_pop();
45+
return true;
46+
} else {
47+
// Path doesn't exist
48+
return false;
49+
}
50+
}

shared-bindings/util.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,3 +12,4 @@
1212
NORETURN void raise_deinited_error(void);
1313
void properties_print_helper(const mp_print_t *print, mp_obj_t self_in, const mp_arg_t *properties, size_t n_properties);
1414
void properties_construct_helper(mp_obj_t self_in, const mp_arg_t *args, const mp_arg_val_t *vals, size_t n_properties);
15+
bool path_exists(const char *path);

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy