Commit 55e49805 authored by Victor Stinner's avatar Victor Stinner Committed by GitHub

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

Fix PYTHONCOERCECLOCALE=1 environment variable: only coerce the C
locale if the LC_CTYPE locale is "C".
parent a4070043
# 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" ...@@ -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): ...@@ -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,
......
Fix PYTHONCOERCECLOCALE=1 environment variable: only coerce the C locale
if the LC_CTYPE locale is "C".
...@@ -1061,11 +1061,17 @@ config_read_complex_options(_PyCoreConfig *config) ...@@ -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) ...@@ -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);
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment