From e503512f83139429713b910d263a52732d8ceb15 Mon Sep 17 00:00:00 2001 From: Paul Sokolovsky Date: Sat, 25 Oct 2014 21:16:24 +0300 Subject: [PATCH] unix: Implement -m option (execute module from stdlib). Support for packages as argument not implemented, but otherwise error and exit handling should be correct. This for example will allow to do: pip-micropython install micropython-test.pystone micropython -m test.pystone --- py/builtinimport.c | 8 +++++ unix/main.c | 83 ++++++++++++++++++++++++++++++++++++---------- 2 files changed, 73 insertions(+), 18 deletions(-) diff --git a/py/builtinimport.c b/py/builtinimport.c index 80c4c77f68..af93aace91 100644 --- a/py/builtinimport.c +++ b/py/builtinimport.c @@ -286,6 +286,14 @@ mp_obj_t mp_builtin___import__(mp_uint_t n_args, const mp_obj_t *args) { module_obj = mp_obj_new_module(mod_name); + // if args[3] (fromtuple) has magic value False, set up + // this module for command-line "-m" option (set module's + // name to __main__ instead of real name). + if (i == mod_len && fromtuple == mp_const_false) { + mp_obj_module_t *o = module_obj; + mp_obj_dict_store(o->globals, MP_OBJ_NEW_QSTR(MP_QSTR___name__), MP_OBJ_NEW_QSTR(MP_QSTR___main__)); + } + if (stat == MP_IMPORT_STAT_DIR) { DEBUG_printf("%s is dir\n", vstr_str(&path)); // https://docs.python.org/3/reference/import.html diff --git a/unix/main.c b/unix/main.c index ca5dea99ac..7bfa96b273 100644 --- a/unix/main.c +++ b/unix/main.c @@ -47,6 +47,7 @@ #include "compile.h" #include "runtime0.h" #include "runtime.h" +#include "builtin.h" #include "repl.h" #include "gc.h" #include "genhdr/py-version.h" @@ -83,8 +84,28 @@ STATIC void sighandler(int signum) { #endif #define FORCED_EXIT (0x100) -// returns standard error codes: 0 for success, 1 for all other errors -// if FORCED_EXIT bit is set then script raised SystemExit and the +// If exc is SystemExit, return value where FORCED_EXIT bit set, +// and lower 8 bits are SystemExit value. For all other exceptions, +// return 1. +STATIC int handle_uncaught_exception(mp_obj_t exc) { + // check for SystemExit + if (mp_obj_is_subclass_fast(mp_obj_get_type(exc), &mp_type_SystemExit)) { + // None is an exit value of 0; an int is its value; anything else is 1 + mp_obj_t exit_val = mp_obj_exception_get_value(exc); + mp_int_t val = 0; + if (exit_val != mp_const_none && !mp_obj_get_int_maybe(exit_val, &val)) { + val = 1; + } + return FORCED_EXIT | (val & 255); + } + + // Report all other exceptions + mp_obj_print_exception(exc); + return 1; +} + +// Returns standard error codes: 0 for success, 1 for all other errors, +// except if FORCED_EXIT bit is set then script raised SystemExit and the // value of the exit is in the lower 8 bits of the return value STATIC int execute_from_lexer(mp_lexer_t *lex, mp_parse_input_kind_t input_kind, bool is_repl) { if (lex == NULL) { @@ -160,19 +181,7 @@ STATIC int execute_from_lexer(mp_lexer_t *lex, mp_parse_input_kind_t input_kind, #ifndef _WIN32 sigaction(SIGINT, &sa, NULL); #endif - // check for SystemExit - mp_obj_t exc = (mp_obj_t)nlr.ret_val; - if (mp_obj_is_subclass_fast(mp_obj_get_type(exc), &mp_type_SystemExit)) { - // None is an exit value of 0; an int is its value; anything else is 1 - mp_obj_t exit_val = mp_obj_exception_get_value(exc); - mp_int_t val = 0; - if (exit_val != mp_const_none && !mp_obj_get_int_maybe(exit_val, &val)) { - val = 1; - } - return FORCED_EXIT | (val & 255); - } - mp_obj_print_exception((mp_obj_t)nlr.ret_val); - return 1; + return handle_uncaught_exception((mp_obj_t)nlr.ret_val); } } @@ -320,6 +329,12 @@ void pre_process_options(int argc, char **argv) { } } +void set_sys_argv(char *argv[], int argc, int start_arg) { + for (int i = start_arg; i < argc; i++) { + mp_obj_list_append(mp_sys_argv, MP_OBJ_NEW_QSTR(qstr_from_str(argv[i]))); + } +} + #ifdef _WIN32 #define PATHLIST_SEP_CHAR ';' #else @@ -417,6 +432,40 @@ int main(int argc, char **argv) { break; } a += 1; + } else if (strcmp(argv[a], "-m") == 0) { + if (a + 1 >= argc) { + return usage(argv); + } + mp_obj_t import_args[4]; + import_args[0] = mp_obj_new_str(argv[a + 1], strlen(argv[a + 1]), false); + import_args[1] = import_args[2] = mp_const_none; + // Ask __import__ to handle imported module specially - set its __name__ + // to __main__, and also return this leaf module, not top-level package + // containing it. + import_args[3] = mp_const_false; + // TODO: https://docs.python.org/3/using/cmdline.html#cmdoption-m : + // "the first element of sys.argv will be the full path to + // the module file (while the module file is being located, + // the first element will be set to "-m")." + set_sys_argv(argv, argc, a + 1); + + mp_obj_t mod; + nlr_buf_t nlr; + if (nlr_push(&nlr) == 0) { + mod = mp_builtin___import__(MP_ARRAY_SIZE(import_args), import_args); + nlr_pop(); + } else { + // uncaught exception + return handle_uncaught_exception((mp_obj_t)nlr.ret_val); + } + + if (mp_obj_is_package(mod)) { + // TODO + fprintf(stderr, "%s: -m for packages not yet implemented\n", argv[0]); + exit(1); + } + ret = 0; + break; } else if (strcmp(argv[a], "-X") == 0) { a += 1; } else if (strcmp(argv[a], "-v") == 0) { @@ -447,9 +496,7 @@ int main(int argc, char **argv) { path_items[0] = MP_OBJ_NEW_QSTR(qstr_from_strn(basedir, p - basedir)); free(pathbuf); - for (int i = a; i < argc; i++) { - mp_obj_list_append(mp_sys_argv, MP_OBJ_NEW_QSTR(qstr_from_str(argv[i]))); - } + set_sys_argv(argv, argc, a); ret = do_file(argv[a]); break; }