Issue #6241: Better type checking for the arguments of io.StringIO.

This commit is contained in:
Alexandre Vassalotti 2009-07-22 03:07:33 +00:00
parent e671fd206b
commit d2bb18b281
3 changed files with 38 additions and 5 deletions

View File

@ -1924,8 +1924,10 @@ class StringIO(TextIOWrapper):
# C version, even under Windows.
if newline is None:
self._writetranslate = False
if initial_value:
if initial_value is not None:
if not isinstance(initial_value, str):
raise TypeError("initial_value must be str or None, not {0}"
.format(type(initial_value).__name__))
initial_value = str(initial_value)
self.write(initial_value)
self.seek(0)

View File

@ -140,6 +140,7 @@ class MemoryTestMixin:
self.assertEqual(memio.getvalue(), buf * 2)
memio.__init__(buf)
self.assertEqual(memio.getvalue(), buf)
self.assertRaises(TypeError, memio.__init__, [])
def test_read(self):
buf = self.buftype("1234567890")
@ -530,6 +531,13 @@ class PyStringIOTest(MemoryTestMixin, MemorySeekTestMixin, unittest.TestCase):
memio = self.ioclass("a\r\nb\r\n", newline=None)
self.assertEqual(memio.read(5), "a\nb\n")
def test_newline_argument(self):
self.assertRaises(TypeError, self.ioclass, newline=b"\n")
self.assertRaises(ValueError, self.ioclass, newline="error")
# These should not raise an error
for newline in (None, "", "\n", "\r", "\r\n"):
self.ioclass(newline=newline)
class CBytesIOTest(PyBytesIOTest):
ioclass = io.BytesIO

View File

@ -550,22 +550,42 @@ stringio_init(stringio *self, PyObject *args, PyObject *kwds)
{
char *kwlist[] = {"initial_value", "newline", NULL};
PyObject *value = NULL;
PyObject *newline_obj = NULL;
char *newline = "\n";
if (!PyArg_ParseTupleAndKeywords(args, kwds, "|Oz:__init__", kwlist,
&value, &newline))
if (!PyArg_ParseTupleAndKeywords(args, kwds, "|OO:__init__", kwlist,
&value, &newline_obj))
return -1;
/* Parse the newline argument. This used to be done with the 'z'
specifier, however this allowed any object with the buffer interface to
be converted. Thus we have to parse it manually since we only want to
allow unicode objects or None. */
if (newline_obj == Py_None) {
newline = NULL;
}
else if (newline_obj) {
if (!PyUnicode_Check(newline_obj)) {
PyErr_Format(PyExc_TypeError,
"newline must be str or None, not %.200s",
Py_TYPE(newline_obj)->tp_name);
return -1;
}
newline = _PyUnicode_AsString(newline_obj);
if (newline == NULL)
return -1;
}
if (newline && newline[0] != '\0'
&& !(newline[0] == '\n' && newline[1] == '\0')
&& !(newline[0] == '\r' && newline[1] == '\0')
&& !(newline[0] == '\r' && newline[1] == '\n' && newline[2] == '\0')) {
PyErr_Format(PyExc_ValueError,
"illegal newline value: %s", newline);
"illegal newline value: %R", newline_obj);
return -1;
}
if (value && value != Py_None && !PyUnicode_Check(value)) {
PyErr_Format(PyExc_ValueError,
PyErr_Format(PyExc_TypeError,
"initial_value must be str or None, not %.200s",
Py_TYPE(value)->tp_name);
return -1;
@ -577,6 +597,9 @@ stringio_init(stringio *self, PyObject *args, PyObject *kwds)
Py_CLEAR(self->writenl);
Py_CLEAR(self->decoder);
assert((newline != NULL && newline_obj != Py_None) ||
(newline == NULL && newline_obj == Py_None));
if (newline) {
self->readnl = PyUnicode_FromString(newline);
if (self->readnl == NULL)