]> granicus.if.org Git - python/commitdiff
Merged revisions 76806,76808 via svnmerge from
authorBenjamin Peterson <benjamin@python.org>
Sun, 13 Dec 2009 19:30:15 +0000 (19:30 +0000)
committerBenjamin Peterson <benjamin@python.org>
Sun, 13 Dec 2009 19:30:15 +0000 (19:30 +0000)
svn+ssh://pythondev@svn.python.org/python/branches/py3k

................
  r76806 | benjamin.peterson | 2009-12-13 13:25:34 -0600 (Sun, 13 Dec 2009) | 14 lines

  Merged revisions 76805 via svnmerge from
  svn+ssh://pythondev@svn.python.org/python/trunk

  ........
    r76805 | benjamin.peterson | 2009-12-13 13:19:07 -0600 (Sun, 13 Dec 2009) | 7 lines

    accept None as the same as having passed no argument in file types #7349

    This is for consistency with imitation file objects like StringIO and BytesIO.

    This commit also adds a few tests, where they were lacking for concerned
    methods.
  ........
................
  r76808 | benjamin.peterson | 2009-12-13 13:28:09 -0600 (Sun, 13 Dec 2009) | 9 lines

  Merged revisions 76807 via svnmerge from
  svn+ssh://pythondev@svn.python.org/python/trunk

  ........
    r76807 | benjamin.peterson | 2009-12-13 13:27:02 -0600 (Sun, 13 Dec 2009) | 1 line

    remove unused variable
  ........
................

Lib/test/test_fileio.py
Lib/test/test_io.py
Misc/NEWS
Modules/_io/_iomodule.c
Modules/_io/_iomodule.h
Modules/_io/bufferedio.c
Modules/_io/fileio.c
Modules/_io/iobase.c
Modules/_io/textio.c

index 679ed088b325e55db7ea71096a31c9e408f332d8..d8f62253691f42ebd90392382a330dee45f63c01 100644 (file)
@@ -69,6 +69,15 @@ class AutoFileTests(unittest.TestCase):
         n = self.f.readinto(a)
         self.assertEquals(array('b', [1, 2]), a[:n])
 
+    def test_none_args(self):
+        self.f.write(b"hi\nbye\nabc")
+        self.f.close()
+        self.f = _FileIO(TESTFN, 'r')
+        self.assertEqual(self.f.read(None), b"hi\nbye\nabc")
+        self.f.seek(0)
+        self.assertEqual(self.f.readline(None), b"hi\n")
+        self.assertEqual(self.f.readlines(None), [b"bye\n", b"abc"])
+
     def testRepr(self):
         self.assertEquals(repr(self.f), "<_io.FileIO name=%r mode=%r>"
                                         % (self.f.name, self.f.mode))
index 150eff48bbc79efe566daa5c415a70aac8d79a94..2f76fed7fc2e401f70c4a0380c344f8ef65335c7 100644 (file)
@@ -336,7 +336,7 @@ class IOTest(unittest.TestCase):
             self.assertEqual(f.readline(2), b"xy")
             self.assertEqual(f.readline(4), b"zzy\n")
             self.assertEqual(f.readline(), b"foo\x00bar\n")
-            self.assertEqual(f.readline(), b"another line")
+            self.assertEqual(f.readline(None), b"another line")
             self.assertRaises(TypeError, f.readline, 5.3)
         with self.open(support.TESTFN, "r") as f:
             self.assertRaises(TypeError, f.readline, 5.3)
@@ -647,9 +647,10 @@ class BufferedReaderTest(unittest.TestCase, CommonBufferedTests):
         self.assertEquals(b"abc", bufio.read())
 
     def test_read(self):
-        rawio = self.MockRawIO((b"abc", b"d", b"efg"))
-        bufio = self.tp(rawio)
-        self.assertEquals(b"abcdef", bufio.read(6))
+        for arg in (None, 7):
+            rawio = self.MockRawIO((b"abc", b"d", b"efg"))
+            bufio = self.tp(rawio)
+            self.assertEquals(b"abcdefg", bufio.read(arg))
         # Invalid args
         self.assertRaises(ValueError, bufio.read, -2)
 
@@ -666,6 +667,7 @@ class BufferedReaderTest(unittest.TestCase, CommonBufferedTests):
         self.assertEquals(b"efg", bufio.read1(100))
         self.assertEquals(rawio._reads, 3)
         self.assertEquals(b"", bufio.read1(100))
+        self.assertEquals(rawio._reads, 4)
         # Invalid args
         self.assertRaises(ValueError, bufio.read1, -1)
 
@@ -684,6 +686,14 @@ class BufferedReaderTest(unittest.TestCase, CommonBufferedTests):
         self.assertEquals(bufio.readinto(b), 0)
         self.assertEquals(b, b"gf")
 
+    def test_readlines(self):
+        def bufio():
+            rawio = self.MockRawIO((b"abc\n", b"d\n", b"ef"))
+            return self.tp(rawio)
+        self.assertEquals(bufio().readlines(), [b"abc\n", b"d\n", b"ef"])
+        self.assertEquals(bufio().readlines(5), [b"abc\n", b"d\n"])
+        self.assertEquals(bufio().readlines(None), [b"abc\n", b"d\n", b"ef"])
+
     def test_buffering(self):
         data = b"abcdefghi"
         dlen = len(data)
@@ -1123,6 +1133,14 @@ class BufferedRWPairTest(unittest.TestCase):
         self.assertEqual(pair.read(3), b"abc")
         self.assertEqual(pair.read(1), b"d")
         self.assertEqual(pair.read(), b"ef")
+        pair = self.tp(self.BytesIO(b"abc"), self.MockRawIO())
+        self.assertEqual(pair.read(None), b"abc")
+
+    def test_readlines(self):
+        pair = lambda: self.tp(self.BytesIO(b"abc\ndef\nh"), self.MockRawIO())
+        self.assertEqual(pair().readlines(), [b"abc\n", b"def\n", b"h"])
+        self.assertEqual(pair().readlines(), [b"abc\n", b"def\n", b"h"])
+        self.assertEqual(pair().readlines(5), [b"abc\n", b"def\n"])
 
     def test_read1(self):
         # .read1() is delegated to the underlying reader object, so this test
@@ -1773,6 +1791,8 @@ class TextIOWrapperTest(unittest.TestCase):
                 self.assertEquals(f.read(), "abc")
                 cookie = f.tell()
                 self.assertEquals(f.seek(0), 0)
+                self.assertEquals(f.read(None), "abc")
+                f.seek(0)
                 self.assertEquals(f.read(2), "ab")
                 self.assertEquals(f.read(1), "c")
                 self.assertEquals(f.read(1), "")
@@ -1943,6 +1963,14 @@ class TextIOWrapperTest(unittest.TestCase):
             reads += c
         self.assertEquals(reads, "AA\nBB")
 
+    def test_readlines(self):
+        txt = self.TextIOWrapper(self.BytesIO(b"AA\nBB\nCC"))
+        self.assertEqual(txt.readlines(), ["AA\n", "BB\n", "CC"])
+        txt.seek(0)
+        self.assertEqual(txt.readlines(None), ["AA\n", "BB\n", "CC"])
+        txt.seek(0)
+        self.assertEqual(txt.readlines(5), ["AA\n", "BB\n"])
+
     # read in amounts equal to TextIOWrapper._CHUNK_SIZE which is 128.
     def test_read_by_chunk(self):
         # make sure "\r\n" straddles 128 char boundary.
index 237558d27238322b07f668d45c58de54e9346d64..c69ca6ab6cc2c028c4821fec54c15c83478a9808 100644 (file)
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -58,6 +58,10 @@ Core and Builtins
 Library
 -------
 
+- Issue #7349: Make methods of file objects in the io module accept None as an
+  argument where file-like objects (ie StringIO and BytesIO) accept them to mean
+  the same as passing no argument.
+
 - Issue #5949: added check for correct lineends in input from IMAP server
   in imaplib.
 
index 02776f3cffaa15c4c907a4d4362e25396919a5d1..dfd66aa7355825ae1988121a77df946daf8e8c0b 100644 (file)
@@ -561,6 +561,30 @@ PyNumber_AsOff_t(PyObject *item, PyObject *err)
     return result;
 }
 
+
+/* Basically the "n" format code with the ability to turn None into -1. */
+int 
+_PyIO_ConvertSsize_t(PyObject *obj, void *result) {
+    Py_ssize_t limit;
+    if (obj == Py_None) {
+        limit = -1;
+    }
+    else if (PyNumber_Check(obj)) {
+        limit = PyNumber_AsSsize_t(obj, PyExc_OverflowError);
+        if (limit == -1 && PyErr_Occurred())
+            return 0;
+    }
+    else {
+        PyErr_Format(PyExc_TypeError,
+                     "integer argument expected, got '%.200s'",
+                     Py_TYPE(obj)->tp_name);
+        return 0;
+    }
+    *((Py_ssize_t *)result) = limit;
+    return 1;
+}
+
+
 static int
 iomodule_traverse(PyObject *mod, visitproc visit, void *arg) {
     _PyIO_State *state = IO_MOD_STATE(mod);
@@ -574,6 +598,7 @@ iomodule_traverse(PyObject *mod, visitproc visit, void *arg) {
     return 0;
 }
 
+
 static int
 iomodule_clear(PyObject *mod) {
     _PyIO_State *state = IO_MOD_STATE(mod);
@@ -591,6 +616,7 @@ iomodule_free(PyObject *mod) {
     iomodule_clear(mod);
 }
 
+
 /*
  * Module definition
  */
index bc0e45215436ad7fa5d1e45186696ac7d906e4c6..16ab6c241d1247801c08add349e8392fd529a17b 100644 (file)
@@ -19,6 +19,9 @@ extern PyTypeObject PyBufferedRandom_Type;
 extern PyTypeObject PyTextIOWrapper_Type;
 extern PyTypeObject PyIncrementalNewlineDecoder_Type;
 
+
+extern int _PyIO_ConvertSsize_t(PyObject *, void *);
+
 /* These functions are used as METH_NOARGS methods, are normally called
  * with args=NULL, and return a new reference.
  * BUT when args=Py_True is passed, they return a borrowed reference.
index d8b6471fd7f03df4d8c9400ae3110f5e30d831ee..7f1bdb02156a748cb1a33c0a2783f4a6a4c735d9 100644 (file)
@@ -716,7 +716,7 @@ buffered_read(buffered *self, PyObject *args)
     PyObject *res;
 
     CHECK_INITIALIZED(self)
-    if (!PyArg_ParseTuple(args, "|n:read", &n)) {
+    if (!PyArg_ParseTuple(args, "|O&:read", &_PyIO_ConvertSsize_t, &n)) {
         return NULL;
     }
     if (n < -1) {
@@ -949,10 +949,8 @@ buffered_readline(buffered *self, PyObject *args)
     Py_ssize_t limit = -1;
 
     CHECK_INITIALIZED(self)
-
-    if (!PyArg_ParseTuple(args, "|n:readline", &limit)) {
+    if (!PyArg_ParseTuple(args, "|O&:readline", &_PyIO_ConvertSsize_t, &limit))
         return NULL;
-    }
     return _buffered_readline(self, limit);
 }
 
index f5ba9715374bc1ef709fc7c145f9aedf8cb4ad99..8162396a4225bd05e0196a0a0a05a027788ef62c 100644 (file)
@@ -602,7 +602,7 @@ fileio_read(fileio *self, PyObject *args)
        if (!self->readable)
                return err_mode("reading");
 
-       if (!PyArg_ParseTuple(args, "|n", &size))
+       if (!PyArg_ParseTuple(args, "|O&", &_PyIO_ConvertSsize_t, &size))
                return NULL;
 
         if (size < 0) {
index 28042c636d816a8d7cb0db2e36c84f9f25bb852f..d4757ed3da4d28a06d66878a0d7ce49350c60b02 100644 (file)
@@ -455,7 +455,7 @@ iobase_readline(PyObject *self, PyObject *args)
     PyObject *buffer, *result;
     Py_ssize_t old_size = -1;
 
-    if (!PyArg_ParseTuple(args, "|n:readline", &limit)) {
+    if (!PyArg_ParseTuple(args, "|O&:readline", &_PyIO_ConvertSsize_t, &limit)) {
         return NULL;
     }
 
@@ -577,16 +577,11 @@ static PyObject *
 iobase_readlines(PyObject *self, PyObject *args)
 {
     Py_ssize_t hint = -1, length = 0;
-    PyObject *hintobj = Py_None, *result;
+    PyObject *result;
 
-    if (!PyArg_ParseTuple(args, "|O:readlines", &hintobj)) {
+    if (!PyArg_ParseTuple(args, "|O&:readlines", &_PyIO_ConvertSsize_t, &hint)) {
         return NULL;
     }
-    if (hintobj != Py_None) {
-        hint = PyNumber_AsSsize_t(hintobj, PyExc_ValueError);
-        if (hint == -1 && PyErr_Occurred())
-            return NULL;
-    }
 
     result = PyList_New(0);
     if (result == NULL)
index 333c93f92087a14fabb51e5f6113f483c6b2e6d4..ba28d59e3e3964018f90e515d7d02febd0c35026 100644 (file)
@@ -1479,7 +1479,7 @@ textiowrapper_read(textio *self, PyObject *args)
 
     CHECK_INITIALIZED(self);
 
-    if (!PyArg_ParseTuple(args, "|n:read", &n))
+    if (!PyArg_ParseTuple(args, "|O&:read", &_PyIO_ConvertSsize_t, &n))
         return NULL;
 
     CHECK_CLOSED(self);