summaryrefslogtreecommitdiffstats
path: root/Lib/_collections_abc.py
diff options
context:
space:
mode:
authorYury Selivanov <yury@magic.io>2016-11-16 23:25:04 (GMT)
committerYury Selivanov <yury@magic.io>2016-11-16 23:25:04 (GMT)
commit22214ab0af2cbea1611b2193354f248ca6b03e87 (patch)
treef7cf45d0205d2dca9f0021f01a1551de395f370e /Lib/_collections_abc.py
parent41782e497092a27efbae20208ce7d48c657e74cb (diff)
downloadcpython-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.py59
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__ = ()