mirror of
https://github.com/python/cpython.git
synced 2025-12-04 00:30:19 +00:00
Issue #28720: Add collections.abc.AsyncGenerator.
This commit is contained in:
parent
41782e4970
commit
22214ab0af
5 changed files with 155 additions and 2 deletions
|
|
@ -19,7 +19,8 @@ from collections import namedtuple, Counter, OrderedDict, _count_elements
|
|||
from collections import UserDict, UserString, UserList
|
||||
from collections import ChainMap
|
||||
from collections import deque
|
||||
from collections.abc import Awaitable, Coroutine, AsyncIterator, AsyncIterable
|
||||
from collections.abc import Awaitable, Coroutine
|
||||
from collections.abc import AsyncIterator, AsyncIterable, AsyncGenerator
|
||||
from collections.abc import Hashable, Iterable, Iterator, Generator, Reversible
|
||||
from collections.abc import Sized, Container, Callable, Collection
|
||||
from collections.abc import Set, MutableSet
|
||||
|
|
@ -959,6 +960,87 @@ class TestOneTrickPonyABCs(ABCTestCase):
|
|||
|
||||
self.assertRaises(RuntimeError, IgnoreGeneratorExit().close)
|
||||
|
||||
def test_AsyncGenerator(self):
|
||||
class NonAGen1:
|
||||
def __aiter__(self): return self
|
||||
def __anext__(self): return None
|
||||
def aclose(self): pass
|
||||
def athrow(self, typ, val=None, tb=None): pass
|
||||
|
||||
class NonAGen2:
|
||||
def __aiter__(self): return self
|
||||
def __anext__(self): return None
|
||||
def aclose(self): pass
|
||||
def asend(self, value): return value
|
||||
|
||||
class NonAGen3:
|
||||
def aclose(self): pass
|
||||
def asend(self, value): return value
|
||||
def athrow(self, typ, val=None, tb=None): pass
|
||||
|
||||
non_samples = [
|
||||
None, 42, 3.14, 1j, b"", "", (), [], {}, set(),
|
||||
iter(()), iter([]), NonAGen1(), NonAGen2(), NonAGen3()]
|
||||
for x in non_samples:
|
||||
self.assertNotIsInstance(x, AsyncGenerator)
|
||||
self.assertFalse(issubclass(type(x), AsyncGenerator), repr(type(x)))
|
||||
|
||||
class Gen:
|
||||
def __aiter__(self): return self
|
||||
async def __anext__(self): return None
|
||||
async def aclose(self): pass
|
||||
async def asend(self, value): return value
|
||||
async def athrow(self, typ, val=None, tb=None): pass
|
||||
|
||||
class MinimalAGen(AsyncGenerator):
|
||||
async def asend(self, value):
|
||||
return value
|
||||
async def athrow(self, typ, val=None, tb=None):
|
||||
await super().athrow(typ, val, tb)
|
||||
|
||||
async def gen():
|
||||
yield 1
|
||||
|
||||
samples = [gen(), Gen(), MinimalAGen()]
|
||||
for x in samples:
|
||||
self.assertIsInstance(x, AsyncIterator)
|
||||
self.assertIsInstance(x, AsyncGenerator)
|
||||
self.assertTrue(issubclass(type(x), AsyncGenerator), repr(type(x)))
|
||||
self.validate_abstract_methods(AsyncGenerator, 'asend', 'athrow')
|
||||
|
||||
def run_async(coro):
|
||||
result = None
|
||||
while True:
|
||||
try:
|
||||
coro.send(None)
|
||||
except StopIteration as ex:
|
||||
result = ex.args[0] if ex.args else None
|
||||
break
|
||||
return result
|
||||
|
||||
# mixin tests
|
||||
mgen = MinimalAGen()
|
||||
self.assertIs(mgen, mgen.__aiter__())
|
||||
self.assertIs(run_async(mgen.asend(None)), run_async(mgen.__anext__()))
|
||||
self.assertEqual(2, run_async(mgen.asend(2)))
|
||||
self.assertIsNone(run_async(mgen.aclose()))
|
||||
with self.assertRaises(ValueError):
|
||||
run_async(mgen.athrow(ValueError))
|
||||
|
||||
class FailOnClose(AsyncGenerator):
|
||||
async def asend(self, value): return value
|
||||
async def athrow(self, *args): raise ValueError
|
||||
|
||||
with self.assertRaises(ValueError):
|
||||
run_async(FailOnClose().aclose())
|
||||
|
||||
class IgnoreGeneratorExit(AsyncGenerator):
|
||||
async def asend(self, value): return value
|
||||
async def athrow(self, *args): pass
|
||||
|
||||
with self.assertRaises(RuntimeError):
|
||||
run_async(IgnoreGeneratorExit().aclose())
|
||||
|
||||
def test_Sized(self):
|
||||
non_samples = [None, 42, 3.14, 1j,
|
||||
_test_gen(),
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue