Skip to content

Commit 62fe1bb

Browse files
committed
Issue #28556: updates to typing.py (add Coroutine, prohibit Generic[T]())
1 parent b7dedc8 commit 62fe1bb

File tree

2 files changed

+45
-9
lines changed

2 files changed

+45
-9
lines changed

Lib/test/test_typing.py

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -517,6 +517,9 @@ def test_basics(self):
517517
Y[str, str]
518518

519519
def test_generic_errors(self):
520+
T = TypeVar('T')
521+
with self.assertRaises(TypeError):
522+
Generic[T]()
520523
with self.assertRaises(TypeError):
521524
isinstance([], List[int])
522525
with self.assertRaises(TypeError):
@@ -1255,7 +1258,7 @@ def blah():
12551258
ASYNCIO_TESTS = """
12561259
import asyncio
12571260
1258-
T_a = TypeVar('T')
1261+
T_a = TypeVar('T_a')
12591262
12601263
class AwaitableWrapper(typing.Awaitable[T_a]):
12611264
@@ -1403,6 +1406,24 @@ def test_awaitable(self):
14031406
self.assertNotIsInstance(foo, typing.Awaitable)
14041407
g.send(None) # Run foo() till completion, to avoid warning.
14051408

1409+
@skipUnless(ASYNCIO, 'Python 3.5 and multithreading required')
1410+
def test_coroutine(self):
1411+
ns = {}
1412+
exec(
1413+
"async def foo():\n"
1414+
" return\n",
1415+
globals(), ns)
1416+
foo = ns['foo']
1417+
g = foo()
1418+
self.assertIsInstance(g, typing.Coroutine)
1419+
with self.assertRaises(TypeError):
1420+
isinstance(g, typing.Coroutine[int])
1421+
self.assertNotIsInstance(foo, typing.Coroutine)
1422+
try:
1423+
g.send(None)
1424+
except StopIteration:
1425+
pass
1426+
14061427
@skipUnless(ASYNCIO, 'Python 3.5 and multithreading required')
14071428
def test_async_iterable(self):
14081429
base_it = range(10) # type: Iterator[int]

Lib/typing.py

Lines changed: 23 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -29,9 +29,6 @@
2929

3030
# ABCs (from collections.abc).
3131
'AbstractSet', # collections.abc.Set.
32-
'Awaitable',
33-
'AsyncIterator',
34-
'AsyncIterable',
3532
'ByteString',
3633
'Container',
3734
'Hashable',
@@ -47,6 +44,14 @@
4744
'Sequence',
4845
'Sized',
4946
'ValuesView',
47+
# The following are added depending on presence
48+
# of their non-generic counterparts in stdlib:
49+
# Awaitable,
50+
# AsyncIterator,
51+
# AsyncIterable,
52+
# Coroutine,
53+
# Collection,
54+
# ContextManager
5055

5156
# Structural checks, a.k.a. protocols.
5257
'Reversible',
@@ -1104,6 +1109,9 @@ def lookup_name(mapping: Mapping[KT, VT], key: KT, default: VT) -> VT:
11041109
__slots__ = ()
11051110

11061111
def __new__(cls, *args, **kwds):
1112+
if _geqv(cls, Generic):
1113+
raise TypeError("Type Generic cannot be instantiated; "
1114+
"it can be used only as a base class")
11071115
return _generic_new(cls.__next_in_mro__, cls, *args, **kwds)
11081116

11091117

@@ -1639,8 +1647,16 @@ class _Protocol(metaclass=_ProtocolMeta):
16391647
if hasattr(collections_abc, 'Awaitable'):
16401648
class Awaitable(Generic[T_co], extra=collections_abc.Awaitable):
16411649
__slots__ = ()
1642-
else:
1643-
Awaitable = None
1650+
1651+
__all__.append('Awaitable')
1652+
1653+
1654+
if hasattr(collections_abc, 'Coroutine'):
1655+
class Coroutine(Awaitable[V_co], Generic[T_co, T_contra, V_co],
1656+
extra=collections_abc.Coroutine):
1657+
__slots__ = ()
1658+
1659+
__all__.append('Coroutine')
16441660

16451661

16461662
if hasattr(collections_abc, 'AsyncIterable'):
@@ -1652,9 +1668,8 @@ class AsyncIterator(AsyncIterable[T_co],
16521668
extra=collections_abc.AsyncIterator):
16531669
__slots__ = ()
16541670

1655-
else:
1656-
AsyncIterable = None
1657-
AsyncIterator = None
1671+
__all__.append('AsyncIterable')
1672+
__all__.append('AsyncIterator')
16581673

16591674

16601675
class Iterable(Generic[T_co], extra=collections_abc.Iterable):

0 commit comments

Comments
 (0)