mirror of https://github.com/python/cpython
Issue #4947: The write() method of sys.stdout and sys.stderr uses their
encoding and errors attributes instead of using utf-8 in strict mode, to get the same behaviour than the print statement.
This commit is contained in:
parent
7738e4b758
commit
caafd77060
|
@ -619,6 +619,39 @@ class StdoutTests(unittest.TestCase):
|
||||||
finally:
|
finally:
|
||||||
sys.stdout = save_stdout
|
sys.stdout = save_stdout
|
||||||
|
|
||||||
|
def test_unicode(self):
|
||||||
|
import subprocess
|
||||||
|
|
||||||
|
def get_message(encoding, *code):
|
||||||
|
code = '\n'.join(code)
|
||||||
|
env = os.environ.copy()
|
||||||
|
env['PYTHONIOENCODING'] = encoding
|
||||||
|
process = subprocess.Popen([sys.executable, "-c", code],
|
||||||
|
stdout=subprocess.PIPE, env=env)
|
||||||
|
stdout, stderr = process.communicate()
|
||||||
|
self.assertEqual(process.returncode, 0)
|
||||||
|
return stdout
|
||||||
|
|
||||||
|
def check_message(text, encoding, expected):
|
||||||
|
stdout = get_message(encoding,
|
||||||
|
"import sys",
|
||||||
|
"sys.stdout.write(%r)" % text,
|
||||||
|
"sys.stdout.flush()")
|
||||||
|
self.assertEqual(stdout, expected)
|
||||||
|
|
||||||
|
check_message(u'\u20ac\n', "iso-8859-15", "\xa4\n")
|
||||||
|
check_message(u'\u20ac\n', "utf-16-le", '\xac\x20\n\x00')
|
||||||
|
check_message(u'15\u20ac\n', "iso-8859-1:ignore", "15\n")
|
||||||
|
check_message(u'15\u20ac\n', "iso-8859-1:replace", "15?\n")
|
||||||
|
check_message(u'15\u20ac\n', "iso-8859-1:backslashreplace",
|
||||||
|
"15\\u20ac\n")
|
||||||
|
|
||||||
|
for objtype in ('buffer', 'bytearray'):
|
||||||
|
stdout = get_message('ascii',
|
||||||
|
'import sys',
|
||||||
|
r'sys.stdout.write(%s("\xe9\n"))' % objtype)
|
||||||
|
self.assertEqual(stdout, "\xe9\n")
|
||||||
|
|
||||||
|
|
||||||
def test_main():
|
def test_main():
|
||||||
# Historically, these tests have been sloppy about removing TESTFN.
|
# Historically, these tests have been sloppy about removing TESTFN.
|
||||||
|
|
|
@ -12,6 +12,10 @@ What's New in Python 2.7.1?
|
||||||
Core and Builtins
|
Core and Builtins
|
||||||
-----------------
|
-----------------
|
||||||
|
|
||||||
|
- Issue #4947: The write() method of sys.stdout and sys.stderr uses their
|
||||||
|
encoding and errors attributes instead of using utf-8 in strict mode, to get
|
||||||
|
the same behaviour than the print statement.
|
||||||
|
|
||||||
- Issue #9737: Fix a crash when trying to delete a slice or an item from
|
- Issue #9737: Fix a crash when trying to delete a slice or an item from
|
||||||
a memoryview object.
|
a memoryview object.
|
||||||
|
|
||||||
|
|
|
@ -1735,8 +1735,10 @@ static PyObject *
|
||||||
file_write(PyFileObject *f, PyObject *args)
|
file_write(PyFileObject *f, PyObject *args)
|
||||||
{
|
{
|
||||||
Py_buffer pbuf;
|
Py_buffer pbuf;
|
||||||
char *s;
|
const char *s;
|
||||||
Py_ssize_t n, n2;
|
Py_ssize_t n, n2;
|
||||||
|
PyObject *encoded = NULL;
|
||||||
|
|
||||||
if (f->f_fp == NULL)
|
if (f->f_fp == NULL)
|
||||||
return err_closed();
|
return err_closed();
|
||||||
if (!f->writable)
|
if (!f->writable)
|
||||||
|
@ -1746,14 +1748,41 @@ file_write(PyFileObject *f, PyObject *args)
|
||||||
return NULL;
|
return NULL;
|
||||||
s = pbuf.buf;
|
s = pbuf.buf;
|
||||||
n = pbuf.len;
|
n = pbuf.len;
|
||||||
} else
|
}
|
||||||
if (!PyArg_ParseTuple(args, "t#", &s, &n))
|
else {
|
||||||
return NULL;
|
const char *encoding, *errors;
|
||||||
|
PyObject *text;
|
||||||
|
if (!PyArg_ParseTuple(args, "O", &text))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
if (PyString_Check(text)) {
|
||||||
|
s = PyString_AS_STRING(text);
|
||||||
|
n = PyString_GET_SIZE(text);
|
||||||
|
} else if (PyUnicode_Check(text)) {
|
||||||
|
if (f->f_encoding != Py_None)
|
||||||
|
encoding = PyString_AS_STRING(f->f_encoding);
|
||||||
|
else
|
||||||
|
encoding = PyUnicode_GetDefaultEncoding();
|
||||||
|
if (f->f_errors != Py_None)
|
||||||
|
errors = PyString_AS_STRING(f->f_errors);
|
||||||
|
else
|
||||||
|
errors = "strict";
|
||||||
|
encoded = PyUnicode_AsEncodedString(text, encoding, errors);
|
||||||
|
if (encoded == NULL)
|
||||||
|
return NULL;
|
||||||
|
s = PyString_AS_STRING(encoded);
|
||||||
|
n = PyString_GET_SIZE(encoded);
|
||||||
|
} else {
|
||||||
|
if (PyObject_AsCharBuffer(text, &s, &n))
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
f->f_softspace = 0;
|
f->f_softspace = 0;
|
||||||
FILE_BEGIN_ALLOW_THREADS(f)
|
FILE_BEGIN_ALLOW_THREADS(f)
|
||||||
errno = 0;
|
errno = 0;
|
||||||
n2 = fwrite(s, 1, n, f->f_fp);
|
n2 = fwrite(s, 1, n, f->f_fp);
|
||||||
FILE_END_ALLOW_THREADS(f)
|
FILE_END_ALLOW_THREADS(f)
|
||||||
|
Py_XDECREF(encoded);
|
||||||
if (f->f_binary)
|
if (f->f_binary)
|
||||||
PyBuffer_Release(&pbuf);
|
PyBuffer_Release(&pbuf);
|
||||||
if (n2 != n) {
|
if (n2 != n) {
|
||||||
|
|
Loading…
Reference in New Issue