| Index: asyncio/futures.py |
| =================================================================== |
| --- a/asyncio/futures.py |
| +++ b/asyncio/futures.py |
| @@ -183,7 +183,7 @@ |
| } |
| self._loop.call_exception_handler(context) |
| - def cancel(self): |
| + def cancel(self, exc=None): |
| """Cancel the future and schedule callbacks. |
| If the future is already done or cancelled, return False. Otherwise, |
| @@ -192,6 +192,13 @@ |
| """ |
| if self._state != _PENDING: |
| return False |
| + if exc is None: |
| + exc = CancelledError |
| + elif (not isinstance(exc, CancelledError) and |
| + not isinstance(exc, type) and |
| + not issubclass(exc, CancelledError)): |
| + raise ValueError('exc must subclass CancelledError') |
| + self._exception = exc |
| self._state = _CANCELLED |
| self._schedule_callbacks() |
| return True |
| @@ -232,7 +239,7 @@ |
| the future is done and has an exception set, this exception is raised. |
| """ |
| if self._state == _CANCELLED: |
| - raise CancelledError |
| + raise self._exception |
| if self._state != _FINISHED: |
| raise InvalidStateError('Result is not ready.') |
| self._log_traceback = False |
| @@ -252,7 +259,7 @@ |
| InvalidStateError. |
| """ |
| if self._state == _CANCELLED: |
| - raise CancelledError |
| + raise self._exception |
| if self._state != _FINISHED: |
| raise InvalidStateError('Exception is not set.') |
| self._log_traceback = False |
| @@ -333,7 +340,7 @@ |
| return |
| assert not self.done() |
| if other.cancelled(): |
| - self.cancel() |
| + self.cancel(self._exception) |
| else: |
| exception = other.exception() |
| if exception is not None: |
| @@ -362,6 +369,8 @@ |
| def _check_cancel_other(f): |
| if f.cancelled(): |
| + # concurrent.futures.Future.cancel() doesn't support custom |
| + # exceptions so we can't pass f._exception here. |
| fut.cancel() |
| new_future.add_done_callback(_check_cancel_other) |