Kaydet (Commit) 328ec745 authored tarafından Antoine Pitrou's avatar Antoine Pitrou

Issue #9854: The default read() implementation in io.RawIOBase now

handles non-blocking readinto() returning None correctly.
üst 9e0b864a
......@@ -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)
......
......@@ -544,6 +544,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)
......@@ -561,7 +563,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")
......
......@@ -48,7 +48,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)
......@@ -56,14 +58,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)
......@@ -110,6 +104,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
......@@ -582,6 +593,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
......@@ -2590,7 +2614,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, MockUnseekableIO)
MockNonBlockWriterIO, MockUnseekableIO, 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}
......
......@@ -52,6 +52,9 @@ Core and Builtins
Library
-------
- Issue #9854: The default read() implementation in io.RawIOBase now
handles non-blocking readinto() returning None correctly.
- Issue #1552: socket.socketpair() now returns regular socket.socket
objects supporting the whole socket API (rather than the "raw"
_socket.socket objects).
......
......@@ -777,9 +777,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);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment