2323 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
2424 * THE SOFTWARE.
2525 */
26+ #include <string.h>
27+
2628#include "py/obj.h"
2729#include "py/runtime.h"
2830#include "py/reload.h"
31+ #include "py/objstr.h"
2932
3033#include "lib/utils/interrupt_char.h"
3134#include "supervisor/shared/autoreload.h"
@@ -112,6 +115,98 @@ STATIC mp_obj_t supervisor_set_next_stack_limit(mp_obj_t size_obj) {
112115}
113116MP_DEFINE_CONST_FUN_OBJ_1 (supervisor_set_next_stack_limit_obj , supervisor_set_next_stack_limit );
114117
118+ //| def set_next_code_file(filename: Optional[str], *, reload_on_success : bool = False, reload_on_error: bool = False, sticky_on_success: bool = False, sticky_on_error: bool = False, sticky_on_reload: bool = False) -> None:
119+ //| """Set what file to run on the next vm run.
120+ //|
121+ //| When not ``None``, the given ``filename`` is inserted at the front of the usual ['code.py',
122+ //| 'main.py'] search sequence.
123+ //|
124+ //| The optional keyword arguments specify what happens after the specified file has run:
125+ //|
126+ //| ``sticky_on_…`` determine whether the newly set filename and options stay in effect: If
127+ //| True, further runs will continue to run that file (unless it says otherwise by calling
128+ //| ``set_next_code_filename()`` itself). If False, the settings will only affect one run and
129+ //| revert to the standard code.py/main.py afterwards.
130+ //|
131+ //| ``reload_on_…`` determine how to continue: If False, wait in the usual "Code done running.
132+ //| Waiting for reload. / Press any key to enter the REPL. Use CTRL-D to reload." state. If
133+ //| True, reload immediately as if CTRL-D was pressed.
134+ //|
135+ //| ``…_on_success`` take effect when the program runs to completion or calls ``sys.exit()``.
136+ //|
137+ //| ``…_on_error`` take effect when the program exits with an exception, including the
138+ //| KeyboardInterrupt caused by CTRL-C.
139+ //|
140+ //| ``…_on_reload`` take effect when the program is interrupted by files being written to the USB
141+ //| drive (auto-reload) or when it calls ``supervisor.reload()``.
142+ //|
143+ //| These settings are stored in RAM, not in persistent memory, and will therefore only affect
144+ //| soft reloads. Powering off or resetting the device will always revert to standard settings.
145+ //|
146+ //| When called multiple times in the same run, only the last call takes effect, replacing any
147+ //| settings made by previous ones. This is the main use of passing ``None`` as a filename: to
148+ //| reset to the standard search sequence."""
149+ //| ...
150+ //|
151+ STATIC mp_obj_t supervisor_set_next_code_file (size_t n_args , const mp_obj_t * pos_args , mp_map_t * kw_args ) {
152+ static const mp_arg_t allowed_args [] = {
153+ { MP_QSTR_filename , MP_ARG_REQUIRED | MP_ARG_OBJ , {.u_rom_obj = mp_const_none } },
154+ { MP_QSTR_reload_on_success , MP_ARG_KW_ONLY | MP_ARG_BOOL , {.u_bool = false} },
155+ { MP_QSTR_reload_on_error , MP_ARG_KW_ONLY | MP_ARG_BOOL , {.u_bool = false} },
156+ { MP_QSTR_sticky_on_success , MP_ARG_KW_ONLY | MP_ARG_BOOL , {.u_bool = false} },
157+ { MP_QSTR_sticky_on_error , MP_ARG_KW_ONLY | MP_ARG_BOOL , {.u_bool = false} },
158+ { MP_QSTR_sticky_on_reload , MP_ARG_KW_ONLY | MP_ARG_BOOL , {.u_bool = false} },
159+ };
160+ struct {
161+ mp_arg_val_t filename ;
162+ mp_arg_val_t reload_on_success ;
163+ mp_arg_val_t reload_on_error ;
164+ mp_arg_val_t sticky_on_success ;
165+ mp_arg_val_t sticky_on_error ;
166+ mp_arg_val_t sticky_on_reload ;
167+ } args ;
168+ mp_arg_parse_all (n_args , pos_args , kw_args , MP_ARRAY_SIZE (allowed_args ), allowed_args , (mp_arg_val_t * )& args );
169+ if (!mp_obj_is_str_or_bytes (args .filename .u_obj ) && args .filename .u_obj != mp_const_none ) {
170+ mp_raise_TypeError (translate ("argument has wrong type" ));
171+ }
172+ if (args .filename .u_obj == mp_const_none ) {
173+ args .filename .u_obj = mp_const_empty_bytes ;
174+ }
175+ uint8_t options = 0 ;
176+ if (args .reload_on_success .u_bool ) {
177+ options |= SUPERVISOR_NEXT_CODE_OPT_RELOAD_ON_SUCCESS ;
178+ }
179+ if (args .reload_on_error .u_bool ) {
180+ options |= SUPERVISOR_NEXT_CODE_OPT_RELOAD_ON_ERROR ;
181+ }
182+ if (args .sticky_on_success .u_bool ) {
183+ options |= SUPERVISOR_NEXT_CODE_OPT_STICKY_ON_SUCCESS ;
184+ }
185+ if (args .sticky_on_error .u_bool ) {
186+ options |= SUPERVISOR_NEXT_CODE_OPT_STICKY_ON_ERROR ;
187+ }
188+ if (args .sticky_on_reload .u_bool ) {
189+ options |= SUPERVISOR_NEXT_CODE_OPT_STICKY_ON_RELOAD ;
190+ }
191+ size_t len ;
192+ const char * filename = mp_obj_str_get_data (args .filename .u_obj , & len );
193+ free_memory (next_code_allocation );
194+ if (options != 0 || len != 0 ) {
195+ next_code_allocation = allocate_memory (align32_size (sizeof (next_code_info_t ) + len + 1 ), false, true);
196+ if (next_code_allocation == NULL ) {
197+ m_malloc_fail (sizeof (next_code_info_t ) + len + 1 );
198+ }
199+ next_code_info_t * next_code = (next_code_info_t * )next_code_allocation -> ptr ;
200+ next_code -> options = options | SUPERVISOR_NEXT_CODE_OPT_NEWLY_SET ;
201+ memcpy (& next_code -> filename , filename , len );
202+ next_code -> filename [len ] = '\0' ;
203+ } else {
204+ next_code_allocation = NULL ;
205+ }
206+ return mp_const_none ;
207+ }
208+ MP_DEFINE_CONST_FUN_OBJ_KW (supervisor_set_next_code_file_obj , 0 , supervisor_set_next_code_file );
209+
115210STATIC const mp_rom_map_elem_t supervisor_module_globals_table [] = {
116211 { MP_ROM_QSTR (MP_QSTR___name__ ), MP_ROM_QSTR (MP_QSTR_supervisor ) },
117212 { MP_ROM_QSTR (MP_QSTR_enable_autoreload ), MP_ROM_PTR (& supervisor_enable_autoreload_obj ) },
@@ -121,7 +216,7 @@ STATIC const mp_rom_map_elem_t supervisor_module_globals_table[] = {
121216 { MP_ROM_QSTR (MP_QSTR_reload ), MP_ROM_PTR (& supervisor_reload_obj ) },
122217 { MP_ROM_QSTR (MP_QSTR_RunReason ), MP_ROM_PTR (& supervisor_run_reason_type ) },
123218 { MP_ROM_QSTR (MP_QSTR_set_next_stack_limit ), MP_ROM_PTR (& supervisor_set_next_stack_limit_obj ) },
124-
219+ { MP_ROM_QSTR ( MP_QSTR_set_next_code_file ), MP_ROM_PTR ( & supervisor_set_next_code_file_obj ) },
125220};
126221
127222STATIC MP_DEFINE_CONST_DICT (supervisor_module_globals , supervisor_module_globals_table );
0 commit comments