mirror of
https://github.com/python/cpython.git
synced 2025-07-29 06:05:00 +00:00
when print() gets unicode arguments, sep and end should be unicode by default #4618
This commit is contained in:
parent
1bf4765369
commit
753d16234f
3 changed files with 107 additions and 25 deletions
|
@ -9,12 +9,7 @@ import unittest
|
||||||
from test import test_support
|
from test import test_support
|
||||||
|
|
||||||
import sys
|
import sys
|
||||||
if sys.version_info[0] == 3:
|
from StringIO import StringIO
|
||||||
# 3.x
|
|
||||||
from io import StringIO
|
|
||||||
else:
|
|
||||||
# 2.x
|
|
||||||
from StringIO import StringIO
|
|
||||||
|
|
||||||
NotDefined = object()
|
NotDefined = object()
|
||||||
|
|
||||||
|
@ -112,6 +107,34 @@ class TestPrint(unittest.TestCase):
|
||||||
self.assertRaises(TypeError, print, '', end=3)
|
self.assertRaises(TypeError, print, '', end=3)
|
||||||
self.assertRaises(AttributeError, print, '', file='')
|
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():
|
def test_main():
|
||||||
test_support.run_unittest(TestPrint)
|
test_support.run_unittest(TestPrint)
|
||||||
|
|
||||||
|
|
|
@ -12,6 +12,9 @@ What's New in Python 2.7 alpha 1
|
||||||
Core and Builtins
|
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
|
- Issue #6119: Fixed a incorrect Py3k warning about order comparisons of builtin
|
||||||
functions and methods.
|
functions and methods.
|
||||||
|
|
||||||
|
|
|
@ -1556,14 +1556,40 @@ static PyObject *
|
||||||
builtin_print(PyObject *self, PyObject *args, PyObject *kwds)
|
builtin_print(PyObject *self, PyObject *args, PyObject *kwds)
|
||||||
{
|
{
|
||||||
static char *kwlist[] = {"sep", "end", "file", 0};
|
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;
|
PyObject *sep = NULL, *end = NULL, *file = NULL;
|
||||||
int i, err;
|
int i, err, use_unicode = 0;
|
||||||
|
|
||||||
if (dummy_args == NULL) {
|
if (dummy_args == NULL) {
|
||||||
if (!(dummy_args = PyTuple_New(0)))
|
if (!(dummy_args = PyTuple_New(0)))
|
||||||
return NULL;
|
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",
|
if (!PyArg_ParseTupleAndKeywords(dummy_args, kwds, "|OOO:print",
|
||||||
kwlist, &sep, &end, &file))
|
kwlist, &sep, &end, &file))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
@ -1573,26 +1599,56 @@ builtin_print(PyObject *self, PyObject *args, PyObject *kwds)
|
||||||
if (file == Py_None)
|
if (file == Py_None)
|
||||||
Py_RETURN_NONE;
|
Py_RETURN_NONE;
|
||||||
}
|
}
|
||||||
|
if (sep == Py_None) {
|
||||||
if (sep && sep != Py_None && !PyString_Check(sep) &&
|
sep = NULL;
|
||||||
!PyUnicode_Check(sep)) {
|
|
||||||
PyErr_Format(PyExc_TypeError,
|
|
||||||
"sep must be None, str or unicode, not %.200s",
|
|
||||||
sep->ob_type->tp_name);
|
|
||||||
return NULL;
|
|
||||||
}
|
}
|
||||||
if (end && end != Py_None && !PyString_Check(end) &&
|
else if (sep) {
|
||||||
!PyUnicode_Check(end)) {
|
if (PyUnicode_Check(sep)) {
|
||||||
PyErr_Format(PyExc_TypeError,
|
use_unicode = 1;
|
||||||
"end must be None, str or unicode, not %.200s",
|
}
|
||||||
end->ob_type->tp_name);
|
else if (!PyString_Check(sep)) {
|
||||||
return NULL;
|
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++) {
|
for (i = 0; i < PyTuple_Size(args); i++) {
|
||||||
if (i > 0) {
|
if (i > 0) {
|
||||||
if (sep == NULL || sep == Py_None)
|
if (sep == NULL)
|
||||||
err = PyFile_WriteString(" ", file);
|
err = PyFile_WriteObject(space, file,
|
||||||
|
Py_PRINT_RAW);
|
||||||
else
|
else
|
||||||
err = PyFile_WriteObject(sep, file,
|
err = PyFile_WriteObject(sep, file,
|
||||||
Py_PRINT_RAW);
|
Py_PRINT_RAW);
|
||||||
|
@ -1605,8 +1661,8 @@ builtin_print(PyObject *self, PyObject *args, PyObject *kwds)
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (end == NULL || end == Py_None)
|
if (end == NULL)
|
||||||
err = PyFile_WriteString("\n", file);
|
err = PyFile_WriteObject(newline, file, Py_PRINT_RAW);
|
||||||
else
|
else
|
||||||
err = PyFile_WriteObject(end, file, Py_PRINT_RAW);
|
err = PyFile_WriteObject(end, file, Py_PRINT_RAW);
|
||||||
if (err)
|
if (err)
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue