Issue #25339: PYTHONIOENCODING now has priority over locale in setting the

error handler for stdin and stdout.
This commit is contained in:
Serhiy Storchaka 2016-04-10 14:34:13 +03:00
parent 731b1b12b8
commit fc43511867
3 changed files with 35 additions and 14 deletions

View file

@ -691,8 +691,10 @@ class SysModuleTest(unittest.TestCase):
args = [sys.executable, "-c", code] args = [sys.executable, "-c", code]
if isolated: if isolated:
args.append("-I") args.append("-I")
elif encoding: if encoding is not None:
env['PYTHONIOENCODING'] = encoding env['PYTHONIOENCODING'] = encoding
else:
env.pop('PYTHONIOENCODING', None)
p = subprocess.Popen(args, p = subprocess.Popen(args,
stdout=subprocess.PIPE, stdout=subprocess.PIPE,
stderr=subprocess.STDOUT, stderr=subprocess.STDOUT,
@ -709,14 +711,31 @@ class SysModuleTest(unittest.TestCase):
'stderr: backslashreplace\n') 'stderr: backslashreplace\n')
# replace the default error handler # replace the default error handler
out = self.c_locale_get_error_handler(encoding=':strict') out = self.c_locale_get_error_handler(encoding=':ignore')
self.assertEqual(out,
'stdin: ignore\n'
'stdout: ignore\n'
'stderr: backslashreplace\n')
# force the encoding
out = self.c_locale_get_error_handler(encoding='iso8859-1')
self.assertEqual(out,
'stdin: strict\n'
'stdout: strict\n'
'stderr: backslashreplace\n')
out = self.c_locale_get_error_handler(encoding='iso8859-1:')
self.assertEqual(out, self.assertEqual(out,
'stdin: strict\n' 'stdin: strict\n'
'stdout: strict\n' 'stdout: strict\n'
'stderr: backslashreplace\n') 'stderr: backslashreplace\n')
# force the encoding # have no any effect
out = self.c_locale_get_error_handler(encoding='iso8859-1') out = self.c_locale_get_error_handler(encoding=':')
self.assertEqual(out,
'stdin: surrogateescape\n'
'stdout: surrogateescape\n'
'stderr: backslashreplace\n')
out = self.c_locale_get_error_handler(encoding='')
self.assertEqual(out, self.assertEqual(out,
'stdin: surrogateescape\n' 'stdin: surrogateescape\n'
'stdout: surrogateescape\n' 'stdout: surrogateescape\n'

View file

@ -10,6 +10,9 @@ Release date: tba
Core and Builtins Core and Builtins
----------------- -----------------
- Issue #25339: PYTHONIOENCODING now has priority over locale in setting the
error handler for stdin and stdout.
- Issue #26494: Fixed crash on iterating exhausting iterators. - Issue #26494: Fixed crash on iterating exhausting iterators.
Affected classes are generic sequence iterators, iterators of str, bytes, Affected classes are generic sequence iterators, iterators of str, bytes,
bytearray, list, tuple, set, frozenset, dict, OrderedDict, corresponding bytearray, list, tuple, set, frozenset, dict, OrderedDict, corresponding

View file

@ -1135,15 +1135,6 @@ initstdio(void)
encoding = _Py_StandardStreamEncoding; encoding = _Py_StandardStreamEncoding;
errors = _Py_StandardStreamErrors; errors = _Py_StandardStreamErrors;
if (!encoding || !errors) { if (!encoding || !errors) {
if (!errors) {
/* When the LC_CTYPE locale is the POSIX locale ("C locale"),
stdin and stdout use the surrogateescape error handler by
default, instead of the strict error handler. */
char *loc = setlocale(LC_CTYPE, NULL);
if (loc != NULL && strcmp(loc, "C") == 0)
errors = "surrogateescape";
}
pythonioencoding = Py_GETENV("PYTHONIOENCODING"); pythonioencoding = Py_GETENV("PYTHONIOENCODING");
if (pythonioencoding) { if (pythonioencoding) {
char *err; char *err;
@ -1156,7 +1147,7 @@ initstdio(void)
if (err) { if (err) {
*err = '\0'; *err = '\0';
err++; err++;
if (*err && !_Py_StandardStreamErrors) { if (*err && !errors) {
errors = err; errors = err;
} }
} }
@ -1164,6 +1155,14 @@ initstdio(void)
encoding = pythonioencoding; encoding = pythonioencoding;
} }
} }
if (!errors && !(pythonioencoding && *pythonioencoding)) {
/* When the LC_CTYPE locale is the POSIX locale ("C locale"),
stdin and stdout use the surrogateescape error handler by
default, instead of the strict error handler. */
char *loc = setlocale(LC_CTYPE, NULL);
if (loc != NULL && strcmp(loc, "C") == 0)
errors = "surrogateescape";
}
} }
/* Set sys.stdin */ /* Set sys.stdin */