[Python-checkins] r84621 - in python/branches/release27-maint: Lib/test/test_file2k.py Misc/NEWS Objects/fileobject.c

victor.stinner python-checkins at python.org
Wed Sep 8 12:51:01 CEST 2010


Author: victor.stinner
Date: Wed Sep 8 12:51:01 2010
New Revision: 84621
Log:
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.
Modified:
 python/branches/release27-maint/Lib/test/test_file2k.py
 python/branches/release27-maint/Misc/NEWS
 python/branches/release27-maint/Objects/fileobject.c
Modified: python/branches/release27-maint/Lib/test/test_file2k.py
==============================================================================
--- python/branches/release27-maint/Lib/test/test_file2k.py	(original)
+++ python/branches/release27-maint/Lib/test/test_file2k.py	Wed Sep 8 12:51:01 2010
@@ -619,6 +619,39 @@
 finally:
 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():
 # Historically, these tests have been sloppy about removing TESTFN.
Modified: python/branches/release27-maint/Misc/NEWS
==============================================================================
--- python/branches/release27-maint/Misc/NEWS	(original)
+++ python/branches/release27-maint/Misc/NEWS	Wed Sep 8 12:51:01 2010
@@ -12,6 +12,10 @@
 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
 a memoryview object.
 
@@ -63,7 +67,7 @@
 - Issue #8750: Fixed MutableSet's methods to correctly handle
 reflexive operations, namely x -= x and x ^= x.
 
-- Issue #9129: smtpd.py is vulnerable to DoS attacks deriving from missing 
+- Issue #9129: smtpd.py is vulnerable to DoS attacks deriving from missing
 error handling when accepting a new connection.
 
 - Issue #658749: asyncore's connect() method now correctly interprets winsock
Modified: python/branches/release27-maint/Objects/fileobject.c
==============================================================================
--- python/branches/release27-maint/Objects/fileobject.c	(original)
+++ python/branches/release27-maint/Objects/fileobject.c	Wed Sep 8 12:51:01 2010
@@ -1735,8 +1735,10 @@
 file_write(PyFileObject *f, PyObject *args)
 {
 Py_buffer pbuf;
- char *s;
+ const char *s;
 Py_ssize_t n, n2;
+ PyObject *encoded = NULL;
+
 if (f->f_fp == NULL)
 return err_closed();
 if (!f->writable)
@@ -1746,14 +1748,41 @@
 return NULL;
 s = pbuf.buf;
 n = pbuf.len;
- } else
- if (!PyArg_ParseTuple(args, "t#", &s, &n))
- return NULL;
+ }
+ else {
+ 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;
 FILE_BEGIN_ALLOW_THREADS(f)
 errno = 0;
 n2 = fwrite(s, 1, n, f->f_fp);
 FILE_END_ALLOW_THREADS(f)
+ Py_XDECREF(encoded);
 if (f->f_binary)
 PyBuffer_Release(&pbuf);
 if (n2 != n) {


More information about the Python-checkins mailing list

AltStyle によって変換されたページ (->オリジナル) /