Update the PEP 538 backport

This commit is contained in:
Charalampos Stratakis 2017-07-18 16:48:45 +02:00
parent 4ff21139d7
commit f13050e2f3
1 changed files with 43 additions and 23 deletions

View File

@ -124,13 +124,14 @@ index ca5f9c2..7aa460b 100644
def assert_python_ok(*args, **env_vars): def assert_python_ok(*args, **env_vars):
diff --git a/Lib/test/test_c_locale_coercion.py b/Lib/test/test_c_locale_coercion.py diff --git a/Lib/test/test_c_locale_coercion.py b/Lib/test/test_c_locale_coercion.py
new file mode 100644 new file mode 100644
index 0000000..a4b4626 index 0000000..635c98f
--- /dev/null --- /dev/null
+++ b/Lib/test/test_c_locale_coercion.py +++ b/Lib/test/test_c_locale_coercion.py
@@ -0,0 +1,353 @@ @@ -0,0 +1,371 @@
+# 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 unittest
+import locale
+import os +import os
+import sys +import sys
+import sysconfig +import sysconfig
@ -146,7 +147,14 @@ index 0000000..a4b4626
+ +
+# Set our expectation for the default encoding used in the C locale +# Set our expectation for the default encoding used in the C locale
+# for the filesystem encoding and the standard streams +# for the filesystem encoding and the standard streams
+C_LOCALE_STREAM_ENCODING = "ascii" +
+# AIX uses iso8859-1 in the C locale, other *nix platforms use ASCII
+if sys.platform.startswith("aix"):
+ C_LOCALE_STREAM_ENCODING = "iso8859-1"
+else:
+ C_LOCALE_STREAM_ENCODING = "ascii"
+
+# FS encoding is UTF-8 on macOS, other *nix platforms use the locale encoding
+if sys.platform == "darwin": +if sys.platform == "darwin":
+ C_LOCALE_FS_ENCODING = "utf-8" + C_LOCALE_FS_ENCODING = "utf-8"
+else: +else:
@ -162,24 +170,34 @@ index 0000000..a4b4626
+ +
+# In order to get the warning messages to match up as expected, the candidate +# In order to get the warning messages to match up as expected, the candidate
+# order here must much the target locale order in Python/pylifecycle.c +# order here must much the target locale order in Python/pylifecycle.c
+_C_UTF8_LOCALES = ("C.UTF-8", "C.utf8") #, "UTF-8") +_C_UTF8_LOCALES = ("C.UTF-8", "C.utf8", "UTF-8")
+
+# XXX (ncoghlan): Using UTF-8 as a target locale is currently disabled due to
+# problems encountered on *BSD systems with those test cases
+# For additional details see:
+# nl_langinfo CODESET error: https://bugs.python.org/issue30647
+# locale handling differences: https://bugs.python.org/issue30672
+ +
+# There's no reliable cross-platform way of checking locale alias +# There's no reliable cross-platform way of checking locale alias
+# lists, so the only way of knowing which of these locales will work +# lists, so the only way of knowing which of these locales will work
+# is to try them with locale.setlocale(). We do that in a subprocess +# is to try them with locale.setlocale(). We do that in a subprocess
+# to avoid altering the locale of the test runner. +# to avoid altering the locale of the test runner.
+#
+# If the relevant locale module attributes exist, and we're not on a platform
+# where we expect it to always succeed, we also check that
+# `locale.nl_langinfo(locale.CODESET)` works, as if it fails, the interpreter
+# will skip locale coercion for that particular target locale
+_check_nl_langinfo_CODESET = bool(
+ sys.platform not in ("darwin", "linux") and
+ hasattr(locale, "nl_langinfo") and
+ hasattr(locale, "CODESET")
+)
+
+def _set_locale_in_subprocess(locale_name): +def _set_locale_in_subprocess(locale_name):
+ cmd_fmt = "import locale; print(locale.setlocale(locale.LC_CTYPE, '{}'))" + cmd_fmt = "import locale; print(locale.setlocale(locale.LC_CTYPE, '{}'))"
+ if _check_nl_langinfo_CODESET:
+ # If there's no valid CODESET, we expect coercion to be skipped
+ cmd_fmt += "; import sys; sys.exit(not locale.nl_langinfo(locale.CODESET))"
+ cmd = cmd_fmt.format(locale_name) + cmd = cmd_fmt.format(locale_name)
+ result, py_cmd = run_python_until_end("-c", cmd, __isolated=True) + result, py_cmd = run_python_until_end("-c", cmd, __isolated=True)
+ return result.rc == 0 + return result.rc == 0
+ +
+
+
+_fields = "fsencoding stdin_info stdout_info stderr_info lang lc_ctype lc_all" +_fields = "fsencoding stdin_info stdout_info stderr_info lang lc_ctype lc_all"
+_EncodingDetails = namedtuple("EncodingDetails", _fields) +_EncodingDetails = namedtuple("EncodingDetails", _fields)
+ +
@ -695,7 +713,7 @@ index a7afbc7..03f8295 100644
for (i = 0; i < argc; i++) { for (i = 0; i < argc; i++) {
PyMem_RawFree(argv_copy2[i]); PyMem_RawFree(argv_copy2[i]);
diff --git a/Python/pylifecycle.c b/Python/pylifecycle.c diff --git a/Python/pylifecycle.c b/Python/pylifecycle.c
index a4f7f82..743d9b6 100644 index a4f7f82..3843297 100644
--- a/Python/pylifecycle.c --- a/Python/pylifecycle.c
+++ b/Python/pylifecycle.c +++ b/Python/pylifecycle.c
@@ -167,6 +167,7 @@ Py_SetStandardStreamEncoding(const char *encoding, const char *errors) @@ -167,6 +167,7 @@ Py_SetStandardStreamEncoding(const char *encoding, const char *errors)
@ -706,7 +724,7 @@ index a4f7f82..743d9b6 100644
/* Global initializations. Can be undone by Py_FinalizeEx(). Don't /* Global initializations. Can be undone by Py_FinalizeEx(). Don't
call this twice without an intervening Py_FinalizeEx() call. When call this twice without an intervening Py_FinalizeEx() call. When
initializations fail, a fatal error is issued and the function does initializations fail, a fatal error is issued and the function does
@@ -301,6 +302,181 @@ import_init(PyInterpreterState *interp, PyObject *sysmod) @@ -301,6 +302,183 @@ import_init(PyInterpreterState *interp, PyObject *sysmod)
} }
@ -779,18 +797,10 @@ index a4f7f82..743d9b6 100644
+static _LocaleCoercionTarget _TARGET_LOCALES[] = { +static _LocaleCoercionTarget _TARGET_LOCALES[] = {
+ {"C.UTF-8"}, + {"C.UTF-8"},
+ {"C.utf8"}, + {"C.utf8"},
+ /* {"UTF-8"}, */ + {"UTF-8"},
+ {NULL} + {NULL}
+}; +};
+ +
+/* XXX (ncoghlan): Using UTF-8 as a target locale is currently disabled due to
+ * problems encountered on *BSD systems with those test cases
+ * For additional details see:
+ * nl_langinfo CODESET error: https://bugs.python.org/issue30647
+ * locale handling differences: https://bugs.python.org/issue30672
+ */
+
+
+static char * +static char *
+get_default_standard_stream_error_handler(void) +get_default_standard_stream_error_handler(void)
+{ +{
@ -873,6 +883,16 @@ index a4f7f82..743d9b6 100644
+ const char *new_locale = setlocale(LC_CTYPE, + const char *new_locale = setlocale(LC_CTYPE,
+ target->locale_name); + target->locale_name);
+ if (new_locale != NULL) { + if (new_locale != NULL) {
+#if !defined(__APPLE__) && defined(HAVE_LANGINFO_H) && defined(CODESET)
+ /* Also ensure that nl_langinfo works in this locale */
+ char *codeset = nl_langinfo(CODESET);
+ if (!codeset || *codeset == '\0') {
+ /* CODESET is not set or empty, so skip coercion */
+ new_locale = NULL;
+ setlocale(LC_CTYPE, "");
+ continue;
+ }
+#endif
+ /* Successfully configured locale, so make it the default */ + /* Successfully configured locale, so make it the default */
+ _coerce_default_locale_settings(target); + _coerce_default_locale_settings(target);
+ return; + return;
@ -888,7 +908,7 @@ index a4f7f82..743d9b6 100644
void void
_Py_InitializeEx_Private(int install_sigs, int install_importlib) _Py_InitializeEx_Private(int install_sigs, int install_importlib)
{ {
@@ -315,11 +491,19 @@ _Py_InitializeEx_Private(int install_sigs, int install_importlib) @@ -315,11 +493,19 @@ _Py_InitializeEx_Private(int install_sigs, int install_importlib)
initialized = 1; initialized = 1;
_Py_Finalizing = NULL; _Py_Finalizing = NULL;
@ -909,7 +929,7 @@ index a4f7f82..743d9b6 100644
#endif #endif
if ((p = Py_GETENV("PYTHONDEBUG")) && *p != '\0') if ((p = Py_GETENV("PYTHONDEBUG")) && *p != '\0')
@@ -1242,12 +1426,8 @@ initstdio(void) @@ -1242,12 +1428,8 @@ initstdio(void)
} }
} }
if (!errors && !(pythonioencoding && *pythonioencoding)) { if (!errors && !(pythonioencoding && *pythonioencoding)) {