Skip to content

Commit 56abd8f

Browse files
JelleZijlstrailevkivskyi
authored andcommitted
add AsyncGenerator (#346)
* add AsyncGenerator * AsyncGenerator: remove redundant __new__, add test case for instantiation * remove redundant line
1 parent 8b71862 commit 56abd8f

File tree

2 files changed

+52
-1
lines changed

2 files changed

+52
-1
lines changed

src/test_typing.py

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1735,6 +1735,23 @@ def test_no_generator_instantiation(self):
17351735
with self.assertRaises(TypeError):
17361736
typing.Generator[int, int, int]()
17371737

1738+
@skipUnless(PY36, 'Python 3.6 required')
1739+
def test_async_generator(self):
1740+
ns = {}
1741+
exec("async def f():\n"
1742+
" yield 42\n", globals(), ns)
1743+
g = ns['f']()
1744+
self.assertIsSubclass(type(g), typing.AsyncGenerator)
1745+
1746+
@skipUnless(PY36, 'Python 3.6 required')
1747+
def test_no_async_generator_instantiation(self):
1748+
with self.assertRaises(TypeError):
1749+
typing.AsyncGenerator()
1750+
with self.assertRaises(TypeError):
1751+
typing.AsyncGenerator[T, T]()
1752+
with self.assertRaises(TypeError):
1753+
typing.AsyncGenerator[int, int]()
1754+
17381755
def test_subclassing(self):
17391756

17401757
class MMA(typing.MutableMapping):
@@ -1804,6 +1821,30 @@ def g(): yield 0
18041821
self.assertIsSubclass(G, collections.Iterable)
18051822
self.assertNotIsSubclass(type(g), G)
18061823

1824+
@skipUnless(PY36, 'Python 3.6 required')
1825+
def test_subclassing_async_generator(self):
1826+
class G(typing.AsyncGenerator[int, int]):
1827+
def asend(self, value):
1828+
pass
1829+
def athrow(self, typ, val=None, tb=None):
1830+
pass
1831+
1832+
ns = {}
1833+
exec('async def g(): yield 0', globals(), ns)
1834+
g = ns['g']
1835+
self.assertIsSubclass(G, typing.AsyncGenerator)
1836+
self.assertIsSubclass(G, typing.AsyncIterable)
1837+
self.assertIsSubclass(G, collections.AsyncGenerator)
1838+
self.assertIsSubclass(G, collections.AsyncIterable)
1839+
self.assertNotIsSubclass(type(g), G)
1840+
1841+
instance = G()
1842+
self.assertIsInstance(instance, typing.AsyncGenerator)
1843+
self.assertIsInstance(instance, typing.AsyncIterable)
1844+
self.assertIsInstance(instance, collections.AsyncGenerator)
1845+
self.assertIsInstance(instance, collections.AsyncIterable)
1846+
self.assertNotIsInstance(type(g), G)
1847+
18071848
def test_subclassing_subclasshook(self):
18081849

18091850
class Base(typing.Iterable):

src/typing.py

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,8 @@
5151
# AsyncIterable,
5252
# Coroutine,
5353
# Collection,
54-
# ContextManager
54+
# ContextManager,
55+
# AsyncGenerator,
5556

5657
# Structural checks, a.k.a. protocols.
5758
'Reversible',
@@ -1900,6 +1901,15 @@ def __new__(cls, *args, **kwds):
19001901
"create a subclass instead")
19011902
return _generic_new(_G_base, cls, *args, **kwds)
19021903

1904+
if hasattr(collections_abc, 'AsyncGenerator'):
1905+
_AG_base = collections_abc.AsyncGenerator
1906+
1907+
class AsyncGenerator(AsyncIterator[T_co], Generic[T_co, T_contra],
1908+
extra=_AG_base):
1909+
__slots__ = ()
1910+
1911+
__all__.append('AsyncGenerator')
1912+
19031913

19041914
# Internal type variable used for Type[].
19051915
CT_co = TypeVar('CT_co', covariant=True, bound=type)

0 commit comments

Comments
 (0)