summaryrefslogtreecommitdiffstats
path: root/Python
diff options
context:
space:
mode:
authorVictor Stinner <vstinner@redhat.com>2019-05-20 15:16:38 (GMT)
committerGitHub <noreply@github.com>2019-05-20 15:16:38 (GMT)
commit0f72147ce2b3d65235b41eddc6a57be40237b5c7 (patch)
treeffab92ed1baf4ff593145661b513e18cc7c8bb88 /Python
parent522ccef8690970fc4f78f51a3adb995f2547871a (diff)
downloadcpython-0f72147ce2b3d65235b41eddc6a57be40237b5c7.zip
cpython-0f72147ce2b3d65235b41eddc6a57be40237b5c7.tar.gz
cpython-0f72147ce2b3d65235b41eddc6a57be40237b5c7.tar.bz2
bpo-36763: Fix _PyRuntime.preconfig.coerce_c_locale (GH-13444)
_PyRuntime.preconfig.coerce_c_locale can now be used to check if the C locale has been coerced. * Fix _Py_LegacyLocaleDetected(): don't attempt to coerce the C locale if LC_ALL environment variable is set. Add 'warn' parameter: emit_stderr_warning_for_legacy_locale() must not the LC_ALL env var. * _PyPreConfig_Write() sets coerce_c_locale to 0 if _Py_CoerceLegacyLocale() fails.
Diffstat (limited to 'Python')
-rw-r--r--Python/preconfig.c26
-rw-r--r--Python/pylifecycle.c26
2 files changed, 35 insertions, 17 deletions
diff --git a/Python/preconfig.c b/Python/preconfig.c
index 71a6ee6..4df6208 100644
--- a/Python/preconfig.c
+++ b/Python/preconfig.c
@@ -660,7 +660,7 @@ preconfig_init_coerce_c_locale(_PyPreConfig *config)
It is only coerced if if the LC_CTYPE locale is "C". */
if (config->coerce_c_locale < 0 || config->coerce_c_locale == 1) {
/* The C locale enables the C locale coercion (PEP 538) */
- if (_Py_LegacyLocaleDetected()) {
+ if (_Py_LegacyLocaleDetected(0)) {
config->coerce_c_locale = 2;
}
else {
@@ -888,32 +888,38 @@ done:
- set the LC_CTYPE locale (coerce C locale, PEP 538) and set the UTF-8 mode
(PEP 540)
- If the memory allocator is changed, config is re-allocated with new
- allocator. So calling _PyPreConfig_Clear(config) is safe after this call.
+ The applied configuration is written into _PyRuntime.preconfig.
+ If the C locale cannot be coerced, set coerce_c_locale to 0.
Do nothing if called after Py_Initialize(): ignore the new
pre-configuration. */
_PyInitError
-_PyPreConfig_Write(const _PyPreConfig *config)
+_PyPreConfig_Write(const _PyPreConfig *src_config)
{
+ _PyPreConfig config;
+ _PyPreConfig_InitFromPreConfig(&config, src_config);
+
if (_PyRuntime.core_initialized) {
/* bpo-34008: Calling this functions after Py_Initialize() ignores
the new configuration. */
return _Py_INIT_OK();
}
- PyMemAllocatorName name = (PyMemAllocatorName)config->allocator;
+ PyMemAllocatorName name = (PyMemAllocatorName)config.allocator;
if (name != PYMEM_ALLOCATOR_NOT_SET) {
if (_PyMem_SetupAllocators(name) < 0) {
return _Py_INIT_ERR("Unknown PYTHONMALLOC allocator");
}
}
- _PyPreConfig_SetGlobalConfig(config);
+ _PyPreConfig_SetGlobalConfig(&config);
- if (config->configure_locale) {
- if (config->coerce_c_locale) {
- _Py_CoerceLegacyLocale(config->coerce_c_locale_warn);
+ if (config.configure_locale) {
+ if (config.coerce_c_locale) {
+ if (!_Py_CoerceLegacyLocale(config.coerce_c_locale_warn)) {
+ /* C locale not coerced */
+ config.coerce_c_locale = 0;
+ }
}
/* Set LC_CTYPE to the user preferred locale */
@@ -921,7 +927,7 @@ _PyPreConfig_Write(const _PyPreConfig *config)
}
/* Write the new pre-configuration into _PyRuntime */
- _PyPreConfig_Copy(&_PyRuntime.preconfig, config);
+ _PyPreConfig_Copy(&_PyRuntime.preconfig, &config);
return _Py_INIT_OK();
}
diff --git a/Python/pylifecycle.c b/Python/pylifecycle.c
index 01f725f..01344db 100644
--- a/Python/pylifecycle.c
+++ b/Python/pylifecycle.c
@@ -231,9 +231,18 @@ init_importlib_external(PyInterpreterState *interp)
*/
int
-_Py_LegacyLocaleDetected(void)
+_Py_LegacyLocaleDetected(int warn)
{
#ifndef MS_WINDOWS
+ if (!warn) {
+ const char *locale_override = getenv("LC_ALL");
+ if (locale_override != NULL && *locale_override != '\0') {
+ /* Don't coerce C locale if the LC_ALL environment variable
+ is set */
+ return 0;
+ }
+ }
+
/* On non-Windows systems, the C locale is considered a legacy locale */
/* XXX (ncoghlan): some platforms (notably Mac OS X) don't appear to treat
* the POSIX locale as a simple alias for the C locale, so
@@ -257,7 +266,7 @@ static void
emit_stderr_warning_for_legacy_locale(_PyRuntimeState *runtime)
{
const _PyPreConfig *preconfig = &runtime->preconfig;
- if (preconfig->coerce_c_locale_warn && _Py_LegacyLocaleDetected()) {
+ if (preconfig->coerce_c_locale_warn && _Py_LegacyLocaleDetected(1)) {
PySys_FormatStderr("%s", _C_LOCALE_WARNING);
}
}
@@ -292,7 +301,7 @@ static const char C_LOCALE_COERCION_WARNING[] =
"Python detected LC_CTYPE=C: LC_CTYPE coerced to %.20s (set another locale "
"or PYTHONCOERCECLOCALE=0 to disable this locale coercion behavior).\n";
-static void
+static int
_coerce_default_locale_settings(int warn, const _LocaleCoercionTarget *target)
{
const char *newloc = target->locale_name;
@@ -304,7 +313,7 @@ _coerce_default_locale_settings(int warn, const _LocaleCoercionTarget *target)
if (setenv("LC_CTYPE", newloc, 1)) {
fprintf(stderr,
"Error setting LC_CTYPE, skipping C locale coercion\n");
- return;
+ return 0;
}
if (warn) {
fprintf(stderr, C_LOCALE_COERCION_WARNING, newloc);
@@ -312,18 +321,20 @@ _coerce_default_locale_settings(int warn, const _LocaleCoercionTarget *target)
/* Reconfigure with the overridden environment variables */
_Py_SetLocaleFromEnv(LC_ALL);
+ return 1;
}
#endif
-void
+int
_Py_CoerceLegacyLocale(int warn)
{
+ int coerced = 0;
#ifdef PY_COERCE_C_LOCALE
char *oldloc = NULL;
oldloc = _PyMem_RawStrdup(setlocale(LC_CTYPE, NULL));
if (oldloc == NULL) {
- return;
+ return coerced;
}
const char *locale_override = getenv("LC_ALL");
@@ -345,7 +356,7 @@ _Py_CoerceLegacyLocale(int warn)
}
#endif
/* Successfully configured locale, so make it the default */
- _coerce_default_locale_settings(warn, target);
+ coerced = _coerce_default_locale_settings(warn, target);
goto done;
}
}
@@ -357,6 +368,7 @@ _Py_CoerceLegacyLocale(int warn)
done:
PyMem_RawFree(oldloc);
#endif
+ return coerced;
}
/* _Py_SetLocaleFromEnv() is a wrapper around setlocale(category, "") to