Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 7143029

Browse files
committed
Issue #19977: When the LC_TYPE locale is the POSIX locale (C locale),
:py:data:`sys.stdin` and :py:data:`sys.stdout` are now using the ``surrogateescape`` error handler, instead of the ``strict`` error handler.
1 parent 01adf06 commit 7143029

4 files changed

Lines changed: 62 additions & 2 deletions

File tree

Doc/whatsnew/3.5.rst

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,10 @@ New built-in features:
7979

8080
Implementation improvements:
8181

82-
* None yet.
82+
* When the ``LC_TYPE`` locale is the POSIX locale (``C`` locale),
83+
:py:data:`sys.stdin` and :py:data:`sys.stdout` are now using the
84+
``surrogateescape`` error handler, instead of the ``strict`` error handler
85+
(:issue:`19977`).
8386

8487
Significantly Improved Library Modules:
8588

Lib/test/test_sys.py

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -615,6 +615,50 @@ def test_getfilesystemencoding(self):
615615
expected = None
616616
self.check_fsencoding(fs_encoding, expected)
617617

618+
@unittest.skipIf(sys.platform == 'win32',
619+
'test specific to UNIX')
620+
def test_c_locale_surrogateescape(self):
621+
# Force the POSIX locale
622+
env = os.environ.copy()
623+
env["LC_ALL"] = "C"
624+
code = '\n'.join((
625+
'import codecs, sys',
626+
'def dump(name):',
627+
' std = getattr(sys, name)',
628+
' encoding = codecs.lookup(std.encoding).name',
629+
' print("%s: %s:%s" % (name, encoding, std.errors))',
630+
'dump("stdin")',
631+
'dump("stdout")',
632+
'dump("stderr")',
633+
))
634+
p = subprocess.Popen([sys.executable, "-I", "-c", code],
635+
stdout=subprocess.PIPE, env=env)
636+
out = p.communicate()[0]
637+
self.assertEqual(out,
638+
b'stdin: ascii:surrogateescape\n'
639+
b'stdout: ascii:surrogateescape\n'
640+
b'stderr: ascii:backslashreplace\n')
641+
642+
# replace the default error handler
643+
env['PYTHONIOENCODING'] = ':strict'
644+
p = subprocess.Popen([sys.executable, "-c", code],
645+
stdout=subprocess.PIPE, env=env)
646+
out = p.communicate()[0]
647+
self.assertEqual(out,
648+
b'stdin: ascii:strict\n'
649+
b'stdout: ascii:strict\n'
650+
b'stderr: ascii:backslashreplace\n')
651+
652+
# force the encoding
653+
env['PYTHONIOENCODING'] = 'iso8859-1'
654+
p = subprocess.Popen([sys.executable, "-c", code],
655+
stdout=subprocess.PIPE, env=env)
656+
out = p.communicate()[0]
657+
self.assertEqual(out,
658+
b'stdin: iso8859-1:surrogateescape\n'
659+
b'stdout: iso8859-1:surrogateescape\n'
660+
b'stderr: iso8859-1:backslashreplace\n')
661+
618662
def test_implementation(self):
619663
# This test applies to all implementations equally.
620664

Misc/NEWS

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,10 @@ Core and Builtins
1313
Library
1414
-------
1515

16+
- Issue #19977: When the ``LC_TYPE`` locale is the POSIX locale (``C`` locale),
17+
:py:data:`sys.stdin` and :py:data:`sys.stdout` are now using the
18+
``surrogateescape`` error handler, instead of the ``strict`` error handler.
19+
1620
- Issue #20574: Implement incremental decoder for cp65001 code (Windows code
1721
page 65001, Microsoft UTF-8).
1822

Python/pythonrun.c

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1156,6 +1156,15 @@ initstdio(void)
11561156
encoding = _Py_StandardStreamEncoding;
11571157
errors = _Py_StandardStreamErrors;
11581158
if (!encoding || !errors) {
1159+
if (!errors) {
1160+
/* When the LC_CTYPE locale is the POSIX locale ("C locale"),
1161+
stdin and stdout use the surrogateescape error handler by
1162+
default, instead of the strict error handler. */
1163+
char *loc = setlocale(LC_CTYPE, NULL);
1164+
if (loc != NULL && strcmp(loc, "C") == 0)
1165+
errors = "surrogateescape";
1166+
}
1167+
11591168
pythonioencoding = Py_GETENV("PYTHONIOENCODING");
11601169
if (pythonioencoding) {
11611170
char *err;
@@ -1168,7 +1177,7 @@ initstdio(void)
11681177
if (err) {
11691178
*err = '\0';
11701179
err++;
1171-
if (*err && !errors) {
1180+
if (*err && !_Py_StandardStreamErrors) {
11721181
errors = err;
11731182
}
11741183
}

0 commit comments

Comments
 (0)