bpo-36763: Fix _PyPreConfig_InitCompatConfig() utf8_mode (GH-13518)
* _PyPreConfig_InitCompatConfig() sets utf8_mode to 0. * Change Py_UTF8Mode default value to 0. * Fix _PyPreConfig_Copy(): copy also _config_init attrbibute. * _PyPreConfig_AsDict() exports _config_init * Fix _PyPreConfig_GetGlobalConfig(): use Py_UTF8Mode if it's greater than 0, even if utf8_mode >= 0. * Add unit tests on environment variables using Python API.
This commit is contained in:
parent
bc2aa81662
commit
20e1e2582e
|
@ -287,6 +287,7 @@ class InitConfigTests(EmbeddingTestsMixin, unittest.TestCase):
|
||||||
IGNORE_CONFIG = object()
|
IGNORE_CONFIG = object()
|
||||||
|
|
||||||
PRE_CONFIG_COMPAT = {
|
PRE_CONFIG_COMPAT = {
|
||||||
|
'_config_init': API_COMPAT,
|
||||||
'allocator': PYMEM_ALLOCATOR_NOT_SET,
|
'allocator': PYMEM_ALLOCATOR_NOT_SET,
|
||||||
'parse_argv': 0,
|
'parse_argv': 0,
|
||||||
'configure_locale': 1,
|
'configure_locale': 1,
|
||||||
|
@ -299,11 +300,13 @@ class InitConfigTests(EmbeddingTestsMixin, unittest.TestCase):
|
||||||
'legacy_windows_fs_encoding': 0,
|
'legacy_windows_fs_encoding': 0,
|
||||||
})
|
})
|
||||||
PRE_CONFIG_PYTHON = dict(PRE_CONFIG_COMPAT,
|
PRE_CONFIG_PYTHON = dict(PRE_CONFIG_COMPAT,
|
||||||
|
_config_init=API_PYTHON,
|
||||||
parse_argv=1,
|
parse_argv=1,
|
||||||
coerce_c_locale=GET_DEFAULT_CONFIG,
|
coerce_c_locale=GET_DEFAULT_CONFIG,
|
||||||
utf8_mode=GET_DEFAULT_CONFIG,
|
utf8_mode=GET_DEFAULT_CONFIG,
|
||||||
)
|
)
|
||||||
PRE_CONFIG_ISOLATED = dict(PRE_CONFIG_COMPAT,
|
PRE_CONFIG_ISOLATED = dict(PRE_CONFIG_COMPAT,
|
||||||
|
_config_init=API_ISOLATED,
|
||||||
configure_locale=0,
|
configure_locale=0,
|
||||||
isolated=1,
|
isolated=1,
|
||||||
use_environment=0,
|
use_environment=0,
|
||||||
|
@ -388,10 +391,12 @@ class InitConfigTests(EmbeddingTestsMixin, unittest.TestCase):
|
||||||
})
|
})
|
||||||
|
|
||||||
CORE_CONFIG_PYTHON = dict(CORE_CONFIG_COMPAT,
|
CORE_CONFIG_PYTHON = dict(CORE_CONFIG_COMPAT,
|
||||||
|
_config_init=API_PYTHON,
|
||||||
configure_c_stdio=1,
|
configure_c_stdio=1,
|
||||||
parse_argv=1,
|
parse_argv=1,
|
||||||
)
|
)
|
||||||
CORE_CONFIG_ISOLATED = dict(CORE_CONFIG_COMPAT,
|
CORE_CONFIG_ISOLATED = dict(CORE_CONFIG_COMPAT,
|
||||||
|
_config_init=API_ISOLATED,
|
||||||
isolated=1,
|
isolated=1,
|
||||||
use_environment=0,
|
use_environment=0,
|
||||||
user_site_directory=0,
|
user_site_directory=0,
|
||||||
|
@ -611,7 +616,6 @@ class InitConfigTests(EmbeddingTestsMixin, unittest.TestCase):
|
||||||
else:
|
else:
|
||||||
default_config = self.CORE_CONFIG_COMPAT
|
default_config = self.CORE_CONFIG_COMPAT
|
||||||
expected_config = dict(default_config, **expected_config)
|
expected_config = dict(default_config, **expected_config)
|
||||||
expected_config['_config_init'] = api
|
|
||||||
|
|
||||||
self.get_expected_config(expected_preconfig,
|
self.get_expected_config(expected_preconfig,
|
||||||
expected_config, env,
|
expected_config, env,
|
||||||
|
@ -708,7 +712,33 @@ class InitConfigTests(EmbeddingTestsMixin, unittest.TestCase):
|
||||||
self.check_config("test_init_from_config", config, preconfig,
|
self.check_config("test_init_from_config", config, preconfig,
|
||||||
api=API_COMPAT)
|
api=API_COMPAT)
|
||||||
|
|
||||||
def test_init_env(self):
|
def test_init_compat_env(self):
|
||||||
|
preconfig = {
|
||||||
|
'allocator': PYMEM_ALLOCATOR_MALLOC,
|
||||||
|
}
|
||||||
|
config = {
|
||||||
|
'use_hash_seed': 1,
|
||||||
|
'hash_seed': 42,
|
||||||
|
'tracemalloc': 2,
|
||||||
|
'import_time': 1,
|
||||||
|
'malloc_stats': 1,
|
||||||
|
'inspect': 1,
|
||||||
|
'optimization_level': 2,
|
||||||
|
'module_search_path_env': '/my/path',
|
||||||
|
'pycache_prefix': 'env_pycache_prefix',
|
||||||
|
'write_bytecode': 0,
|
||||||
|
'verbose': 1,
|
||||||
|
'buffered_stdio': 0,
|
||||||
|
'stdio_encoding': 'iso8859-1',
|
||||||
|
'stdio_errors': 'replace',
|
||||||
|
'user_site_directory': 0,
|
||||||
|
'faulthandler': 1,
|
||||||
|
'warnoptions': ['EnvVar'],
|
||||||
|
}
|
||||||
|
self.check_config("test_init_compat_env", config, preconfig,
|
||||||
|
api=API_COMPAT)
|
||||||
|
|
||||||
|
def test_init_python_env(self):
|
||||||
preconfig = {
|
preconfig = {
|
||||||
'allocator': PYMEM_ALLOCATOR_MALLOC,
|
'allocator': PYMEM_ALLOCATOR_MALLOC,
|
||||||
'utf8_mode': 1,
|
'utf8_mode': 1,
|
||||||
|
@ -732,8 +762,8 @@ class InitConfigTests(EmbeddingTestsMixin, unittest.TestCase):
|
||||||
'faulthandler': 1,
|
'faulthandler': 1,
|
||||||
'warnoptions': ['EnvVar'],
|
'warnoptions': ['EnvVar'],
|
||||||
}
|
}
|
||||||
self.check_config("test_init_env", config, preconfig,
|
self.check_config("test_init_python_env", config, preconfig,
|
||||||
api=API_COMPAT)
|
api=API_PYTHON)
|
||||||
|
|
||||||
def test_init_env_dev_mode(self):
|
def test_init_env_dev_mode(self):
|
||||||
preconfig = dict(allocator=PYMEM_ALLOCATOR_DEBUG)
|
preconfig = dict(allocator=PYMEM_ALLOCATOR_DEBUG)
|
||||||
|
|
|
@ -638,7 +638,7 @@ static void set_all_env_vars(void)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static int test_init_env(void)
|
static int test_init_compat_env(void)
|
||||||
{
|
{
|
||||||
/* Test initialization from environment variables */
|
/* Test initialization from environment variables */
|
||||||
Py_IgnoreEnvironmentFlag = 0;
|
Py_IgnoreEnvironmentFlag = 0;
|
||||||
|
@ -650,6 +650,29 @@ static int test_init_env(void)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int test_init_python_env(void)
|
||||||
|
{
|
||||||
|
_PyInitError err;
|
||||||
|
|
||||||
|
set_all_env_vars();
|
||||||
|
|
||||||
|
_PyCoreConfig config;
|
||||||
|
err = _PyCoreConfig_InitPythonConfig(&config);
|
||||||
|
if (_PyInitError_Failed(err)) {
|
||||||
|
_Py_ExitInitError(err);
|
||||||
|
}
|
||||||
|
config.program_name = L"./_testembed";
|
||||||
|
|
||||||
|
err = _Py_InitializeFromConfig(&config);
|
||||||
|
if (_PyInitError_Failed(err)) {
|
||||||
|
_Py_ExitInitError(err);
|
||||||
|
}
|
||||||
|
dump_config();
|
||||||
|
Py_Finalize();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static void set_all_env_vars_dev_mode(void)
|
static void set_all_env_vars_dev_mode(void)
|
||||||
{
|
{
|
||||||
putenv("PYTHONMALLOC=");
|
putenv("PYTHONMALLOC=");
|
||||||
|
@ -1257,7 +1280,8 @@ static struct TestCase TestCases[] = {
|
||||||
{"test_init_from_config", test_init_from_config},
|
{"test_init_from_config", test_init_from_config},
|
||||||
{"test_init_parse_argv", test_init_parse_argv},
|
{"test_init_parse_argv", test_init_parse_argv},
|
||||||
{"test_init_dont_parse_argv", test_init_dont_parse_argv},
|
{"test_init_dont_parse_argv", test_init_dont_parse_argv},
|
||||||
{"test_init_env", test_init_env},
|
{"test_init_compat_env", test_init_compat_env},
|
||||||
|
{"test_init_python_env", test_init_python_env},
|
||||||
{"test_init_env_dev_mode", test_init_env_dev_mode},
|
{"test_init_env_dev_mode", test_init_env_dev_mode},
|
||||||
{"test_init_env_dev_mode_alloc", test_init_env_dev_mode_alloc},
|
{"test_init_env_dev_mode_alloc", test_init_env_dev_mode_alloc},
|
||||||
{"test_init_dont_configure_locale", test_init_dont_configure_locale},
|
{"test_init_dont_configure_locale", test_init_dont_configure_locale},
|
||||||
|
|
|
@ -107,9 +107,8 @@ static const char usage_6[] =
|
||||||
/* --- Global configuration variables ----------------------------- */
|
/* --- Global configuration variables ----------------------------- */
|
||||||
|
|
||||||
/* UTF-8 mode (PEP 540): if equals to 1, use the UTF-8 encoding, and change
|
/* UTF-8 mode (PEP 540): if equals to 1, use the UTF-8 encoding, and change
|
||||||
stdin and stdout error handler to "surrogateescape". It is equal to
|
stdin and stdout error handler to "surrogateescape". */
|
||||||
-1 by default: unknown, will be set by Py_Main() */
|
int Py_UTF8Mode = 0;
|
||||||
int Py_UTF8Mode = -1;
|
|
||||||
int Py_DebugFlag = 0; /* Needed by parser.c */
|
int Py_DebugFlag = 0; /* Needed by parser.c */
|
||||||
int Py_VerboseFlag = 0; /* Needed by import.c */
|
int Py_VerboseFlag = 0; /* Needed by import.c */
|
||||||
int Py_QuietFlag = 0; /* Needed by sysmodule.c */
|
int Py_QuietFlag = 0; /* Needed by sysmodule.c */
|
||||||
|
|
|
@ -272,7 +272,16 @@ _PyPreConfig_InitCompatConfig(_PyPreConfig *config)
|
||||||
config->isolated = -1;
|
config->isolated = -1;
|
||||||
config->use_environment = -1;
|
config->use_environment = -1;
|
||||||
config->configure_locale = 1;
|
config->configure_locale = 1;
|
||||||
config->utf8_mode = -1;
|
|
||||||
|
/* bpo-36443: C locale coercion (PEP 538) and UTF-8 Mode (PEP 540)
|
||||||
|
are disabled by default using the Compat configuration.
|
||||||
|
|
||||||
|
Py_UTF8Mode=1 enables the UTF-8 mode. PYTHONUTF8 environment variable
|
||||||
|
is ignored (even if use_environment=1). */
|
||||||
|
config->utf8_mode = 0;
|
||||||
|
config->coerce_c_locale = 0;
|
||||||
|
config->coerce_c_locale_warn = 0;
|
||||||
|
|
||||||
config->dev_mode = -1;
|
config->dev_mode = -1;
|
||||||
config->allocator = PYMEM_ALLOCATOR_NOT_SET;
|
config->allocator = PYMEM_ALLOCATOR_NOT_SET;
|
||||||
#ifdef MS_WINDOWS
|
#ifdef MS_WINDOWS
|
||||||
|
@ -353,6 +362,7 @@ _PyPreConfig_Copy(_PyPreConfig *config, const _PyPreConfig *config2)
|
||||||
{
|
{
|
||||||
#define COPY_ATTR(ATTR) config->ATTR = config2->ATTR
|
#define COPY_ATTR(ATTR) config->ATTR = config2->ATTR
|
||||||
|
|
||||||
|
COPY_ATTR(_config_init);
|
||||||
COPY_ATTR(parse_argv);
|
COPY_ATTR(parse_argv);
|
||||||
COPY_ATTR(isolated);
|
COPY_ATTR(isolated);
|
||||||
COPY_ATTR(use_environment);
|
COPY_ATTR(use_environment);
|
||||||
|
@ -393,6 +403,7 @@ _PyPreConfig_AsDict(const _PyPreConfig *config)
|
||||||
} \
|
} \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
|
SET_ITEM_INT(_config_init);
|
||||||
SET_ITEM_INT(parse_argv);
|
SET_ITEM_INT(parse_argv);
|
||||||
SET_ITEM_INT(isolated);
|
SET_ITEM_INT(isolated);
|
||||||
SET_ITEM_INT(use_environment);
|
SET_ITEM_INT(use_environment);
|
||||||
|
@ -452,7 +463,9 @@ _PyPreConfig_GetGlobalConfig(_PyPreConfig *config)
|
||||||
|
|
||||||
COPY_FLAG(isolated, Py_IsolatedFlag);
|
COPY_FLAG(isolated, Py_IsolatedFlag);
|
||||||
COPY_NOT_FLAG(use_environment, Py_IgnoreEnvironmentFlag);
|
COPY_NOT_FLAG(use_environment, Py_IgnoreEnvironmentFlag);
|
||||||
COPY_FLAG(utf8_mode, Py_UTF8Mode);
|
if (Py_UTF8Mode > 0) {
|
||||||
|
config->utf8_mode = Py_UTF8Mode;
|
||||||
|
}
|
||||||
#ifdef MS_WINDOWS
|
#ifdef MS_WINDOWS
|
||||||
COPY_FLAG(legacy_windows_fs_encoding, Py_LegacyWindowsFSEncodingFlag);
|
COPY_FLAG(legacy_windows_fs_encoding, Py_LegacyWindowsFSEncodingFlag);
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Reference in New Issue