summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorYury Selivanov <yselivanov@sprymix.com>2015-05-14 16:19:16 (GMT)
committerYury Selivanov <yselivanov@sprymix.com>2015-05-14 16:19:16 (GMT)
commite0104ae1034eff71539e487caaab35365f08f181 (patch)
tree3cd672d0ae8a9eb77f980cbf1079704a467ea5df
parent7d0d6ee525a6c75fc3a48105dcd448673bcf4a44 (diff)
downloadcpython-e0104ae1034eff71539e487caaab35365f08f181.zip
cpython-e0104ae1034eff71539e487caaab35365f08f181.tar.gz
cpython-e0104ae1034eff71539e487caaab35365f08f181.tar.bz2
Issue 24184: Add AsyncIterator and AsyncIterable to collections.abc.
-rw-r--r--Lib/_collections_abc.py39
-rw-r--r--Lib/test/test_collections.py36
-rw-r--r--Misc/NEWS3
3 files changed, 76 insertions, 2 deletions
diff --git a/Lib/_collections_abc.py b/Lib/_collections_abc.py
index ea80403..2f83543 100644
--- a/Lib/_collections_abc.py
+++ b/Lib/_collections_abc.py
@@ -9,7 +9,7 @@ Unit tests are in test_collections.
from abc import ABCMeta, abstractmethod
import sys
-__all__ = ["Awaitable", "Coroutine",
+__all__ = ["Awaitable", "Coroutine", "AsyncIterable", "AsyncIterator",
"Hashable", "Iterable", "Iterator", "Generator",
"Sized", "Container", "Callable",
"Set", "MutableSet",
@@ -148,6 +148,43 @@ class Awaitable(metaclass=_CoroutineMeta):
Awaitable.register(Coroutine)
+class AsyncIterable(metaclass=ABCMeta):
+
+ __slots__ = ()
+
+ @abstractmethod
+ async def __aiter__(self):
+ return AsyncIterator()
+
+ @classmethod
+ def __subclasshook__(cls, C):
+ if cls is AsyncIterable:
+ if any("__aiter__" in B.__dict__ for B in C.__mro__):
+ return True
+ return NotImplemented
+
+
+class AsyncIterator(AsyncIterable):
+
+ __slots__ = ()
+
+ @abstractmethod
+ async def __anext__(self):
+ """Return the next item or raise StopAsyncIteration when exhausted."""
+ raise StopAsyncIteration
+
+ async def __aiter__(self):
+ return self
+
+ @classmethod
+ def __subclasshook__(cls, C):
+ if cls is AsyncIterator:
+ if (any("__anext__" in B.__dict__ for B in C.__mro__) and
+ any("__aiter__" in B.__dict__ for B in C.__mro__)):
+ return True
+ return NotImplemented
+
+
class Iterable(metaclass=ABCMeta):
__slots__ = ()
diff --git a/Lib/test/test_collections.py b/Lib/test/test_collections.py
index 16c26ad..d96eae7 100644
--- a/Lib/test/test_collections.py
+++ b/Lib/test/test_collections.py
@@ -15,7 +15,7 @@ import types
from collections import UserDict
from collections import ChainMap
from collections import deque
-from collections.abc import Awaitable, Coroutine
+from collections.abc import Awaitable, Coroutine, AsyncIterator, AsyncIterable
from collections.abc import Hashable, Iterable, Iterator, Generator
from collections.abc import Sized, Container, Callable
from collections.abc import Set, MutableSet
@@ -573,6 +573,40 @@ class TestOneTrickPonyABCs(ABCTestCase):
self.validate_abstract_methods(Hashable, '__hash__')
self.validate_isinstance(Hashable, '__hash__')
+ def test_AsyncIterable(self):
+ class AI:
+ async def __aiter__(self):
+ return self
+ self.assertTrue(isinstance(AI(), AsyncIterable))
+ self.assertTrue(issubclass(AI, AsyncIterable))
+ # Check some non-iterables
+ non_samples = [None, object, []]
+ for x in non_samples:
+ self.assertNotIsInstance(x, AsyncIterable)
+ self.assertFalse(issubclass(type(x), AsyncIterable), repr(type(x)))
+ self.validate_abstract_methods(AsyncIterable, '__aiter__')
+ self.validate_isinstance(AsyncIterable, '__aiter__')
+
+ def test_AsyncIterator(self):
+ class AI:
+ async def __aiter__(self):
+ return self
+ async def __anext__(self):
+ raise StopAsyncIteration
+ self.assertTrue(isinstance(AI(), AsyncIterator))
+ self.assertTrue(issubclass(AI, AsyncIterator))
+ non_samples = [None, object, []]
+ # Check some non-iterables
+ for x in non_samples:
+ self.assertNotIsInstance(x, AsyncIterator)
+ self.assertFalse(issubclass(type(x), AsyncIterator), repr(type(x)))
+ # Similarly to regular iterators (see issue 10565)
+ class AnextOnly:
+ async def __anext__(self):
+ raise StopAsyncIteration
+ self.assertNotIsInstance(AnextOnly(), AsyncIterator)
+ self.validate_abstract_methods(AsyncIterator, '__anext__', '__aiter__')
+
def test_Iterable(self):
# Check some non-iterables
non_samples = [None, 42, 3.14, 1j]
diff --git a/Misc/NEWS b/Misc/NEWS
index b433848..b181f76 100644
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -122,6 +122,9 @@ Library
- Issue 24179: Support 'async for' for asyncio.StreamReader.
Contributed by Yury Selivanov.
+- Issue 24184: Add AsyncIterator and AsyncIterable ABCs to
+ collections.abc. Contributed by Yury Selivanov.
+
Tests
-----