Issue 24184: Add AsyncIterator and AsyncIterable to collections.abc.
This commit is contained in:
parent
7d0d6ee525
commit
e0104ae103
|
@ -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__ = ()
|
||||
|
|
|
@ -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]
|
||||
|
|
Loading…
Reference in New Issue