From e0104ae1034eff71539e487caaab35365f08f181 Mon Sep 17 00:00:00 2001 From: Yury Selivanov Date: Thu, 14 May 2015 12:19:16 -0400 Subject: [PATCH] Issue 24184: Add AsyncIterator and AsyncIterable to collections.abc. --- Lib/_collections_abc.py | 39 +++++++++++++++++++++++++++++++++++- Lib/test/test_collections.py | 36 ++++++++++++++++++++++++++++++++- Misc/NEWS | 3 +++ 3 files changed, 76 insertions(+), 2 deletions(-) diff --git a/Lib/_collections_abc.py b/Lib/_collections_abc.py index ea804031d5..2f83543124 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 16c26ad1f4..d96eae7458 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 b4338489e5..b181f76823 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 ----- -- 2.40.0