extmod/uasyncio: Implement stream read(-1) to read all data up to EOF.

Fixes issue #6355.

Signed-off-by: Damien George <damien@micropython.org>
This commit is contained in:
Damien George 2020-08-22 16:39:15 +10:00
parent 2a2589738c
commit db7682e02d
4 changed files with 83 additions and 5 deletions

View File

@ -237,9 +237,11 @@ TCP stream connections
This is a coroutine.
.. method:: Stream.read(n)
.. method:: Stream.read(n=-1)
Read up to *n* bytes and return them.
Read up to *n* bytes and return them. If *n* is not provided or -1 then read all
bytes until EOF. The returned value will be an empty bytes object if EOF is
encountered before any bytes are read.
This is a coroutine.

View File

@ -26,9 +26,17 @@ class Stream:
# TODO yield?
self.s.close()
async def read(self, n):
yield core._io_queue.queue_read(self.s)
return self.s.read(n)
async def read(self, n=-1):
r = b""
while True:
yield core._io_queue.queue_read(self.s)
r2 = self.s.read(n)
if r2 is not None:
if n >= 0:
return r2
if not len(r2):
return r
r += r2
async def readinto(self, buf):
yield core._io_queue.queue_read(self.s)

View File

@ -0,0 +1,60 @@
# Test uasyncio stream read(-1) method using TCP server/client
try:
import uasyncio as asyncio
except ImportError:
try:
import asyncio
except ImportError:
print("SKIP")
raise SystemExit
PORT = 8000
async def handle_connection(reader, writer):
writer.write(b"a")
await writer.drain()
# Split the first 2 bytes up so the client must wait for the second one
await asyncio.sleep(0.1)
writer.write(b"b")
await writer.drain()
writer.write(b"c")
await writer.drain()
print("close")
writer.close()
await writer.wait_closed()
print("done")
ev.set()
async def tcp_server():
global ev
ev = asyncio.Event()
server = await asyncio.start_server(handle_connection, "0.0.0.0", PORT)
print("server running")
multitest.next()
async with server:
await asyncio.wait_for(ev.wait(), 2)
async def tcp_client():
reader, writer = await asyncio.open_connection(IP, PORT)
print(await reader.read())
print(await reader.read()) # should be empty
print(await reader.read(1)) # should be empty
def instance0():
multitest.globals(IP=multitest.get_network_ip())
asyncio.run(tcp_server())
def instance1():
multitest.next()
asyncio.run(tcp_client())

View File

@ -0,0 +1,8 @@
--- instance0 ---
server running
close
done
--- instance1 ---
b'abc'
b''
b''