mirror of
https://github.com/python/cpython.git
synced 2025-09-30 20:31:52 +00:00
bpo-22671: Clarify and test default read method implementations (GH-4568) (#4796)
Original patch written by Martin Panter, enhanced by Sanyam Khurana.
(cherry picked from commit 1b74f9b77a
)
This commit is contained in:
parent
71d8f36eb4
commit
0aa2a1d003
2 changed files with 59 additions and 7 deletions
|
@ -205,8 +205,8 @@ ABC Inherits Stub Methods Mixin M
|
|||
``writable``, and ``writelines``
|
||||
:class:`RawIOBase` :class:`IOBase` ``readinto`` and Inherited :class:`IOBase` methods, ``read``,
|
||||
``write`` and ``readall``
|
||||
:class:`BufferedIOBase` :class:`IOBase` ``detach``, ``read``, Inherited :class:`IOBase` methods, ``readinto``
|
||||
``read1``, and ``write``
|
||||
:class:`BufferedIOBase` :class:`IOBase` ``detach``, ``read``, Inherited :class:`IOBase` methods, ``readinto``,
|
||||
``read1``, and ``write`` and ``readinto1``
|
||||
:class:`TextIOBase` :class:`IOBase` ``detach``, ``read``, Inherited :class:`IOBase` methods, ``encoding``,
|
||||
``readline``, and ``errors``, and ``newlines``
|
||||
``write``
|
||||
|
@ -385,14 +385,17 @@ I/O Base Classes
|
|||
.. method:: read(size=-1)
|
||||
|
||||
Read up to *size* bytes from the object and return them. As a convenience,
|
||||
if *size* is unspecified or -1, :meth:`readall` is called. Otherwise,
|
||||
only one system call is ever made. Fewer than *size* bytes may be
|
||||
returned if the operating system call returns fewer than *size* bytes.
|
||||
if *size* is unspecified or -1, all bytes until EOF are returned.
|
||||
Otherwise, only one system call is ever made. Fewer than *size* bytes may
|
||||
be returned if the operating system call returns fewer than *size* bytes.
|
||||
|
||||
If 0 bytes are returned, and *size* was not 0, this indicates end of file.
|
||||
If the object is in non-blocking mode and no bytes are available,
|
||||
``None`` is returned.
|
||||
|
||||
The default implementation defers to :meth:`readall` and
|
||||
:meth:`readinto`.
|
||||
|
||||
.. method:: readall()
|
||||
|
||||
Read and return all the bytes from the stream until EOF, using multiple
|
||||
|
|
|
@ -796,8 +796,8 @@ class IOTest(unittest.TestCase):
|
|||
self.assertRaises(ValueError, f.flush)
|
||||
|
||||
def test_RawIOBase_read(self):
|
||||
# Exercise the default RawIOBase.read() implementation (which calls
|
||||
# readinto() internally).
|
||||
# Exercise the default limited RawIOBase.read(n) 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")
|
||||
|
@ -905,6 +905,55 @@ class IOTest(unittest.TestCase):
|
|||
with self.assertRaisesRegex(ValueError, 'read/write/append mode'):
|
||||
self.open(PathLike(support.TESTFN), 'rwxa')
|
||||
|
||||
def test_RawIOBase_readall(self):
|
||||
# Exercise the default unlimited RawIOBase.read() and readall()
|
||||
# implementations.
|
||||
rawio = self.MockRawIOWithoutRead((b"abc", b"d", b"efg"))
|
||||
self.assertEqual(rawio.read(), b"abcdefg")
|
||||
rawio = self.MockRawIOWithoutRead((b"abc", b"d", b"efg"))
|
||||
self.assertEqual(rawio.readall(), b"abcdefg")
|
||||
|
||||
def test_BufferedIOBase_readinto(self):
|
||||
# Exercise the default BufferedIOBase.readinto() and readinto1()
|
||||
# implementations (which call read() or read1() internally).
|
||||
class Reader(self.BufferedIOBase):
|
||||
def __init__(self, avail):
|
||||
self.avail = avail
|
||||
def read(self, size):
|
||||
result = self.avail[:size]
|
||||
self.avail = self.avail[size:]
|
||||
return result
|
||||
def read1(self, size):
|
||||
"""Returns no more than 5 bytes at once"""
|
||||
return self.read(min(size, 5))
|
||||
tests = (
|
||||
# (test method, total data available, read buffer size, expected
|
||||
# read size)
|
||||
("readinto", 10, 5, 5),
|
||||
("readinto", 10, 6, 6), # More than read1() can return
|
||||
("readinto", 5, 6, 5), # Buffer larger than total available
|
||||
("readinto", 6, 7, 6),
|
||||
("readinto", 10, 0, 0), # Empty buffer
|
||||
("readinto1", 10, 5, 5), # Result limited to single read1() call
|
||||
("readinto1", 10, 6, 5), # Buffer larger than read1() can return
|
||||
("readinto1", 5, 6, 5), # Buffer larger than total available
|
||||
("readinto1", 6, 7, 5),
|
||||
("readinto1", 10, 0, 0), # Empty buffer
|
||||
)
|
||||
UNUSED_BYTE = 0x81
|
||||
for test in tests:
|
||||
with self.subTest(test):
|
||||
method, avail, request, result = test
|
||||
reader = Reader(bytes(range(avail)))
|
||||
buffer = bytearray((UNUSED_BYTE,) * request)
|
||||
method = getattr(reader, method)
|
||||
self.assertEqual(method(buffer), result)
|
||||
self.assertEqual(len(buffer), request)
|
||||
self.assertSequenceEqual(buffer[:result], range(result))
|
||||
unused = (UNUSED_BYTE,) * (request - result)
|
||||
self.assertSequenceEqual(buffer[result:], unused)
|
||||
self.assertEqual(len(reader.avail), avail - result)
|
||||
|
||||
|
||||
class CIOTest(IOTest):
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue