[Python-checkins] r73776 - in python/trunk: Lib/test/test_print.py Misc/NEWS Python/bltinmodule.c

benjamin.peterson python-checkins at python.org
Thu Jul 2 20:16:46 CEST 2009


Author: benjamin.peterson
Date: Thu Jul  2 20:16:45 2009
New Revision: 73776

Log:
when print() gets unicode arguments, sep and end should be unicode by default #4618

Modified:
   python/trunk/Lib/test/test_print.py
   python/trunk/Misc/NEWS
   python/trunk/Python/bltinmodule.c

Modified: python/trunk/Lib/test/test_print.py
==============================================================================
--- python/trunk/Lib/test/test_print.py	(original)
+++ python/trunk/Lib/test/test_print.py	Thu Jul  2 20:16:45 2009
@@ -9,12 +9,7 @@
 from test import test_support
 
 import sys
-if sys.version_info[0] == 3:
-    # 3.x
-    from io import StringIO
-else:
-    # 2.x
-    from StringIO import StringIO
+from StringIO import StringIO
 
 NotDefined = object()
 
@@ -112,6 +107,34 @@
         self.assertRaises(TypeError, print, '', end=3)
         self.assertRaises(AttributeError, print, '', file='')
 
+    def test_mixed_args(self):
+        # If an unicode arg is passed, sep and end should be unicode, too.
+        class Recorder(object):
+
+            def __init__(self, must_be_unicode):
+                self.buf = []
+                self.force_unicode = must_be_unicode
+
+            def write(self, what):
+                if self.force_unicode and not isinstance(what, unicode):
+                    raise AssertionError("{0!r} is not unicode".format(what))
+                self.buf.append(what)
+
+        buf = Recorder(True)
+        print(u'hi', file=buf)
+        self.assertEqual(u''.join(buf.buf), 'hi\n')
+        del buf.buf[:]
+        print(u'hi', u'nothing', file=buf)
+        self.assertEqual(u''.join(buf.buf), 'hi nothing\n')
+        buf = Recorder(False)
+        print('hi', 'bye', end=u'\n', file=buf)
+        self.assertTrue(isinstance(buf.buf[1], unicode))
+        self.assertTrue(isinstance(buf.buf[3], unicode))
+        del buf.buf[:]
+        print(sep=u'x', file=buf)
+        self.assertTrue(isinstance(buf.buf[-1], unicode))
+
+
 def test_main():
     test_support.run_unittest(TestPrint)
 

Modified: python/trunk/Misc/NEWS
==============================================================================
--- python/trunk/Misc/NEWS	(original)
+++ python/trunk/Misc/NEWS	Thu Jul  2 20:16:45 2009
@@ -12,6 +12,9 @@
 Core and Builtins
 -----------------
 
+- Issue #4618: When unicode arguments are passed to print(), the default
+  separator and end should be unicode also.
+
 - Issue #6119: Fixed a incorrect Py3k warning about order comparisons of builtin
   functions and methods.
 

Modified: python/trunk/Python/bltinmodule.c
==============================================================================
--- python/trunk/Python/bltinmodule.c	(original)
+++ python/trunk/Python/bltinmodule.c	Thu Jul  2 20:16:45 2009
@@ -1556,14 +1556,40 @@
 builtin_print(PyObject *self, PyObject *args, PyObject *kwds)
 {
 	static char *kwlist[] = {"sep", "end", "file", 0};
-	static PyObject *dummy_args;
+	static PyObject *dummy_args = NULL;
+	static PyObject *unicode_newline = NULL, *unicode_space = NULL;
+	static PyObject *str_newline = NULL, *str_space = NULL;
+	PyObject *newline, *space;
 	PyObject *sep = NULL, *end = NULL, *file = NULL;
-	int i, err;
+	int i, err, use_unicode = 0;
 
 	if (dummy_args == NULL) {
 		if (!(dummy_args = PyTuple_New(0)))
 			return NULL;
 	}
+	if (str_newline == NULL) {
+		str_newline = PyString_FromString("\n");
+		if (str_newline == NULL)
+			return NULL;
+		str_space = PyString_FromString(" ");
+		if (str_space == NULL) {
+			Py_CLEAR(str_newline);
+			return NULL;
+		}
+		unicode_newline = PyUnicode_FromString("\n");
+		if (unicode_newline == NULL) {
+			Py_CLEAR(str_newline);
+			Py_CLEAR(str_space);
+			return NULL;
+		}
+		unicode_space = PyUnicode_FromString(" ");
+		if (unicode_space == NULL) {
+			Py_CLEAR(str_newline);
+			Py_CLEAR(str_space);
+			Py_CLEAR(unicode_space);
+			return NULL;
+		}
+	}
 	if (!PyArg_ParseTupleAndKeywords(dummy_args, kwds, "|OOO:print",
 					 kwlist, &sep, &end, &file))
 		return NULL;
@@ -1573,26 +1599,56 @@
 		if (file == Py_None)
 			Py_RETURN_NONE;
 	}
+	if (sep == Py_None) {
+		sep = NULL;
+	}
+	else if (sep) {
+		if (PyUnicode_Check(sep)) {
+			use_unicode = 1;
+		}
+		else if (!PyString_Check(sep)) {
+			PyErr_Format(PyExc_TypeError,
+				     "sep must be None, str or unicode, not %.200s",
+				     sep->ob_type->tp_name);
+			return NULL;
+		}
+	}
+	if (end == Py_None)
+		end = NULL;
+	else if (end) {
+		if (PyUnicode_Check(end)) {
+			use_unicode = 1;
+		}
+		else if (!PyString_Check(end)) {
+			PyErr_Format(PyExc_TypeError,
+				     "end must be None, str or unicode, not %.200s",
+				     end->ob_type->tp_name);
+			return NULL;
+		}
+	}
 
-	if (sep && sep != Py_None && !PyString_Check(sep) &&
-            !PyUnicode_Check(sep)) {
-		PyErr_Format(PyExc_TypeError,
-			     "sep must be None, str or unicode, not %.200s",
-			     sep->ob_type->tp_name);
-		return NULL;
+	if (!use_unicode) {
+		for (i = 0; i < PyTuple_Size(args); i++) {
+			if (PyUnicode_Check(PyTuple_GET_ITEM(args, i))) {
+				use_unicode = 1;
+				break;
+			}
+		}
 	}
-	if (end && end != Py_None && !PyString_Check(end) &&
-	    !PyUnicode_Check(end)) {
-		PyErr_Format(PyExc_TypeError,
-			     "end must be None, str or unicode, not %.200s",
-			     end->ob_type->tp_name);
-		return NULL;
+	if (use_unicode) {
+		newline = unicode_newline;
+		space = unicode_space;
+	}
+	else {
+		newline = str_newline;
+		space = str_space;
 	}
 
 	for (i = 0; i < PyTuple_Size(args); i++) {
 		if (i > 0) {
-			if (sep == NULL || sep == Py_None)
-				err = PyFile_WriteString(" ", file);
+			if (sep == NULL)
+				err = PyFile_WriteObject(space, file,
+							 Py_PRINT_RAW);
 			else
 				err = PyFile_WriteObject(sep, file,
 							 Py_PRINT_RAW);
@@ -1605,8 +1661,8 @@
 			return NULL;
 	}
 
-	if (end == NULL || end == Py_None)
-		err = PyFile_WriteString("\n", file);
+	if (end == NULL)
+		err = PyFile_WriteObject(newline, file, Py_PRINT_RAW);
 	else
 		err = PyFile_WriteObject(end, file, Py_PRINT_RAW);
 	if (err)


More information about the Python-checkins mailing list