Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit e5e75c6

Browse files
committed
Merged revisions 84814 via svnmerge from
svn+ssh://[email protected]/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. ........
1 parent 0e428f2 commit e5e75c6

5 files changed

Lines changed: 45 additions & 15 deletions

File tree

Doc/library/io.rst

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -361,8 +361,9 @@ I/O Base Classes
361361

362362
.. method:: readinto(b)
363363

364-
Read up to len(b) bytes into bytearray *b* and return the number of bytes
365-
read.
364+
Read up to len(b) bytes into bytearray *b* and return the number ofbytes
365+
read. If the object is in non-blocking mode and no bytes are available,
366+
``None`` is returned.
366367

367368
.. method:: write(b)
368369

Lib/_pyio.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -542,6 +542,8 @@ def read(self, n: int = -1) -> bytes:
542542
return self.readall()
543543
b = bytearray(n.__index__())
544544
n = self.readinto(b)
545+
if n is None:
546+
return None
545547
del b[n:]
546548
return bytes(b)
547549

@@ -559,7 +561,7 @@ def readinto(self, b: bytearray) -> int:
559561
"""Read up to len(b) bytes into b.
560562
561563
Returns number of bytes read (0 for EOF), or None if the object
562-
is set not to block as has no data to read.
564+
is set not to block and has no data to read.
563565
"""
564566
self._unsupported("readinto")
565567

Lib/test/test_io.py

Lines changed: 34 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -47,22 +47,16 @@ def _default_chunk_size():
4747
return f._CHUNK_SIZE
4848

4949

50-
class MockRawIO:
50+
class MockRawIOWithoutRead:
51+
"""A RawIO implementation without read(), so as to exercise the default
52+
RawIO.read() which calls readinto()."""
5153

5254
def __init__(self, read_stack=()):
5355
self._read_stack = list(read_stack)
5456
self._write_stack = []
5557
self._reads = 0
5658
self._extraneous_reads = 0
5759

58-
def read(self, n=None):
59-
self._reads += 1
60-
try:
61-
return self._read_stack.pop(0)
62-
except:
63-
self._extraneous_reads += 1
64-
return b""
65-
6660
def write(self, b):
6761
self._write_stack.append(bytes(b))
6862
return len(b)
@@ -109,6 +103,23 @@ def readinto(self, buf):
109103
def truncate(self, pos=None):
110104
return pos
111105

106+
class CMockRawIOWithoutRead(MockRawIOWithoutRead, io.RawIOBase):
107+
pass
108+
109+
class PyMockRawIOWithoutRead(MockRawIOWithoutRead, pyio.RawIOBase):
110+
pass
111+
112+
113+
class MockRawIO(MockRawIOWithoutRead):
114+
115+
def read(self, n=None):
116+
self._reads += 1
117+
try:
118+
return self._read_stack.pop(0)
119+
except:
120+
self._extraneous_reads += 1
121+
return b""
122+
112123
class CMockRawIO(MockRawIO, io.RawIOBase):
113124
pass
114125

@@ -554,6 +565,19 @@ def test_multi_close(self):
554565
f.close()
555566
self.assertRaises(ValueError, f.flush)
556567

568+
def test_RawIOBase_read(self):
569+
# Exercise the default RawIOBase.read() implementation (which calls
570+
# readinto() internally).
571+
rawio = self.MockRawIOWithoutRead((b"abc", b"d", None, b"efg", None))
572+
self.assertEqual(rawio.read(2), b"ab")
573+
self.assertEqual(rawio.read(2), b"c")
574+
self.assertEqual(rawio.read(2), b"d")
575+
self.assertEqual(rawio.read(2), None)
576+
self.assertEqual(rawio.read(2), b"ef")
577+
self.assertEqual(rawio.read(2), b"g")
578+
self.assertEqual(rawio.read(2), None)
579+
self.assertEqual(rawio.read(2), b"")
580+
557581
class CIOTest(IOTest):
558582
pass
559583

@@ -2557,7 +2581,7 @@ def test_main():
25572581
# Put the namespaces of the IO module we are testing and some useful mock
25582582
# classes in the __dict__ of each test.
25592583
mocks = (MockRawIO, MisbehavedRawIO, MockFileIO, CloseFailureIO,
2560-
MockNonBlockWriterIO)
2584+
MockNonBlockWriterIO, MockRawIOWithoutRead)
25612585
all_members = io.__all__ + ["IncrementalNewlineDecoder"]
25622586
c_io_ns = {name : getattr(io, name) for name in all_members}
25632587
py_io_ns = {name : getattr(pyio, name) for name in all_members}

Misc/NEWS

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,9 @@ C-API
117117
Library
118118
-------
119119

120+
- Issue #9854: The default read() implementation in io.RawIOBase now
121+
handles non-blocking readinto() returning None correctly.
122+
120123
- Issue #9853: Fix the signature of SSLSocket.recvfrom() and
121124
SSLSocket.sendto() to match the corresponding socket methods.
122125

Modules/_io/iobase.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -776,9 +776,9 @@ rawiobase_read(PyObject *self, PyObject *args)
776776
return NULL;
777777

778778
res = PyObject_CallMethodObjArgs(self, _PyIO_str_readinto, b, NULL);
779-
if (res == NULL) {
779+
if (res == NULL || res == Py_None) {
780780
Py_DECREF(b);
781-
return NULL;
781+
return res;
782782
}
783783

784784
n = PyNumber_AsSsize_t(res, PyExc_ValueError);

0 commit comments

Comments
 (0)