diff options
author | Yury Selivanov <yury@magic.io> | 2016-11-16 23:25:04 (GMT) |
---|---|---|
committer | Yury Selivanov <yury@magic.io> | 2016-11-16 23:25:04 (GMT) |
commit | 22214ab0af2cbea1611b2193354f248ca6b03e87 (patch) | |
tree | f7cf45d0205d2dca9f0021f01a1551de395f370e /Lib/_collections_abc.py | |
parent | 41782e497092a27efbae20208ce7d48c657e74cb (diff) | |
download | cpython-22214ab0af2cbea1611b2193354f248ca6b03e87.zip cpython-22214ab0af2cbea1611b2193354f248ca6b03e87.tar.gz cpython-22214ab0af2cbea1611b2193354f248ca6b03e87.tar.bz2 |
Issue #28720: Add collections.abc.AsyncGenerator.
Diffstat (limited to 'Lib/_collections_abc.py')
-rw-r--r-- | Lib/_collections_abc.py | 59 |
1 files changed, 58 insertions, 1 deletions
diff --git a/Lib/_collections_abc.py b/Lib/_collections_abc.py index ee7d0f1..b172f3f 100644 --- a/Lib/_collections_abc.py +++ b/Lib/_collections_abc.py @@ -9,7 +9,8 @@ Unit tests are in test_collections. from abc import ABCMeta, abstractmethod import sys -__all__ = ["Awaitable", "Coroutine", "AsyncIterable", "AsyncIterator", +__all__ = ["Awaitable", "Coroutine", + "AsyncIterable", "AsyncIterator", "AsyncGenerator", "Hashable", "Iterable", "Iterator", "Generator", "Reversible", "Sized", "Container", "Callable", "Collection", "Set", "MutableSet", @@ -59,6 +60,11 @@ _coro = _coro() coroutine = type(_coro) _coro.close() # Prevent ResourceWarning del _coro +## asynchronous generator ## +async def _ag(): yield +_ag = _ag() +async_generator = type(_ag) +del _ag ### ONE-TRICK PONIES ### @@ -183,6 +189,57 @@ class AsyncIterator(AsyncIterable): return NotImplemented +class AsyncGenerator(AsyncIterator): + + __slots__ = () + + async def __anext__(self): + """Return the next item from the asynchronous generator. + When exhausted, raise StopAsyncIteration. + """ + return await self.asend(None) + + @abstractmethod + async def asend(self, value): + """Send a value into the asynchronous generator. + Return next yielded value or raise StopAsyncIteration. + """ + raise StopAsyncIteration + + @abstractmethod + async def athrow(self, typ, val=None, tb=None): + """Raise an exception in the asynchronous generator. + Return next yielded value or raise StopAsyncIteration. + """ + if val is None: + if tb is None: + raise typ + val = typ() + if tb is not None: + val = val.with_traceback(tb) + raise val + + async def aclose(self): + """Raise GeneratorExit inside coroutine. + """ + try: + await self.athrow(GeneratorExit) + except (GeneratorExit, StopAsyncIteration): + pass + else: + raise RuntimeError("asynchronous generator ignored GeneratorExit") + + @classmethod + def __subclasshook__(cls, C): + if cls is AsyncGenerator: + return _check_methods(C, '__aiter__', '__anext__', + 'asend', 'athrow', 'aclose') + return NotImplemented + + +AsyncGenerator.register(async_generator) + + class Iterable(metaclass=ABCMeta): __slots__ = () |