From b5fd9ad05e0f15f8272b8f1b829af22077230584 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Thu, 14 Dec 2017 02:20:52 +0100 Subject: [PATCH] bpo-32030: Rewrite _PyMainInterpreterConfig (#4854) _PyMainInterpreterConfig now contains Python objects, whereas _PyCoreConfig contains wchar_t* strings. Core config: * Rename _PyMainInterpreterConfig_ReadEnv() to _PyCoreConfig_ReadEnv() * Move 3 strings from _PyMainInterpreterConfig to _PyCoreConfig: module_search_path_env, home, program_name. * Add _PyCoreConfig_Clear() * _PyPathConfig_Calculate() now takes core config rather than main config * _PyMainInterpreterConfig_Read() now requires also a core config Main config: * Add _PyMainInterpreterConfig.module_search_path: sys.path list * Add _PyMainInterpreterConfig.argv: sys.argv list * _PyMainInterpreterConfig_Read() now computes module_search_path --- Include/internal/pystate.h | 2 +- Include/pylifecycle.h | 10 +- Include/pystate.h | 13 +- Modules/getpath.c | 59 ++++---- Modules/main.c | 289 ++++++++++++++++++++++++------------- PC/getpathp.c | 45 +++--- Python/pathconfig.c | 22 +-- Python/pylifecycle.c | 42 +++--- 8 files changed, 285 insertions(+), 197 deletions(-) diff --git a/Include/internal/pystate.h b/Include/internal/pystate.h index 6b527fbe214..305526d136c 100644 --- a/Include/internal/pystate.h +++ b/Include/internal/pystate.h @@ -61,7 +61,7 @@ PyAPI_DATA(_PyPathConfig) _Py_path_config; PyAPI_FUNC(_PyInitError) _PyPathConfig_Calculate( _PyPathConfig *config, - const _PyMainInterpreterConfig *main_config); + const _PyCoreConfig *core_config); PyAPI_FUNC(void) _PyPathConfig_Clear(_PyPathConfig *config); diff --git a/Include/pylifecycle.h b/Include/pylifecycle.h index 17ed110b83b..61ed6ccf021 100644 --- a/Include/pylifecycle.h +++ b/Include/pylifecycle.h @@ -54,8 +54,11 @@ PyAPI_FUNC(int) Py_SetStandardStreamEncoding(const char *encoding, PyAPI_FUNC(_PyInitError) _Py_InitializeCore(const _PyCoreConfig *); PyAPI_FUNC(int) _Py_IsCoreInitialized(void); -PyAPI_FUNC(_PyInitError) _PyMainInterpreterConfig_Read(_PyMainInterpreterConfig *); -PyAPI_FUNC(_PyInitError) _PyMainInterpreterConfig_ReadEnv(_PyMainInterpreterConfig *); +PyAPI_FUNC(_PyInitError) _PyCoreConfig_ReadEnv(_PyCoreConfig *); +PyAPI_FUNC(_PyInitError) _PyCoreConfig_Read(_PyCoreConfig *); +PyAPI_FUNC(void) _PyCoreConfig_Clear(_PyCoreConfig *); + +PyAPI_FUNC(_PyInitError) _PyMainInterpreterConfig_Read(_PyMainInterpreterConfig *, _PyCoreConfig *); PyAPI_FUNC(void) _PyMainInterpreterConfig_Clear(_PyMainInterpreterConfig *); PyAPI_FUNC(_PyInitError) _Py_InitializeMainInterpreter(const _PyMainInterpreterConfig *); @@ -103,8 +106,7 @@ PyAPI_FUNC(wchar_t *) Py_GetPrefix(void); PyAPI_FUNC(wchar_t *) Py_GetExecPrefix(void); PyAPI_FUNC(wchar_t *) Py_GetPath(void); #ifdef Py_BUILD_CORE -PyAPI_FUNC(_PyInitError) _PyPathConfig_Init( - const _PyMainInterpreterConfig *main_config); +PyAPI_FUNC(_PyInitError) _PyPathConfig_Init(const _PyCoreConfig *core_config); PyAPI_FUNC(PyObject*) _PyPathConfig_ComputeArgv0(int argc, wchar_t **argv); #endif PyAPI_FUNC(void) Py_SetPath(const wchar_t *); diff --git a/Include/pystate.h b/Include/pystate.h index c7ea179cf7d..9a26cc3909f 100644 --- a/Include/pystate.h +++ b/Include/pystate.h @@ -39,6 +39,11 @@ typedef struct { int dump_refs; /* PYTHONDUMPREFS */ int malloc_stats; /* PYTHONMALLOCSTATS */ int utf8_mode; /* -X utf8 or PYTHONUTF8 environment variable */ + + wchar_t *module_search_path_env; /* PYTHONPATH environment variable */ + wchar_t *home; /* PYTHONHOME environment variable, + see also Py_SetPythonHome(). */ + wchar_t *program_name; /* Program name, see also Py_GetProgramName() */ } _PyCoreConfig; #define _PyCoreConfig_INIT (_PyCoreConfig){.use_hash_seed = -1} @@ -52,12 +57,8 @@ typedef struct { */ typedef struct { int install_signal_handlers; - /* PYTHONPATH environment variable */ - wchar_t *module_search_path_env; - /* PYTHONHOME environment variable, see also Py_SetPythonHome(). */ - wchar_t *home; - /* Program name, see also Py_GetProgramName() */ - wchar_t *program_name; + PyObject *argv; /* sys.argv list, can be NULL */ + PyObject *module_search_path; /* sys.path list */ } _PyMainInterpreterConfig; #define _PyMainInterpreterConfig_INIT \ diff --git a/Modules/getpath.c b/Modules/getpath.c index 11babf0a00b..6208a17f02e 100644 --- a/Modules/getpath.c +++ b/Modules/getpath.c @@ -356,15 +356,15 @@ find_env_config_value(FILE * env_file, const wchar_t * key, wchar_t * value) bytes long. */ static int -search_for_prefix(const _PyMainInterpreterConfig *main_config, +search_for_prefix(const _PyCoreConfig *core_config, PyCalculatePath *calculate, wchar_t *prefix) { size_t n; wchar_t *vpath; /* If PYTHONHOME is set, we believe it unconditionally */ - if (main_config->home) { - wcsncpy(prefix, main_config->home, MAXPATHLEN); + if (core_config->home) { + wcsncpy(prefix, core_config->home, MAXPATHLEN); prefix[MAXPATHLEN] = L'\0'; wchar_t *delim = wcschr(prefix, DELIM); if (delim) { @@ -423,10 +423,10 @@ search_for_prefix(const _PyMainInterpreterConfig *main_config, static void -calculate_prefix(const _PyMainInterpreterConfig *main_config, +calculate_prefix(const _PyCoreConfig *core_config, PyCalculatePath *calculate, wchar_t *prefix) { - calculate->prefix_found = search_for_prefix(main_config, calculate, prefix); + calculate->prefix_found = search_for_prefix(core_config, calculate, prefix); if (!calculate->prefix_found) { if (!Py_FrozenFlag) { fprintf(stderr, @@ -468,19 +468,19 @@ calculate_reduce_prefix(PyCalculatePath *calculate, wchar_t *prefix) MAXPATHLEN bytes long. */ static int -search_for_exec_prefix(const _PyMainInterpreterConfig *main_config, +search_for_exec_prefix(const _PyCoreConfig *core_config, PyCalculatePath *calculate, wchar_t *exec_prefix) { size_t n; /* If PYTHONHOME is set, we believe it unconditionally */ - if (main_config->home) { - wchar_t *delim = wcschr(main_config->home, DELIM); + if (core_config->home) { + wchar_t *delim = wcschr(core_config->home, DELIM); if (delim) { wcsncpy(exec_prefix, delim+1, MAXPATHLEN); } else { - wcsncpy(exec_prefix, main_config->home, MAXPATHLEN); + wcsncpy(exec_prefix, core_config->home, MAXPATHLEN); } exec_prefix[MAXPATHLEN] = L'\0'; joinpath(exec_prefix, calculate->lib_python); @@ -551,10 +551,10 @@ search_for_exec_prefix(const _PyMainInterpreterConfig *main_config, static void -calculate_exec_prefix(const _PyMainInterpreterConfig *main_config, +calculate_exec_prefix(const _PyCoreConfig *core_config, PyCalculatePath *calculate, wchar_t *exec_prefix) { - calculate->exec_prefix_found = search_for_exec_prefix(main_config, + calculate->exec_prefix_found = search_for_exec_prefix(core_config, calculate, exec_prefix); if (!calculate->exec_prefix_found) { @@ -587,7 +587,7 @@ calculate_reduce_exec_prefix(PyCalculatePath *calculate, wchar_t *exec_prefix) static _PyInitError -calculate_program_full_path(const _PyMainInterpreterConfig *main_config, +calculate_program_full_path(const _PyCoreConfig *core_config, PyCalculatePath *calculate, _PyPathConfig *config) { wchar_t program_full_path[MAXPATHLEN+1]; @@ -607,8 +607,8 @@ calculate_program_full_path(const _PyMainInterpreterConfig *main_config, * other way to find a directory to start the search from. If * $PATH isn't exported, you lose. */ - if (wcschr(main_config->program_name, SEP)) { - wcsncpy(program_full_path, main_config->program_name, MAXPATHLEN); + if (wcschr(core_config->program_name, SEP)) { + wcsncpy(program_full_path, core_config->program_name, MAXPATHLEN); } #ifdef __APPLE__ /* On Mac OS X, if a script uses an interpreter of the form @@ -650,7 +650,7 @@ calculate_program_full_path(const _PyMainInterpreterConfig *main_config, wcsncpy(program_full_path, path, MAXPATHLEN); } - joinpath(program_full_path, main_config->program_name); + joinpath(program_full_path, core_config->program_name); if (isxfile(program_full_path)) { break; } @@ -815,15 +815,15 @@ calculate_zip_path(PyCalculatePath *calculate, const wchar_t *prefix) static _PyInitError -calculate_module_search_path(const _PyMainInterpreterConfig *main_config, +calculate_module_search_path(const _PyCoreConfig *core_config, PyCalculatePath *calculate, const wchar_t *prefix, const wchar_t *exec_prefix, _PyPathConfig *config) { /* Calculate size of return buffer */ size_t bufsz = 0; - if (main_config->module_search_path_env != NULL) { - bufsz += wcslen(main_config->module_search_path_env) + 1; + if (core_config->module_search_path_env != NULL) { + bufsz += wcslen(core_config->module_search_path_env) + 1; } wchar_t *defpath = calculate->pythonpath; @@ -857,8 +857,8 @@ calculate_module_search_path(const _PyMainInterpreterConfig *main_config, buf[0] = '\0'; /* Run-time value of $PYTHONPATH goes first */ - if (main_config->module_search_path_env) { - wcscpy(buf, main_config->module_search_path_env); + if (core_config->module_search_path_env) { + wcscpy(buf, core_config->module_search_path_env); wcscat(buf, delimiter); } @@ -907,7 +907,7 @@ calculate_module_search_path(const _PyMainInterpreterConfig *main_config, static _PyInitError calculate_init(PyCalculatePath *calculate, - const _PyMainInterpreterConfig *main_config) + const _PyCoreConfig *core_config) { size_t len; const char *path = getenv("PATH"); @@ -950,12 +950,12 @@ calculate_free(PyCalculatePath *calculate) static _PyInitError -calculate_path_impl(const _PyMainInterpreterConfig *main_config, +calculate_path_impl(const _PyCoreConfig *core_config, PyCalculatePath *calculate, _PyPathConfig *config) { _PyInitError err; - err = calculate_program_full_path(main_config, calculate, config); + err = calculate_program_full_path(core_config, calculate, config); if (_Py_INIT_FAILED(err)) { return err; } @@ -969,13 +969,13 @@ calculate_path_impl(const _PyMainInterpreterConfig *main_config, wchar_t prefix[MAXPATHLEN+1]; memset(prefix, 0, sizeof(prefix)); - calculate_prefix(main_config, calculate, prefix); + calculate_prefix(core_config, calculate, prefix); calculate_zip_path(calculate, prefix); wchar_t exec_prefix[MAXPATHLEN+1]; memset(exec_prefix, 0, sizeof(exec_prefix)); - calculate_exec_prefix(main_config, calculate, exec_prefix); + calculate_exec_prefix(core_config, calculate, exec_prefix); if ((!calculate->prefix_found || !calculate->exec_prefix_found) && !Py_FrozenFlag) @@ -984,7 +984,7 @@ calculate_path_impl(const _PyMainInterpreterConfig *main_config, "Consider setting $PYTHONHOME to [:]\n"); } - err = calculate_module_search_path(main_config, calculate, + err = calculate_module_search_path(core_config, calculate, prefix, exec_prefix, config); if (_Py_INIT_FAILED(err)) { return err; @@ -1009,18 +1009,17 @@ calculate_path_impl(const _PyMainInterpreterConfig *main_config, _PyInitError -_PyPathConfig_Calculate(_PyPathConfig *config, - const _PyMainInterpreterConfig *main_config) +_PyPathConfig_Calculate(_PyPathConfig *config, const _PyCoreConfig *core_config) { PyCalculatePath calculate; memset(&calculate, 0, sizeof(calculate)); - _PyInitError err = calculate_init(&calculate, main_config); + _PyInitError err = calculate_init(&calculate, core_config); if (_Py_INIT_FAILED(err)) { goto done; } - err = calculate_path_impl(main_config, &calculate, config); + err = calculate_path_impl(core_config, &calculate, config); if (_Py_INIT_FAILED(err)) { goto done; } diff --git a/Modules/main.c b/Modules/main.c index 7c717750610..3f942fe067a 100644 --- a/Modules/main.c +++ b/Modules/main.c @@ -410,13 +410,6 @@ typedef struct { #endif } _Py_CommandLineDetails; -/* FIXME: temporary structure until sys module configuration can be moved - into _PyMainInterpreterConfig */ -typedef struct { - PyObject *argv; /* sys.argv list */ - PyObject *path0; /* path0: if set, it is prepended to sys.path */ -} _PySysConfig; - /* Structure used by Py_Main() to pass data to subfunctions */ typedef struct { /* Exit status ("exit code") */ @@ -426,7 +419,6 @@ typedef struct { int stdin_is_interactive; _PyCoreConfig core_config; _PyMainInterpreterConfig config; - _PySysConfig sys_config; _Py_CommandLineDetails cmdline; PyObject *main_importer_path; /* non-zero if filename, command (-c) or module (-m) is set @@ -438,6 +430,9 @@ typedef struct { _Py_OptList env_warning_options; int argc; wchar_t **argv; + + int sys_argc; + wchar_t **sys_argv; } _PyMain; /* .cmdline is initialized to zeros */ @@ -472,7 +467,7 @@ pymain_free_globals(_PyMain *pymain) { _PyPathConfig_Clear(&_Py_path_config); _PyImport_Fini2(); - _PyMainInterpreterConfig_Clear(&pymain->config); + _PyCoreConfig_Clear(&pymain->core_config); #ifdef __INSURE__ /* Insure++ is a memory analysis tool that aids in discovering @@ -497,13 +492,21 @@ pymain_free_pymain(_PyMain *pymain) pymain_optlist_clear(&cmdline->xoptions); PyMem_RawFree(cmdline->command); + PyMem_RawFree(pymain->sys_argv); pymain_optlist_clear(&pymain->env_warning_options); +} + + +/* Clear Python ojects */ +static void +pymain_free_python(_PyMain *pymain) +{ Py_CLEAR(pymain->main_importer_path); - Py_CLEAR(pymain->sys_config.argv); - Py_CLEAR(pymain->sys_config.path0); + _PyMainInterpreterConfig_Clear(&pymain->config); } + static void pymain_free(_PyMain *pymain) { @@ -511,12 +514,14 @@ pymain_free(_PyMain *pymain) PyMemAllocatorEx old_alloc; _PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc); + pymain_free_python(pymain); pymain_free_pymain(pymain); pymain_free_globals(pymain); PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc); } + static int pymain_run_main_from_importer(_PyMain *pymain) { @@ -974,7 +979,7 @@ pymain_init_stdio(_PyMain *pymain) /* Get the program name: use PYTHONEXECUTABLE and __PYVENV_LAUNCHER__ environment variables on macOS if available. */ static _PyInitError -config_get_program_name(_PyMainInterpreterConfig *config) +config_get_program_name(_PyCoreConfig *config) { assert(config->program_name == NULL); @@ -1035,10 +1040,10 @@ config_get_program_name(_PyMainInterpreterConfig *config) static int pymain_get_program_name(_PyMain *pymain) { - if (pymain->config.program_name == NULL) { + if (pymain->core_config.program_name == NULL) { /* Use argv[0] by default */ - pymain->config.program_name = pymain_wstrdup(pymain, pymain->argv[0]); - if (pymain->config.program_name == NULL) { + pymain->core_config.program_name = pymain_wstrdup(pymain, pymain->argv[0]); + if (pymain->core_config.program_name == NULL) { return -1; } } @@ -1086,36 +1091,40 @@ pymain_header(_PyMain *pymain) } -static PyObject * -pymain_create_argv_list(int argc, wchar_t **argv) +static int +pymain_create_argv_list(_PyMain *pymain) { - if (argc <= 0 || argv == NULL) { + int argc = pymain->sys_argc; + wchar_t** argv = pymain->sys_argv; + + if (argc <= 0 || pymain->sys_argv == NULL) { /* Ensure at least one (empty) argument is seen */ static wchar_t *empty_argv[1] = {L""}; argv = empty_argv; argc = 1; } - PyObject *av = PyList_New(argc); - if (av == NULL) { - return NULL; + PyObject *list = PyList_New(argc); + if (list == NULL) { + return -1; } for (int i = 0; i < argc; i++) { PyObject *v = PyUnicode_FromWideChar(argv[i], -1); if (v == NULL) { - Py_DECREF(av); - return NULL; + Py_DECREF(list); + return -1; } - PyList_SET_ITEM(av, i, v); + PyList_SET_ITEM(list, i, v); } - return av; + + pymain->config.argv = list; + return 0; } -/* Create sys.argv list and maybe also path0 */ static int -pymain_compute_argv(_PyMain *pymain) +pymain_init_sys_argv(_PyMain *pymain) { _Py_CommandLineDetails *cmdline = &pymain->cmdline; @@ -1125,84 +1134,61 @@ pymain_compute_argv(_PyMain *pymain) } /* Copy argv to be able to modify it (to force -c/-m) */ - int argc2 = pymain->argc - _PyOS_optind; - size_t size = argc2 * sizeof(pymain->argv[0]); - wchar_t **argv2 = PyMem_RawMalloc(size); - if (argv2 == NULL) { + pymain->sys_argc = pymain->argc - _PyOS_optind; + size_t size = pymain->sys_argc * sizeof(pymain->argv[0]); + pymain->sys_argv = PyMem_RawMalloc(size); + if (pymain->sys_argv == NULL) { pymain->err = _Py_INIT_NO_MEMORY(); return -1; } - memcpy(argv2, &pymain->argv[_PyOS_optind], size); + memcpy(pymain->sys_argv, &pymain->argv[_PyOS_optind], size); - /* TODO: Move this to _Py_InitializeMainInterpreter */ if (cmdline->command != NULL) { /* Force sys.argv[0] = '-c' */ - argv2[0] = L"-c"; + pymain->sys_argv[0] = L"-c"; } else if (cmdline->module != NULL) { /* Force sys.argv[0] = '-m'*/ - argv2[0] = L"-m"; + pymain->sys_argv[0] = L"-m"; } - - /* Create sys.argv list */ - pymain->sys_config.argv = pymain_create_argv_list(argc2, argv2); - if (pymain->sys_config.argv == NULL) { - pymain->err = _Py_INIT_ERR("failed to create sys.argv"); - goto error; - } - - /* Need to update sys.path[0]? */ - int update_path; - if (pymain->main_importer_path != NULL) { - /* Let pymain_run_main_from_importer() adjust sys.path[0] later */ - update_path = 0; - } else { - /* Use config settings to decide whether or not to update sys.path[0] */ - update_path = (Py_IsolatedFlag == 0); - } - - /* If '-c' and '-m' options are not used in the command line - and update_path is non-zero, prepend argv[0] to sys.path. If argv[0] is - a symlink, use the real path. */ - if (update_path) { - pymain->sys_config.path0 = _PyPathConfig_ComputeArgv0(argc2, argv2); - if (pymain->sys_config.path0 == NULL) { - pymain->err = _Py_INIT_NO_MEMORY(); - goto error; - } - } - PyMem_RawFree(argv2); return 0; - -error: - return -1; } + static int -pymain_set_sys_argv(_PyMain *pymain) +pymain_update_sys_path(_PyMain *pymain) { - /* Set sys.argv */ - if (PySys_SetObject("argv", pymain->sys_config.argv) != 0) { - pymain->err = _Py_INIT_ERR("can't assign sys.argv"); + if (pymain->main_importer_path != NULL) { + /* Let pymain_run_main_from_importer() adjust sys.path[0] later */ + return 0; + } + + if (Py_IsolatedFlag) { + return 0; + } + + /* Prepend argv[0] to sys.path. + If argv[0] is a symlink, use the real path. */ + PyObject *sys_path = PySys_GetObject("path"); + if (sys_path == NULL) { + pymain->err = _Py_INIT_ERR("can't get sys.path"); return -1; } - Py_CLEAR(pymain->sys_config.argv); - if (pymain->sys_config.path0 != NULL) { - /* Prepend path0 to sys.path */ - PyObject *sys_path = PySys_GetObject("path"); - if (sys_path == NULL) { - pymain->err = _Py_INIT_ERR("can't get sys.path"); - return -1; - } - - if (PyList_Insert(sys_path, 0, pymain->sys_config.path0) < 0) { - pymain->err = _Py_INIT_ERR("sys.path.insert(0, path0) failed"); - return -1; - } - Py_CLEAR(pymain->sys_config.path0); + PyObject *path0 = _PyPathConfig_ComputeArgv0(pymain->sys_argc, pymain->sys_argv); + if (path0 == NULL) { + pymain->err = _Py_INIT_NO_MEMORY(); + return -1; } + /* Prepend path0 to sys.path */ + if (PyList_Insert(sys_path, 0, path0) < 0) { + Py_DECREF(path0); + pymain->err = _Py_INIT_ERR("sys.path.insert(0, path0) failed"); + return -1; + } + Py_DECREF(path0); + return 0; } @@ -1627,7 +1613,7 @@ config_get_env_var_dup(wchar_t **dest, wchar_t *wname, char *name) static _PyInitError -config_init_pythonpath(_PyMainInterpreterConfig *config) +config_init_pythonpath(_PyCoreConfig *config) { wchar_t *path; int res = config_get_env_var_dup(&path, L"PYTHONPATH", "PYTHONPATH"); @@ -1640,7 +1626,7 @@ config_init_pythonpath(_PyMainInterpreterConfig *config) static _PyInitError -config_init_home(_PyMainInterpreterConfig *config) +config_init_home(_PyCoreConfig *config) { wchar_t *home; @@ -1664,7 +1650,7 @@ config_init_home(_PyMainInterpreterConfig *config) _PyInitError -_PyMainInterpreterConfig_ReadEnv(_PyMainInterpreterConfig *config) +_PyCoreConfig_ReadEnv(_PyCoreConfig *config) { _PyInitError err = config_init_home(config); if (_Py_INIT_FAILED(err)) { @@ -1756,7 +1742,7 @@ pymain_parse_envvars(_PyMain *pymain) return -1; } - _PyInitError err = _PyMainInterpreterConfig_ReadEnv(&pymain->config); + _PyInitError err = _PyCoreConfig_ReadEnv(&pymain->core_config); if (_Py_INIT_FAILED(pymain->err)) { pymain->err = err; return -1; @@ -1834,12 +1820,15 @@ pymain_parse_cmdline_envvars_impl(_PyMain *pymain) } /* FIXME: if utf8_mode value changed, parse again cmdline */ - _PyInitError err = _PyMainInterpreterConfig_Read(&pymain->config); + if (pymain_init_sys_argv(pymain) < 0) { + return -1; + } + + _PyInitError err = _PyCoreConfig_Read(&pymain->core_config); if (_Py_INIT_FAILED(err)) { pymain->err = err; return -1; } - return 0; } @@ -1858,10 +1847,85 @@ pymain_parse_cmdline_envvars(_PyMain *pymain) return res; } -static int -pymain_init_python(_PyMain *pymain) -{ +static PyObject * +config_create_path_list(const wchar_t *path, wchar_t delim) +{ + int i, n; + const wchar_t *p; + PyObject *v; + + n = 1; + p = path; + while ((p = wcschr(p, delim)) != NULL) { + n++; + p++; + } + v = PyList_New(n); + if (v == NULL) { + return NULL; + } + for (i = 0; ; i++) { + p = wcschr(path, delim); + if (p == NULL) { + p = path + wcslen(path); /* End of string */ + } + PyObject *w = PyUnicode_FromWideChar(path, (Py_ssize_t)(p - path)); + if (w == NULL) { + Py_DECREF(v); + return NULL; + } + PyList_SET_ITEM(v, i, w); + if (*p == '\0') { + break; + } + path = p+1; + } + return v; +} + + +static _PyInitError +config_init_module_search_path(_PyMainInterpreterConfig *config, _PyCoreConfig *core_config) +{ + _PyInitError err = _PyPathConfig_Init(core_config); + if (_Py_INIT_FAILED(err)) { + return err; + } + wchar_t *sys_path = Py_GetPath(); + + config->module_search_path = config_create_path_list(sys_path, DELIM); + if (config->module_search_path == NULL) { + return _Py_INIT_NO_MEMORY(); + } + return _Py_INIT_OK(); +} + + +_PyInitError +_PyMainInterpreterConfig_Read(_PyMainInterpreterConfig *config, _PyCoreConfig *core_config) +{ + /* Signal handlers are installed by default */ + if (config->install_signal_handlers < 0) { + config->install_signal_handlers = 1; + } + + if (config->module_search_path == NULL && + !core_config->_disable_importlib) + { + _PyInitError err = config_init_module_search_path(config, core_config); + if (_Py_INIT_FAILED(err)) { + return err; + } + } + + return _Py_INIT_OK(); +} + + +static int +pymain_init_python_core(_PyMain *pymain) +{ pymain_set_global_config(pymain); pymain_init_stdio(pymain); @@ -1870,7 +1934,13 @@ pymain_init_python(_PyMain *pymain) if (_Py_INIT_FAILED(pymain->err)) { return -1; } + return 0; +} + +static int +pymain_init_python_main(_PyMain *pymain) +{ if (pymain_add_xoptions(pymain)) { return -1; } @@ -1878,6 +1948,19 @@ pymain_init_python(_PyMain *pymain) return -1; } + /* Create sys.argv list */ + if (pymain_create_argv_list(pymain) < 0) { + pymain->err = _Py_INIT_ERR("failed to create sys.argv"); + return -1; + } + + _PyInitError err = _PyMainInterpreterConfig_Read(&pymain->config, + &pymain->core_config); + if (_Py_INIT_FAILED(err)) { + pymain->err = err; + return -1; + } + if (pymain_init_main_interpreter(pymain)) { return -1; } @@ -1890,14 +1973,7 @@ pymain_init_python(_PyMain *pymain) pymain->main_importer_path = pymain_get_importer(pymain->cmdline.filename); } - /* FIXME: put argv into _PyMainInterpreterConfig. - Currently, PySys_SetArgvEx() can still modify sys.path and so must be - called after _Py_InitializeMainInterpreter() which calls - _PyPathConfig_Init(). */ - if (pymain_compute_argv(pymain) < 0) { - return -1; - } - if (pymain_set_sys_argv(pymain) < 0) { + if (pymain_update_sys_path(pymain) < 0) { return -1; } return 0; @@ -1962,13 +2038,20 @@ pymain_impl(_PyMain *pymain) return 0; } - res = pymain_init_python(pymain); + res = pymain_init_python_core(pymain); + if (res < 0) { + return -1; + } + + res = pymain_init_python_main(pymain); if (res < 0) { return -1; } pymain_run_python(pymain); + pymain_free_python(pymain); + if (Py_FinalizeEx() < 0) { /* Value unlikely to be confused with a non-error exit status or other special meaning */ diff --git a/PC/getpathp.c b/PC/getpathp.c index e142e365052..fe4ef1a1ab3 100644 --- a/PC/getpathp.c +++ b/PC/getpathp.c @@ -498,7 +498,7 @@ get_dll_path(PyCalculatePath *calculate, _PyPathConfig *config) static _PyInitError -get_program_full_path(const _PyMainInterpreterConfig *main_config, +get_program_full_path(const _PyCoreConfig *core_config, PyCalculatePath *calculate, _PyPathConfig *config) { wchar_t program_full_path[MAXPATHLEN+1]; @@ -514,13 +514,13 @@ get_program_full_path(const _PyMainInterpreterConfig *main_config, * $PATH isn't exported, you lose. */ #ifdef ALTSEP - if (wcschr(main_config->program_name, SEP) || - wcschr(main_config->program_name, ALTSEP)) + if (wcschr(core_config->program_name, SEP) || + wcschr(core_config->program_name, ALTSEP)) #else - if (wcschr(main_config->program_name, SEP)) + if (wcschr(core_config->program_name, SEP)) #endif { - wcsncpy(program_full_path, main_config->program_name, MAXPATHLEN); + wcsncpy(program_full_path, core_config->program_name, MAXPATHLEN); } else if (calculate->path_env) { const wchar_t *path = calculate->path_env; @@ -539,7 +539,7 @@ get_program_full_path(const _PyMainInterpreterConfig *main_config, } /* join() is safe for MAXPATHLEN+1 size buffer */ - join(program_full_path, main_config->program_name); + join(program_full_path, core_config->program_name); if (exists(program_full_path)) { break; } @@ -707,9 +707,9 @@ read_pth_file(_PyPathConfig *config, wchar_t *prefix, const wchar_t *path, static void calculate_init(PyCalculatePath *calculate, - const _PyMainInterpreterConfig *main_config) + const _PyCoreConfig *core_config) { - calculate->home = main_config->home; + calculate->home = core_config->home; calculate->path_env = _wgetenv(L"PATH"); } @@ -813,7 +813,7 @@ calculate_home_prefix(PyCalculatePath *calculate, wchar_t *prefix) static _PyInitError -calculate_module_search_path(const _PyMainInterpreterConfig *main_config, +calculate_module_search_path(const _PyCoreConfig *core_config, PyCalculatePath *calculate, _PyPathConfig *config, wchar_t *prefix) { @@ -824,7 +824,7 @@ calculate_module_search_path(const _PyMainInterpreterConfig *main_config, #endif /* We only use the default relative PYTHONPATH if we haven't anything better to use! */ - int skipdefault = (main_config->module_search_path_env != NULL || + int skipdefault = (core_config->module_search_path_env != NULL || calculate->home != NULL || calculate->machine_path != NULL || calculate->user_path != NULL); @@ -863,8 +863,8 @@ calculate_module_search_path(const _PyMainInterpreterConfig *main_config, bufsz += wcslen(calculate->machine_path) + 1; } bufsz += wcslen(calculate->zip_path) + 1; - if (main_config->module_search_path_env != NULL) { - bufsz += wcslen(main_config->module_search_path_env) + 1; + if (core_config->module_search_path_env != NULL) { + bufsz += wcslen(core_config->module_search_path_env) + 1; } wchar_t *buf, *start_buf; @@ -872,9 +872,9 @@ calculate_module_search_path(const _PyMainInterpreterConfig *main_config, if (buf == NULL) { /* We can't exit, so print a warning and limp along */ fprintf(stderr, "Can't malloc dynamic PYTHONPATH.\n"); - if (main_config->module_search_path_env) { + if (core_config->module_search_path_env) { fprintf(stderr, "Using environment $PYTHONPATH.\n"); - config->module_search_path = main_config->module_search_path_env; + config->module_search_path = core_config->module_search_path_env; } else { fprintf(stderr, "Using default static path.\n"); @@ -884,9 +884,9 @@ calculate_module_search_path(const _PyMainInterpreterConfig *main_config, } start_buf = buf; - if (main_config->module_search_path_env) { + if (core_config->module_search_path_env) { if (wcscpy_s(buf, bufsz - (buf - start_buf), - main_config->module_search_path_env)) { + core_config->module_search_path_env)) { return INIT_ERR_BUFFER_OVERFLOW(); } buf = wcschr(buf, L'\0'); @@ -999,7 +999,7 @@ calculate_module_search_path(const _PyMainInterpreterConfig *main_config, static _PyInitError -calculate_path_impl(const _PyMainInterpreterConfig *main_config, +calculate_path_impl(const _PyCoreConfig *core_config, PyCalculatePath *calculate, _PyPathConfig *config) { _PyInitError err; @@ -1009,7 +1009,7 @@ calculate_path_impl(const _PyMainInterpreterConfig *main_config, return err; } - err = get_program_full_path(main_config, calculate, config); + err = get_program_full_path(core_config, calculate, config); if (_Py_INIT_FAILED(err)) { return err; } @@ -1035,7 +1035,7 @@ calculate_path_impl(const _PyMainInterpreterConfig *main_config, calculate_home_prefix(calculate, prefix); - err = calculate_module_search_path(main_config, calculate, config, prefix); + err = calculate_module_search_path(core_config, calculate, config, prefix); if (_Py_INIT_FAILED(err)) { return err; } @@ -1059,15 +1059,14 @@ calculate_free(PyCalculatePath *calculate) _PyInitError -_PyPathConfig_Calculate(_PyPathConfig *config, - const _PyMainInterpreterConfig *main_config) +_PyPathConfig_Calculate(_PyPathConfig *config, const _PyCoreConfig *core_config) { PyCalculatePath calculate; memset(&calculate, 0, sizeof(calculate)); - calculate_init(&calculate, main_config); + calculate_init(&calculate, core_config); - _PyInitError err = calculate_path_impl(main_config, &calculate, config); + _PyInitError err = calculate_path_impl(core_config, &calculate, config); if (_Py_INIT_FAILED(err)) { goto done; } diff --git a/Python/pathconfig.c b/Python/pathconfig.c index b17ae822a7a..748084ba448 100644 --- a/Python/pathconfig.c +++ b/Python/pathconfig.c @@ -46,7 +46,7 @@ _PyPathConfig_Clear(_PyPathConfig *config) /* Initialize paths for Py_GetPath(), Py_GetPrefix(), Py_GetExecPrefix() and Py_GetProgramFullPath() */ _PyInitError -_PyPathConfig_Init(const _PyMainInterpreterConfig *main_config) +_PyPathConfig_Init(const _PyCoreConfig *core_config) { if (_Py_path_config.module_search_path) { /* Already initialized */ @@ -61,15 +61,15 @@ _PyPathConfig_Init(const _PyMainInterpreterConfig *main_config) /* Calculate program_full_path, prefix, exec_prefix (Unix) or dll_path (Windows), and module_search_path */ - err = _PyPathConfig_Calculate(&new_config, main_config); + err = _PyPathConfig_Calculate(&new_config, core_config); if (_Py_INIT_FAILED(err)) { _PyPathConfig_Clear(&new_config); goto done; } - /* Copy home and program_name from main_config */ - if (main_config->home != NULL) { - new_config.home = _PyMem_RawWcsdup(main_config->home); + /* Copy home and program_name from core_config */ + if (core_config->home != NULL) { + new_config.home = _PyMem_RawWcsdup(core_config->home); if (new_config.home == NULL) { err = _Py_INIT_NO_MEMORY(); goto done; @@ -79,7 +79,7 @@ _PyPathConfig_Init(const _PyMainInterpreterConfig *main_config) new_config.home = NULL; } - new_config.program_name = _PyMem_RawWcsdup(main_config->program_name); + new_config.program_name = _PyMem_RawWcsdup(core_config->program_name); if (new_config.program_name == NULL) { err = _Py_INIT_NO_MEMORY(); goto done; @@ -105,14 +105,14 @@ pathconfig_global_init(void) } _PyInitError err; - _PyMainInterpreterConfig config = _PyMainInterpreterConfig_INIT; + _PyCoreConfig config = _PyCoreConfig_INIT; - err = _PyMainInterpreterConfig_ReadEnv(&config); + err = _PyCoreConfig_ReadEnv(&config); if (_Py_INIT_FAILED(err)) { goto error; } - err = _PyMainInterpreterConfig_Read(&config); + err = _PyCoreConfig_Read(&config); if (_Py_INIT_FAILED(err)) { goto error; } @@ -122,11 +122,11 @@ pathconfig_global_init(void) goto error; } - _PyMainInterpreterConfig_Clear(&config); + _PyCoreConfig_Clear(&config); return; error: - _PyMainInterpreterConfig_Clear(&config); + _PyCoreConfig_Clear(&config); _Py_FatalInitError(err); } diff --git a/Python/pylifecycle.c b/Python/pylifecycle.c index 2bac23d1cb0..31965f503ca 100644 --- a/Python/pylifecycle.c +++ b/Python/pylifecycle.c @@ -792,13 +792,8 @@ _Py_InitializeCore(const _PyCoreConfig *config) */ _PyInitError -_PyMainInterpreterConfig_Read(_PyMainInterpreterConfig *config) +_PyCoreConfig_Read(_PyCoreConfig *config) { - /* Signal handlers are installed by default */ - if (config->install_signal_handlers < 0) { - config->install_signal_handlers = 1; - } - if (config->program_name == NULL) { #ifdef MS_WINDOWS const wchar_t *program_name = L"python"; @@ -814,9 +809,8 @@ _PyMainInterpreterConfig_Read(_PyMainInterpreterConfig *config) return _Py_INIT_OK(); } - void -_PyMainInterpreterConfig_Clear(_PyMainInterpreterConfig *config) +_PyCoreConfig_Clear(_PyCoreConfig *config) { #define CLEAR(ATTR) \ do { \ @@ -831,6 +825,14 @@ _PyMainInterpreterConfig_Clear(_PyMainInterpreterConfig *config) } +void +_PyMainInterpreterConfig_Clear(_PyMainInterpreterConfig *config) +{ + Py_CLEAR(config->argv); + Py_CLEAR(config->module_search_path); +} + + /* Update interpreter state based on supplied configuration settings * * After calling this function, most of the restrictions on the interpreter @@ -881,16 +883,11 @@ _Py_InitializeMainInterpreter(const _PyMainInterpreterConfig *config) return _Py_INIT_ERR("can't initialize time"); } - /* GetPath may initialize state that _PySys_EndInit locks - in, and so has to be called first. */ - err = _PyPathConfig_Init(&interp->config); - if (_Py_INIT_FAILED(err)) { - return err; + assert(interp->config.module_search_path != NULL); + if (PySys_SetObject("path", interp->config.module_search_path) != 0) { + return _Py_INIT_ERR("can't assign sys.path"); } - wchar_t *sys_path = Py_GetPath(); - /* Finish setting up the sys module and import system */ - PySys_SetPath(sys_path); if (_PySys_EndInit(interp->sysdict) < 0) return _Py_INIT_ERR("can't finish initializing sys"); @@ -949,6 +946,12 @@ _Py_InitializeMainInterpreter(const _PyMainInterpreterConfig *config) } } + if (interp->config.argv != NULL) { + if (PySys_SetObject("argv", interp->config.argv) != 0) { + return _Py_INIT_ERR("can't assign sys.argv"); + } + } + return _Py_INIT_OK(); } @@ -970,12 +973,12 @@ _Py_InitializeEx_Private(int install_sigs, int install_importlib) goto done; } - err = _PyMainInterpreterConfig_ReadEnv(&config); + err = _PyCoreConfig_ReadEnv(&core_config); if (_Py_INIT_FAILED(err)) { goto done; } - err = _PyMainInterpreterConfig_Read(&config); + err = _PyMainInterpreterConfig_Read(&config, &core_config); if (_Py_INIT_FAILED(err)) { goto done; } @@ -988,6 +991,7 @@ _Py_InitializeEx_Private(int install_sigs, int install_importlib) err = _Py_INIT_OK(); done: + _PyCoreConfig_Clear(&core_config); _PyMainInterpreterConfig_Clear(&config); return err; } @@ -1342,7 +1346,7 @@ new_interpreter(PyThreadState **tstate_p) interp->config = main_interp->config; } - err = _PyPathConfig_Init(&interp->config); + err = _PyPathConfig_Init(&interp->core_config); if (_Py_INIT_FAILED(err)) { return err; }