diff options
author | Antoine Pitrou <solipsis@pitrou.net> | 2010-09-14 18:53:07 (GMT) |
---|---|---|
committer | Antoine Pitrou <solipsis@pitrou.net> | 2010-09-14 18:53:07 (GMT) |
commit | e5e75c64f24dc8c7e5ee17bfa46d7f3222ebc0fc (patch) | |
tree | 46b65cc31d41f1049dda849d4d8fb41d9f46d73b | |
parent | 0e428f2c3a30d627c34dfbbfab0b1eadb828fdfa (diff) | |
download | cpython-e5e75c64f24dc8c7e5ee17bfa46d7f3222ebc0fc.zip cpython-e5e75c64f24dc8c7e5ee17bfa46d7f3222ebc0fc.tar.gz cpython-e5e75c64f24dc8c7e5ee17bfa46d7f3222ebc0fc.tar.bz2 |
Merged revisions 84814 via svnmerge from
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.
........
-rw-r--r-- | Doc/library/io.rst | 5 | ||||
-rw-r--r-- | Lib/_pyio.py | 4 | ||||
-rw-r--r-- | Lib/test/test_io.py | 44 | ||||
-rw-r--r-- | Misc/NEWS | 3 | ||||
-rw-r--r-- | Modules/_io/iobase.c | 4 |
5 files changed, 45 insertions, 15 deletions
diff --git a/Doc/library/io.rst b/Doc/library/io.rst index b2e586a..faf1aea 100644 --- a/Doc/library/io.rst +++ b/Doc/library/io.rst @@ -361,8 +361,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) diff --git a/Lib/_pyio.py b/Lib/_pyio.py index ffbfda1..4485233 100644 --- a/Lib/_pyio.py +++ b/Lib/_pyio.py @@ -542,6 +542,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) @@ -559,7 +561,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") diff --git a/Lib/test/test_io.py b/Lib/test/test_io.py index 3a3e074..4c7ce31 100644 --- a/Lib/test/test_io.py +++ b/Lib/test/test_io.py @@ -47,7 +47,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) @@ -55,14 +57,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) @@ -109,6 +103,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 @@ -554,6 +565,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 @@ -2557,7 +2581,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 = {name : getattr(io, name) for name in all_members} py_io_ns = {name : getattr(pyio, name) for name in all_members} @@ -117,6 +117,9 @@ C-API Library ------- +- Issue #9854: The default read() implementation in io.RawIOBase now + handles non-blocking readinto() returning None correctly. + - Issue #9853: Fix the signature of SSLSocket.recvfrom() and SSLSocket.sendto() to match the corresponding socket methods. diff --git a/Modules/_io/iobase.c b/Modules/_io/iobase.c index 2d664ab..dfc1a3a 100644 --- a/Modules/_io/iobase.c +++ b/Modules/_io/iobase.c @@ -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); |