From d53fe5f407ff4b529628b01a1bcbf21a6aad5c3a Mon Sep 17 00:00:00 2001 From: Serhiy Storchaka Date: Wed, 13 Mar 2019 22:59:55 +0200 Subject: bpo-36254: Fix invalid uses of %d in format strings in C. (GH-12264) --- Python/coreconfig.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Python/coreconfig.c') diff --git a/Python/coreconfig.c b/Python/coreconfig.c index cd4ef22ff6..845e4c9a16 100644 --- a/Python/coreconfig.c +++ b/Python/coreconfig.c @@ -1103,7 +1103,7 @@ get_locale_encoding(char **locale_encoding) { #ifdef MS_WINDOWS char encoding[20]; - PyOS_snprintf(encoding, sizeof(encoding), "cp%d", GetACP()); + PyOS_snprintf(encoding, sizeof(encoding), "cp%u", GetACP()); #elif defined(__ANDROID__) || defined(__VXWORKS__) const char *encoding = "UTF-8"; #else -- cgit v1.2.1 From 74f6568bbd3e70806ea3219e8bacb386ad802ccf Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Fri, 15 Mar 2019 15:08:05 +0100 Subject: bpo-36301: Add _PyWstrList structure (GH-12343) Replace messy _Py_wstrlist_xxx() functions with a new clean _PyWstrList structure and new _PyWstrList_xxx() functions. Changes: * Add _PyCoreConfig.use_module_search_paths to decide if _PyCoreConfig.module_search_paths should be computed or not, to support empty search path list. * _PyWstrList_Clear() sets length to 0 and items to NULL, whereas _Py_wstrlist_clear() only freed memory. * _PyWstrList_Append() returns an int, whereas _Py_wstrlist_append() returned _PyInitError. * _PyWstrList uses Py_ssize_t for the length, instead of int. * Replace (int, wchar_t**) with _PyWstrList in: * _PyPreConfig * _PyCoreConfig * _PyPreCmdline * _PyCmdline * Replace "int orig_argv; wchar_t **orig_argv;" with "_PyWstrList orig_argv". * _PyCmdline and _PyPreCmdline now also copy wchar_argv. * Rename _PyArgv_Decode() to _PyArgv_AsWstrList(). * PySys_SetArgvEx() now pass the fixed (argc, argv) to _PyPathConfig_ComputeArgv0() (don't pass negative argc or NULL argv). * _PyOS_GetOpt() uses Py_ssize_t --- Python/coreconfig.c | 364 ++++++++++++++++++++++++---------------------------- 1 file changed, 166 insertions(+), 198 deletions(-) (limited to 'Python/coreconfig.c') diff --git a/Python/coreconfig.c b/Python/coreconfig.c index 845e4c9a16..15107fa36c 100644 --- a/Python/coreconfig.c +++ b/Python/coreconfig.c @@ -202,81 +202,128 @@ fail: } -/* --- _Py_wstrlist ----------------------------------------------- */ +/* --- _PyWstrList ------------------------------------------------ */ + +#ifndef NDEBUG +int +_PyWstrList_CheckConsistency(const _PyWstrList *list) +{ + assert(list->length >= 0); + if (list->length != 0) { + assert(list->items != NULL); + } + for (Py_ssize_t i = 0; i < list->length; i++) { + assert(list->items[i] != NULL); + } + return 1; +} +#endif /* Py_DEBUG */ + void -_Py_wstrlist_clear(int len, wchar_t **list) +_PyWstrList_Clear(_PyWstrList *list) { - for (int i=0; i < len; i++) { - PyMem_RawFree(list[i]); + assert(_PyWstrList_CheckConsistency(list)); + for (Py_ssize_t i=0; i < list->length; i++) { + PyMem_RawFree(list->items[i]); } - PyMem_RawFree(list); + PyMem_RawFree(list->items); + list->length = 0; + list->items = NULL; } -wchar_t** -_Py_wstrlist_copy(int len, wchar_t * const *list) +int +_PyWstrList_Copy(_PyWstrList *list, const _PyWstrList *list2) { - assert((len > 0 && list != NULL) || len == 0); - size_t size = len * sizeof(list[0]); - wchar_t **list_copy = PyMem_RawMalloc(size); - if (list_copy == NULL) { - return NULL; + assert(_PyWstrList_CheckConsistency(list)); + assert(_PyWstrList_CheckConsistency(list2)); + + if (list2->length == 0) { + _PyWstrList_Clear(list); + return 0; } - for (int i=0; i < len; i++) { - wchar_t* arg = _PyMem_RawWcsdup(list[i]); - if (arg == NULL) { - _Py_wstrlist_clear(i, list_copy); - return NULL; + + _PyWstrList copy = _PyWstrList_INIT; + + size_t size = list2->length * sizeof(list2->items[0]); + copy.items = PyMem_RawMalloc(size); + if (copy.items == NULL) { + return -1; + } + + for (Py_ssize_t i=0; i < list2->length; i++) { + wchar_t *item = _PyMem_RawWcsdup(list2->items[i]); + if (item == NULL) { + _PyWstrList_Clear(©); + return -1; } - list_copy[i] = arg; + copy.items[i] = item; + copy.length = i + 1; } - return list_copy; + + _PyWstrList_Clear(list); + *list = copy; + return 0; } -_PyInitError -_Py_wstrlist_append(int *len, wchar_t ***list, const wchar_t *str) +int +_PyWstrList_Append(_PyWstrList *list, const wchar_t *item) { - if (*len == INT_MAX) { - /* len+1 would overflow */ - return _Py_INIT_NO_MEMORY(); + if (list->length == PY_SSIZE_T_MAX) { + /* lenght+1 would overflow */ + return -1; } - wchar_t *str2 = _PyMem_RawWcsdup(str); - if (str2 == NULL) { - return _Py_INIT_NO_MEMORY(); + + wchar_t *item2 = _PyMem_RawWcsdup(item); + if (item2 == NULL) { + return -1; } - size_t size = (*len + 1) * sizeof(list[0]); - wchar_t **list2 = (wchar_t **)PyMem_RawRealloc(*list, size); - if (list2 == NULL) { - PyMem_RawFree(str2); - return _Py_INIT_NO_MEMORY(); + size_t size = (list->length + 1) * sizeof(list->items[0]); + wchar_t **items2 = (wchar_t **)PyMem_RawRealloc(list->items, size); + if (items2 == NULL) { + PyMem_RawFree(item2); + return -1; } - list2[*len] = str2; - *list = list2; - (*len)++; - return _Py_INIT_OK(); + + items2[list->length] = item2; + list->items = items2; + list->length++; + return 0; +} + + +static int +_PyWstrList_Extend(_PyWstrList *list, const _PyWstrList *list2) +{ + for (Py_ssize_t i = 0; i < list2->length; i++) { + if (_PyWstrList_Append(list, list2->items[i])) { + return -1; + } + } + return 0; } PyObject* -_Py_wstrlist_as_pylist(int len, wchar_t **list) +_PyWstrList_AsList(const _PyWstrList *list) { - assert(list != NULL || len < 1); + assert(_PyWstrList_CheckConsistency(list)); - PyObject *pylist = PyList_New(len); + PyObject *pylist = PyList_New(list->length); if (pylist == NULL) { return NULL; } - for (int i = 0; i < len; i++) { - PyObject *v = PyUnicode_FromWideChar(list[i], -1); - if (v == NULL) { + for (Py_ssize_t i = 0; i < list->length; i++) { + PyObject *item = PyUnicode_FromWideChar(list->items[i], -1); + if (item == NULL) { Py_DECREF(pylist); return NULL; } - PyList_SET_ITEM(pylist, i, v); + PyList_SET_ITEM(pylist, i, item); } return pylist; } @@ -369,8 +416,7 @@ _Py_ClearStandardStreamEncoding(void) /* --- Py_GetArgcArgv() ------------------------------------------- */ /* For Py_GetArgcArgv(); set by _Py_SetArgcArgv() */ -static int orig_argc = 0; -static wchar_t **orig_argv = NULL; +static _PyWstrList orig_argv = {.length = 0, .items = NULL}; void @@ -379,32 +425,22 @@ _Py_ClearArgcArgv(void) PyMemAllocatorEx old_alloc; _PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc); - _Py_wstrlist_clear(orig_argc, orig_argv); - orig_argc = 0; - orig_argv = NULL; + _PyWstrList_Clear(&orig_argv); PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc); } static int -_Py_SetArgcArgv(int argc, wchar_t * const *argv) +_Py_SetArgcArgv(Py_ssize_t argc, wchar_t * const *argv) { + const _PyWstrList argv_list = {.length = argc, .items = (wchar_t **)argv}; int res; PyMemAllocatorEx old_alloc; _PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc); - wchar_t **argv_copy = _Py_wstrlist_copy(argc, argv); - if (argv_copy != NULL) { - _Py_ClearArgcArgv(); - orig_argc = argc; - orig_argv = argv_copy; - res = 0; - } - else { - res = -1; - } + res = _PyWstrList_Copy(&orig_argv, &argv_list); PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc); return res; @@ -416,8 +452,8 @@ _Py_SetArgcArgv(int argc, wchar_t * const *argv) void Py_GetArgcArgv(int *argc, wchar_t ***argv) { - *argc = orig_argc; - *argv = orig_argv; + *argc = (int)orig_argv.length; + *argv = orig_argv.items; } @@ -439,12 +475,6 @@ _PyCoreConfig_Clear(_PyCoreConfig *config) PyMem_RawFree(ATTR); \ ATTR = NULL; \ } while (0) -#define CLEAR_WSTRLIST(LEN, LIST) \ - do { \ - _Py_wstrlist_clear(LEN, LIST); \ - LEN = 0; \ - LIST = NULL; \ - } while (0) CLEAR(config->pycache_prefix); CLEAR(config->module_search_path_env); @@ -452,13 +482,11 @@ _PyCoreConfig_Clear(_PyCoreConfig *config) CLEAR(config->program_name); CLEAR(config->program); - CLEAR_WSTRLIST(config->argc, config->argv); - config->argc = -1; - - CLEAR_WSTRLIST(config->nwarnoption, config->warnoptions); - CLEAR_WSTRLIST(config->nxoption, config->xoptions); - CLEAR_WSTRLIST(config->nmodule_search_path, config->module_search_paths); - config->nmodule_search_path = -1; + _PyWstrList_Clear(&config->argv); + _PyWstrList_Clear(&config->warnoptions); + _PyWstrList_Clear(&config->xoptions); + _PyWstrList_Clear(&config->module_search_paths); + config->use_module_search_paths = 0; CLEAR(config->executable); CLEAR(config->prefix); @@ -477,7 +505,6 @@ _PyCoreConfig_Clear(_PyCoreConfig *config) CLEAR(config->run_module); CLEAR(config->run_filename); #undef CLEAR -#undef CLEAR_WSTRLIST } @@ -509,15 +536,11 @@ _PyCoreConfig_Copy(_PyCoreConfig *config, const _PyCoreConfig *config2) } \ } \ } while (0) -#define COPY_WSTRLIST(LEN, LIST) \ +#define COPY_WSTRLIST(LIST) \ do { \ - if (config2->LIST != NULL) { \ - config->LIST = _Py_wstrlist_copy(config2->LEN, config2->LIST); \ - if (config->LIST == NULL) { \ - return -1; \ - } \ + if (_PyWstrList_Copy(&config->LIST, &config2->LIST) < 0 ) { \ + return -1; \ } \ - config->LEN = config2->LEN; \ } while (0) COPY_ATTR(install_signal_handlers); @@ -538,10 +561,11 @@ _PyCoreConfig_Copy(_PyCoreConfig *config, const _PyCoreConfig *config2) COPY_WSTR_ATTR(program_name); COPY_WSTR_ATTR(program); - COPY_WSTRLIST(argc, argv); - COPY_WSTRLIST(nwarnoption, warnoptions); - COPY_WSTRLIST(nxoption, xoptions); - COPY_WSTRLIST(nmodule_search_path, module_search_paths); + COPY_WSTRLIST(argv); + COPY_WSTRLIST(warnoptions); + COPY_WSTRLIST(xoptions); + COPY_WSTRLIST(module_search_paths); + COPY_ATTR(use_module_search_paths); COPY_WSTR_ATTR(executable); COPY_WSTR_ATTR(prefix); @@ -817,7 +841,7 @@ config_init_executable(_PyCoreConfig *config) static const wchar_t* config_get_xoption(const _PyCoreConfig *config, wchar_t *name) { - return _Py_get_xoption(config->nxoption, config->xoptions, name); + return _Py_get_xoption(&config->xoptions, name); } @@ -1427,9 +1451,6 @@ _PyCoreConfig_Read(_PyCoreConfig *config, const _PyPreConfig *preconfig) if (config->tracemalloc < 0) { config->tracemalloc = 0; } - if (config->argc < 0) { - config->argc = 0; - } if (config->filesystem_encoding == NULL || config->filesystem_errors == NULL) { err = config_init_fs_encoding(config); @@ -1449,6 +1470,7 @@ _PyCoreConfig_Read(_PyCoreConfig *config, const _PyPreConfig *preconfig) assert(config->stdio_encoding != NULL); assert(config->stdio_errors != NULL); assert(config->_check_hash_pycs_mode != NULL); + assert(_PyWstrList_CheckConsistency(&config->argv)); return _Py_INIT_OK(); } @@ -1546,8 +1568,8 @@ _PyCoreConfig_AsDict(const _PyCoreConfig *config) : (Py_INCREF(Py_None), Py_None)) #define SET_ITEM_WSTR(ATTR) \ SET_ITEM(#ATTR, FROM_WSTRING(config->ATTR)) -#define SET_ITEM_WSTRLIST(NOPTION, OPTIONS) \ - SET_ITEM(#OPTIONS, _Py_wstrlist_as_pylist(config->NOPTION, config->OPTIONS)) +#define SET_ITEM_WSTRLIST(LIST) \ + SET_ITEM(#LIST, _PyWstrList_AsList(&config->LIST)) SET_ITEM_INT(install_signal_handlers); SET_ITEM_INT(use_hash_seed); @@ -1563,13 +1585,13 @@ _PyCoreConfig_AsDict(const _PyCoreConfig *config) SET_ITEM_STR(filesystem_errors); SET_ITEM_WSTR(pycache_prefix); SET_ITEM_WSTR(program_name); - SET_ITEM_WSTRLIST(argc, argv); + SET_ITEM_WSTRLIST(argv); SET_ITEM_WSTR(program); - SET_ITEM_WSTRLIST(nxoption, xoptions); - SET_ITEM_WSTRLIST(nwarnoption, warnoptions); + SET_ITEM_WSTRLIST(xoptions); + SET_ITEM_WSTRLIST(warnoptions); SET_ITEM_WSTR(module_search_path_env); SET_ITEM_WSTR(home); - SET_ITEM_WSTRLIST(nmodule_search_path, module_search_paths); + SET_ITEM_WSTRLIST(module_search_paths); SET_ITEM_WSTR(executable); SET_ITEM_WSTR(prefix); SET_ITEM_WSTR(base_prefix); @@ -1622,13 +1644,9 @@ fail: /* --- _PyCmdline ------------------------------------------------- */ typedef struct { - const _PyArgv *args; - int argc; - wchar_t **argv; - int nwarnoption; /* Number of -W command line options */ - wchar_t **warnoptions; /* Command line -W options */ - int nenv_warnoption; /* Number of PYTHONWARNINGS environment variables */ - wchar_t **env_warnoptions; /* PYTHONWARNINGS environment variables */ + _PyWstrList argv; + _PyWstrList warnoptions; /* Command line -W options */ + _PyWstrList env_warnoptions; /* PYTHONWARNINGS environment variables */ int print_help; /* -h, -? options */ int print_version; /* -V option */ } _PyCmdline; @@ -1637,18 +1655,9 @@ typedef struct { static void cmdline_clear(_PyCmdline *cmdline) { - _Py_wstrlist_clear(cmdline->nwarnoption, cmdline->warnoptions); - cmdline->nwarnoption = 0; - cmdline->warnoptions = NULL; - - _Py_wstrlist_clear(cmdline->nenv_warnoption, cmdline->env_warnoptions); - cmdline->nenv_warnoption = 0; - cmdline->env_warnoptions = NULL; - - if (cmdline->args->use_bytes_argv && cmdline->argv != NULL) { - _Py_wstrlist_clear(cmdline->args->argc, cmdline->argv); - } - cmdline->argv = NULL; + _PyWstrList_Clear(&cmdline->warnoptions); + _PyWstrList_Clear(&cmdline->env_warnoptions); + _PyWstrList_Clear(&cmdline->argv); } @@ -1659,11 +1668,10 @@ static _PyInitError config_parse_cmdline(_PyCoreConfig *config, _PyCmdline *cmdline, int *need_usage) { - _PyInitError err; _PyOS_ResetGetOpt(); do { int longindex = -1; - int c = _PyOS_GetOpt(cmdline->args->argc, cmdline->argv, &longindex); + int c = _PyOS_GetOpt(cmdline->argv.length, cmdline->argv.items, &longindex); if (c == EOF) { break; } @@ -1775,20 +1783,14 @@ config_parse_cmdline(_PyCoreConfig *config, _PyCmdline *cmdline, break; case 'W': - err = _Py_wstrlist_append(&cmdline->nwarnoption, - &cmdline->warnoptions, - _PyOS_optarg); - if (_Py_INIT_FAILED(err)) { - return err; + if (_PyWstrList_Append(&cmdline->warnoptions, _PyOS_optarg) < 0) { + return _Py_INIT_NO_MEMORY(); } break; case 'X': - err = _Py_wstrlist_append(&config->nxoption, - &config->xoptions, - _PyOS_optarg); - if (_Py_INIT_FAILED(err)) { - return err; + if (_PyWstrList_Append(&config->xoptions, _PyOS_optarg) < 0) { + return _Py_INIT_NO_MEMORY(); } break; @@ -1810,10 +1812,10 @@ config_parse_cmdline(_PyCoreConfig *config, _PyCmdline *cmdline, } while (1); if (config->run_command == NULL && config->run_module == NULL - && _PyOS_optind < cmdline->args->argc - && wcscmp(cmdline->argv[_PyOS_optind], L"-") != 0) + && _PyOS_optind < cmdline->argv.length + && wcscmp(cmdline->argv.items[_PyOS_optind], L"-") != 0) { - config->run_filename = _PyMem_RawWcsdup(cmdline->argv[_PyOS_optind]); + config->run_filename = _PyMem_RawWcsdup(cmdline->argv.items[_PyOS_optind]); if (config->run_filename == NULL) { return _Py_INIT_NO_MEMORY(); } @@ -1858,12 +1860,9 @@ cmdline_init_env_warnoptions(_PyCmdline *cmdline, const _PyCoreConfig *config) warning != NULL; warning = WCSTOK(NULL, L",", &context)) { - _PyInitError err = _Py_wstrlist_append(&cmdline->nenv_warnoption, - &cmdline->env_warnoptions, - warning); - if (_Py_INIT_FAILED(err)) { + if (_PyWstrList_Append(&cmdline->env_warnoptions, warning) < 0) { PyMem_RawFree(env); - return err; + return _Py_INIT_NO_MEMORY(); } } PyMem_RawFree(env); @@ -1875,8 +1874,8 @@ static _PyInitError config_init_program(_PyCoreConfig *config, const _PyCmdline *cmdline) { wchar_t *program; - if (cmdline->args->argc >= 1 && cmdline->argv != NULL) { - program = cmdline->argv[0]; + if (cmdline->argv.length >= 1) { + program = cmdline->argv.items[0]; } else { program = L""; @@ -1890,28 +1889,10 @@ config_init_program(_PyCoreConfig *config, const _PyCmdline *cmdline) } -static _PyInitError -config_add_warnings_optlist(_PyCoreConfig *config, - int len, wchar_t * const *options) -{ - for (int i = 0; i < len; i++) { - _PyInitError err = _Py_wstrlist_append(&config->nwarnoption, - &config->warnoptions, - options[i]); - if (_Py_INIT_FAILED(err)) { - return err; - } - } - return _Py_INIT_OK(); -} - - static _PyInitError config_init_warnoptions(_PyCoreConfig *config, const _PyCmdline *cmdline) { - _PyInitError err; - - assert(config->nwarnoption == 0); + assert(config->warnoptions.length == 0); /* The priority order for warnings configuration is (highest precedence * first): @@ -1929,26 +1910,17 @@ config_init_warnoptions(_PyCoreConfig *config, const _PyCmdline *cmdline) */ if (config->preconfig.dev_mode) { - err = _Py_wstrlist_append(&config->nwarnoption, - &config->warnoptions, - L"default"); - if (_Py_INIT_FAILED(err)) { - return err; + if (_PyWstrList_Append(&config->warnoptions, L"default")) { + return _Py_INIT_NO_MEMORY(); } } - err = config_add_warnings_optlist(config, - cmdline->nenv_warnoption, - cmdline->env_warnoptions); - if (_Py_INIT_FAILED(err)) { - return err; + if (_PyWstrList_Extend(&config->warnoptions, &cmdline->env_warnoptions) < 0) { + return _Py_INIT_NO_MEMORY(); } - err = config_add_warnings_optlist(config, - cmdline->nwarnoption, - cmdline->warnoptions); - if (_Py_INIT_FAILED(err)) { - return err; + if (_PyWstrList_Extend(&config->warnoptions, &cmdline->warnoptions) < 0) { + return _Py_INIT_NO_MEMORY(); } /* If the bytes_warning_flag isn't set, bytesobject.c and bytearrayobject.c @@ -1956,18 +1928,15 @@ config_init_warnoptions(_PyCoreConfig *config, const _PyCmdline *cmdline) * case. */ if (config->bytes_warning) { - wchar_t *filter; + const wchar_t *filter; if (config->bytes_warning> 1) { filter = L"error::BytesWarning"; } else { filter = L"default::BytesWarning"; } - err = _Py_wstrlist_append(&config->nwarnoption, - &config->warnoptions, - filter); - if (_Py_INIT_FAILED(err)) { - return err; + if (_PyWstrList_Append(&config->warnoptions, filter)) { + return _Py_INIT_NO_MEMORY(); } } return _Py_INIT_OK(); @@ -1977,23 +1946,24 @@ config_init_warnoptions(_PyCoreConfig *config, const _PyCmdline *cmdline) static _PyInitError config_init_argv(_PyCoreConfig *config, const _PyCmdline *cmdline) { - /* Copy argv to be able to modify it (to force -c/-m) */ - int argc = cmdline->args->argc - _PyOS_optind; - wchar_t **argv; + _PyWstrList wargv = _PyWstrList_INIT; - if (argc <= 0 || cmdline->argv == NULL) { + /* Copy argv to be able to modify it (to force -c/-m) */ + if (cmdline->argv.length <= _PyOS_optind) { /* Ensure at least one (empty) argument is seen */ - static wchar_t *empty_argv[1] = {L""}; - argc = 1; - argv = _Py_wstrlist_copy(1, empty_argv); + if (_PyWstrList_Append(&wargv, L"") < 0) { + return _Py_INIT_NO_MEMORY(); + } } else { - argv = _Py_wstrlist_copy(argc, &cmdline->argv[_PyOS_optind]); - } - - if (argv == NULL) { - return _Py_INIT_NO_MEMORY(); + _PyWstrList slice; + slice.length = cmdline->argv.length - _PyOS_optind; + slice.items = &cmdline->argv.items[_PyOS_optind]; + if (_PyWstrList_Copy(&wargv, &slice) < 0) { + return _Py_INIT_NO_MEMORY(); + } } + assert(wargv.length >= 1); wchar_t *arg0 = NULL; if (config->run_command != NULL) { @@ -2007,17 +1977,16 @@ config_init_argv(_PyCoreConfig *config, const _PyCmdline *cmdline) if (arg0 != NULL) { arg0 = _PyMem_RawWcsdup(arg0); if (arg0 == NULL) { - _Py_wstrlist_clear(argc, argv); + _PyWstrList_Clear(&wargv); return _Py_INIT_NO_MEMORY(); } - assert(argc >= 1); - PyMem_RawFree(argv[0]); - argv[0] = arg0; + PyMem_RawFree(wargv.items[0]); + wargv.items[0] = arg0; } - config->argc = argc; - config->argv = argv; + _PyWstrList_Clear(&config->argv); + config->argv = wargv; return _Py_INIT_OK(); } @@ -2097,7 +2066,7 @@ config_from_cmdline(_PyCoreConfig *config, _PyCmdline *cmdline, return err; } - if (_Py_SetArgcArgv(cmdline->args->argc, cmdline->argv) < 0) { + if (_Py_SetArgcArgv(cmdline->argv.length, cmdline->argv.items) < 0) { return _Py_INIT_NO_MEMORY(); } return _Py_INIT_OK(); @@ -2117,9 +2086,8 @@ _PyCoreConfig_ReadFromArgv(_PyCoreConfig *config, const _PyArgv *args, _PyCmdline cmdline; memset(&cmdline, 0, sizeof(cmdline)); - cmdline.args = args; - err = _PyArgv_Decode(cmdline.args, &cmdline.argv); + err = _PyArgv_AsWstrList(args, &cmdline.argv); if (_Py_INIT_FAILED(err)) { goto done; } -- cgit v1.2.1 From 625997622b4736e9184bdd8bf1e22a7b51be1afc Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Fri, 15 Mar 2019 16:03:23 +0100 Subject: bpo-36301: _PyCoreConfig_Read() ensures that argv is not empty (GH-12347) If argv is empty, add an empty string. --- Python/coreconfig.c | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'Python/coreconfig.c') diff --git a/Python/coreconfig.c b/Python/coreconfig.c index 15107fa36c..0827376509 100644 --- a/Python/coreconfig.c +++ b/Python/coreconfig.c @@ -1464,6 +1464,13 @@ _PyCoreConfig_Read(_PyCoreConfig *config, const _PyPreConfig *preconfig) return err; } + if (config->argv.length < 1) { + /* Ensure at least one (empty) argument is seen */ + if (_PyWstrList_Append(&config->argv, L"") < 0) { + return _Py_INIT_NO_MEMORY(); + } + } + assert(config->preconfig.use_environment >= 0); assert(config->filesystem_encoding != NULL); assert(config->filesystem_errors != NULL); -- cgit v1.2.1 From f29084d611a6ca504c99a0967371374febf0ccc3 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Wed, 20 Mar 2019 02:20:13 +0100 Subject: bpo-36301: Add _PyRuntime.pre_initialized (GH-12457) * Add _PyRuntime.pre_initialized: set to 1 when Python is pre-initialized * Add _Py_PreInitialize() and _Py_PreInitializeFromPreConfig(). * _PyCoreConfig_Read() now calls _Py_PreInitialize(). * Move _PyPreConfig_GetGlobalConfig() and _PyCoreConfig_GetGlobalConfig() calls from main.c to preconfig.c and coreconfig.c. --- Python/coreconfig.c | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'Python/coreconfig.c') diff --git a/Python/coreconfig.c b/Python/coreconfig.c index 0827376509..de2058c0f3 100644 --- a/Python/coreconfig.c +++ b/Python/coreconfig.c @@ -1367,6 +1367,11 @@ _PyCoreConfig_Read(_PyCoreConfig *config, const _PyPreConfig *preconfig) { _PyInitError err; + err = _Py_PreInitialize(); + if (_Py_INIT_FAILED(err)) { + return err; + } + _PyCoreConfig_GetGlobalConfig(config); if (preconfig != NULL) { @@ -2025,6 +2030,8 @@ config_from_cmdline(_PyCoreConfig *config, _PyCmdline *cmdline, int need_usage = 0; _PyInitError err; + _PyCoreConfig_GetGlobalConfig(config); + err = config_init_program(config, cmdline); if (_Py_INIT_FAILED(err)) { return err; -- cgit v1.2.1 From 4a1468e593c4b67d8c78b78070fff9e18ec5d790 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Wed, 20 Mar 2019 03:11:38 +0100 Subject: bpo-36356: Fix _PyCoreConfig_Read() (GH-12454) Don't override parameters which are already set by the user. --- Python/coreconfig.c | 55 +++++++++++++++++++++++++++++++---------------------- 1 file changed, 32 insertions(+), 23 deletions(-) (limited to 'Python/coreconfig.c') diff --git a/Python/coreconfig.c b/Python/coreconfig.c index de2058c0f3..e1d883c51c 100644 --- a/Python/coreconfig.c +++ b/Python/coreconfig.c @@ -961,13 +961,15 @@ config_read_env_vars(_PyCoreConfig *config) config->malloc_stats = 1; } - wchar_t *path; - int res = _PyCoreConfig_GetEnvDup(config, &path, - L"PYTHONPATH", "PYTHONPATH"); - if (res < 0) { - return DECODE_LOCALE_ERR("PYTHONPATH", res); + if (config->module_search_path_env == NULL) { + wchar_t *path; + int res = _PyCoreConfig_GetEnvDup(config, &path, + L"PYTHONPATH", "PYTHONPATH"); + if (res < 0) { + return DECODE_LOCALE_ERR("PYTHONPATH", res); + } + config->module_search_path_env = path; } - config->module_search_path_env = path; if (config->use_hash_seed < 0) { _PyInitError err = config_init_hash_seed(config); @@ -1689,18 +1691,20 @@ config_parse_cmdline(_PyCoreConfig *config, _PyCmdline *cmdline, } if (c == 'c') { - /* -c is the last option; following arguments - that look like options are left for the - command to interpret. */ - size_t len = wcslen(_PyOS_optarg) + 1 + 1; - wchar_t *command = PyMem_RawMalloc(sizeof(wchar_t) * len); - if (command == NULL) { - return _Py_INIT_NO_MEMORY(); + if (config->run_command == NULL) { + /* -c is the last option; following arguments + that look like options are left for the + command to interpret. */ + size_t len = wcslen(_PyOS_optarg) + 1 + 1; + wchar_t *command = PyMem_RawMalloc(sizeof(wchar_t) * len); + if (command == NULL) { + return _Py_INIT_NO_MEMORY(); + } + memcpy(command, _PyOS_optarg, (len - 2) * sizeof(wchar_t)); + command[len - 2] = '\n'; + command[len - 1] = 0; + config->run_command = command; } - memcpy(command, _PyOS_optarg, (len - 2) * sizeof(wchar_t)); - command[len - 2] = '\n'; - command[len - 1] = 0; - config->run_command = command; break; } @@ -1708,9 +1712,11 @@ config_parse_cmdline(_PyCoreConfig *config, _PyCmdline *cmdline, /* -m is the last option; following arguments that look like options are left for the module to interpret. */ - config->run_module = _PyMem_RawWcsdup(_PyOS_optarg); if (config->run_module == NULL) { - return _Py_INIT_NO_MEMORY(); + config->run_module = _PyMem_RawWcsdup(_PyOS_optarg); + if (config->run_module == NULL) { + return _Py_INIT_NO_MEMORY(); + } } break; } @@ -1825,7 +1831,8 @@ config_parse_cmdline(_PyCoreConfig *config, _PyCmdline *cmdline, if (config->run_command == NULL && config->run_module == NULL && _PyOS_optind < cmdline->argv.length - && wcscmp(cmdline->argv.items[_PyOS_optind], L"-") != 0) + && wcscmp(cmdline->argv.items[_PyOS_optind], L"-") != 0 + && config->run_filename == NULL) { config->run_filename = _PyMem_RawWcsdup(cmdline->argv.items[_PyOS_optind]); if (config->run_filename == NULL) { @@ -2032,9 +2039,11 @@ config_from_cmdline(_PyCoreConfig *config, _PyCmdline *cmdline, _PyCoreConfig_GetGlobalConfig(config); - err = config_init_program(config, cmdline); - if (_Py_INIT_FAILED(err)) { - return err; + if (config->program == NULL) { + err = config_init_program(config, cmdline); + if (_Py_INIT_FAILED(err)) { + return err; + } } err = config_parse_cmdline(config, cmdline, &need_usage); -- cgit v1.2.1 From fa1537684869186da7938e4330361bf02363bac8 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Wed, 20 Mar 2019 04:25:38 +0100 Subject: bpo-36301: Add _PyPreCmdline internal API (GH-12458) _PyCoreConfig_ReadFromArgv() now reuses the code parsing command line options from preconfig.c. --- Python/coreconfig.c | 67 ++++++++++++++++++++++++++++++----------------------- 1 file changed, 38 insertions(+), 29 deletions(-) (limited to 'Python/coreconfig.c') diff --git a/Python/coreconfig.c b/Python/coreconfig.c index e1d883c51c..1881f00bf2 100644 --- a/Python/coreconfig.c +++ b/Python/coreconfig.c @@ -1658,7 +1658,7 @@ fail: /* --- _PyCmdline ------------------------------------------------- */ typedef struct { - _PyWstrList argv; + _PyPreCmdline precmdline; _PyWstrList warnoptions; /* Command line -W options */ _PyWstrList env_warnoptions; /* PYTHONWARNINGS environment variables */ int print_help; /* -h, -? options */ @@ -1669,9 +1669,9 @@ typedef struct { static void cmdline_clear(_PyCmdline *cmdline) { + _PyPreCmdline_Clear(&cmdline->precmdline); _PyWstrList_Clear(&cmdline->warnoptions); _PyWstrList_Clear(&cmdline->env_warnoptions); - _PyWstrList_Clear(&cmdline->argv); } @@ -1682,10 +1682,12 @@ static _PyInitError config_parse_cmdline(_PyCoreConfig *config, _PyCmdline *cmdline, int *need_usage) { + const _PyWstrList *argv = &cmdline->precmdline.argv; + _PyOS_ResetGetOpt(); do { int longindex = -1; - int c = _PyOS_GetOpt(cmdline->argv.length, cmdline->argv.items, &longindex); + int c = _PyOS_GetOpt(argv->length, argv->items, &longindex); if (c == EOF) { break; } @@ -1754,6 +1756,7 @@ config_parse_cmdline(_PyCoreConfig *config, _PyCmdline *cmdline, case 'E': case 'I': + case 'X': /* option handled by _PyPreConfig_ReadFromArgv() */ break; @@ -1806,12 +1809,6 @@ config_parse_cmdline(_PyCoreConfig *config, _PyCmdline *cmdline, } break; - case 'X': - if (_PyWstrList_Append(&config->xoptions, _PyOS_optarg) < 0) { - return _Py_INIT_NO_MEMORY(); - } - break; - case 'q': config->quiet++; break; @@ -1830,11 +1827,11 @@ config_parse_cmdline(_PyCoreConfig *config, _PyCmdline *cmdline, } while (1); if (config->run_command == NULL && config->run_module == NULL - && _PyOS_optind < cmdline->argv.length - && wcscmp(cmdline->argv.items[_PyOS_optind], L"-") != 0 + && _PyOS_optind < argv->length + && wcscmp(argv->items[_PyOS_optind], L"-") != 0 && config->run_filename == NULL) { - config->run_filename = _PyMem_RawWcsdup(cmdline->argv.items[_PyOS_optind]); + config->run_filename = _PyMem_RawWcsdup(argv->items[_PyOS_optind]); if (config->run_filename == NULL) { return _Py_INIT_NO_MEMORY(); } @@ -1892,9 +1889,10 @@ cmdline_init_env_warnoptions(_PyCmdline *cmdline, const _PyCoreConfig *config) static _PyInitError config_init_program(_PyCoreConfig *config, const _PyCmdline *cmdline) { + const _PyWstrList *argv = &cmdline->precmdline.argv; wchar_t *program; - if (cmdline->argv.length >= 1) { - program = cmdline->argv.items[0]; + if (argv->length >= 1) { + program = argv->items[0]; } else { program = L""; @@ -1965,24 +1963,25 @@ config_init_warnoptions(_PyCoreConfig *config, const _PyCmdline *cmdline) static _PyInitError config_init_argv(_PyCoreConfig *config, const _PyCmdline *cmdline) { - _PyWstrList wargv = _PyWstrList_INIT; + const _PyWstrList *cmdline_argv = &cmdline->precmdline.argv; + _PyWstrList config_argv = _PyWstrList_INIT; /* Copy argv to be able to modify it (to force -c/-m) */ - if (cmdline->argv.length <= _PyOS_optind) { + if (cmdline_argv->length <= _PyOS_optind) { /* Ensure at least one (empty) argument is seen */ - if (_PyWstrList_Append(&wargv, L"") < 0) { + if (_PyWstrList_Append(&config_argv, L"") < 0) { return _Py_INIT_NO_MEMORY(); } } else { _PyWstrList slice; - slice.length = cmdline->argv.length - _PyOS_optind; - slice.items = &cmdline->argv.items[_PyOS_optind]; - if (_PyWstrList_Copy(&wargv, &slice) < 0) { + slice.length = cmdline_argv->length - _PyOS_optind; + slice.items = &cmdline_argv->items[_PyOS_optind]; + if (_PyWstrList_Copy(&config_argv, &slice) < 0) { return _Py_INIT_NO_MEMORY(); } } - assert(wargv.length >= 1); + assert(config_argv.length >= 1); wchar_t *arg0 = NULL; if (config->run_command != NULL) { @@ -1996,16 +1995,16 @@ config_init_argv(_PyCoreConfig *config, const _PyCmdline *cmdline) if (arg0 != NULL) { arg0 = _PyMem_RawWcsdup(arg0); if (arg0 == NULL) { - _PyWstrList_Clear(&wargv); + _PyWstrList_Clear(&config_argv); return _Py_INIT_NO_MEMORY(); } - PyMem_RawFree(wargv.items[0]); - wargv.items[0] = arg0; + PyMem_RawFree(config_argv.items[0]); + config_argv.items[0] = arg0; } _PyWstrList_Clear(&config->argv); - config->argv = wargv; + config->argv = config_argv; return _Py_INIT_OK(); } @@ -2046,6 +2045,16 @@ config_from_cmdline(_PyCoreConfig *config, _PyCmdline *cmdline, } } + err = _PyPreCmdline_Read(&cmdline->precmdline); + if (_Py_INIT_FAILED(err)) { + return err; + } + + _PyPreCmdline_SetPreConfig(&cmdline->precmdline, &config->preconfig); + if (_PyWstrList_Extend(&config->xoptions, &cmdline->precmdline.xoptions) < 0) { + return _Py_INIT_NO_MEMORY(); + } + err = config_parse_cmdline(config, cmdline, &need_usage); if (_Py_INIT_FAILED(err)) { return err; @@ -2089,7 +2098,8 @@ config_from_cmdline(_PyCoreConfig *config, _PyCmdline *cmdline, return err; } - if (_Py_SetArgcArgv(cmdline->argv.length, cmdline->argv.items) < 0) { + const _PyWstrList *argv = &cmdline->precmdline.argv; + if (_Py_SetArgcArgv(argv->length, argv->items) < 0) { return _Py_INIT_NO_MEMORY(); } return _Py_INIT_OK(); @@ -2107,10 +2117,9 @@ _PyCoreConfig_ReadFromArgv(_PyCoreConfig *config, const _PyArgv *args, { _PyInitError err; - _PyCmdline cmdline; - memset(&cmdline, 0, sizeof(cmdline)); + _PyCmdline cmdline = {.precmdline = _PyPreCmdline_INIT}; - err = _PyArgv_AsWstrList(args, &cmdline.argv); + err = _PyPreCmdline_Init(&cmdline.precmdline, args); if (_Py_INIT_FAILED(err)) { goto done; } -- cgit v1.2.1 From 6d5ee973f0600a3a9444f569dcf0dd346bfa2a11 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Sat, 23 Mar 2019 12:05:43 +0100 Subject: bpo-36301: Add _PyRuntimeState.preconfig (GH-12506) _PyPreConfig_Write() now writes the applied pre-configuration into _PyRuntimeState.preconfig. --- Python/coreconfig.c | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) (limited to 'Python/coreconfig.c') diff --git a/Python/coreconfig.c b/Python/coreconfig.c index 1881f00bf2..540e608fb0 100644 --- a/Python/coreconfig.c +++ b/Python/coreconfig.c @@ -5,6 +5,7 @@ #include "pycore_getopt.h" #include "pycore_pylifecycle.h" #include "pycore_pymem.h" +#include "pycore_pystate.h" /* _PyRuntime */ #include "pycore_pathconfig.h" #include /* setlocale() */ #ifdef HAVE_LANGINFO_H @@ -1358,6 +1359,17 @@ done: } +static _PyInitError +_PyCoreConfig_GetPreConfig(_PyCoreConfig *config) +{ + /* Read config written by _PyPreConfig_Write() */ + if (_PyPreConfig_Copy(&config->preconfig, &_PyRuntime.preconfig) < 0) { + return _Py_INIT_NO_MEMORY(); + } + return _Py_INIT_OK(); +} + + /* Read the configuration into _PyCoreConfig from: * Environment variables @@ -1374,6 +1386,11 @@ _PyCoreConfig_Read(_PyCoreConfig *config, const _PyPreConfig *preconfig) return err; } + err = _PyCoreConfig_GetPreConfig(config); + if (_Py_INIT_FAILED(err)) { + return err; + } + _PyCoreConfig_GetGlobalConfig(config); if (preconfig != NULL) { @@ -2117,6 +2134,11 @@ _PyCoreConfig_ReadFromArgv(_PyCoreConfig *config, const _PyArgv *args, { _PyInitError err; + err = _Py_PreInitialize(); + if (_Py_INIT_FAILED(err)) { + return err; + } + _PyCmdline cmdline = {.precmdline = _PyPreCmdline_INIT}; err = _PyPreCmdline_Init(&cmdline.precmdline, args); -- cgit v1.2.1 From f72346c47537657a287a862305f65eb5d7594fbf Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Mon, 25 Mar 2019 17:54:58 +0100 Subject: bpo-36301: Cleanup preconfig code (GH-12535) Prepare code to move some _PyPreConfig parameters into _PyPreCmdline. Changes: * _PyCoreConfig_ReadFromArgv(): remove preconfig parameter, use _PyRuntime.preconfig. * Add _PyPreCmdline_GetPreConfig() (called by _PyPreConfig_Read()). * Rename _PyPreCmdline_Init() to _PyPreCmdline_SetArgv() * Factorize _Py_PreInitializeFromPreConfig() code: add pyinit_preinit(). * _PyPreConfig_Read() now sets coerce_c_locale to 2 if it must be coerced. * Remove _PyCoreConfig_ReadPreConfig(). * _PyCoreConfig_Write() now copies updated preconfig into _PyRuntime. --- Python/coreconfig.c | 86 +++++++++++++---------------------------------------- 1 file changed, 21 insertions(+), 65 deletions(-) (limited to 'Python/coreconfig.c') diff --git a/Python/coreconfig.c b/Python/coreconfig.c index 540e608fb0..130dfccc4d 100644 --- a/Python/coreconfig.c +++ b/Python/coreconfig.c @@ -1330,46 +1330,6 @@ config_init_fs_encoding(_PyCoreConfig *config) } -static _PyInitError -_PyCoreConfig_ReadPreConfig(_PyCoreConfig *config) -{ - _PyInitError err; - _PyPreConfig local_preconfig = _PyPreConfig_INIT; - _PyPreConfig_GetGlobalConfig(&local_preconfig); - - if (_PyPreConfig_Copy(&local_preconfig, &config->preconfig) < 0) { - err = _Py_INIT_NO_MEMORY(); - goto done; - } - - err = _PyPreConfig_Read(&local_preconfig); - if (_Py_INIT_FAILED(err)) { - goto done; - } - - if (_PyPreConfig_Copy(&config->preconfig, &local_preconfig) < 0) { - err = _Py_INIT_NO_MEMORY(); - goto done; - } - err = _Py_INIT_OK(); - -done: - _PyPreConfig_Clear(&local_preconfig); - return err; -} - - -static _PyInitError -_PyCoreConfig_GetPreConfig(_PyCoreConfig *config) -{ - /* Read config written by _PyPreConfig_Write() */ - if (_PyPreConfig_Copy(&config->preconfig, &_PyRuntime.preconfig) < 0) { - return _Py_INIT_NO_MEMORY(); - } - return _Py_INIT_OK(); -} - - /* Read the configuration into _PyCoreConfig from: * Environment variables @@ -1377,7 +1337,7 @@ _PyCoreConfig_GetPreConfig(_PyCoreConfig *config) See _PyCoreConfig_ReadFromArgv() to parse also command line arguments. */ _PyInitError -_PyCoreConfig_Read(_PyCoreConfig *config, const _PyPreConfig *preconfig) +_PyCoreConfig_Read(_PyCoreConfig *config) { _PyInitError err; @@ -1386,25 +1346,12 @@ _PyCoreConfig_Read(_PyCoreConfig *config, const _PyPreConfig *preconfig) return err; } - err = _PyCoreConfig_GetPreConfig(config); - if (_Py_INIT_FAILED(err)) { - return err; + if (_PyPreConfig_Copy(&config->preconfig, &_PyRuntime.preconfig) < 0) { + return _Py_INIT_NO_MEMORY(); } _PyCoreConfig_GetGlobalConfig(config); - if (preconfig != NULL) { - if (_PyPreConfig_Copy(&config->preconfig, preconfig) < 0) { - return _Py_INIT_NO_MEMORY(); - } - } - else { - err = _PyCoreConfig_ReadPreConfig(config); - if (_Py_INIT_FAILED(err)) { - return err; - } - } - assert(config->preconfig.use_environment >= 0); if (config->preconfig.isolated > 0) { @@ -1548,11 +1495,22 @@ config_init_stdio(const _PyCoreConfig *config) - set Py_xxx global configuration variables - initialize C standard streams (stdin, stdout, stderr) */ -void +_PyInitError _PyCoreConfig_Write(const _PyCoreConfig *config) { _PyCoreConfig_SetGlobalConfig(config); config_init_stdio(config); + + /* Write the new pre-configuration into _PyRuntime */ + PyMemAllocatorEx old_alloc; + _PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc); + int res = _PyPreConfig_Copy(&_PyRuntime.preconfig, &config->preconfig); + PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc); + if (res < 0) { + return _Py_INIT_NO_MEMORY(); + } + + return _Py_INIT_OK(); } @@ -2047,8 +2005,7 @@ config_usage(int error, const wchar_t* program) /* Parse command line options and environment variables. */ static _PyInitError -config_from_cmdline(_PyCoreConfig *config, _PyCmdline *cmdline, - const _PyPreConfig *preconfig) +config_from_cmdline(_PyCoreConfig *config, _PyCmdline *cmdline) { int need_usage = 0; _PyInitError err; @@ -2067,7 +2024,7 @@ config_from_cmdline(_PyCoreConfig *config, _PyCmdline *cmdline, return err; } - _PyPreCmdline_SetPreConfig(&cmdline->precmdline, &config->preconfig); + _PyPreCmdline_SetPreConfig(&cmdline->precmdline, &_PyRuntime.preconfig); if (_PyWstrList_Extend(&config->xoptions, &cmdline->precmdline.xoptions) < 0) { return _Py_INIT_NO_MEMORY(); } @@ -2098,7 +2055,7 @@ config_from_cmdline(_PyCoreConfig *config, _PyCmdline *cmdline, return err; } - err = _PyCoreConfig_Read(config, preconfig); + err = _PyCoreConfig_Read(config); if (_Py_INIT_FAILED(err)) { return err; } @@ -2129,8 +2086,7 @@ config_from_cmdline(_PyCoreConfig *config, _PyCmdline *cmdline, * Environment variables * Py_xxx global configuration variables */ _PyInitError -_PyCoreConfig_ReadFromArgv(_PyCoreConfig *config, const _PyArgv *args, - const _PyPreConfig *preconfig) +_PyCoreConfig_ReadFromArgv(_PyCoreConfig *config, const _PyArgv *args) { _PyInitError err; @@ -2141,12 +2097,12 @@ _PyCoreConfig_ReadFromArgv(_PyCoreConfig *config, const _PyArgv *args, _PyCmdline cmdline = {.precmdline = _PyPreCmdline_INIT}; - err = _PyPreCmdline_Init(&cmdline.precmdline, args); + err = _PyPreCmdline_SetArgv(&cmdline.precmdline, args); if (_Py_INIT_FAILED(err)) { goto done; } - err = config_from_cmdline(config, &cmdline, preconfig); + err = config_from_cmdline(config, &cmdline); if (_Py_INIT_FAILED(err)) { goto done; } -- cgit v1.2.1 From a6fbc4e25e1dc7d1c9a26888b9115bc6c2afc101 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Mon, 25 Mar 2019 18:37:10 +0100 Subject: bpo-36301: Add _Py_PreInitializeFromConfig() (GH-12536) * Initialize _PyPreConfig.dev_mode to -1. * _PyPreConfig_Read(): coreconfig has the priority over preconfig. * _PyCoreConfig_Read() now calls _PyPreCmdline_Read() internally. * config_from_cmdline() now pass _PyPreCmdline to config_read(). * Add _PyPreCmdline_Copy(). --- Python/coreconfig.c | 62 ++++++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 54 insertions(+), 8 deletions(-) (limited to 'Python/coreconfig.c') diff --git a/Python/coreconfig.c b/Python/coreconfig.c index 130dfccc4d..ba5abb6ca4 100644 --- a/Python/coreconfig.c +++ b/Python/coreconfig.c @@ -1336,16 +1336,30 @@ config_init_fs_encoding(_PyCoreConfig *config) * Py_xxx global configuration variables See _PyCoreConfig_ReadFromArgv() to parse also command line arguments. */ -_PyInitError -_PyCoreConfig_Read(_PyCoreConfig *config) +static _PyInitError +config_read_impl(_PyCoreConfig *config, _PyPreCmdline *cmdline) { _PyInitError err; - err = _Py_PreInitialize(); + err = _Py_PreInitializeFromConfig(config); + if (_Py_INIT_FAILED(err)) { + return err; + } + + _PyPreCmdline_GetPreConfig(cmdline, &_PyRuntime.preconfig); + _PyPreCmdline_GetCoreConfig(cmdline, config); + + err = _PyPreCmdline_Read(cmdline); if (_Py_INIT_FAILED(err)) { return err; } + _PyPreCmdline_SetCoreConfig(cmdline, config); + + if (_PyWstrList_Extend(&config->xoptions, &cmdline->xoptions) < 0) { + return _Py_INIT_NO_MEMORY(); + } + if (_PyPreConfig_Copy(&config->preconfig, &_PyRuntime.preconfig) < 0) { return _Py_INIT_NO_MEMORY(); } @@ -1454,6 +1468,41 @@ _PyCoreConfig_Read(_PyCoreConfig *config) } +static _PyInitError +config_read(_PyCoreConfig *config, const _PyPreCmdline *src_cmdline) +{ + _PyInitError err; + + err = _Py_PreInitializeFromConfig(config); + if (_Py_INIT_FAILED(err)) { + return err; + } + + _PyPreCmdline cmdline = _PyPreCmdline_INIT; + + if (src_cmdline) { + if (_PyPreCmdline_Copy(&cmdline, src_cmdline) < 0) { + err = _Py_INIT_NO_MEMORY(); + goto done; + } + } + + err = config_read_impl(config, &cmdline); + +done: + _PyPreCmdline_Clear(&cmdline); + return err; + +} + + +_PyInitError +_PyCoreConfig_Read(_PyCoreConfig *config) +{ + return config_read(config, NULL); +} + + static void config_init_stdio(const _PyCoreConfig *config) { @@ -2025,9 +2074,6 @@ config_from_cmdline(_PyCoreConfig *config, _PyCmdline *cmdline) } _PyPreCmdline_SetPreConfig(&cmdline->precmdline, &_PyRuntime.preconfig); - if (_PyWstrList_Extend(&config->xoptions, &cmdline->precmdline.xoptions) < 0) { - return _Py_INIT_NO_MEMORY(); - } err = config_parse_cmdline(config, cmdline, &need_usage); if (_Py_INIT_FAILED(err)) { @@ -2055,7 +2101,7 @@ config_from_cmdline(_PyCoreConfig *config, _PyCmdline *cmdline) return err; } - err = _PyCoreConfig_Read(config); + err = config_read(config, &cmdline->precmdline); if (_Py_INIT_FAILED(err)) { return err; } @@ -2090,7 +2136,7 @@ _PyCoreConfig_ReadFromArgv(_PyCoreConfig *config, const _PyArgv *args) { _PyInitError err; - err = _Py_PreInitialize(); + err = _Py_PreInitializeFromConfig(config); if (_Py_INIT_FAILED(err)) { return err; } -- cgit v1.2.1 From 1075d1684ab84dc7c28d93cfb46e95e70d3b6d3b Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Mon, 25 Mar 2019 23:19:57 +0100 Subject: bpo-36301: Add _Py_GetConfigsAsDict() function (GH-12540) * Add _Py_GetConfigsAsDict() function to get all configurations as a dict. * dump_config() of _testembed.c now dumps preconfig as a separated key: call _Py_GetConfigsAsDict(). * Make _PyMainInterpreterConfig_AsDict() private. --- Python/coreconfig.c | 73 ++++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 66 insertions(+), 7 deletions(-) (limited to 'Python/coreconfig.c') diff --git a/Python/coreconfig.c b/Python/coreconfig.c index ba5abb6ca4..a434b258f2 100644 --- a/Python/coreconfig.c +++ b/Python/coreconfig.c @@ -131,7 +131,7 @@ int Py_LegacyWindowsStdioFlag = 0; /* Uses FileIO instead of WindowsConsoleIO */ #endif -PyObject * +static PyObject * _Py_GetGlobalVariablesAsDict(void) { PyObject *dict, *obj; @@ -1563,7 +1563,7 @@ _PyCoreConfig_Write(const _PyCoreConfig *config) } -PyObject * +static PyObject * _PyCoreConfig_AsDict(const _PyCoreConfig *config) { PyObject *dict; @@ -1573,11 +1573,6 @@ _PyCoreConfig_AsDict(const _PyCoreConfig *config) return NULL; } - if (_PyPreConfig_AsDict(&config->preconfig, dict) < 0) { - Py_DECREF(dict); - return NULL; - } - #define SET_ITEM(KEY, EXPR) \ do { \ PyObject *obj = (EXPR); \ @@ -2158,3 +2153,67 @@ done: cmdline_clear(&cmdline); return err; } + + +PyObject* +_Py_GetConfigsAsDict(void) +{ + PyObject *config = NULL; + PyObject *dict = NULL; + + config = PyDict_New(); + if (config == NULL) { + goto error; + } + + /* global config */ + dict = _Py_GetGlobalVariablesAsDict(); + if (dict == NULL) { + goto error; + } + if (PyDict_SetItemString(config, "global_config", dict) < 0) { + goto error; + } + Py_CLEAR(dict); + + /* pre config */ + PyInterpreterState *interp = _PyInterpreterState_Get(); + const _PyCoreConfig *core_config = _PyInterpreterState_GetCoreConfig(interp); + const _PyPreConfig *pre_config = &core_config->preconfig; + dict = _PyPreConfig_AsDict(pre_config); + if (dict == NULL) { + goto error; + } + if (PyDict_SetItemString(config, "pre_config", dict) < 0) { + goto error; + } + Py_CLEAR(dict); + + /* core config */ + dict = _PyCoreConfig_AsDict(core_config); + if (dict == NULL) { + goto error; + } + if (PyDict_SetItemString(config, "core_config", dict) < 0) { + goto error; + } + Py_CLEAR(dict); + + /* main config */ + const _PyMainInterpreterConfig *main_config = _PyInterpreterState_GetMainConfig(interp); + dict = _PyMainInterpreterConfig_AsDict(main_config); + if (dict == NULL) { + goto error; + } + if (PyDict_SetItemString(config, "main_config", dict) < 0) { + goto error; + } + Py_CLEAR(dict); + + return config; + +error: + Py_XDECREF(config); + Py_XDECREF(dict); + return NULL; +} -- cgit v1.2.1 From f78a5e9ce8f32a195f5f788aade79578437f30a6 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Tue, 26 Mar 2019 00:03:15 +0100 Subject: bpo-36301: Add _Py_GetEnv() function (GH-12542) * Make _PyPreConfig_GetEnv(), _PyCoreConfig_GetEnv() and _PyCoreConfig_GetEnvDup() private * _Py_get_env_flag() first parameter becomes "int use_environment" --- Python/coreconfig.c | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) (limited to 'Python/coreconfig.c') diff --git a/Python/coreconfig.c b/Python/coreconfig.c index a434b258f2..1245aef54b 100644 --- a/Python/coreconfig.c +++ b/Python/coreconfig.c @@ -610,14 +610,14 @@ _PyCoreConfig_Copy(_PyCoreConfig *config, const _PyCoreConfig *config2) } -const char* +static const char* _PyCoreConfig_GetEnv(const _PyCoreConfig *config, const char *name) { - return _PyPreConfig_GetEnv(&config->preconfig, name); + return _Py_GetEnv(config->preconfig.use_environment, name); } -int +static int _PyCoreConfig_GetEnvDup(const _PyCoreConfig *config, wchar_t **dest, wchar_t *wname, char *name) @@ -924,34 +924,34 @@ config_wstr_to_int(const wchar_t *wstr, int *result) static _PyInitError config_read_env_vars(_PyCoreConfig *config) { - _PyPreConfig *preconfig = &config->preconfig; + int use_env = config->preconfig.use_environment; /* Get environment variables */ - _Py_get_env_flag(preconfig, &config->parser_debug, "PYTHONDEBUG"); - _Py_get_env_flag(preconfig, &config->verbose, "PYTHONVERBOSE"); - _Py_get_env_flag(preconfig, &config->optimization_level, "PYTHONOPTIMIZE"); - _Py_get_env_flag(preconfig, &config->inspect, "PYTHONINSPECT"); + _Py_get_env_flag(use_env, &config->parser_debug, "PYTHONDEBUG"); + _Py_get_env_flag(use_env, &config->verbose, "PYTHONVERBOSE"); + _Py_get_env_flag(use_env, &config->optimization_level, "PYTHONOPTIMIZE"); + _Py_get_env_flag(use_env, &config->inspect, "PYTHONINSPECT"); int dont_write_bytecode = 0; - _Py_get_env_flag(preconfig, &dont_write_bytecode, "PYTHONDONTWRITEBYTECODE"); + _Py_get_env_flag(use_env, &dont_write_bytecode, "PYTHONDONTWRITEBYTECODE"); if (dont_write_bytecode) { config->write_bytecode = 0; } int no_user_site_directory = 0; - _Py_get_env_flag(preconfig, &no_user_site_directory, "PYTHONNOUSERSITE"); + _Py_get_env_flag(use_env, &no_user_site_directory, "PYTHONNOUSERSITE"); if (no_user_site_directory) { config->user_site_directory = 0; } int unbuffered_stdio = 0; - _Py_get_env_flag(preconfig, &unbuffered_stdio, "PYTHONUNBUFFERED"); + _Py_get_env_flag(use_env, &unbuffered_stdio, "PYTHONUNBUFFERED"); if (unbuffered_stdio) { config->buffered_stdio = 0; } #ifdef MS_WINDOWS - _Py_get_env_flag(preconfig, &config->legacy_windows_stdio, + _Py_get_env_flag(use_env, &config->legacy_windows_stdio, "PYTHONLEGACYWINDOWSSTDIO"); #endif -- cgit v1.2.1 From 20004959d23d07ac784eef51ecb161012180faa8 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Tue, 26 Mar 2019 02:31:11 +0100 Subject: bpo-36301: Remove _PyCoreConfig.preconfig (GH-12546) * Replace _PyCoreConfig.preconfig with 3 new fields in _PyCoreConfig: isolated, use_environment, dev_mode. * Add _PyPreCmdline.dev_mode. * Add _Py_PreInitializeFromPreConfigInPlace(). --- Python/coreconfig.c | 85 ++++++++++++++++++++++------------------------------- 1 file changed, 35 insertions(+), 50 deletions(-) (limited to 'Python/coreconfig.c') diff --git a/Python/coreconfig.c b/Python/coreconfig.c index 1245aef54b..2e6eb40298 100644 --- a/Python/coreconfig.c +++ b/Python/coreconfig.c @@ -469,8 +469,6 @@ Py_GetArgcArgv(int *argc, wchar_t ***argv) void _PyCoreConfig_Clear(_PyCoreConfig *config) { - _PyPreConfig_Clear(&config->preconfig); - #define CLEAR(ATTR) \ do { \ PyMem_RawFree(ATTR); \ @@ -514,10 +512,6 @@ _PyCoreConfig_Copy(_PyCoreConfig *config, const _PyCoreConfig *config2) { _PyCoreConfig_Clear(config); - if (_PyPreConfig_Copy(&config->preconfig, &config2->preconfig) < 0) { - return -1; - } - #define COPY_ATTR(ATTR) config->ATTR = config2->ATTR #define COPY_STR_ATTR(ATTR) \ do { \ @@ -544,6 +538,9 @@ _PyCoreConfig_Copy(_PyCoreConfig *config, const _PyCoreConfig *config2) } \ } while (0) + COPY_ATTR(isolated); + COPY_ATTR(use_environment); + COPY_ATTR(dev_mode); COPY_ATTR(install_signal_handlers); COPY_ATTR(use_hash_seed); COPY_ATTR(hash_seed); @@ -613,7 +610,7 @@ _PyCoreConfig_Copy(_PyCoreConfig *config, const _PyCoreConfig *config2) static const char* _PyCoreConfig_GetEnv(const _PyCoreConfig *config, const char *name) { - return _Py_GetEnv(config->preconfig.use_environment, name); + return _Py_GetEnv(config->use_environment, name); } @@ -622,9 +619,9 @@ _PyCoreConfig_GetEnvDup(const _PyCoreConfig *config, wchar_t **dest, wchar_t *wname, char *name) { - assert(config->preconfig.use_environment >= 0); + assert(config->use_environment >= 0); - if (!config->preconfig.use_environment) { + if (!config->use_environment) { *dest = NULL; return 0; } @@ -668,8 +665,6 @@ _PyCoreConfig_GetEnvDup(const _PyCoreConfig *config, void _PyCoreConfig_GetGlobalConfig(_PyCoreConfig *config) { - _PyPreConfig_GetGlobalConfig(&config->preconfig); - #define COPY_FLAG(ATTR, VALUE) \ if (config->ATTR == -1) { \ config->ATTR = VALUE; \ @@ -679,6 +674,8 @@ _PyCoreConfig_GetGlobalConfig(_PyCoreConfig *config) config->ATTR = !(VALUE); \ } + COPY_FLAG(isolated, Py_IsolatedFlag); + COPY_NOT_FLAG(use_environment, Py_IgnoreEnvironmentFlag); COPY_FLAG(bytes_warning, Py_BytesWarningFlag); COPY_FLAG(inspect, Py_InspectFlag); COPY_FLAG(interactive, Py_InteractiveFlag); @@ -714,6 +711,8 @@ _PyCoreConfig_SetGlobalConfig(const _PyCoreConfig *config) VAR = !config->ATTR; \ } + COPY_FLAG(isolated, Py_IsolatedFlag); + COPY_NOT_FLAG(use_environment, Py_IgnoreEnvironmentFlag); COPY_FLAG(bytes_warning, Py_BytesWarningFlag); COPY_FLAG(inspect, Py_InspectFlag); COPY_FLAG(interactive, Py_InteractiveFlag); @@ -924,7 +923,7 @@ config_wstr_to_int(const wchar_t *wstr, int *result) static _PyInitError config_read_env_vars(_PyCoreConfig *config) { - int use_env = config->preconfig.use_environment; + int use_env = config->use_environment; /* Get environment variables */ _Py_get_env_flag(use_env, &config->parser_debug, "PYTHONDEBUG"); @@ -1149,7 +1148,8 @@ get_locale_encoding(char **locale_encoding) static _PyInitError -config_init_stdio_encoding(_PyCoreConfig *config) +config_init_stdio_encoding(_PyCoreConfig *config, + const _PyPreConfig *preconfig) { /* If Py_SetStandardStreamEncoding() have been called, use these parameters. */ @@ -1219,7 +1219,7 @@ config_init_stdio_encoding(_PyCoreConfig *config) } /* UTF-8 Mode uses UTF-8/surrogateescape */ - if (config->preconfig.utf8_mode) { + if (preconfig->utf8_mode) { if (config->stdio_encoding == NULL) { config->stdio_encoding = _PyMem_RawStrdup("utf-8"); if (config->stdio_encoding == NULL) { @@ -1254,10 +1254,10 @@ config_init_stdio_encoding(_PyCoreConfig *config) static _PyInitError -config_init_fs_encoding(_PyCoreConfig *config) +config_init_fs_encoding(_PyCoreConfig *config, const _PyPreConfig *preconfig) { #ifdef MS_WINDOWS - if (config->preconfig.legacy_windows_fs_encoding) { + if (preconfig->legacy_windows_fs_encoding) { /* Legacy Windows filesystem encoding: mbcs/replace */ if (config->filesystem_encoding == NULL) { config->filesystem_encoding = _PyMem_RawStrdup("mbcs"); @@ -1292,7 +1292,7 @@ config_init_fs_encoding(_PyCoreConfig *config) } #else if (config->filesystem_encoding == NULL) { - if (config->preconfig.utf8_mode) { + if (preconfig->utf8_mode) { /* UTF-8 Mode use: utf-8/surrogateescape */ config->filesystem_encoding = _PyMem_RawStrdup("utf-8"); /* errors defaults to surrogateescape above */ @@ -1341,12 +1341,8 @@ config_read_impl(_PyCoreConfig *config, _PyPreCmdline *cmdline) { _PyInitError err; - err = _Py_PreInitializeFromConfig(config); - if (_Py_INIT_FAILED(err)) { - return err; - } - - _PyPreCmdline_GetPreConfig(cmdline, &_PyRuntime.preconfig); + const _PyPreConfig *preconfig = &_PyRuntime.preconfig; + _PyPreCmdline_GetPreConfig(cmdline, preconfig); _PyPreCmdline_GetCoreConfig(cmdline, config); err = _PyPreCmdline_Read(cmdline); @@ -1360,19 +1356,16 @@ config_read_impl(_PyCoreConfig *config, _PyPreCmdline *cmdline) return _Py_INIT_NO_MEMORY(); } - if (_PyPreConfig_Copy(&config->preconfig, &_PyRuntime.preconfig) < 0) { - return _Py_INIT_NO_MEMORY(); - } - _PyCoreConfig_GetGlobalConfig(config); - assert(config->preconfig.use_environment >= 0); + assert(config->use_environment >= 0); - if (config->preconfig.isolated > 0) { + if (config->isolated > 0) { + config->use_environment = 0; config->user_site_directory = 0; } - if (config->preconfig.use_environment) { + if (config->use_environment) { err = config_read_env_vars(config); if (_Py_INIT_FAILED(err)) { return err; @@ -1421,7 +1414,7 @@ config_read_impl(_PyCoreConfig *config, _PyPreCmdline *cmdline) } /* default values */ - if (config->preconfig.dev_mode) { + if (config->dev_mode) { if (config->faulthandler < 0) { config->faulthandler = 1; } @@ -1438,13 +1431,13 @@ config_read_impl(_PyCoreConfig *config, _PyPreCmdline *cmdline) } if (config->filesystem_encoding == NULL || config->filesystem_errors == NULL) { - err = config_init_fs_encoding(config); + err = config_init_fs_encoding(config, preconfig); if (_Py_INIT_FAILED(err)) { return err; } } - err = config_init_stdio_encoding(config); + err = config_init_stdio_encoding(config, preconfig); if (_Py_INIT_FAILED(err)) { return err; } @@ -1456,7 +1449,7 @@ config_read_impl(_PyCoreConfig *config, _PyPreCmdline *cmdline) } } - assert(config->preconfig.use_environment >= 0); + assert(config->use_environment >= 0); assert(config->filesystem_encoding != NULL); assert(config->filesystem_errors != NULL); assert(config->stdio_encoding != NULL); @@ -1544,22 +1537,11 @@ config_init_stdio(const _PyCoreConfig *config) - set Py_xxx global configuration variables - initialize C standard streams (stdin, stdout, stderr) */ -_PyInitError +void _PyCoreConfig_Write(const _PyCoreConfig *config) { _PyCoreConfig_SetGlobalConfig(config); config_init_stdio(config); - - /* Write the new pre-configuration into _PyRuntime */ - PyMemAllocatorEx old_alloc; - _PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc); - int res = _PyPreConfig_Copy(&_PyRuntime.preconfig, &config->preconfig); - PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc); - if (res < 0) { - return _Py_INIT_NO_MEMORY(); - } - - return _Py_INIT_OK(); } @@ -1604,6 +1586,9 @@ _PyCoreConfig_AsDict(const _PyCoreConfig *config) #define SET_ITEM_WSTRLIST(LIST) \ SET_ITEM(#LIST, _PyWstrList_AsList(&config->LIST)) + SET_ITEM_INT(isolated); + SET_ITEM_INT(use_environment); + SET_ITEM_INT(dev_mode); SET_ITEM_INT(install_signal_handlers); SET_ITEM_INT(use_hash_seed); SET_ITEM_UINT(hash_seed); @@ -1945,7 +1930,7 @@ config_init_warnoptions(_PyCoreConfig *config, const _PyCmdline *cmdline) * the lowest precedence entries first so that later entries override them. */ - if (config->preconfig.dev_mode) { + if (config->dev_mode) { if (_PyWstrList_Append(&config->warnoptions, L"default")) { return _Py_INIT_NO_MEMORY(); } @@ -2101,7 +2086,7 @@ config_from_cmdline(_PyCoreConfig *config, _PyCmdline *cmdline) return err; } - if (config->preconfig.use_environment) { + if (config->use_environment) { err = cmdline_init_env_warnoptions(cmdline, config); if (_Py_INIT_FAILED(err)) { return err; @@ -2178,8 +2163,7 @@ _Py_GetConfigsAsDict(void) /* pre config */ PyInterpreterState *interp = _PyInterpreterState_Get(); - const _PyCoreConfig *core_config = _PyInterpreterState_GetCoreConfig(interp); - const _PyPreConfig *pre_config = &core_config->preconfig; + const _PyPreConfig *pre_config = &_PyRuntime.preconfig; dict = _PyPreConfig_AsDict(pre_config); if (dict == NULL) { goto error; @@ -2190,6 +2174,7 @@ _Py_GetConfigsAsDict(void) Py_CLEAR(dict); /* core config */ + const _PyCoreConfig *core_config = _PyInterpreterState_GetCoreConfig(interp); dict = _PyCoreConfig_AsDict(core_config); if (dict == NULL) { goto error; -- cgit v1.2.1 From f8ba6f5afc317d1be3025db1be410ac66a7e5a27 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Tue, 26 Mar 2019 16:58:50 +0100 Subject: bpo-36301: Cleanup preconfig.c and coreconfig.c (GH-12563) * _PyCoreConfig_Write() now updates _PyRuntime.preconfig * Remove _PyPreCmdline_Copy() * _PyPreCmdline_Read() now accepts _PyPreConfig and _PyCoreConfig optional configurations. * Rename _PyPreConfig_ReadFromArgv() to _PyPreConfig_Read(). Simplify the code. * Calling _PyCoreConfig_Read() no longer adds the warning options twice: don't add a warning option if it's already in the list. * Rename _PyCoreConfig_ReadFromArgv() to _PyCoreConfig_Read(). * Rename config_from_cmdline() to _PyCoreConfig_ReadFromArgv(). * Add more assertions on _PyCoreConfig in _PyCoreConfig_Read(). * Move some functions. * Make some config functions private. --- Python/coreconfig.c | 574 +++++++++++++++++++++++++++------------------------- 1 file changed, 299 insertions(+), 275 deletions(-) (limited to 'Python/coreconfig.c') diff --git a/Python/coreconfig.c b/Python/coreconfig.c index 2e6eb40298..2f54e79081 100644 --- a/Python/coreconfig.c +++ b/Python/coreconfig.c @@ -296,7 +296,7 @@ _PyWstrList_Append(_PyWstrList *list, const wchar_t *item) } -static int +int _PyWstrList_Extend(_PyWstrList *list, const _PyWstrList *list2) { for (Py_ssize_t i = 0; i < list2->length; i++) { @@ -308,6 +308,18 @@ _PyWstrList_Extend(_PyWstrList *list, const _PyWstrList *list2) } +static int +_PyWstrList_Find(_PyWstrList *list, const wchar_t *item) +{ + for (Py_ssize_t i = 0; i < list->length; i++) { + if (wcscmp(list->items[i], item) == 0) { + return 1; + } + } + return 0; +} + + PyObject* _PyWstrList_AsList(const _PyWstrList *list) { @@ -607,6 +619,120 @@ _PyCoreConfig_Copy(_PyCoreConfig *config, const _PyCoreConfig *config2) } +static PyObject * +_PyCoreConfig_AsDict(const _PyCoreConfig *config) +{ + PyObject *dict; + + dict = PyDict_New(); + if (dict == NULL) { + return NULL; + } + +#define SET_ITEM(KEY, EXPR) \ + do { \ + PyObject *obj = (EXPR); \ + if (obj == NULL) { \ + goto fail; \ + } \ + int res = PyDict_SetItemString(dict, (KEY), obj); \ + Py_DECREF(obj); \ + if (res < 0) { \ + goto fail; \ + } \ + } while (0) +#define FROM_STRING(STR) \ + ((STR != NULL) ? \ + PyUnicode_FromString(STR) \ + : (Py_INCREF(Py_None), Py_None)) +#define SET_ITEM_INT(ATTR) \ + SET_ITEM(#ATTR, PyLong_FromLong(config->ATTR)) +#define SET_ITEM_UINT(ATTR) \ + SET_ITEM(#ATTR, PyLong_FromUnsignedLong(config->ATTR)) +#define SET_ITEM_STR(ATTR) \ + SET_ITEM(#ATTR, FROM_STRING(config->ATTR)) +#define FROM_WSTRING(STR) \ + ((STR != NULL) ? \ + PyUnicode_FromWideChar(STR, -1) \ + : (Py_INCREF(Py_None), Py_None)) +#define SET_ITEM_WSTR(ATTR) \ + SET_ITEM(#ATTR, FROM_WSTRING(config->ATTR)) +#define SET_ITEM_WSTRLIST(LIST) \ + SET_ITEM(#LIST, _PyWstrList_AsList(&config->LIST)) + + SET_ITEM_INT(isolated); + SET_ITEM_INT(use_environment); + SET_ITEM_INT(dev_mode); + SET_ITEM_INT(install_signal_handlers); + SET_ITEM_INT(use_hash_seed); + SET_ITEM_UINT(hash_seed); + SET_ITEM_INT(faulthandler); + SET_ITEM_INT(tracemalloc); + SET_ITEM_INT(import_time); + SET_ITEM_INT(show_ref_count); + SET_ITEM_INT(show_alloc_count); + SET_ITEM_INT(dump_refs); + SET_ITEM_INT(malloc_stats); + SET_ITEM_STR(filesystem_encoding); + SET_ITEM_STR(filesystem_errors); + SET_ITEM_WSTR(pycache_prefix); + SET_ITEM_WSTR(program_name); + SET_ITEM_WSTRLIST(argv); + SET_ITEM_WSTR(program); + SET_ITEM_WSTRLIST(xoptions); + SET_ITEM_WSTRLIST(warnoptions); + SET_ITEM_WSTR(module_search_path_env); + SET_ITEM_WSTR(home); + SET_ITEM_WSTRLIST(module_search_paths); + SET_ITEM_WSTR(executable); + SET_ITEM_WSTR(prefix); + SET_ITEM_WSTR(base_prefix); + SET_ITEM_WSTR(exec_prefix); + SET_ITEM_WSTR(base_exec_prefix); +#ifdef MS_WINDOWS + SET_ITEM_WSTR(dll_path); +#endif + SET_ITEM_INT(site_import); + SET_ITEM_INT(bytes_warning); + SET_ITEM_INT(inspect); + SET_ITEM_INT(interactive); + SET_ITEM_INT(optimization_level); + SET_ITEM_INT(parser_debug); + SET_ITEM_INT(write_bytecode); + SET_ITEM_INT(verbose); + SET_ITEM_INT(quiet); + SET_ITEM_INT(user_site_directory); + SET_ITEM_INT(buffered_stdio); + SET_ITEM_STR(stdio_encoding); + SET_ITEM_STR(stdio_errors); +#ifdef MS_WINDOWS + SET_ITEM_INT(legacy_windows_stdio); +#endif + SET_ITEM_INT(skip_source_first_line); + SET_ITEM_WSTR(run_command); + SET_ITEM_WSTR(run_module); + SET_ITEM_WSTR(run_filename); + SET_ITEM_INT(_install_importlib); + SET_ITEM_STR(_check_hash_pycs_mode); + SET_ITEM_INT(_frozen); + + return dict; + +fail: + Py_DECREF(dict); + return NULL; + +#undef FROM_STRING +#undef FROM_WSTRING +#undef SET_ITEM +#undef SET_ITEM_INT +#undef SET_ITEM_UINT +#undef SET_ITEM_STR +#undef SET_ITEM_WSTR +#undef SET_ITEM_WSTRLIST +} + + static const char* _PyCoreConfig_GetEnv(const _PyCoreConfig *config, const char *name) { @@ -614,6 +740,9 @@ _PyCoreConfig_GetEnv(const _PyCoreConfig *config, const char *name) } +/* Get a copy of the environment variable as wchar_t*. + Return 0 on success, but *dest can be NULL. + Return -1 on memory allocation failure. Return -2 on decoding error. */ static int _PyCoreConfig_GetEnvDup(const _PyCoreConfig *config, wchar_t **dest, @@ -662,7 +791,7 @@ _PyCoreConfig_GetEnvDup(const _PyCoreConfig *config, } -void +static void _PyCoreConfig_GetGlobalConfig(_PyCoreConfig *config) { #define COPY_FLAG(ATTR, VALUE) \ @@ -699,7 +828,7 @@ _PyCoreConfig_GetGlobalConfig(_PyCoreConfig *config) /* Set Py_xxx global configuration variables from 'config' configuration. */ -void +static void _PyCoreConfig_SetGlobalConfig(const _PyCoreConfig *config) { #define COPY_FLAG(ATTR, VAR) \ @@ -848,10 +977,10 @@ config_get_xoption(const _PyCoreConfig *config, wchar_t *name) static _PyInitError config_init_home(_PyCoreConfig *config) { - wchar_t *home; + assert(config->home == NULL); /* If Py_SetPythonHome() was called, use its value */ - home = _Py_path_config.home; + wchar_t *home = _Py_path_config.home; if (home) { config->home = _PyMem_RawWcsdup(home); if (config->home == NULL) { @@ -1098,7 +1227,7 @@ config_read_complex_options(_PyCoreConfig *config) static const char * -get_stdio_errors(const _PyCoreConfig *config) +config_get_stdio_errors(const _PyCoreConfig *config) { #ifndef MS_WINDOWS const char *loc = setlocale(LC_CTYPE, NULL); @@ -1125,7 +1254,7 @@ get_stdio_errors(const _PyCoreConfig *config) static _PyInitError -get_locale_encoding(char **locale_encoding) +config_get_locale_encoding(char **locale_encoding) { #ifdef MS_WINDOWS char encoding[20]; @@ -1236,13 +1365,13 @@ config_init_stdio_encoding(_PyCoreConfig *config, /* Choose the default error handler based on the current locale. */ if (config->stdio_encoding == NULL) { - _PyInitError err = get_locale_encoding(&config->stdio_encoding); + _PyInitError err = config_get_locale_encoding(&config->stdio_encoding); if (_Py_INIT_FAILED(err)) { return err; } } if (config->stdio_errors == NULL) { - const char *errors = get_stdio_errors(config); + const char *errors = config_get_stdio_errors(config); config->stdio_errors = _PyMem_RawStrdup(errors); if (config->stdio_errors == NULL) { return _Py_INIT_NO_MEMORY(); @@ -1306,7 +1435,7 @@ config_init_fs_encoding(_PyCoreConfig *config, const _PyPreConfig *preconfig) #if defined(__APPLE__) || defined(__ANDROID__) config->filesystem_encoding = _PyMem_RawStrdup("utf-8"); #else - _PyInitError err = get_locale_encoding(&config->filesystem_encoding); + _PyInitError err = config_get_locale_encoding(&config->filesystem_encoding); if (_Py_INIT_FAILED(err)) { return err; } @@ -1330,38 +1459,22 @@ config_init_fs_encoding(_PyCoreConfig *config, const _PyPreConfig *preconfig) } -/* Read the configuration into _PyCoreConfig from: - - * Environment variables - * Py_xxx global configuration variables - - See _PyCoreConfig_ReadFromArgv() to parse also command line arguments. */ static _PyInitError -config_read_impl(_PyCoreConfig *config, _PyPreCmdline *cmdline) +config_read(_PyCoreConfig *config, _PyPreCmdline *cmdline) { _PyInitError err; const _PyPreConfig *preconfig = &_PyRuntime.preconfig; - _PyPreCmdline_GetPreConfig(cmdline, preconfig); - _PyPreCmdline_GetCoreConfig(cmdline, config); - - err = _PyPreCmdline_Read(cmdline); + err = _PyPreCmdline_Read(cmdline, preconfig, config); if (_Py_INIT_FAILED(err)) { return err; } - _PyPreCmdline_SetCoreConfig(cmdline, config); - - if (_PyWstrList_Extend(&config->xoptions, &cmdline->xoptions) < 0) { + if (_PyPreCmdline_SetCoreConfig(cmdline, config) < 0) { return _Py_INIT_NO_MEMORY(); } - _PyCoreConfig_GetGlobalConfig(config); - - assert(config->use_environment >= 0); - if (config->isolated > 0) { - config->use_environment = 0; config->user_site_directory = 0; } @@ -1419,16 +1532,16 @@ config_read_impl(_PyCoreConfig *config, _PyPreCmdline *cmdline) config->faulthandler = 1; } } - if (config->use_hash_seed < 0) { - config->use_hash_seed = 0; - config->hash_seed = 0; - } if (config->faulthandler < 0) { config->faulthandler = 0; } if (config->tracemalloc < 0) { config->tracemalloc = 0; } + if (config->use_hash_seed < 0) { + config->use_hash_seed = 0; + config->hash_seed = 0; + } if (config->filesystem_encoding == NULL || config->filesystem_errors == NULL) { err = config_init_fs_encoding(config, preconfig); @@ -1449,53 +1562,10 @@ config_read_impl(_PyCoreConfig *config, _PyPreCmdline *cmdline) } } - assert(config->use_environment >= 0); - assert(config->filesystem_encoding != NULL); - assert(config->filesystem_errors != NULL); - assert(config->stdio_encoding != NULL); - assert(config->stdio_errors != NULL); - assert(config->_check_hash_pycs_mode != NULL); - assert(_PyWstrList_CheckConsistency(&config->argv)); - return _Py_INIT_OK(); } -static _PyInitError -config_read(_PyCoreConfig *config, const _PyPreCmdline *src_cmdline) -{ - _PyInitError err; - - err = _Py_PreInitializeFromConfig(config); - if (_Py_INIT_FAILED(err)) { - return err; - } - - _PyPreCmdline cmdline = _PyPreCmdline_INIT; - - if (src_cmdline) { - if (_PyPreCmdline_Copy(&cmdline, src_cmdline) < 0) { - err = _Py_INIT_NO_MEMORY(); - goto done; - } - } - - err = config_read_impl(config, &cmdline); - -done: - _PyPreCmdline_Clear(&cmdline); - return err; - -} - - -_PyInitError -_PyCoreConfig_Read(_PyCoreConfig *config) -{ - return config_read(config, NULL); -} - - static void config_init_stdio(const _PyCoreConfig *config) { @@ -1542,139 +1612,30 @@ _PyCoreConfig_Write(const _PyCoreConfig *config) { _PyCoreConfig_SetGlobalConfig(config); config_init_stdio(config); -} - - -static PyObject * -_PyCoreConfig_AsDict(const _PyCoreConfig *config) -{ - PyObject *dict; - - dict = PyDict_New(); - if (dict == NULL) { - return NULL; - } -#define SET_ITEM(KEY, EXPR) \ - do { \ - PyObject *obj = (EXPR); \ - if (obj == NULL) { \ - goto fail; \ - } \ - int res = PyDict_SetItemString(dict, (KEY), obj); \ - Py_DECREF(obj); \ - if (res < 0) { \ - goto fail; \ - } \ - } while (0) -#define FROM_STRING(STR) \ - ((STR != NULL) ? \ - PyUnicode_FromString(STR) \ - : (Py_INCREF(Py_None), Py_None)) -#define SET_ITEM_INT(ATTR) \ - SET_ITEM(#ATTR, PyLong_FromLong(config->ATTR)) -#define SET_ITEM_UINT(ATTR) \ - SET_ITEM(#ATTR, PyLong_FromUnsignedLong(config->ATTR)) -#define SET_ITEM_STR(ATTR) \ - SET_ITEM(#ATTR, FROM_STRING(config->ATTR)) -#define FROM_WSTRING(STR) \ - ((STR != NULL) ? \ - PyUnicode_FromWideChar(STR, -1) \ - : (Py_INCREF(Py_None), Py_None)) -#define SET_ITEM_WSTR(ATTR) \ - SET_ITEM(#ATTR, FROM_WSTRING(config->ATTR)) -#define SET_ITEM_WSTRLIST(LIST) \ - SET_ITEM(#LIST, _PyWstrList_AsList(&config->LIST)) - - SET_ITEM_INT(isolated); - SET_ITEM_INT(use_environment); - SET_ITEM_INT(dev_mode); - SET_ITEM_INT(install_signal_handlers); - SET_ITEM_INT(use_hash_seed); - SET_ITEM_UINT(hash_seed); - SET_ITEM_INT(faulthandler); - SET_ITEM_INT(tracemalloc); - SET_ITEM_INT(import_time); - SET_ITEM_INT(show_ref_count); - SET_ITEM_INT(show_alloc_count); - SET_ITEM_INT(dump_refs); - SET_ITEM_INT(malloc_stats); - SET_ITEM_STR(filesystem_encoding); - SET_ITEM_STR(filesystem_errors); - SET_ITEM_WSTR(pycache_prefix); - SET_ITEM_WSTR(program_name); - SET_ITEM_WSTRLIST(argv); - SET_ITEM_WSTR(program); - SET_ITEM_WSTRLIST(xoptions); - SET_ITEM_WSTRLIST(warnoptions); - SET_ITEM_WSTR(module_search_path_env); - SET_ITEM_WSTR(home); - SET_ITEM_WSTRLIST(module_search_paths); - SET_ITEM_WSTR(executable); - SET_ITEM_WSTR(prefix); - SET_ITEM_WSTR(base_prefix); - SET_ITEM_WSTR(exec_prefix); - SET_ITEM_WSTR(base_exec_prefix); -#ifdef MS_WINDOWS - SET_ITEM_WSTR(dll_path); -#endif - SET_ITEM_INT(site_import); - SET_ITEM_INT(bytes_warning); - SET_ITEM_INT(inspect); - SET_ITEM_INT(interactive); - SET_ITEM_INT(optimization_level); - SET_ITEM_INT(parser_debug); - SET_ITEM_INT(write_bytecode); - SET_ITEM_INT(verbose); - SET_ITEM_INT(quiet); - SET_ITEM_INT(user_site_directory); - SET_ITEM_INT(buffered_stdio); - SET_ITEM_STR(stdio_encoding); - SET_ITEM_STR(stdio_errors); -#ifdef MS_WINDOWS - SET_ITEM_INT(legacy_windows_stdio); -#endif - SET_ITEM_INT(skip_source_first_line); - SET_ITEM_WSTR(run_command); - SET_ITEM_WSTR(run_module); - SET_ITEM_WSTR(run_filename); - SET_ITEM_INT(_install_importlib); - SET_ITEM_STR(_check_hash_pycs_mode); - SET_ITEM_INT(_frozen); - - return dict; - -fail: - Py_DECREF(dict); - return NULL; - -#undef FROM_STRING -#undef FROM_WSTRING -#undef SET_ITEM -#undef SET_ITEM_INT -#undef SET_ITEM_UINT -#undef SET_ITEM_STR -#undef SET_ITEM_WSTR -#undef SET_ITEM_WSTRLIST + /* Write the new pre-configuration into _PyRuntime */ + _PyPreConfig *preconfig = &_PyRuntime.preconfig; + preconfig->isolated = config->isolated; + preconfig->use_environment = config->use_environment; + preconfig->dev_mode = config->dev_mode; } /* --- _PyCmdline ------------------------------------------------- */ typedef struct { - _PyPreCmdline precmdline; - _PyWstrList warnoptions; /* Command line -W options */ + _PyWstrList cmdline_warnoptions; /* Command line -W options */ _PyWstrList env_warnoptions; /* PYTHONWARNINGS environment variables */ int print_help; /* -h, -? options */ int print_version; /* -V option */ + int need_usage; } _PyCmdline; static void cmdline_clear(_PyCmdline *cmdline) { - _PyPreCmdline_Clear(&cmdline->precmdline); - _PyWstrList_Clear(&cmdline->warnoptions); + _PyWstrList_Clear(&cmdline->cmdline_warnoptions); _PyWstrList_Clear(&cmdline->env_warnoptions); } @@ -1684,9 +1645,9 @@ cmdline_clear(_PyCmdline *cmdline) /* Parse the command line arguments */ static _PyInitError config_parse_cmdline(_PyCoreConfig *config, _PyCmdline *cmdline, - int *need_usage) + _PyPreCmdline *precmdline) { - const _PyWstrList *argv = &cmdline->precmdline.argv; + const _PyWstrList *argv = &precmdline->argv; _PyOS_ResetGetOpt(); do { @@ -1740,7 +1701,7 @@ config_parse_cmdline(_PyCoreConfig *config, _PyCmdline *cmdline, } else { fprintf(stderr, "--check-hash-based-pycs must be one of " "'default', 'always', or 'never'\n"); - *need_usage = 1; + cmdline->need_usage = 1; return _Py_INIT_OK(); } break; @@ -1761,7 +1722,7 @@ config_parse_cmdline(_PyCoreConfig *config, _PyCmdline *cmdline, case 'E': case 'I': case 'X': - /* option handled by _PyPreConfig_ReadFromArgv() */ + /* option handled by _PyPreCmdline_Read() */ break; /* case 'J': reserved for Jython */ @@ -1808,7 +1769,7 @@ config_parse_cmdline(_PyCoreConfig *config, _PyCmdline *cmdline, break; case 'W': - if (_PyWstrList_Append(&cmdline->warnoptions, _PyOS_optarg) < 0) { + if (_PyWstrList_Append(&cmdline->cmdline_warnoptions, _PyOS_optarg) < 0) { return _Py_INIT_NO_MEMORY(); } break; @@ -1825,7 +1786,7 @@ config_parse_cmdline(_PyCoreConfig *config, _PyCmdline *cmdline, default: /* unknown argument: parsing failed */ - *need_usage = 1; + cmdline->need_usage = 1; return _Py_INIT_OK(); } } while (1); @@ -1891,9 +1852,9 @@ cmdline_init_env_warnoptions(_PyCmdline *cmdline, const _PyCoreConfig *config) static _PyInitError -config_init_program(_PyCoreConfig *config, const _PyCmdline *cmdline) +config_init_program(_PyCoreConfig *config, const _PyPreCmdline *cmdline) { - const _PyWstrList *argv = &cmdline->precmdline.argv; + const _PyWstrList *argv = &cmdline->argv; wchar_t *program; if (argv->length >= 1) { program = argv->items[0]; @@ -1910,11 +1871,23 @@ config_init_program(_PyCoreConfig *config, const _PyCmdline *cmdline) } +static int +config_add_warnoption(_PyCoreConfig *config, const wchar_t *option) +{ + if (_PyWstrList_Find(&config->warnoptions, option)) { + /* Already present: do nothing */ + return 0; + } + if (_PyWstrList_Append(&config->warnoptions, option)) { + return -1; + } + return 0; +} + + static _PyInitError config_init_warnoptions(_PyCoreConfig *config, const _PyCmdline *cmdline) { - assert(config->warnoptions.length == 0); - /* The priority order for warnings configuration is (highest precedence * first): * @@ -1931,17 +1904,26 @@ config_init_warnoptions(_PyCoreConfig *config, const _PyCmdline *cmdline) */ if (config->dev_mode) { - if (_PyWstrList_Append(&config->warnoptions, L"default")) { + if (config_add_warnoption(config, L"default") < 0) { return _Py_INIT_NO_MEMORY(); } } - if (_PyWstrList_Extend(&config->warnoptions, &cmdline->env_warnoptions) < 0) { - return _Py_INIT_NO_MEMORY(); + Py_ssize_t i; + const _PyWstrList *options; + + options = &cmdline->env_warnoptions; + for (i = 0; i < options->length; i++) { + if (config_add_warnoption(config, options->items[i]) < 0) { + return _Py_INIT_NO_MEMORY(); + } } - if (_PyWstrList_Extend(&config->warnoptions, &cmdline->warnoptions) < 0) { - return _Py_INIT_NO_MEMORY(); + options = &cmdline->cmdline_warnoptions; + for (i = 0; i < options->length; i++) { + if (config_add_warnoption(config, options->items[i]) < 0) { + return _Py_INIT_NO_MEMORY(); + } } /* If the bytes_warning_flag isn't set, bytesobject.c and bytearrayobject.c @@ -1956,7 +1938,7 @@ config_init_warnoptions(_PyCoreConfig *config, const _PyCmdline *cmdline) else { filter = L"default::BytesWarning"; } - if (_PyWstrList_Append(&config->warnoptions, filter)) { + if (config_add_warnoption(config, filter) < 0) { return _Py_INIT_NO_MEMORY(); } } @@ -1965,9 +1947,9 @@ config_init_warnoptions(_PyCoreConfig *config, const _PyCmdline *cmdline) static _PyInitError -config_init_argv(_PyCoreConfig *config, const _PyCmdline *cmdline) +config_init_argv(_PyCoreConfig *config, const _PyPreCmdline *cmdline) { - const _PyWstrList *cmdline_argv = &cmdline->precmdline.argv; + const _PyWstrList *cmdline_argv = &cmdline->argv; _PyWstrList config_argv = _PyWstrList_INIT; /* Copy argv to be able to modify it (to force -c/-m) */ @@ -2032,110 +2014,152 @@ config_usage(int error, const wchar_t* program) } -/* Parse command line options and environment variables. */ -static _PyInitError -config_from_cmdline(_PyCoreConfig *config, _PyCmdline *cmdline) +/* Read the configuration into _PyCoreConfig from: + + * Command line arguments + * Environment variables + * Py_xxx global configuration variables */ +_PyInitError +_PyCoreConfig_Read(_PyCoreConfig *config, const _PyArgv *args) { - int need_usage = 0; _PyInitError err; + err = _Py_PreInitializeFromConfig(config); + if (_Py_INIT_FAILED(err)) { + return err; + } + _PyCoreConfig_GetGlobalConfig(config); + _PyPreCmdline precmdline = _PyPreCmdline_INIT; + if (args) { + err = _PyPreCmdline_SetArgv(&precmdline, args); + if (_Py_INIT_FAILED(err)) { + goto done; + } + } + if (config->program == NULL) { - err = config_init_program(config, cmdline); + err = config_init_program(config, &precmdline); if (_Py_INIT_FAILED(err)) { - return err; + goto done; } } - err = _PyPreCmdline_Read(&cmdline->precmdline); + const _PyPreConfig *preconfig = &_PyRuntime.preconfig; + err = _PyPreCmdline_Read(&precmdline, preconfig, config); if (_Py_INIT_FAILED(err)) { - return err; + goto done; } - _PyPreCmdline_SetPreConfig(&cmdline->precmdline, &_PyRuntime.preconfig); + _PyCmdline cmdline; + memset(&cmdline, 0, sizeof(cmdline)); - err = config_parse_cmdline(config, cmdline, &need_usage); - if (_Py_INIT_FAILED(err)) { - return err; - } + if (args) { + err = config_parse_cmdline(config, &cmdline, &precmdline); + if (_Py_INIT_FAILED(err)) { + goto done; + } - if (need_usage) { - config_usage(1, config->program); - return _Py_INIT_EXIT(2); - } + if (cmdline.need_usage) { + config_usage(1, config->program); + err = _Py_INIT_EXIT(2); + goto done; + } - if (cmdline->print_help) { - config_usage(0, config->program); - return _Py_INIT_EXIT(0); - } + if (cmdline.print_help) { + config_usage(0, config->program); + err = _Py_INIT_EXIT(0); + goto done; + } - if (cmdline->print_version) { - printf("Python %s\n", - (cmdline->print_version >= 2) ? Py_GetVersion() : PY_VERSION); - return _Py_INIT_EXIT(0); - } + if (cmdline.print_version) { + printf("Python %s\n", + (cmdline.print_version >= 2) ? Py_GetVersion() : PY_VERSION); + err = _Py_INIT_EXIT(0); + goto done; + } - err = config_init_argv(config, cmdline); - if (_Py_INIT_FAILED(err)) { - return err; + err = config_init_argv(config, &precmdline); + if (_Py_INIT_FAILED(err)) { + goto done; + } } - err = config_read(config, &cmdline->precmdline); + err = config_read(config, &precmdline); if (_Py_INIT_FAILED(err)) { - return err; + goto done; } if (config->use_environment) { - err = cmdline_init_env_warnoptions(cmdline, config); + err = cmdline_init_env_warnoptions(&cmdline, config); if (_Py_INIT_FAILED(err)) { - return err; + goto done; } } - err = config_init_warnoptions(config, cmdline); + err = config_init_warnoptions(config, &cmdline); if (_Py_INIT_FAILED(err)) { - return err; + goto done; } - const _PyWstrList *argv = &cmdline->precmdline.argv; + const _PyWstrList *argv = &precmdline.argv; if (_Py_SetArgcArgv(argv->length, argv->items) < 0) { - return _Py_INIT_NO_MEMORY(); - } - return _Py_INIT_OK(); -} - - -/* Read the configuration into _PyCoreConfig from: - - * Command line arguments - * Environment variables - * Py_xxx global configuration variables */ -_PyInitError -_PyCoreConfig_ReadFromArgv(_PyCoreConfig *config, const _PyArgv *args) -{ - _PyInitError err; - - err = _Py_PreInitializeFromConfig(config); - if (_Py_INIT_FAILED(err)) { - return err; - } - - _PyCmdline cmdline = {.precmdline = _PyPreCmdline_INIT}; - - err = _PyPreCmdline_SetArgv(&cmdline.precmdline, args); - if (_Py_INIT_FAILED(err)) { + err = _Py_INIT_NO_MEMORY(); goto done; } - err = config_from_cmdline(config, &cmdline); - if (_Py_INIT_FAILED(err)) { - goto done; + /* Check config consistency */ + assert(config->isolated >= 0); + assert(config->use_environment >= 0); + assert(config->dev_mode >= 0); + assert(config->install_signal_handlers >= 0); + assert(config->use_hash_seed >= 0); + assert(config->faulthandler >= 0); + assert(config->tracemalloc >= 0); + assert(config->site_import >= 0); + assert(config->bytes_warning >= 0); + assert(config->inspect >= 0); + assert(config->interactive >= 0); + assert(config->optimization_level >= 0); + assert(config->parser_debug >= 0); + assert(config->write_bytecode >= 0); + assert(config->verbose >= 0); + assert(config->quiet >= 0); + assert(config->user_site_directory >= 0); + assert(config->buffered_stdio >= 0); + assert(config->program_name != NULL); + assert(config->program != NULL); + assert(_PyWstrList_CheckConsistency(&config->argv)); + assert(_PyWstrList_CheckConsistency(&config->xoptions)); + assert(_PyWstrList_CheckConsistency(&config->warnoptions)); + assert(_PyWstrList_CheckConsistency(&config->module_search_paths)); + if (config->_install_importlib) { + assert(config->executable != NULL); + assert(config->prefix != NULL); + assert(config->base_prefix != NULL); + assert(config->exec_prefix != NULL); + assert(config->base_exec_prefix != NULL); +#ifdef MS_WINDOWS + assert(config->dll_path != NULL); +#endif } + assert(config->filesystem_encoding != NULL); + assert(config->filesystem_errors != NULL); + assert(config->stdio_encoding != NULL); + assert(config->stdio_errors != NULL); +#ifdef MS_WINDOWS + assert(config->legacy_windows_stdio >= 0); +#endif + assert(config->_check_hash_pycs_mode != NULL); + assert(config->_install_importlib >= 0); + assert(config->_frozen >= 0); + err = _Py_INIT_OK(); done: cmdline_clear(&cmdline); + _PyPreCmdline_Clear(&precmdline); return err; } -- cgit v1.2.1 From 8b9dbc017a190d13f717e714630d620adb7c7ac2 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Wed, 27 Mar 2019 01:36:16 +0100 Subject: bpo-36444: Remove _PyMainInterpreterConfig (GH-12571) --- Python/coreconfig.c | 11 ----------- 1 file changed, 11 deletions(-) (limited to 'Python/coreconfig.c') diff --git a/Python/coreconfig.c b/Python/coreconfig.c index 2f54e79081..944a9e22ca 100644 --- a/Python/coreconfig.c +++ b/Python/coreconfig.c @@ -2208,17 +2208,6 @@ _Py_GetConfigsAsDict(void) } Py_CLEAR(dict); - /* main config */ - const _PyMainInterpreterConfig *main_config = _PyInterpreterState_GetMainConfig(interp); - dict = _PyMainInterpreterConfig_AsDict(main_config); - if (dict == NULL) { - goto error; - } - if (PyDict_SetItemString(config, "main_config", dict) < 0) { - goto error; - } - Py_CLEAR(dict); - return config; error: -- cgit v1.2.1 From 484f20d2ff95cc2e1bea759852da307bc1d1d944 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Wed, 27 Mar 2019 02:04:16 +0100 Subject: bpo-36444: Add _PyCoreConfig._init_main (GH-12572) * Add _PyCoreConfig._init_main: if equals to zero, _Py_InitializeFromConfig() doesn't call _Py_InitializeMainInterpreter(). * Add interp_p parameter to _Py_InitializeFromConfig(). * pymain_init() now calls _Py_InitializeFromConfig(). * Make _Py_InitializeCore() private. --- Python/coreconfig.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'Python/coreconfig.c') diff --git a/Python/coreconfig.c b/Python/coreconfig.c index 944a9e22ca..ecb22e5667 100644 --- a/Python/coreconfig.c +++ b/Python/coreconfig.c @@ -610,6 +610,7 @@ _PyCoreConfig_Copy(_PyCoreConfig *config, const _PyCoreConfig *config2) COPY_WSTR_ATTR(run_filename); COPY_ATTR(_check_hash_pycs_mode); COPY_ATTR(_frozen); + COPY_ATTR(_init_main); #undef COPY_ATTR #undef COPY_STR_ATTR @@ -715,6 +716,7 @@ _PyCoreConfig_AsDict(const _PyCoreConfig *config) SET_ITEM_INT(_install_importlib); SET_ITEM_STR(_check_hash_pycs_mode); SET_ITEM_INT(_frozen); + SET_ITEM_INT(_init_main); return dict; -- cgit v1.2.1 From 5ac27a50ff2b42216746fedc0522a92c53089bb3 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Wed, 27 Mar 2019 13:40:14 +0100 Subject: bpo-36444: Rework _Py_InitializeFromConfig() API (GH-12576) --- Python/coreconfig.c | 50 +++++++++++++++++++++++++++++++++----------------- 1 file changed, 33 insertions(+), 17 deletions(-) (limited to 'Python/coreconfig.c') diff --git a/Python/coreconfig.c b/Python/coreconfig.c index ecb22e5667..13aa227201 100644 --- a/Python/coreconfig.c +++ b/Python/coreconfig.c @@ -1465,12 +1465,7 @@ static _PyInitError config_read(_PyCoreConfig *config, _PyPreCmdline *cmdline) { _PyInitError err; - const _PyPreConfig *preconfig = &_PyRuntime.preconfig; - err = _PyPreCmdline_Read(cmdline, preconfig, config); - if (_Py_INIT_FAILED(err)) { - return err; - } if (_PyPreCmdline_SetCoreConfig(cmdline, config) < 0) { return _Py_INIT_NO_MEMORY(); @@ -2016,6 +2011,35 @@ config_usage(int error, const wchar_t* program) } +static _PyInitError +core_read_precmdline(_PyCoreConfig *config, const _PyArgv *args, + _PyPreCmdline *precmdline) +{ + _PyInitError err; + + if (args) { + err = _PyPreCmdline_SetArgv(precmdline, args); + if (_Py_INIT_FAILED(err)) { + return err; + } + } + + _PyPreConfig preconfig = _PyPreConfig_INIT; + if (_PyPreConfig_Copy(&preconfig, &_PyRuntime.preconfig) < 0) { + err = _Py_INIT_NO_MEMORY(); + goto done; + } + + _PyCoreConfig_GetCoreConfig(&preconfig, config); + + err = _PyPreCmdline_Read(precmdline, &preconfig); + +done: + _PyPreConfig_Clear(&preconfig); + return err; +} + + /* Read the configuration into _PyCoreConfig from: * Command line arguments @@ -2026,7 +2050,7 @@ _PyCoreConfig_Read(_PyCoreConfig *config, const _PyArgv *args) { _PyInitError err; - err = _Py_PreInitializeFromConfig(config); + err = _Py_PreInitializeFromCoreConfig(config); if (_Py_INIT_FAILED(err)) { return err; } @@ -2034,11 +2058,9 @@ _PyCoreConfig_Read(_PyCoreConfig *config, const _PyArgv *args) _PyCoreConfig_GetGlobalConfig(config); _PyPreCmdline precmdline = _PyPreCmdline_INIT; - if (args) { - err = _PyPreCmdline_SetArgv(&precmdline, args); - if (_Py_INIT_FAILED(err)) { - goto done; - } + err = core_read_precmdline(config, args, &precmdline); + if (_Py_INIT_FAILED(err)) { + goto done; } if (config->program == NULL) { @@ -2048,12 +2070,6 @@ _PyCoreConfig_Read(_PyCoreConfig *config, const _PyArgv *args) } } - const _PyPreConfig *preconfig = &_PyRuntime.preconfig; - err = _PyPreCmdline_Read(&precmdline, preconfig, config); - if (_Py_INIT_FAILED(err)) { - goto done; - } - _PyCmdline cmdline; memset(&cmdline, 0, sizeof(cmdline)); -- cgit v1.2.1