summaryrefslogtreecommitdiffstats
path: root/contrib/tools/python3/src/Python/initconfig.c
diff options
context:
space:
mode:
authorshadchin <[email protected]>2022-04-18 12:39:32 +0300
committershadchin <[email protected]>2022-04-18 12:39:32 +0300
commitd4be68e361f4258cf0848fc70018dfe37a2acc24 (patch)
tree153e294cd97ac8b5d7a989612704a0c1f58e8ad4 /contrib/tools/python3/src/Python/initconfig.c
parent260c02f5ccf242d9d9b8a873afaf6588c00237d6 (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.c630
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: