mirror of
				https://github.com/python/cpython.git
				synced 2025-11-04 03:44:55 +00:00 
			
		
		
		
	Issue 24184: Add AsyncIterator and AsyncIterable to collections.abc.
This commit is contained in:
		
							parent
							
								
									7d0d6ee525
								
							
						
					
					
						commit
						e0104ae103
					
				
					 3 changed files with 76 additions and 2 deletions
				
			
		| 
						 | 
				
			
			@ -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]
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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
 | 
			
		||||
-----
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue