diff options
| author | shadchin <[email protected]> | 2022-04-18 12:39:32 +0300 |
|---|---|---|
| committer | shadchin <[email protected]> | 2022-04-18 12:39:32 +0300 |
| commit | d4be68e361f4258cf0848fc70018dfe37a2acc24 (patch) | |
| tree | 153e294cd97ac8b5d7a989612704a0c1f58e8ad4 /contrib/tools/python3/src/Python/initconfig.c | |
| parent | 260c02f5ccf242d9d9b8a873afaf6588c00237d6 (diff) | |
IGNIETFERRO-1816 Update Python 3 from 3.9.12 to 3.10.4
ref:9f96be6d02ee8044fdd6f124b799b270c20ce641
Diffstat (limited to 'contrib/tools/python3/src/Python/initconfig.c')
| -rw-r--r-- | contrib/tools/python3/src/Python/initconfig.c | 630 |
1 files changed, 462 insertions, 168 deletions
diff --git a/contrib/tools/python3/src/Python/initconfig.c b/contrib/tools/python3/src/Python/initconfig.c index 9c109cef2c1..86472c0ff8f 100644 --- a/contrib/tools/python3/src/Python/initconfig.c +++ b/contrib/tools/python3/src/Python/initconfig.c @@ -11,11 +11,7 @@ #include "osdefs.h" // DELIM #include <locale.h> // setlocale() -#ifdef HAVE_LANGINFO_H -# include <langinfo.h> // nl_langinfo(CODESET) -#endif #if defined(MS_WINDOWS) || defined(__CYGWIN__) -# include <windows.h> // GetACP() # ifdef HAVE_IO_H # include <io.h> # endif @@ -73,7 +69,6 @@ static const char usage_3[] = "\ -X opt : set implementation-specific option. The following options are available:\n\ \n\ -X faulthandler: enable faulthandler\n\ - -X oldparser: enable the traditional LL(1) parser; also PYTHONOLDPARSER\n\ -X showrefcount: output the total reference count and number of used\n\ memory blocks when the program finishes or after each statement in the\n\ interactive interpreter. This only works on debug builds\n\ @@ -99,6 +94,7 @@ static const char usage_3[] = "\ otherwise activate automatically)\n\ -X pycache_prefix=PATH: enable writing .pyc files to a parallel tree rooted at the\n\ given directory instead of to the code tree\n\ + -X warn_default_encoding: enable opt-in EncodingWarning for 'encoding=None'\n\ \n\ --check-hash-based-pycs always|default|never:\n\ control how Python invalidates hash-based .pyc files\n\ @@ -134,7 +130,8 @@ static const char usage_6[] = "PYTHONBREAKPOINT: if this variable is set to 0, it disables the default\n" " debugger. It can be set to the callable of your debugger of choice.\n" "PYTHONDEVMODE: enable the development mode.\n" -"PYTHONPYCACHEPREFIX: root directory for bytecode cache (pyc) files.\n"; +"PYTHONPYCACHEPREFIX: root directory for bytecode cache (pyc) files.\n" +"PYTHONWARNDEFAULTENCODING: enable opt-in EncodingWarning for 'encoding=None'.\n"; #if defined(MS_WINDOWS) # define PYTHONHOMEHELP "<prefix>\\python{major}{minor}" @@ -248,8 +245,9 @@ PyStatus PyStatus_Ok(void) PyStatus PyStatus_Error(const char *err_msg) { + assert(err_msg != NULL); return (PyStatus){._type = _PyStatus_TYPE_ERROR, - .err_msg = err_msg}; + .err_msg = err_msg}; } PyStatus PyStatus_NoMemory(void) @@ -268,6 +266,23 @@ int PyStatus_IsExit(PyStatus status) int PyStatus_Exception(PyStatus status) { return _PyStatus_EXCEPTION(status); } +PyObject* +_PyErr_SetFromPyStatus(PyStatus status) +{ + if (!_PyStatus_IS_ERROR(status)) { + PyErr_Format(PyExc_SystemError, + "%s() expects an error PyStatus", + _PyStatus_GET_FUNC()); + } + else if (status.func) { + PyErr_Format(PyExc_ValueError, "%s: %s", status.func, status.err_msg); + } + else { + PyErr_Format(PyExc_ValueError, "%s", status.err_msg); + } + return NULL; +} + /* --- PyWideStringList ------------------------------------------------ */ @@ -549,6 +564,7 @@ _Py_SetArgcArgv(Py_ssize_t argc, wchar_t * const *argv) } +// _PyConfig_Write() calls _Py_SetArgcArgv() with PyConfig.orig_argv. void Py_GetArgcArgv(int *argc, wchar_t ***argv) { @@ -570,6 +586,66 @@ Py_InitArgcArgv(int argc, wchar_t **argv) ? _PyStatus_ERR("cannot decode " NAME) \ : _PyStatus_NO_MEMORY()) +#define MAX_HASH_SEED 4294967295UL + + +#ifndef NDEBUG +static int +config_check_consistency(const PyConfig *config) +{ + /* 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->hash_seed <= MAX_HASH_SEED); + assert(config->faulthandler >= 0); + assert(config->tracemalloc >= 0); + assert(config->import_time >= 0); + assert(config->show_ref_count >= 0); + assert(config->dump_refs >= 0); + assert(config->malloc_stats >= 0); + assert(config->site_import >= 0); + assert(config->bytes_warning >= 0); + assert(config->warn_default_encoding >= 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->parse_argv >= 0); + assert(config->configure_c_stdio >= 0); + assert(config->buffered_stdio >= 0); + assert(config->program_name != NULL); + assert(_PyWideStringList_CheckConsistency(&config->orig_argv)); + assert(_PyWideStringList_CheckConsistency(&config->argv)); + /* sys.argv must be non-empty: empty argv is replaced with [''] */ + assert(config->argv.length >= 1); + assert(_PyWideStringList_CheckConsistency(&config->xoptions)); + assert(_PyWideStringList_CheckConsistency(&config->warnoptions)); + assert(_PyWideStringList_CheckConsistency(&config->module_search_paths)); + assert(config->module_search_paths_set >= 0); + assert(config->platlibdir != NULL); + 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 + /* -c and -m options are exclusive */ + assert(!(config->run_command != NULL && config->run_module != NULL)); + assert(config->check_hash_pycs_mode != NULL); + assert(config->_install_importlib >= 0); + assert(config->pathconfig_warnings >= 0); + return 1; +} +#endif + /* Free memory allocated in config, but don't clear all attributes */ void @@ -609,7 +685,7 @@ PyConfig_Clear(PyConfig *config) CLEAR(config->run_filename); CLEAR(config->check_hash_pycs_mode); - _PyWideStringList_Clear(&config->_orig_argv); + _PyWideStringList_Clear(&config->orig_argv); #undef CLEAR } @@ -631,6 +707,7 @@ _PyConfig_InitCompatConfig(PyConfig *config) config->parse_argv = 0; config->site_import = -1; config->bytes_warning = -1; + config->warn_default_encoding = 0; config->inspect = -1; config->interactive = -1; config->optimization_level = -1; @@ -649,7 +726,6 @@ _PyConfig_InitCompatConfig(PyConfig *config) #ifdef MS_WINDOWS config->legacy_windows_stdio = -1; #endif - config->_use_peg_parser = 1; } @@ -775,7 +851,7 @@ config_set_bytes_string(PyConfig *config, wchar_t **config_str, configured. */ PyStatus PyConfig_SetBytesString(PyConfig *config, wchar_t **config_str, - const char *str) + const char *str) { return CONFIG_SET_BYTES_STR(config, config_str, str, "string"); } @@ -807,7 +883,6 @@ _PyConfig_Copy(PyConfig *config, const PyConfig *config2) COPY_ATTR(isolated); COPY_ATTR(use_environment); COPY_ATTR(dev_mode); - COPY_ATTR(_use_peg_parser); COPY_ATTR(install_signal_handlers); COPY_ATTR(use_hash_seed); COPY_ATTR(hash_seed); @@ -841,6 +916,7 @@ _PyConfig_Copy(PyConfig *config, const PyConfig *config2) COPY_ATTR(site_import); COPY_ATTR(bytes_warning); + COPY_ATTR(warn_default_encoding); COPY_ATTR(inspect); COPY_ATTR(interactive); COPY_ATTR(optimization_level); @@ -866,7 +942,7 @@ _PyConfig_Copy(PyConfig *config, const PyConfig *config2) COPY_ATTR(pathconfig_warnings); COPY_ATTR(_init_main); COPY_ATTR(_isolated_interpreter); - COPY_WSTRLIST(_orig_argv); + COPY_WSTRLIST(orig_argv); #undef COPY_ATTR #undef COPY_WSTR_ATTR @@ -875,12 +951,10 @@ _PyConfig_Copy(PyConfig *config, const PyConfig *config2) } -static PyObject * -config_as_dict(const PyConfig *config) +PyObject * +_PyConfig_AsDict(const PyConfig *config) { - PyObject *dict; - - dict = PyDict_New(); + PyObject *dict = PyDict_New(); if (dict == NULL) { return NULL; } @@ -914,7 +988,6 @@ config_as_dict(const PyConfig *config) SET_ITEM_INT(isolated); SET_ITEM_INT(use_environment); SET_ITEM_INT(dev_mode); - SET_ITEM_INT(_use_peg_parser); SET_ITEM_INT(install_signal_handlers); SET_ITEM_INT(use_hash_seed); SET_ITEM_UINT(hash_seed); @@ -934,6 +1007,7 @@ config_as_dict(const PyConfig *config) SET_ITEM_WSTRLIST(warnoptions); SET_ITEM_WSTR(pythonpath_env); SET_ITEM_WSTR(home); + SET_ITEM_INT(module_search_paths_set); SET_ITEM_WSTRLIST(module_search_paths); SET_ITEM_WSTR(executable); SET_ITEM_WSTR(base_executable); @@ -944,6 +1018,7 @@ config_as_dict(const PyConfig *config) SET_ITEM_WSTR(platlibdir); SET_ITEM_INT(site_import); SET_ITEM_INT(bytes_warning); + SET_ITEM_INT(warn_default_encoding); SET_ITEM_INT(inspect); SET_ITEM_INT(interactive); SET_ITEM_INT(optimization_level); @@ -968,7 +1043,7 @@ config_as_dict(const PyConfig *config) SET_ITEM_INT(pathconfig_warnings); SET_ITEM_INT(_init_main); SET_ITEM_INT(_isolated_interpreter); - SET_ITEM_WSTRLIST(_orig_argv); + SET_ITEM_WSTRLIST(orig_argv); return dict; @@ -985,6 +1060,280 @@ fail: } +static PyObject* +config_dict_get(PyObject *dict, const char *name) +{ + PyObject *item = _PyDict_GetItemStringWithError(dict, name); + if (item == NULL && !PyErr_Occurred()) { + PyErr_Format(PyExc_ValueError, "missing config key: %s", name); + return NULL; + } + return item; +} + + +static void +config_dict_invalid_value(const char *name) +{ + PyErr_Format(PyExc_ValueError, "invalid config value: %s", name); +} + + +static void +config_dict_invalid_type(const char *name) +{ + PyErr_Format(PyExc_TypeError, "invalid config type: %s", name); +} + + +static int +config_dict_get_int(PyObject *dict, const char *name, int *result) +{ + PyObject *item = config_dict_get(dict, name); + if (item == NULL) { + return -1; + } + int value = _PyLong_AsInt(item); + if (value == -1 && PyErr_Occurred()) { + if (PyErr_ExceptionMatches(PyExc_TypeError)) { + config_dict_invalid_type(name); + } + else if (PyErr_ExceptionMatches(PyExc_OverflowError)) { + config_dict_invalid_value(name); + } + return -1; + } + *result = value; + return 0; +} + + +static int +config_dict_get_ulong(PyObject *dict, const char *name, unsigned long *result) +{ + PyObject *item = config_dict_get(dict, name); + if (item == NULL) { + return -1; + } + unsigned long value = PyLong_AsUnsignedLong(item); + if (value == (unsigned long)-1 && PyErr_Occurred()) { + if (PyErr_ExceptionMatches(PyExc_TypeError)) { + config_dict_invalid_type(name); + } + else if (PyErr_ExceptionMatches(PyExc_OverflowError)) { + config_dict_invalid_value(name); + } + return -1; + } + *result = value; + return 0; +} + + +static int +config_dict_get_wstr(PyObject *dict, const char *name, PyConfig *config, + wchar_t **result) +{ + PyObject *item = config_dict_get(dict, name); + if (item == NULL) { + return -1; + } + PyStatus status; + if (item == Py_None) { + status = PyConfig_SetString(config, result, NULL); + } + else if (!PyUnicode_Check(item)) { + config_dict_invalid_type(name); + return -1; + } + else { + wchar_t *wstr = PyUnicode_AsWideCharString(item, NULL); + if (wstr == NULL) { + return -1; + } + status = PyConfig_SetString(config, result, wstr); + PyMem_Free(wstr); + } + if (_PyStatus_EXCEPTION(status)) { + PyErr_NoMemory(); + return -1; + } + return 0; +} + + +static int +config_dict_get_wstrlist(PyObject *dict, const char *name, PyConfig *config, + PyWideStringList *result) +{ + PyObject *list = config_dict_get(dict, name); + if (list == NULL) { + return -1; + } + + if (!PyList_CheckExact(list)) { + config_dict_invalid_type(name); + return -1; + } + + PyWideStringList wstrlist = _PyWideStringList_INIT; + for (Py_ssize_t i=0; i < PyList_GET_SIZE(list); i++) { + PyObject *item = PyList_GET_ITEM(list, i); + + if (item == Py_None) { + config_dict_invalid_value(name); + goto error; + } + else if (!PyUnicode_Check(item)) { + config_dict_invalid_type(name); + goto error; + } + wchar_t *wstr = PyUnicode_AsWideCharString(item, NULL); + if (wstr == NULL) { + goto error; + } + PyStatus status = PyWideStringList_Append(&wstrlist, wstr); + PyMem_Free(wstr); + if (_PyStatus_EXCEPTION(status)) { + PyErr_NoMemory(); + goto error; + } + } + + if (_PyWideStringList_Copy(result, &wstrlist) < 0) { + PyErr_NoMemory(); + goto error; + } + _PyWideStringList_Clear(&wstrlist); + return 0; + +error: + _PyWideStringList_Clear(&wstrlist); + return -1; +} + + +int +_PyConfig_FromDict(PyConfig *config, PyObject *dict) +{ + if (!PyDict_Check(dict)) { + PyErr_SetString(PyExc_TypeError, "dict expected"); + return -1; + } + +#define CHECK_VALUE(NAME, TEST) \ + if (!(TEST)) { \ + config_dict_invalid_value(NAME); \ + return -1; \ + } +#define GET_UINT(KEY) \ + do { \ + if (config_dict_get_int(dict, #KEY, &config->KEY) < 0) { \ + return -1; \ + } \ + CHECK_VALUE(#KEY, config->KEY >= 0); \ + } while (0) +#define GET_WSTR(KEY) \ + do { \ + if (config_dict_get_wstr(dict, #KEY, config, &config->KEY) < 0) { \ + return -1; \ + } \ + CHECK_VALUE(#KEY, config->KEY != NULL); \ + } while (0) +#define GET_WSTR_OPT(KEY) \ + do { \ + if (config_dict_get_wstr(dict, #KEY, config, &config->KEY) < 0) { \ + return -1; \ + } \ + } while (0) +#define GET_WSTRLIST(KEY) \ + do { \ + if (config_dict_get_wstrlist(dict, #KEY, config, &config->KEY) < 0) { \ + return -1; \ + } \ + } while (0) + + GET_UINT(_config_init); + CHECK_VALUE("_config_init", + config->_config_init == _PyConfig_INIT_COMPAT + || config->_config_init == _PyConfig_INIT_PYTHON + || config->_config_init == _PyConfig_INIT_ISOLATED); + GET_UINT(isolated); + GET_UINT(use_environment); + GET_UINT(dev_mode); + GET_UINT(install_signal_handlers); + GET_UINT(use_hash_seed); + if (config_dict_get_ulong(dict, "hash_seed", &config->hash_seed) < 0) { + return -1; + } + CHECK_VALUE("hash_seed", config->hash_seed <= MAX_HASH_SEED); + GET_UINT(faulthandler); + GET_UINT(tracemalloc); + GET_UINT(import_time); + GET_UINT(show_ref_count); + GET_UINT(dump_refs); + GET_UINT(malloc_stats); + GET_WSTR(filesystem_encoding); + GET_WSTR(filesystem_errors); + GET_WSTR_OPT(pycache_prefix); + GET_UINT(parse_argv); + GET_WSTRLIST(orig_argv); + GET_WSTRLIST(argv); + GET_WSTRLIST(xoptions); + GET_WSTRLIST(warnoptions); + GET_UINT(site_import); + GET_UINT(bytes_warning); + GET_UINT(warn_default_encoding); + GET_UINT(inspect); + GET_UINT(interactive); + GET_UINT(optimization_level); + GET_UINT(parser_debug); + GET_UINT(write_bytecode); + GET_UINT(verbose); + GET_UINT(quiet); + GET_UINT(user_site_directory); + GET_UINT(configure_c_stdio); + GET_UINT(buffered_stdio); + GET_WSTR(stdio_encoding); + GET_WSTR(stdio_errors); +#ifdef MS_WINDOWS + GET_UINT(legacy_windows_stdio); +#endif + GET_WSTR(check_hash_pycs_mode); + + GET_UINT(pathconfig_warnings); + GET_WSTR(program_name); + GET_WSTR_OPT(pythonpath_env); + GET_WSTR_OPT(home); + GET_WSTR(platlibdir); + + // Path configuration output + GET_UINT(module_search_paths_set); + GET_WSTRLIST(module_search_paths); + GET_WSTR_OPT(executable); + GET_WSTR_OPT(base_executable); + GET_WSTR_OPT(prefix); + GET_WSTR_OPT(base_prefix); + GET_WSTR_OPT(exec_prefix); + GET_WSTR_OPT(base_exec_prefix); + + GET_UINT(skip_source_first_line); + GET_WSTR_OPT(run_command); + GET_WSTR_OPT(run_module); + GET_WSTR_OPT(run_filename); + + GET_UINT(_install_importlib); + GET_UINT(_init_main); + GET_UINT(_isolated_interpreter); + +#undef CHECK_VALUE +#undef GET_UINT +#undef GET_WSTR +#undef GET_WSTR_OPT + return 0; +} + + static const char* config_get_env(const PyConfig *config, const char *name) { @@ -1252,7 +1601,6 @@ config_init_home(PyConfig *config) L"PYTHONHOME", "PYTHONHOME"); } - static PyStatus config_init_hash_seed(PyConfig *config) { @@ -1266,7 +1614,7 @@ config_init_hash_seed(PyConfig *config) errno = 0; seed = strtoul(seed_text, (char **)&endptr, 10); if (*endptr != '\0' - || seed > 4294967295UL + || seed > MAX_HASH_SEED || (errno == ERANGE && seed == ULONG_MAX)) { return _PyStatus_ERR("PYTHONHASHSEED must be \"random\" " @@ -1335,7 +1683,7 @@ config_read_env_vars(PyConfig *config) #ifdef MS_WINDOWS _Py_get_env_flag(use_env, &config->legacy_windows_stdio, - "PYTHONLEGACYWINDOWSSTDIO"); + "PYTHONLEGACYWINDOWSSTDIO"); #endif if (config_get_env(config, "PYTHONDUMPREFS")) { @@ -1460,11 +1808,6 @@ config_read_complex_options(PyConfig *config) config->import_time = 1; } - if (config_get_env(config, "PYTHONOLDPARSER") - || config_get_xoption(config, L"oldparser")) { - config->_use_peg_parser = 0; - } - PyStatus status; if (config->tracemalloc < 0) { status = config_init_tracemalloc(config); @@ -1484,8 +1827,13 @@ config_read_complex_options(PyConfig *config) static const wchar_t * -config_get_stdio_errors(void) +config_get_stdio_errors(const PyPreConfig *preconfig) { + if (preconfig->utf8_mode) { + /* UTF-8 Mode uses UTF-8/surrogateescape */ + return L"surrogateescape"; + } + #ifndef MS_WINDOWS const char *loc = setlocale(LC_CTYPE, NULL); if (loc != NULL) { @@ -1510,26 +1858,18 @@ config_get_stdio_errors(void) } +// See also config_get_fs_encoding() static PyStatus -config_get_locale_encoding(PyConfig *config, wchar_t **locale_encoding) +config_get_locale_encoding(PyConfig *config, const PyPreConfig *preconfig, + wchar_t **locale_encoding) { -#ifdef MS_WINDOWS - char encoding[20]; - PyOS_snprintf(encoding, sizeof(encoding), "cp%u", GetACP()); - return PyConfig_SetBytesString(config, locale_encoding, encoding); -#elif defined(_Py_FORCE_UTF8_LOCALE) - return PyConfig_SetString(config, locale_encoding, L"utf-8"); -#else - const char *encoding = nl_langinfo(CODESET); - if (!encoding || encoding[0] == '\0') { - return _PyStatus_ERR("failed to get the locale encoding: " - "nl_langinfo(CODESET) failed"); + wchar_t *encoding = _Py_GetLocaleEncoding(); + if (encoding == NULL) { + return _PyStatus_NO_MEMORY(); } - /* nl_langinfo(CODESET) is decoded by Py_DecodeLocale() */ - return CONFIG_SET_BYTES_STR(config, - locale_encoding, encoding, - "nl_langinfo(CODESET)"); -#endif + PyStatus status = PyConfig_SetString(config, locale_encoding, encoding); + PyMem_RawFree(encoding); + return status; } @@ -1539,8 +1879,8 @@ config_init_stdio_encoding(PyConfig *config, { PyStatus status; - /* If Py_SetStandardStreamEncoding() have been called, use these - parameters. */ + /* If Py_SetStandardStreamEncoding() has been called, use its + arguments if they are not NULL. */ if (config->stdio_encoding == NULL && _Py_StandardStreamEncoding != NULL) { status = CONFIG_SET_BYTES_STR(config, &config->stdio_encoding, _Py_StandardStreamEncoding, @@ -1559,6 +1899,7 @@ config_init_stdio_encoding(PyConfig *config, } } + // Exit if encoding and errors are defined if (config->stdio_encoding != NULL && config->stdio_errors != NULL) { return _PyStatus_OK(); } @@ -1614,33 +1955,16 @@ config_init_stdio_encoding(PyConfig *config, PyMem_RawFree(pythonioencoding); } - /* UTF-8 Mode uses UTF-8/surrogateescape */ - if (preconfig->utf8_mode) { - if (config->stdio_encoding == NULL) { - status = PyConfig_SetString(config, &config->stdio_encoding, - L"utf-8"); - if (_PyStatus_EXCEPTION(status)) { - return status; - } - } - if (config->stdio_errors == NULL) { - status = PyConfig_SetString(config, &config->stdio_errors, - L"surrogateescape"); - if (_PyStatus_EXCEPTION(status)) { - return status; - } - } - } - /* Choose the default error handler based on the current locale. */ if (config->stdio_encoding == NULL) { - status = config_get_locale_encoding(config, &config->stdio_encoding); + status = config_get_locale_encoding(config, preconfig, + &config->stdio_encoding); if (_PyStatus_EXCEPTION(status)) { return status; } } if (config->stdio_errors == NULL) { - const wchar_t *errors = config_get_stdio_errors(); + const wchar_t *errors = config_get_stdio_errors(preconfig); assert(errors != NULL); status = PyConfig_SetString(config, &config->stdio_errors, errors); @@ -1653,46 +1977,46 @@ config_init_stdio_encoding(PyConfig *config, } +// See also config_get_locale_encoding() +static PyStatus +config_get_fs_encoding(PyConfig *config, const PyPreConfig *preconfig, + wchar_t **fs_encoding) +{ +#ifdef _Py_FORCE_UTF8_FS_ENCODING + return PyConfig_SetString(config, fs_encoding, L"utf-8"); +#elif defined(MS_WINDOWS) + const wchar_t *encoding; + if (preconfig->legacy_windows_fs_encoding) { + // Legacy Windows filesystem encoding: mbcs/replace + encoding = L"mbcs"; + } + else { + // Windows defaults to utf-8/surrogatepass (PEP 529) + encoding = L"utf-8"; + } + return PyConfig_SetString(config, fs_encoding, encoding); +#else // !MS_WINDOWS + if (preconfig->utf8_mode) { + return PyConfig_SetString(config, fs_encoding, L"utf-8"); + } + + if (_Py_GetForceASCII()) { + return PyConfig_SetString(config, fs_encoding, L"ascii"); + } + + return config_get_locale_encoding(config, preconfig, fs_encoding); +#endif // !MS_WINDOWS +} + + static PyStatus config_init_fs_encoding(PyConfig *config, const PyPreConfig *preconfig) { PyStatus status; if (config->filesystem_encoding == NULL) { -#ifdef _Py_FORCE_UTF8_FS_ENCODING - status = PyConfig_SetString(config, &config->filesystem_encoding, L"utf-8"); -#else - -#ifdef MS_WINDOWS - if (preconfig->legacy_windows_fs_encoding) { - /* Legacy Windows filesystem encoding: mbcs/replace */ - status = PyConfig_SetString(config, &config->filesystem_encoding, - L"mbcs"); - } - else -#endif - if (preconfig->utf8_mode) { - status = PyConfig_SetString(config, &config->filesystem_encoding, - L"utf-8"); - } -#ifndef MS_WINDOWS - else if (_Py_GetForceASCII()) { - status = PyConfig_SetString(config, &config->filesystem_encoding, - L"ascii"); - } -#endif - else { -#ifdef MS_WINDOWS - /* Windows defaults to utf-8/surrogatepass (PEP 529). */ - status = PyConfig_SetString(config, &config->filesystem_encoding, - L"utf-8"); -#else - status = config_get_locale_encoding(config, - &config->filesystem_encoding); -#endif - } -#endif /* !_Py_FORCE_UTF8_FS_ENCODING */ - + status = config_get_fs_encoding(config, preconfig, + &config->filesystem_encoding); if (_PyStatus_EXCEPTION(status)) { return status; } @@ -1720,7 +2044,7 @@ config_init_fs_encoding(PyConfig *config, const PyPreConfig *preconfig) static PyStatus -config_read(PyConfig *config) +config_read(PyConfig *config, int compute_path_config) { PyStatus status; const PyPreConfig *preconfig = &_PyRuntime.preconfig; @@ -1765,7 +2089,7 @@ config_read(PyConfig *config) } if (config->_install_importlib) { - status = _PyConfig_InitPathConfig(config); + status = _PyConfig_InitPathConfig(config, compute_path_config); if (_PyStatus_EXCEPTION(status)) { return status; } @@ -1820,6 +2144,11 @@ config_read(PyConfig *config) config->configure_c_stdio = 1; } + // Only parse arguments once. + if (config->parse_argv == 1) { + config->parse_argv = 2; + } + return _PyStatus_OK(); } @@ -1880,8 +2209,8 @@ _PyConfig_Write(const PyConfig *config, _PyRuntimeState *runtime) preconfig->use_environment = config->use_environment; preconfig->dev_mode = config->dev_mode; - if (_Py_SetArgcArgv(config->_orig_argv.length, - config->_orig_argv.items) < 0) + if (_Py_SetArgcArgv(config->orig_argv.length, + config->orig_argv.items) < 0) { return _PyStatus_NO_MEMORY(); } @@ -2310,7 +2639,7 @@ core_read_precmdline(PyConfig *config, _PyPreCmdline *precmdline) { PyStatus status; - if (config->parse_argv) { + if (config->parse_argv == 1) { if (_PyWideStringList_Copy(&precmdline->argv, &config->argv) < 0) { return _PyStatus_NO_MEMORY(); } @@ -2388,7 +2717,7 @@ config_read_cmdline(PyConfig *config) } } - if (config->parse_argv) { + if (config->parse_argv == 1) { Py_ssize_t opt_index; status = config_parse_cmdline(config, &cmdline_warnoptions, &opt_index); if (_PyStatus_EXCEPTION(status)) { @@ -2506,7 +2835,7 @@ PyConfig_SetWideStringList(PyConfig *config, PyWideStringList *list, The only side effects are to modify config and to call _Py_SetArgcArgv(). */ PyStatus -PyConfig_Read(PyConfig *config) +_PyConfig_Read(PyConfig *config, int compute_path_config) { PyStatus status; @@ -2517,11 +2846,11 @@ PyConfig_Read(PyConfig *config) config_get_global_vars(config); - if (config->_orig_argv.length == 0 + if (config->orig_argv.length == 0 && !(config->argv.length == 1 && wcscmp(config->argv.items[0], L"") == 0)) { - if (_PyWideStringList_Copy(&config->_orig_argv, &config->argv) < 0) { + if (_PyWideStringList_Copy(&config->orig_argv, &config->argv) < 0) { return _PyStatus_NO_MEMORY(); } } @@ -2549,64 +2878,12 @@ PyConfig_Read(PyConfig *config) goto done; } - status = config_read(config); + status = config_read(config, compute_path_config); if (_PyStatus_EXCEPTION(status)) { goto done; } - /* Check config consistency */ - assert(config->isolated >= 0); - assert(config->use_environment >= 0); - assert(config->dev_mode >= 0); - assert(config->_use_peg_parser >= 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->parse_argv >= 0); - assert(config->configure_c_stdio >= 0); - assert(config->buffered_stdio >= 0); - assert(config->program_name != NULL); - assert(_PyWideStringList_CheckConsistency(&config->argv)); - /* sys.argv must be non-empty: empty argv is replaced with [''] */ - assert(config->argv.length >= 1); - assert(_PyWideStringList_CheckConsistency(&config->xoptions)); - assert(_PyWideStringList_CheckConsistency(&config->warnoptions)); - assert(_PyWideStringList_CheckConsistency(&config->module_search_paths)); - if (config->_install_importlib) { - assert(config->module_search_paths_set != 0); - /* don't check config->module_search_paths */ - assert(config->executable != NULL); - assert(config->base_executable != NULL); - assert(config->prefix != NULL); - assert(config->base_prefix != NULL); - assert(config->exec_prefix != NULL); - assert(config->base_exec_prefix != NULL); - } - assert(config->platlibdir != NULL); - 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 - /* -c and -m options are exclusive */ - assert(!(config->run_command != NULL && config->run_module != NULL)); - assert(config->check_hash_pycs_mode != NULL); - assert(config->_install_importlib >= 0); - assert(config->pathconfig_warnings >= 0); - assert(_PyWideStringList_CheckConsistency(&config->_orig_argv)); + assert(config_check_consistency(config)); status = _PyStatus_OK(); @@ -2616,6 +2893,13 @@ done: } +PyStatus +PyConfig_Read(PyConfig *config) +{ + return _PyConfig_Read(config, 1); +} + + PyObject* _Py_GetConfigsAsDict(void) { @@ -2638,8 +2922,8 @@ _Py_GetConfigsAsDict(void) Py_CLEAR(dict); /* pre config */ - PyThreadState *tstate = _PyThreadState_GET(); - const PyPreConfig *pre_config = &tstate->interp->runtime->preconfig; + PyInterpreterState *interp = _PyInterpreterState_GET(); + const PyPreConfig *pre_config = &interp->runtime->preconfig; dict = _PyPreConfig_AsDict(pre_config); if (dict == NULL) { goto error; @@ -2650,8 +2934,8 @@ _Py_GetConfigsAsDict(void) Py_CLEAR(dict); /* core config */ - const PyConfig *config = _PyInterpreterState_GetConfig(tstate->interp); - dict = config_as_dict(config); + const PyConfig *config = _PyInterpreterState_GetConfig(interp); + dict = _PyConfig_AsDict(config); if (dict == NULL) { goto error; } @@ -2660,6 +2944,16 @@ _Py_GetConfigsAsDict(void) } Py_CLEAR(dict); + /* path config */ + dict = _PyPathConfig_AsDict(); + if (dict == NULL) { + goto error; + } + if (PyDict_SetItemString(result, "path_config", dict) < 0) { + goto error; + } + Py_CLEAR(dict); + return result; error: |
