From: Victor Stinner Date: Fri, 30 Nov 2018 10:34:47 +0000 (+0100) Subject: bpo-35336: Fix PYTHONCOERCECLOCALE=1 (GH-10806) X-Git-Tag: v3.8.0a1~383 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=55e498058faf8c97840556f6d791c2c392732dc3;p=python bpo-35336: Fix PYTHONCOERCECLOCALE=1 (GH-10806) Fix PYTHONCOERCECLOCALE=1 environment variable: only coerce the C locale if the LC_CTYPE locale is "C". --- diff --git a/Lib/test/test_c_locale_coercion.py b/Lib/test/test_c_locale_coercion.py index ce8ac4eb84..35272b5c15 100644 --- a/Lib/test/test_c_locale_coercion.py +++ b/Lib/test/test_c_locale_coercion.py @@ -1,11 +1,12 @@ # Tests the attempted automatic coercion of the C locale to a UTF-8 locale -import unittest import locale import os +import shutil +import subprocess import sys import sysconfig -import shutil +import unittest from collections import namedtuple 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 EXPECT_COERCION_IN_DEFAULT_LOCALE = True +TARGET_LOCALES = ["C.UTF-8", "C.utf8", "UTF-8"] + # Apply some platform dependent overrides if sys.platform.startswith("linux"): if support.is_android: @@ -413,6 +416,27 @@ class LocaleCoercionTests(_LocaleHandlingTestCase): expected_warnings=[LEGACY_LOCALE_WARNING], 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(): support.run_unittest( LocaleConfigurationTests, diff --git a/Misc/NEWS.d/next/Core and Builtins/2018-11-29-23-59-52.bpo-35336.8LOz4F.rst b/Misc/NEWS.d/next/Core and Builtins/2018-11-29-23-59-52.bpo-35336.8LOz4F.rst new file mode 100644 index 0000000000..28f8f9bd4d --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2018-11-29-23-59-52.bpo-35336.8LOz4F.rst @@ -0,0 +1,2 @@ +Fix PYTHONCOERCECLOCALE=1 environment variable: only coerce the C locale +if the LC_CTYPE locale is "C". diff --git a/Python/coreconfig.c b/Python/coreconfig.c index ad22300e56..2fb4e3fd19 100644 --- a/Python/coreconfig.c +++ b/Python/coreconfig.c @@ -1061,11 +1061,17 @@ config_read_complex_options(_PyCoreConfig *config) static void 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) */ if (_Py_LegacyLocaleDetected()) { config->coerce_c_locale = 1; } + else { + config->coerce_c_locale = 0; + } } #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); }