This issue tracker has been migrated to GitHub, and is currently read-only.
For more information, see the GitHub FAQs in the Python's Developer Guide.

Author yselivanov
Recipients asvetlov, gvanrossum, ncoghlan, python-dev, scoder, vstinner, yselivanov
Date 2015-05-28.03:54:41
SpamBayes Score -1.0
Marked as misclassified Yes
Message-id <1432785281.63.0.593517313764.issue24017@psf.upfronthosting.co.za>
In-reply-to
Content
> 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?

It *is* correct, see PEP 492.  Awaitable is either a coroutine *or* an object with an __await__ method.  Generally, being an awaitable means that the object can be used in "await" expression.


> 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):

Just implement tp_await/__await__ for coroutine-like objects coming from C-API or Cython.  In general, iteration protocol is still the foundation for Future-like objects, so there is nothing wrong with this.

Generator ABC isn't supposed to be used with "await" expression.


> 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.)

Coroutines are implemented on top of generators.  Until we clearly separate them (in 3.6?) I don't think we should allow coroutines to bubble up StopIteration.

> 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.

This is a special backwards-compatibility thing.  In general, generators cannot yield-from coroutines (unless they are decorated with @types.coroutine).
History
Date User Action Args
2015-05-28 03:54:41yselivanovsetrecipients: + yselivanov, gvanrossum, ncoghlan, scoder, vstinner, asvetlov, python-dev
2015-05-28 03:54:41yselivanovsetmessageid: <1432785281.63.0.593517313764.issue24017@psf.upfronthosting.co.za>
2015-05-28 03:54:41yselivanovlinkissue24017 messages
2015-05-28 03:54:41yselivanovcreate