summaryrefslogtreecommitdiffstats
path: root/Lib
diff options
context:
space:
mode:
authorGuido van Rossum <guido@python.org>2017-01-18 21:10:36 (GMT)
committerGuido van Rossum <guido@python.org>2017-01-18 21:10:36 (GMT)
commitc75340a8fda52007855ca143513d2252c8cb1574 (patch)
treea42b156e15813c1bc21576c819191a6add6ef555 /Lib
parentfa025f112f7467b124f7ac4be5e9c7bb3cc05ad8 (diff)
parent38a49bec7a2522773f907bcee76d5b1305ef2260 (diff)
downloadcpython-c75340a8fda52007855ca143513d2252c8cb1574.zip
cpython-c75340a8fda52007855ca143513d2252c8cb1574.tar.gz
cpython-c75340a8fda52007855ca143513d2252c8cb1574.tar.bz2
Issue #29198: add AsyncGenerator (Jelle Zijlstra) (3.6->3.7)
Diffstat (limited to 'Lib')
-rw-r--r--Lib/test/test_typing.py42
-rw-r--r--Lib/typing.py10
2 files changed, 51 insertions, 1 deletions
diff --git a/Lib/test/test_typing.py b/Lib/test/test_typing.py
index 44712b6..9ab42a3 100644
--- a/Lib/test/test_typing.py
+++ b/Lib/test/test_typing.py
@@ -1735,6 +1735,23 @@ class CollectionsAbcTests(BaseTestCase):
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):
@@ -1804,6 +1821,31 @@ class CollectionsAbcTests(BaseTestCase):
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):
diff --git a/Lib/typing.py b/Lib/typing.py
index 0aeb089..00ef440 100644
--- a/Lib/typing.py
+++ b/Lib/typing.py
@@ -51,7 +51,8 @@ __all__ = [
# AsyncIterable,
# Coroutine,
# Collection,
- # ContextManager
+ # ContextManager,
+ # AsyncGenerator,
# Structural checks, a.k.a. protocols.
'Reversible',
@@ -1900,6 +1901,13 @@ class Generator(Iterator[T_co], Generic[T_co, T_contra, V_co],
"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)