[Python-checkins] r74157 - in python/branches/py3k: Lib/_pyio.py Lib/test/test_memoryio.py Modules/_io/stringio.c

alexandre.vassalotti python-checkins at python.org
Wed Jul 22 05:07:33 CEST 2009


Author: alexandre.vassalotti
Date: Wed Jul 22 05:07:33 2009
New Revision: 74157

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


Modified:
   python/branches/py3k/Lib/_pyio.py
   python/branches/py3k/Lib/test/test_memoryio.py
   python/branches/py3k/Modules/_io/stringio.c

Modified: python/branches/py3k/Lib/_pyio.py
==============================================================================
--- python/branches/py3k/Lib/_pyio.py	(original)
+++ python/branches/py3k/Lib/_pyio.py	Wed Jul 22 05:07:33 2009
@@ -1924,8 +1924,10 @@
         # 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)

Modified: python/branches/py3k/Lib/test/test_memoryio.py
==============================================================================
--- python/branches/py3k/Lib/test/test_memoryio.py	(original)
+++ python/branches/py3k/Lib/test/test_memoryio.py	Wed Jul 22 05:07:33 2009
@@ -140,6 +140,7 @@
         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 @@
         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

Modified: python/branches/py3k/Modules/_io/stringio.c
==============================================================================
--- python/branches/py3k/Modules/_io/stringio.c	(original)
+++ python/branches/py3k/Modules/_io/stringio.c	Wed Jul 22 05:07:33 2009
@@ -550,22 +550,42 @@
 {
     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 @@
     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)


More information about the Python-checkins mailing list