|
19 | 19 | from collections import UserDict, UserString, UserList |
20 | 20 | from collections import ChainMap |
21 | 21 | from collections import deque |
22 | | -from collections.abc import Awaitable, Coroutine, AsyncIterator, AsyncIterable |
| 22 | +from collections.abc import Awaitable, Coroutine |
| 23 | +from collections.abc import AsyncIterator, AsyncIterable, AsyncGenerator |
23 | 24 | from collections.abc import Hashable, Iterable, Iterator, Generator, Reversible |
24 | 25 | from collections.abc import Sized, Container, Callable, Collection |
25 | 26 | from collections.abc import Set, MutableSet |
@@ -959,6 +960,87 @@ def throw(self, *args): pass |
959 | 960 |
|
960 | 961 | self.assertRaises(RuntimeError, IgnoreGeneratorExit().close) |
961 | 962 |
|
| 963 | + def test_AsyncGenerator(self): |
| 964 | + class NonAGen1: |
| 965 | + def __aiter__(self): return self |
| 966 | + def __anext__(self): return None |
| 967 | + def aclose(self): pass |
| 968 | + def athrow(self, typ, val=None, tb=None): pass |
| 969 | + |
| 970 | + class NonAGen2: |
| 971 | + def __aiter__(self): return self |
| 972 | + def __anext__(self): return None |
| 973 | + def aclose(self): pass |
| 974 | + def asend(self, value): return value |
| 975 | + |
| 976 | + class NonAGen3: |
| 977 | + def aclose(self): pass |
| 978 | + def asend(self, value): return value |
| 979 | + def athrow(self, typ, val=None, tb=None): pass |
| 980 | + |
| 981 | + non_samples = [ |
| 982 | + None, 42, 3.14, 1j, b"", "", (), [], {}, set(), |
| 983 | + iter(()), iter([]), NonAGen1(), NonAGen2(), NonAGen3()] |
| 984 | + for x in non_samples: |
| 985 | + self.assertNotIsInstance(x, AsyncGenerator) |
| 986 | + self.assertFalse(issubclass(type(x), AsyncGenerator), repr(type(x))) |
| 987 | + |
| 988 | + class Gen: |
| 989 | + def __aiter__(self): return self |
| 990 | + async def __anext__(self): return None |
| 991 | + async def aclose(self): pass |
| 992 | + async def asend(self, value): return value |
| 993 | + async def athrow(self, typ, val=None, tb=None): pass |
| 994 | + |
| 995 | + class MinimalAGen(AsyncGenerator): |
| 996 | + async def asend(self, value): |
| 997 | + return value |
| 998 | + async def athrow(self, typ, val=None, tb=None): |
| 999 | + await super().athrow(typ, val, tb) |
| 1000 | + |
| 1001 | + async def gen(): |
| 1002 | + yield 1 |
| 1003 | + |
| 1004 | + samples = [gen(), Gen(), MinimalAGen()] |
| 1005 | + for x in samples: |
| 1006 | + self.assertIsInstance(x, AsyncIterator) |
| 1007 | + self.assertIsInstance(x, AsyncGenerator) |
| 1008 | + self.assertTrue(issubclass(type(x), AsyncGenerator), repr(type(x))) |
| 1009 | + self.validate_abstract_methods(AsyncGenerator, 'asend', 'athrow') |
| 1010 | + |
| 1011 | + def run_async(coro): |
| 1012 | + result = None |
| 1013 | + while True: |
| 1014 | + try: |
| 1015 | + coro.send(None) |
| 1016 | + except StopIteration as ex: |
| 1017 | + result = ex.args[0] if ex.args else None |
| 1018 | + break |
| 1019 | + return result |
| 1020 | + |
| 1021 | + # mixin tests |
| 1022 | + mgen = MinimalAGen() |
| 1023 | + self.assertIs(mgen, mgen.__aiter__()) |
| 1024 | + self.assertIs(run_async(mgen.asend(None)), run_async(mgen.__anext__())) |
| 1025 | + self.assertEqual(2, run_async(mgen.asend(2))) |
| 1026 | + self.assertIsNone(run_async(mgen.aclose())) |
| 1027 | + with self.assertRaises(ValueError): |
| 1028 | + run_async(mgen.athrow(ValueError)) |
| 1029 | + |
| 1030 | + class FailOnClose(AsyncGenerator): |
| 1031 | + async def asend(self, value): return value |
| 1032 | + async def athrow(self, *args): raise ValueError |
| 1033 | + |
| 1034 | + with self.assertRaises(ValueError): |
| 1035 | + run_async(FailOnClose().aclose()) |
| 1036 | + |
| 1037 | + class IgnoreGeneratorExit(AsyncGenerator): |
| 1038 | + async def asend(self, value): return value |
| 1039 | + async def athrow(self, *args): pass |
| 1040 | + |
| 1041 | + with self.assertRaises(RuntimeError): |
| 1042 | + run_async(IgnoreGeneratorExit().aclose()) |
| 1043 | + |
962 | 1044 | def test_Sized(self): |
963 | 1045 | non_samples = [None, 42, 3.14, 1j, |
964 | 1046 | _test_gen(), |
|
0 commit comments