Skip to content

Commit

Permalink
Issue python#29198: add AsyncGenerator (Jelle Zijlstra)
Browse files Browse the repository at this point in the history
  • Loading branch information
gvanrossum committed Jan 18, 2017
1 parent 3c268be commit e9ed560
Show file tree
Hide file tree
Showing 2 changed files with 51 additions and 1 deletion.
42 changes: 42 additions & 0 deletions Lib/test/test_typing.py
Original file line number Diff line number Diff line change
Expand Up @@ -1735,6 +1735,23 @@ def test_no_generator_instantiation(self):
with self.assertRaises(TypeError):
typing.Generator[int, int, int]()

@skipUnless(PY36, 'Python 3.6 required')
def test_async_generator(self):
ns = {}
exec("async def f():\n"
" yield 42\n", globals(), ns)
g = ns['f']()
self.assertIsSubclass(type(g), typing.AsyncGenerator)

@skipUnless(PY36, 'Python 3.6 required')
def test_no_async_generator_instantiation(self):
with self.assertRaises(TypeError):
typing.AsyncGenerator()
with self.assertRaises(TypeError):
typing.AsyncGenerator[T, T]()
with self.assertRaises(TypeError):
typing.AsyncGenerator[int, int]()

def test_subclassing(self):

class MMA(typing.MutableMapping):
Expand Down Expand Up @@ -1804,6 +1821,31 @@ def g(): yield 0
self.assertIsSubclass(G, collections.Iterable)
self.assertNotIsSubclass(type(g), G)

@skipUnless(PY36, 'Python 3.6 required')
def test_subclassing_async_generator(self):
class G(typing.AsyncGenerator[int, int]):
def asend(self, value):
pass
def athrow(self, typ, val=None, tb=None):
pass

ns = {}
exec('async def g(): yield 0', globals(), ns)
g = ns['g']
self.assertIsSubclass(G, typing.AsyncGenerator)
self.assertIsSubclass(G, typing.AsyncIterable)
self.assertIsSubclass(G, collections.AsyncGenerator)
self.assertIsSubclass(G, collections.AsyncIterable)
self.assertNotIsSubclass(type(g), G)

instance = G()
self.assertIsInstance(instance, typing.AsyncGenerator)
self.assertIsInstance(instance, typing.AsyncIterable)
self.assertIsInstance(instance, collections.AsyncGenerator)
self.assertIsInstance(instance, collections.AsyncIterable)
self.assertNotIsInstance(type(g), G)
self.assertNotIsInstance(g, G)

def test_subclassing_subclasshook(self):

class Base(typing.Iterable):
Expand Down
10 changes: 9 additions & 1 deletion Lib/typing.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,8 @@
# AsyncIterable,
# Coroutine,
# Collection,
# ContextManager
# ContextManager,
# AsyncGenerator,

# Structural checks, a.k.a. protocols.
'Reversible',
Expand Down Expand Up @@ -1900,6 +1901,13 @@ def __new__(cls, *args, **kwds):
"create a subclass instead")
return _generic_new(_G_base, cls, *args, **kwds)

if hasattr(collections_abc, 'AsyncGenerator'):
class AsyncGenerator(AsyncIterator[T_co], Generic[T_co, T_contra],
extra=collections_abc.AsyncGenerator):
__slots__ = ()

__all__.append('AsyncGenerator')


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

0 comments on commit e9ed560

Please sign in to comment.