summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--docs/library/uasyncio.rst6
-rw-r--r--extmod/uasyncio/stream.py14
-rw-r--r--tests/multi_net/uasyncio_tcp_readall.py60
-rw-r--r--tests/multi_net/uasyncio_tcp_readall.py.exp8
4 files changed, 83 insertions, 5 deletions
diff --git a/docs/library/uasyncio.rst b/docs/library/uasyncio.rst
index 0c7170242..0abbf8dd8 100644
--- a/docs/library/uasyncio.rst
+++ b/docs/library/uasyncio.rst
@@ -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.
diff --git a/extmod/uasyncio/stream.py b/extmod/uasyncio/stream.py
index 750d8e974..785e43555 100644
--- a/extmod/uasyncio/stream.py
+++ b/extmod/uasyncio/stream.py
@@ -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)
diff --git a/tests/multi_net/uasyncio_tcp_readall.py b/tests/multi_net/uasyncio_tcp_readall.py
new file mode 100644
index 000000000..c411f1c69
--- /dev/null
+++ b/tests/multi_net/uasyncio_tcp_readall.py
@@ -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())
diff --git a/tests/multi_net/uasyncio_tcp_readall.py.exp b/tests/multi_net/uasyncio_tcp_readall.py.exp
new file mode 100644
index 000000000..0bf3dcba6
--- /dev/null
+++ b/tests/multi_net/uasyncio_tcp_readall.py.exp
@@ -0,0 +1,8 @@
+--- instance0 ---
+server running
+close
+done
+--- instance1 ---
+b'abc'
+b''
+b''