Skip to content

Commit 8f36f76

Browse files
committed
bpo-41305: Add StreamReader.readinto() (GH-21491)
This function is useful when you want to fill an already allocated buffer with data read from the stream.
1 parent 0108b2a commit 8f36f76

File tree

3 files changed

+46
-0
lines changed

3 files changed

+46
-0
lines changed

Doc/library/asyncio-stream.rst

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -211,6 +211,13 @@ StreamReader
211211

212212
.. versionadded:: 3.5.2
213213

214+
.. coroutinemethod:: readinto(buf)
215+
216+
Read up to *n* bytes with *n* being equal to the length of *buf* and
217+
copy the buffer read from the stream into *buf*.
218+
219+
Return the number of bytes read from the stream.
220+
214221
.. method:: at_eof()
215222

216223
Return ``True`` if the buffer is empty and :meth:`feed_eof`

Lib/asyncio/streams.py

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -690,6 +690,44 @@ async def read(self, n=-1):
690690
self._maybe_resume_transport()
691691
return data
692692

693+
async def readinto(self, buf):
694+
"""Read up to the length of `buf` number of bytes from the stream and
695+
fill the `buf` bytes object with what was read from the stream.
696+
697+
Returns the number of bytes read from the stream.
698+
699+
If `buf` is empty, return 0 immediately.
700+
701+
If `buf` is not empty, this function tries to read the length of `buf`
702+
number of bytes, and may fill the buffer with less or equal bytes than
703+
requested, but at least one byte. If EOF was received before any byte
704+
is read, this function returns 0.
705+
706+
Returned value is not limited with limit, configured at stream
707+
creation.
708+
709+
If stream was paused, this function will automatically resume it if
710+
needed.
711+
"""
712+
n = len(buf)
713+
714+
if self._exception is not None:
715+
raise self._exception
716+
717+
if n == 0:
718+
return 0
719+
720+
if not self._buffer and not self._eof:
721+
await self._wait_for_data('readinto')
722+
723+
length = min(n, len(self._buffer))
724+
if length > 0:
725+
buf[:length] = self._buffer[:length]
726+
727+
del self._buffer[:n]
728+
self._maybe_resume_transport()
729+
return length
730+
693731
async def readexactly(self, n):
694732
"""Read exactly `n` bytes.
695733
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Add the ``StreamReader.readinto(buf)`` function.

0 commit comments

Comments
 (0)