Message316085
asyncio.gather() returns a _GatheringFuture, which inherits from asyncio.Future. This is weird in current asyncio, as futures are supposed to be created with loop.create_future(). So I tried to reimplement gather() without this weird special future. I succeeded, yet I stumbled over weird inconsistencies with cancellation. There are three cases:
- coroutines have no special notion of cancellation, they treat CancelledError as any other exception
- futures have a clear distinction between exceptions and cancellation: future.set_exception(CancelledError()) is different from future.cancel(), as only for the latter future.cancelled() is True. This is used in the _GatheringFuture: it is cancelled() only if it got cancelled via future.cancel(), if its children gets cancelled it may set_exception(CancelledError()), but it will not be cancelled itself.
- Tasks consider raising a CancelledError always as a cancellation, whether it actually got cancelled or the wrapped coroutine raised CancelledError for whatever other reason. There is one exception: if the coroutine manages to return immediately after being cancelled, it raises a CancelledError, but task.cancelled() is false. So if a coroutine ends in
current_task().cancel()
return
the current task raises a CancelledError, but task.cancelled() is false.
I consider the last exception actually a bug, but it allows me to make my inheritance-free gather() look to the outside exactly like it used to be. |
|
Date |
User |
Action |
Args |
2018-05-02 18:39:18 | Martin.Teichmann | set | recipients:
+ Martin.Teichmann |
2018-05-02 18:39:18 | Martin.Teichmann | set | messageid: <1525286358.11.0.682650639539.issue33413@psf.upfronthosting.co.za> |
2018-05-02 18:39:18 | Martin.Teichmann | link | issue33413 messages |
2018-05-02 18:39:17 | Martin.Teichmann | create | |
|