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 <[email protected]>
<http://bugs.python.org/issue24017>
_______________________________________
_______________________________________________
Python-bugs-list mailing list
Unsubscribe:
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com