Stefan Behnel added the comment: I added a couple of review comments to patch 6, but since no-one has responded so far, I guess they simply haven't been noticed. So I'll just repeat them here.
1) getawaitablefunc / aiternextfunc / getaiterfunc Is there a reason why these need to have their specific C type name instead of just reusing unaryfunc, or at least the existing iternextfunc / getiterfunc? They are unprefixed global names in the C namespace and I think we should be careful when adding more of those. 2) Awaitable.register(Coroutine) I think this is incorrect. A Coroutine is not Awaitable unless it also implements "__await__". How else should it be awaited? 3) I propose to use this wrapping code as a fallback for types.coroutine() in the case that a Generator (ABC) is passed instead of a generator (yield): class types_coroutine(object): def __init__(self, gen): self._gen = gen class as_coroutine(object): def __init__(self, gen): self._gen = gen self.send = gen.send self.throw = gen.throw self.close = gen.close def __await__(self): return self._gen def __call__(self, *args, **kwargs): return self.as_coroutine(self._gen(*args, **kwargs)) Note that the resulting Awaitable Coroutine type is not an Iterable. This differs from a (yield) coroutine, but it matches the Coroutine and Awaitable protocols, and the intention to separate both in order to avoid mistakes on user side. Additionally, regarding the tests: 4) def test_func_2(self): async def foo(): raise StopIteration with self.assertRaisesRegex( RuntimeError, "generator raised StopIteration"): run_async(foo()) Why is this actually necessary? I'm aware that it's also mentioned in the PEP, but is there an actual reason why a coroutine should behave the same as a generator here? Is it just an implementation detail for legacy reasons because generators and coroutines happen to share the same type implementation? (I don't think they need to, BTW.) 5) def test_func_8(self): @types.coroutine def bar(): return (yield from foo()) async def foo(): return 'spam' self.assertEqual(run_async(bar()), ([], 'spam') ) I find it surprising that this works at all. Yield-from iterates, and a coroutine is not supposed to be iterable, only awaitable (at least, that's what all error messages tell me when I try it). So why should "yield from" work on them? What if foo() was not an Iterable but a Coroutine? Should "yield from" then call "__await__" on it internally? I would find that *really* surprising, but given the above, I think it would be necessary to achieve consistency. ---------- _______________________________________ Python tracker <rep...@bugs.python.org> <http://bugs.python.org/issue24017> _______________________________________ _______________________________________________ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com