Merged revisions 73776 via svnmerge from

svn+ssh://pythondev@svn.python.org/python/trunk

........
  r73776 | benjamin.peterson | 2009-07-02 13:16:45 -0500 (Thu, 02 Jul 2009) | 1 line

  when print() gets unicode arguments, sep and end should be unicode by default #4618
........
This commit is contained in:
Benjamin Peterson 2009-07-02 18:19:47 +00:00
parent f921469383
commit 7d6b01417f
3 changed files with 107 additions and 25 deletions

View File

@ -9,12 +9,7 @@ import unittest
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 @@ class TestPrint(unittest.TestCase):
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)

View File

@ -15,6 +15,9 @@ Core and Builtins
- Issue #4547: When debugging a very large function, it was not always
possible to update the lineno attribute of the current frame.
- 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.

View File

@ -1556,14 +1556,40 @@ static PyObject *
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 @@ builtin_print(PyObject *self, PyObject *args, PyObject *kwds)
if (file == Py_None)
Py_RETURN_NONE;
}
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 (sep == Py_None) {
sep = NULL;
}
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;
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 (!use_unicode) {
for (i = 0; i < PyTuple_Size(args); i++) {
if (PyUnicode_Check(PyTuple_GET_ITEM(args, i))) {
use_unicode = 1;
break;
}
}
}
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 @@ builtin_print(PyObject *self, PyObject *args, PyObject *kwds)
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)