bpo-35336: Fix PYTHONCOERCECLOCALE=1 (GH-10806)

Fix PYTHONCOERCECLOCALE=1 environment variable: only coerce the C
locale if the LC_CTYPE locale is "C".
This commit is contained in:
Victor Stinner 2018-11-30 11:34:47 +01:00 committed by GitHub
parent a407004391
commit 55e498058f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 36 additions and 4 deletions

View File

@ -1,11 +1,12 @@
# Tests the attempted automatic coercion of the C locale to a UTF-8 locale # Tests the attempted automatic coercion of the C locale to a UTF-8 locale
import unittest
import locale import locale
import os import os
import shutil
import subprocess
import sys import sys
import sysconfig import sysconfig
import shutil import unittest
from collections import namedtuple from collections import namedtuple
from test import support from test import support
@ -25,6 +26,8 @@ EXPECTED_C_LOCALE_FS_ENCODING = "ascii"
# Set our expectation for the default locale used when none is specified # Set our expectation for the default locale used when none is specified
EXPECT_COERCION_IN_DEFAULT_LOCALE = True EXPECT_COERCION_IN_DEFAULT_LOCALE = True
TARGET_LOCALES = ["C.UTF-8", "C.utf8", "UTF-8"]
# Apply some platform dependent overrides # Apply some platform dependent overrides
if sys.platform.startswith("linux"): if sys.platform.startswith("linux"):
if support.is_android: if support.is_android:
@ -413,6 +416,27 @@ class LocaleCoercionTests(_LocaleHandlingTestCase):
expected_warnings=[LEGACY_LOCALE_WARNING], expected_warnings=[LEGACY_LOCALE_WARNING],
coercion_expected=False) coercion_expected=False)
def test_PYTHONCOERCECLOCALE_set_to_one(self):
# skip the test if the LC_CTYPE locale is C or coerced
old_loc = locale.setlocale(locale.LC_CTYPE, None)
self.addCleanup(locale.setlocale, locale.LC_CTYPE, old_loc)
loc = locale.setlocale(locale.LC_CTYPE, "")
if loc == "C":
self.skipTest("test requires LC_CTYPE locale different than C")
if loc in TARGET_LOCALES :
self.skipTest("coerced LC_CTYPE locale: %s" % loc)
# bpo-35336: PYTHONCOERCECLOCALE=1 must not coerce the LC_CTYPE locale
# if it's not equal to "C"
code = 'import locale; print(locale.setlocale(locale.LC_CTYPE, None))'
env = dict(os.environ, PYTHONCOERCECLOCALE='1')
cmd = subprocess.run([sys.executable, '-c', code],
stdout=subprocess.PIPE,
env=env,
text=True)
self.assertEqual(cmd.stdout.rstrip(), loc)
def test_main(): def test_main():
support.run_unittest( support.run_unittest(
LocaleConfigurationTests, LocaleConfigurationTests,

View File

@ -0,0 +1,2 @@
Fix PYTHONCOERCECLOCALE=1 environment variable: only coerce the C locale
if the LC_CTYPE locale is "C".

View File

@ -1061,11 +1061,17 @@ config_read_complex_options(_PyCoreConfig *config)
static void static void
config_init_locale(_PyCoreConfig *config) config_init_locale(_PyCoreConfig *config)
{ {
if (config->coerce_c_locale < 0) { /* Test also if coerce_c_locale equals 1: PYTHONCOERCECLOCALE=1 doesn't
imply that the C locale is always coerced. It is only coerced if
if the LC_CTYPE locale is "C". */
if (config->coerce_c_locale != 0) {
/* The C locale enables the C locale coercion (PEP 538) */ /* The C locale enables the C locale coercion (PEP 538) */
if (_Py_LegacyLocaleDetected()) { if (_Py_LegacyLocaleDetected()) {
config->coerce_c_locale = 1; config->coerce_c_locale = 1;
} }
else {
config->coerce_c_locale = 0;
}
} }
#ifndef MS_WINDOWS #ifndef MS_WINDOWS
@ -1394,7 +1400,7 @@ _PyCoreConfig_Read(_PyCoreConfig *config)
} }
} }
if (config->utf8_mode < 0 || config->coerce_c_locale < 0) { if (config->coerce_c_locale != 0 || config->utf8_mode < 0) {
config_init_locale(config); config_init_locale(config);
} }