]> granicus.if.org Git - python/commitdiff
Merged revisions 84814 via svnmerge from
authorAntoine Pitrou <solipsis@pitrou.net>
Tue, 14 Sep 2010 18:48:19 +0000 (18:48 +0000)
committerAntoine Pitrou <solipsis@pitrou.net>
Tue, 14 Sep 2010 18:48:19 +0000 (18:48 +0000)
svn+ssh://pythondev@svn.python.org/python/branches/py3k

........
  r84814 | antoine.pitrou | 2010-09-14 20:37:24 +0200 (mar., 14 sept. 2010) | 4 lines

  Issue #9854: The default read() implementation in io.RawIOBase now
  handles non-blocking readinto() returning None correctly.
........

Doc/library/io.rst
Lib/_pyio.py
Lib/test/test_io.py
Misc/NEWS
Modules/_io/iobase.c

index f3cd261f132cb93e9034a526cc8e185a852e4c70..7ae656e0e9853ae349feece5f38d21fae6710c9f 100644 (file)
@@ -371,8 +371,9 @@ I/O Base Classes
 
    .. method:: readinto(b)
 
-      Read up to len(b) bytes into bytearray *b* and return the number of bytes
-      read.
+      Read up to len(b) bytes into bytearray *b* and return the number ofbytes
+      read.  If the object is in non-blocking mode and no bytes are available,
+      ``None`` is returned.
 
    .. method:: write(b)
 
index e6911e455b153ccef18ebdfee5abaf1851ff86ff..3377df8b607eb8bd7de56c42653b16c232131dd3 100644 (file)
@@ -546,6 +546,8 @@ class RawIOBase(IOBase):
             return self.readall()
         b = bytearray(n.__index__())
         n = self.readinto(b)
+        if n is None:
+            return None
         del b[n:]
         return bytes(b)
 
@@ -563,7 +565,7 @@ class RawIOBase(IOBase):
         """Read up to len(b) bytes into b.
 
         Returns number of bytes read (0 for EOF), or None if the object
-        is set not to block as has no data to read.
+        is set not to block and has no data to read.
         """
         self._unsupported("readinto")
 
index d2ad2a6aa728ad70ad59a1e7293c360318176ef8..38cbcbcc2bf6f8f454da0d28932002a624aee4f4 100644 (file)
@@ -53,7 +53,9 @@ def _default_chunk_size():
         return f._CHUNK_SIZE
 
 
-class MockRawIO:
+class MockRawIOWithoutRead:
+    """A RawIO implementation without read(), so as to exercise the default
+    RawIO.read() which calls readinto()."""
 
     def __init__(self, read_stack=()):
         self._read_stack = list(read_stack)
@@ -61,14 +63,6 @@ class MockRawIO:
         self._reads = 0
         self._extraneous_reads = 0
 
-    def read(self, n=None):
-        self._reads += 1
-        try:
-            return self._read_stack.pop(0)
-        except:
-            self._extraneous_reads += 1
-            return b""
-
     def write(self, b):
         self._write_stack.append(bytes(b))
         return len(b)
@@ -115,6 +109,23 @@ class MockRawIO:
     def truncate(self, pos=None):
         return pos
 
+class CMockRawIOWithoutRead(MockRawIOWithoutRead, io.RawIOBase):
+    pass
+
+class PyMockRawIOWithoutRead(MockRawIOWithoutRead, pyio.RawIOBase):
+    pass
+
+
+class MockRawIO(MockRawIOWithoutRead):
+
+    def read(self, n=None):
+        self._reads += 1
+        try:
+            return self._read_stack.pop(0)
+        except:
+            self._extraneous_reads += 1
+            return b""
+
 class CMockRawIO(MockRawIO, io.RawIOBase):
     pass
 
@@ -560,6 +571,19 @@ class IOTest(unittest.TestCase):
         f.close()
         self.assertRaises(ValueError, f.flush)
 
+    def test_RawIOBase_read(self):
+        # Exercise the default RawIOBase.read() implementation (which calls
+        # readinto() internally).
+        rawio = self.MockRawIOWithoutRead((b"abc", b"d", None, b"efg", None))
+        self.assertEqual(rawio.read(2), b"ab")
+        self.assertEqual(rawio.read(2), b"c")
+        self.assertEqual(rawio.read(2), b"d")
+        self.assertEqual(rawio.read(2), None)
+        self.assertEqual(rawio.read(2), b"ef")
+        self.assertEqual(rawio.read(2), b"g")
+        self.assertEqual(rawio.read(2), None)
+        self.assertEqual(rawio.read(2), b"")
+
 class CIOTest(IOTest):
     pass
 
@@ -2558,7 +2582,7 @@ def test_main():
     # Put the namespaces of the IO module we are testing and some useful mock
     # classes in the __dict__ of each test.
     mocks = (MockRawIO, MisbehavedRawIO, MockFileIO, CloseFailureIO,
-             MockNonBlockWriterIO)
+             MockNonBlockWriterIO, MockRawIOWithoutRead)
     all_members = io.__all__ + ["IncrementalNewlineDecoder"]
     c_io_ns = dict((name, getattr(io, name)) for name in all_members)
     py_io_ns = dict((name, getattr(pyio, name)) for name in all_members)
index 2b97d633e8e13e6382a7c27ae6fef41689a903f6..30f62c4f5babf80f0eb15f5a8c9bda1034410ccb 100644 (file)
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -43,6 +43,9 @@ Core and Builtins
 Library
 -------
 
+- Issue #9854: The default read() implementation in io.RawIOBase now
+  handles non-blocking readinto() returning None correctly.
+
 - Issue #9729: Fix the signature of SSLSocket.recvfrom() and
   SSLSocket.sendto() to match the corresponding socket methods.  Also,
   fix various SSLSocket methods to raise socket.error rather than an
index 353056251465d12edaaec969b5d4c6ef8382dd71..56c007ccb46d61ddbe79db330f393b10d9afccc7 100644 (file)
@@ -776,9 +776,9 @@ rawiobase_read(PyObject *self, PyObject *args)
         return NULL;
 
     res = PyObject_CallMethodObjArgs(self, _PyIO_str_readinto, b, NULL);
-    if (res == NULL) {
+    if (res == NULL || res == Py_None) {
         Py_DECREF(b);
-        return NULL;
+        return res;
     }
 
     n = PyNumber_AsSsize_t(res, PyExc_ValueError);