mirror of
https://github.com/python/cpython.git
synced 2025-10-17 04:08:28 +00:00
Issue #6241: Better type checking for the arguments of io.StringIO.
This commit is contained in:
parent
e671fd206b
commit
d2bb18b281
3 changed files with 38 additions and 5 deletions
|
@ -1924,8 +1924,10 @@ class StringIO(TextIOWrapper):
|
||||||
# C version, even under Windows.
|
# C version, even under Windows.
|
||||||
if newline is None:
|
if newline is None:
|
||||||
self._writetranslate = False
|
self._writetranslate = False
|
||||||
if initial_value:
|
if initial_value is not None:
|
||||||
if not isinstance(initial_value, str):
|
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)
|
initial_value = str(initial_value)
|
||||||
self.write(initial_value)
|
self.write(initial_value)
|
||||||
self.seek(0)
|
self.seek(0)
|
||||||
|
|
|
@ -140,6 +140,7 @@ class MemoryTestMixin:
|
||||||
self.assertEqual(memio.getvalue(), buf * 2)
|
self.assertEqual(memio.getvalue(), buf * 2)
|
||||||
memio.__init__(buf)
|
memio.__init__(buf)
|
||||||
self.assertEqual(memio.getvalue(), buf)
|
self.assertEqual(memio.getvalue(), buf)
|
||||||
|
self.assertRaises(TypeError, memio.__init__, [])
|
||||||
|
|
||||||
def test_read(self):
|
def test_read(self):
|
||||||
buf = self.buftype("1234567890")
|
buf = self.buftype("1234567890")
|
||||||
|
@ -530,6 +531,13 @@ class PyStringIOTest(MemoryTestMixin, MemorySeekTestMixin, unittest.TestCase):
|
||||||
memio = self.ioclass("a\r\nb\r\n", newline=None)
|
memio = self.ioclass("a\r\nb\r\n", newline=None)
|
||||||
self.assertEqual(memio.read(5), "a\nb\n")
|
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):
|
class CBytesIOTest(PyBytesIOTest):
|
||||||
ioclass = io.BytesIO
|
ioclass = io.BytesIO
|
||||||
|
|
|
@ -550,22 +550,42 @@ stringio_init(stringio *self, PyObject *args, PyObject *kwds)
|
||||||
{
|
{
|
||||||
char *kwlist[] = {"initial_value", "newline", NULL};
|
char *kwlist[] = {"initial_value", "newline", NULL};
|
||||||
PyObject *value = NULL;
|
PyObject *value = NULL;
|
||||||
|
PyObject *newline_obj = NULL;
|
||||||
char *newline = "\n";
|
char *newline = "\n";
|
||||||
|
|
||||||
if (!PyArg_ParseTupleAndKeywords(args, kwds, "|Oz:__init__", kwlist,
|
if (!PyArg_ParseTupleAndKeywords(args, kwds, "|OO:__init__", kwlist,
|
||||||
&value, &newline))
|
&value, &newline_obj))
|
||||||
return -1;
|
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'
|
if (newline && newline[0] != '\0'
|
||||||
&& !(newline[0] == '\n' && newline[1] == '\0')
|
&& !(newline[0] == '\n' && newline[1] == '\0')
|
||||||
&& !(newline[0] == '\r' && newline[1] == '\0')
|
&& !(newline[0] == '\r' && newline[1] == '\0')
|
||||||
&& !(newline[0] == '\r' && newline[1] == '\n' && newline[2] == '\0')) {
|
&& !(newline[0] == '\r' && newline[1] == '\n' && newline[2] == '\0')) {
|
||||||
PyErr_Format(PyExc_ValueError,
|
PyErr_Format(PyExc_ValueError,
|
||||||
"illegal newline value: %s", newline);
|
"illegal newline value: %R", newline_obj);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
if (value && value != Py_None && !PyUnicode_Check(value)) {
|
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",
|
"initial_value must be str or None, not %.200s",
|
||||||
Py_TYPE(value)->tp_name);
|
Py_TYPE(value)->tp_name);
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -577,6 +597,9 @@ stringio_init(stringio *self, PyObject *args, PyObject *kwds)
|
||||||
Py_CLEAR(self->writenl);
|
Py_CLEAR(self->writenl);
|
||||||
Py_CLEAR(self->decoder);
|
Py_CLEAR(self->decoder);
|
||||||
|
|
||||||
|
assert((newline != NULL && newline_obj != Py_None) ||
|
||||||
|
(newline == NULL && newline_obj == Py_None));
|
||||||
|
|
||||||
if (newline) {
|
if (newline) {
|
||||||
self->readnl = PyUnicode_FromString(newline);
|
self->readnl = PyUnicode_FromString(newline);
|
||||||
if (self->readnl == NULL)
|
if (self->readnl == NULL)
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue