diff --git a/Lib/asyncio/streams.py b/Lib/asyncio/streams.py index 64ff3d2edc4..176c65e3969 100644 --- a/Lib/asyncio/streams.py +++ b/Lib/asyncio/streams.py @@ -6,6 +6,7 @@ __all__ = ['StreamReader', 'StreamWriter', 'StreamReaderProtocol', ] import socket +import sys if hasattr(socket, 'AF_UNIX'): __all__.extend(['open_unix_connection', 'start_unix_server']) @@ -19,6 +20,7 @@ from .log import logger _DEFAULT_LIMIT = 2**16 +_PY35 = sys.version_info >= (3, 5) class IncompleteReadError(EOFError): @@ -485,3 +487,15 @@ class StreamReader: n -= len(block) return b''.join(blocks) + + if _PY35: + @coroutine + def __aiter__(self): + return self + + @coroutine + def __anext__(self): + val = yield from self.readline() + if val == b'': + raise StopAsyncIteration + return val diff --git a/Lib/test/test_asyncio/test_pep492.py b/Lib/test/test_asyncio/test_pep492.py index c9a2f969a44..3d8d1b8c7a3 100644 --- a/Lib/test/test_asyncio/test_pep492.py +++ b/Lib/test/test_asyncio/test_pep492.py @@ -64,5 +64,24 @@ class LockTests(BaseTest): self.assertFalse(primitive.locked()) +class StreamReaderTests(BaseTest): + + def test_readline(self): + DATA = b'line1\nline2\nline3' + + stream = asyncio.StreamReader(loop=self.loop) + stream.feed_data(DATA) + stream.feed_eof() + + async def reader(): + data = [] + async for line in stream: + data.append(line) + return data + + data = self.loop.run_until_complete(reader()) + self.assertEqual(data, [b'line1\n', b'line2\n', b'line3']) + + if __name__ == '__main__': unittest.main() diff --git a/Misc/NEWS b/Misc/NEWS index b7cd1c7a606..b4338489e59 100644 --- a/Misc/NEWS +++ b/Misc/NEWS @@ -119,6 +119,9 @@ Library - Issue 24178: asyncio.Lock, Condition, Semaphore, and BoundedSemaphore support new 'async with' syntax. Contributed by Yury Selivanov. +- Issue 24179: Support 'async for' for asyncio.StreamReader. + Contributed by Yury Selivanov. + Tests -----