Skip to content

Add Coroutine generic ABC #312

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Oct 29, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions python2/test_typing.py
Original file line number Diff line number Diff line change
Expand Up @@ -490,6 +490,9 @@ def test_basics(self):
Y[unicode, unicode]

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):
Expand Down
3 changes: 3 additions & 0 deletions python2/typing.py
Original file line number Diff line number Diff line change
Expand Up @@ -1194,6 +1194,9 @@ def lookup_name(mapping: Mapping[KT, VT], key: KT, default: VT) -> VT:
__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)


Expand Down
23 changes: 22 additions & 1 deletion src/test_typing.py
Original file line number Diff line number Diff line change
Expand Up @@ -517,6 +517,9 @@ def test_basics(self):
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):
Expand Down Expand Up @@ -1255,7 +1258,7 @@ def blah():
ASYNCIO_TESTS = """
import asyncio

T_a = TypeVar('T')
T_a = TypeVar('T_a')

class AwaitableWrapper(typing.Awaitable[T_a]):

Expand Down Expand Up @@ -1403,6 +1406,24 @@ def test_awaitable(self):
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]
Expand Down
31 changes: 23 additions & 8 deletions src/typing.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,6 @@

# ABCs (from collections.abc).
'AbstractSet', # collections.abc.Set.
'Awaitable',
'AsyncIterator',
'AsyncIterable',
'ByteString',
'Container',
'Hashable',
Expand All @@ -47,6 +44,14 @@
'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',
Expand Down Expand Up @@ -1104,6 +1109,9 @@ def lookup_name(mapping: Mapping[KT, VT], key: KT, default: VT) -> VT:
__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)


Expand Down Expand Up @@ -1639,8 +1647,16 @@ class _Protocol(metaclass=_ProtocolMeta):
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'):
Expand All @@ -1652,9 +1668,8 @@ class AsyncIterator(AsyncIterable[T_co],
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):
Expand Down