Skip to content

Commit 2edc23b

Browse files
author
Roy Williams
committed
Add Async classes to typehinting.
1 parent 3819cbc commit 2edc23b

File tree

3 files changed

+79
-0
lines changed

3 files changed

+79
-0
lines changed

pep-0484.txt

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1256,6 +1256,12 @@ collection types defined below, e.g. ``Mapping``, ``Sequence`` or
12561256

12571257
Generic variants of container ABCs (and a few non-containers):
12581258

1259+
* Awaitable
1260+
1261+
* AsyncIterable
1262+
1263+
* AsyncIterator
1264+
12591265
* ByteString
12601266

12611267
* Callable (see above, listed here for completeness)

src/test_typing.py

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import asyncio
12
import pickle
23
import re
34
import sys
@@ -959,6 +960,34 @@ def blah():
959960
pass
960961

961962

963+
T_a = TypeVar('T')
964+
965+
966+
class AwaitableWrapper(typing.Awaitable[T_a]):
967+
def __init__(self, value):
968+
self.value = value
969+
970+
def __await__(self) -> typing.Iterator[T_a]:
971+
yield
972+
return self.value
973+
974+
975+
class AsyncIteratorWrapper(typing.AsyncIterator[T_a]):
976+
def __init__(self, value: typing.Iterable[T_a]):
977+
self.value = value
978+
979+
def __aiter__(self) -> typing.AsyncIterator[T_a]:
980+
return self
981+
982+
@asyncio.coroutine
983+
def __anext__(self) -> T_a:
984+
data = yield from self.value
985+
if data:
986+
return data
987+
else:
988+
raise StopAsyncIteration
989+
990+
962991
class CollectionsAbcTests(TestCase):
963992

964993
def test_hashable(self):
@@ -983,6 +1012,35 @@ def test_iterator(self):
9831012
assert isinstance(it, typing.Iterator[int])
9841013
assert not isinstance(42, typing.Iterator)
9851014

1015+
def test_awaitable(self):
1016+
async def foo() -> typing.Awaitable[int]:
1017+
return await AwaitableWrapper(42)
1018+
g = foo()
1019+
assert issubclass(type(g), typing.Awaitable[int])
1020+
assert isinstance(g, typing.Awaitable)
1021+
assert not isinstance(foo, typing.Awaitable)
1022+
assert issubclass(typing.Awaitable[Manager],
1023+
typing.Awaitable[Employee])
1024+
assert not issubclass(typing.Awaitable[Employee],
1025+
typing.Awaitable[Manager])
1026+
1027+
def test_async_iterable(self):
1028+
base_it = range(10) # type: Iterator[int]
1029+
it = AsyncIteratorWrapper(base_it)
1030+
assert isinstance(it, typing.AsyncIterable)
1031+
assert isinstance(it, typing.AsyncIterable)
1032+
assert issubclass(typing.AsyncIterable[Manager],
1033+
typing.AsyncIterable[Employee])
1034+
assert not isinstance(42, typing.AsyncIterable)
1035+
1036+
def test_async_iterator(self):
1037+
base_it = range(10) # type: Iterator[int]
1038+
it = AsyncIteratorWrapper(base_it)
1039+
assert isinstance(it, typing.AsyncIterator)
1040+
assert issubclass(typing.AsyncIterator[Manager],
1041+
typing.AsyncIterator[Employee])
1042+
assert not isinstance(42, typing.AsyncIterator)
1043+
9861044
def test_sized(self):
9871045
assert isinstance([], typing.Sized)
9881046
assert not isinstance(42, typing.Sized)

src/typing.py

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,9 @@
2828

2929
# ABCs (from collections.abc).
3030
'AbstractSet', # collections.abc.Set.
31+
'Awaitable',
32+
'AsyncIterator',
33+
'AsyncIterable',
3134
'ByteString',
3235
'Container',
3336
'Hashable',
@@ -1261,6 +1264,18 @@ class _Protocol(metaclass=_ProtocolMeta):
12611264
Hashable = collections_abc.Hashable # Not generic.
12621265

12631266

1267+
class Awaitable(Generic[T_co], extra=collections_abc.Awaitable):
1268+
__slots__ = ()
1269+
1270+
1271+
class AsyncIterable(Generic[T_co], extra=collections_abc.AsyncIterable):
1272+
__slots__ = ()
1273+
1274+
1275+
class AsyncIterator(AsyncIterable[T_co], extra=collections_abc.AsyncIterator):
1276+
__slots__ = ()
1277+
1278+
12641279
class Iterable(Generic[T_co], extra=collections_abc.Iterable):
12651280
__slots__ = ()
12661281

0 commit comments

Comments
 (0)