summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorVictor Stinner <vstinner@redhat.com>2019-05-23 02:12:27 (GMT)
committerGitHub <noreply@github.com>2019-05-23 02:12:27 (GMT)
commit20e1e2582e5e69e43af88ff58699c8883d146acb (patch)
tree2726fa5c02f6b7ddd00eede7ecdaa2f5587e6fd7
parentbc2aa816620c5e02ad8e94d8514b7e8f3f551ca1 (diff)
downloadcpython-20e1e2582e5e69e43af88ff58699c8883d146acb.zip
cpython-20e1e2582e5e69e43af88ff58699c8883d146acb.tar.gz
cpython-20e1e2582e5e69e43af88ff58699c8883d146acb.tar.bz2
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.
-rw-r--r--Lib/test/test_embed.py38
-rw-r--r--Programs/_testembed.c28
-rw-r--r--Python/coreconfig.c5
-rw-r--r--Python/preconfig.c17
4 files changed, 77 insertions, 11 deletions
diff --git a/Lib/test/test_embed.py b/Lib/test/test_embed.py
index bd0451a..32aabe3 100644
--- a/Lib/test/test_embed.py
+++ b/Lib/test/test_embed.py
@@ -287,6 +287,7 @@ class InitConfigTests(EmbeddingTestsMixin, unittest.TestCase):
IGNORE_CONFIG = object()
PRE_CONFIG_COMPAT = {
+ '_config_init': API_COMPAT,
'allocator': PYMEM_ALLOCATOR_NOT_SET,
'parse_argv': 0,
'configure_locale': 1,
@@ -299,11 +300,13 @@ class InitConfigTests(EmbeddingTestsMixin, unittest.TestCase):
'legacy_windows_fs_encoding': 0,
})
PRE_CONFIG_PYTHON = dict(PRE_CONFIG_COMPAT,
+ _config_init=API_PYTHON,
parse_argv=1,
coerce_c_locale=GET_DEFAULT_CONFIG,
utf8_mode=GET_DEFAULT_CONFIG,
)
PRE_CONFIG_ISOLATED = dict(PRE_CONFIG_COMPAT,
+ _config_init=API_ISOLATED,
configure_locale=0,
isolated=1,
use_environment=0,
@@ -388,10 +391,12 @@ class InitConfigTests(EmbeddingTestsMixin, unittest.TestCase):
})
CORE_CONFIG_PYTHON = dict(CORE_CONFIG_COMPAT,
+ _config_init=API_PYTHON,
configure_c_stdio=1,
parse_argv=1,
)
CORE_CONFIG_ISOLATED = dict(CORE_CONFIG_COMPAT,
+ _config_init=API_ISOLATED,
isolated=1,
use_environment=0,
user_site_directory=0,
@@ -611,7 +616,6 @@ class InitConfigTests(EmbeddingTestsMixin, unittest.TestCase):
else:
default_config = self.CORE_CONFIG_COMPAT
expected_config = dict(default_config, **expected_config)
- expected_config['_config_init'] = api
self.get_expected_config(expected_preconfig,
expected_config, env,
@@ -708,10 +712,9 @@ class InitConfigTests(EmbeddingTestsMixin, unittest.TestCase):
self.check_config("test_init_from_config", config, preconfig,
api=API_COMPAT)
- def test_init_env(self):
+ def test_init_compat_env(self):
preconfig = {
'allocator': PYMEM_ALLOCATOR_MALLOC,
- 'utf8_mode': 1,
}
config = {
'use_hash_seed': 1,
@@ -732,9 +735,36 @@ class InitConfigTests(EmbeddingTestsMixin, unittest.TestCase):
'faulthandler': 1,
'warnoptions': ['EnvVar'],
}
- self.check_config("test_init_env", config, preconfig,
+ self.check_config("test_init_compat_env", config, preconfig,
api=API_COMPAT)
+ def test_init_python_env(self):
+ preconfig = {
+ 'allocator': PYMEM_ALLOCATOR_MALLOC,
+ 'utf8_mode': 1,
+ }
+ 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_python_env", config, preconfig,
+ api=API_PYTHON)
+
def test_init_env_dev_mode(self):
preconfig = dict(allocator=PYMEM_ALLOCATOR_DEBUG)
config = dict(dev_mode=1,
diff --git a/Programs/_testembed.c b/Programs/_testembed.c
index 7f8ea07..6bd55de 100644
--- a/Programs/_testembed.c
+++ b/Programs/_testembed.c
@@ -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 */
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)
{
putenv("PYTHONMALLOC=");
@@ -1257,7 +1280,8 @@ static struct TestCase TestCases[] = {
{"test_init_from_config", test_init_from_config},
{"test_init_parse_argv", test_init_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_alloc", test_init_env_dev_mode_alloc},
{"test_init_dont_configure_locale", test_init_dont_configure_locale},
diff --git a/Python/coreconfig.c b/Python/coreconfig.c
index 40dba4e..89ccff4 100644
--- a/Python/coreconfig.c
+++ b/Python/coreconfig.c
@@ -107,9 +107,8 @@ static const char usage_6[] =
/* --- Global configuration variables ----------------------------- */
/* 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
- -1 by default: unknown, will be set by Py_Main() */
-int Py_UTF8Mode = -1;
+ stdin and stdout error handler to "surrogateescape". */
+int Py_UTF8Mode = 0;
int Py_DebugFlag = 0; /* Needed by parser.c */
int Py_VerboseFlag = 0; /* Needed by import.c */
int Py_QuietFlag = 0; /* Needed by sysmodule.c */
diff --git a/Python/preconfig.c b/Python/preconfig.c
index 392324f..a6d1346 100644
--- a/Python/preconfig.c
+++ b/Python/preconfig.c
@@ -272,7 +272,16 @@ _PyPreConfig_InitCompatConfig(_PyPreConfig *config)
config->isolated = -1;
config->use_environment = -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->allocator = PYMEM_ALLOCATOR_NOT_SET;
#ifdef MS_WINDOWS
@@ -353,6 +362,7 @@ _PyPreConfig_Copy(_PyPreConfig *config, const _PyPreConfig *config2)
{
#define COPY_ATTR(ATTR) config->ATTR = config2->ATTR
+ COPY_ATTR(_config_init);
COPY_ATTR(parse_argv);
COPY_ATTR(isolated);
COPY_ATTR(use_environment);
@@ -393,6 +403,7 @@ _PyPreConfig_AsDict(const _PyPreConfig *config)
} \
} while (0)
+ SET_ITEM_INT(_config_init);
SET_ITEM_INT(parse_argv);
SET_ITEM_INT(isolated);
SET_ITEM_INT(use_environment);
@@ -452,7 +463,9 @@ _PyPreConfig_GetGlobalConfig(_PyPreConfig *config)
COPY_FLAG(isolated, Py_IsolatedFlag);
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
COPY_FLAG(legacy_windows_fs_encoding, Py_LegacyWindowsFSEncodingFlag);
#endif