]> granicus.if.org Git - python/commitdiff
Issue #28556: updates to typing.py (add Coroutine, prohibit Generic[T]())
authorGuido van Rossum <guido@python.org>
Sat, 29 Oct 2016 23:05:26 +0000 (16:05 -0700)
committerGuido van Rossum <guido@python.org>
Sat, 29 Oct 2016 23:05:26 +0000 (16:05 -0700)
Lib/test/test_typing.py
Lib/typing.py

index b50f36679d315735a4ea4ff626ce8f23cd5d552b..7a5b415baef4af3b79150592cc231663989069d2 100644 (file)
@@ -517,6 +517,9 @@ class GenericTests(BaseTestCase):
             Y[str, str]
 
     def test_generic_errors(self):
+        T = TypeVar('T')
+        with self.assertRaises(TypeError):
+            Generic[T]()
         with self.assertRaises(TypeError):
             isinstance([], List[int])
         with self.assertRaises(TypeError):
@@ -1255,7 +1258,7 @@ ASYNCIO = sys.version_info[:2] >= (3, 5)
 ASYNCIO_TESTS = """
 import asyncio
 
-T_a = TypeVar('T')
+T_a = TypeVar('T_a')
 
 class AwaitableWrapper(typing.Awaitable[T_a]):
 
@@ -1403,6 +1406,24 @@ class CollectionsAbcTests(BaseTestCase):
         self.assertNotIsInstance(foo, typing.Awaitable)
         g.send(None)  # Run foo() till completion, to avoid warning.
 
+    @skipUnless(ASYNCIO, 'Python 3.5 and multithreading required')
+    def test_coroutine(self):
+        ns = {}
+        exec(
+            "async def foo():\n"
+            "    return\n",
+            globals(), ns)
+        foo = ns['foo']
+        g = foo()
+        self.assertIsInstance(g, typing.Coroutine)
+        with self.assertRaises(TypeError):
+            isinstance(g, typing.Coroutine[int])
+        self.assertNotIsInstance(foo, typing.Coroutine)
+        try:
+            g.send(None)
+        except StopIteration:
+            pass
+
     @skipUnless(ASYNCIO, 'Python 3.5 and multithreading required')
     def test_async_iterable(self):
         base_it = range(10)  # type: Iterator[int]
index 572708b5ed6f89dab81d8cc994017129761a671e..2a1ea081f2d612282ce94d74cd4a3c35fefb5a7d 100644 (file)
@@ -29,9 +29,6 @@ __all__ = [
 
     # ABCs (from collections.abc).
     'AbstractSet',  # collections.abc.Set.
-    'Awaitable',
-    'AsyncIterator',
-    'AsyncIterable',
     'ByteString',
     'Container',
     'Hashable',
@@ -47,6 +44,14 @@ __all__ = [
     'Sequence',
     'Sized',
     'ValuesView',
+    # The following are added depending on presence
+    # of their non-generic counterparts in stdlib:
+    # Awaitable,
+    # AsyncIterator,
+    # AsyncIterable,
+    # Coroutine,
+    # Collection,
+    # ContextManager
 
     # Structural checks, a.k.a. protocols.
     'Reversible',
@@ -1104,6 +1109,9 @@ class Generic(metaclass=GenericMeta):
     __slots__ = ()
 
     def __new__(cls, *args, **kwds):
+        if _geqv(cls, Generic):
+            raise TypeError("Type Generic cannot be instantiated; "
+                            "it can be used only as a base class")
         return _generic_new(cls.__next_in_mro__, cls, *args, **kwds)
 
 
@@ -1639,8 +1647,16 @@ Hashable = collections_abc.Hashable  # Not generic.
 if hasattr(collections_abc, 'Awaitable'):
     class Awaitable(Generic[T_co], extra=collections_abc.Awaitable):
         __slots__ = ()
-else:
-    Awaitable = None
+
+    __all__.append('Awaitable')
+
+
+if hasattr(collections_abc, 'Coroutine'):
+    class Coroutine(Awaitable[V_co], Generic[T_co, T_contra, V_co],
+                    extra=collections_abc.Coroutine):
+        __slots__ = ()
+
+    __all__.append('Coroutine')
 
 
 if hasattr(collections_abc, 'AsyncIterable'):
@@ -1652,9 +1668,8 @@ if hasattr(collections_abc, 'AsyncIterable'):
                         extra=collections_abc.AsyncIterator):
         __slots__ = ()
 
-else:
-    AsyncIterable = None
-    AsyncIterator = None
+    __all__.append('AsyncIterable')
+    __all__.append('AsyncIterator')
 
 
 class Iterable(Generic[T_co], extra=collections_abc.Iterable):