Message244252
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. |
|
Date |
User |
Action |
Args |
2015-05-28 03:30:02 | scoder | set | recipients:
+ scoder, gvanrossum, ncoghlan, vstinner, asvetlov, python-dev, yselivanov |
2015-05-28 03:30:02 | scoder | set | messageid: <1432783802.3.0.484424800159.issue24017@psf.upfronthosting.co.za> |
2015-05-28 03:30:02 | scoder | link | issue24017 messages |
2015-05-28 03:30:02 | scoder | create | |
|