Skip to content

Commit 9a63a27

Browse files
committed
feat: support task methods for exception and result
1 parent c277db5 commit 9a63a27

File tree

2 files changed

+89
-2
lines changed

2 files changed

+89
-2
lines changed

asyncio/core.py

+6
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,12 @@ class CancelledError(BaseException):
3535
pass
3636

3737

38+
class InvalidStateError(Exception):
39+
"""Can be raised in situations like setting a result value for a task object that already has a result value set."""
40+
41+
pass
42+
43+
3844
class TimeoutError(Exception):
3945
"""Raised when waiting for a task longer than the specified timeout."""
4046

asyncio/task.py

+83-2
Original file line numberDiff line numberDiff line change
@@ -188,7 +188,7 @@ def done(self):
188188

189189
return not self.state
190190

191-
def cancel(self):
191+
def cancel(self, msg=None):
192192
"""Cancel the task by injecting a ``CancelledError`` into it. The task
193193
may or may not ignore this exception.
194194
"""
@@ -211,5 +211,86 @@ def cancel(self):
211211
# On the main running queue but scheduled in the future, so bring it forward to now.
212212
core._task_queue.remove(self)
213213
core._task_queue.push(self)
214-
self.data = core.CancelledError
214+
cancelled_error = core.CancelledError(msg)
215+
self.data = cancelled_error
215216
return True
217+
218+
def get_coro(self):
219+
return self.coro
220+
221+
def add_done_callback(self, callback):
222+
raise NotImplementedError()
223+
224+
def remove_done_callback(self, callback):
225+
raise NotImplementedError()
226+
227+
def set_result(self, result):
228+
raise RuntimeError('Task does not support set_result operation')
229+
230+
def result(self):
231+
"""
232+
Return the result of the Task.
233+
234+
If the Task is done, the result of the wrapped coroutine is returned (or if the coroutine raised an exception, that exception is re-raised.)
235+
236+
If the Task has been cancelled, this method raises a CancelledError exception.
237+
238+
If the Task’s result isn’t yet available, this method raises a InvalidStateError exception.
239+
240+
"""
241+
if not self.done():
242+
raise InvalidStateError()
243+
244+
exception = self.exception()
245+
246+
if exception is not None:
247+
raise exception
248+
249+
if not isinstance(self.data, StopIteration):
250+
# If this isn't the case then we're in an odd state.
251+
return None
252+
253+
return self.data.value
254+
255+
def set_exception(self, exception):
256+
raise RuntimeError('Task does not support set_exception operation')
257+
258+
def exception(self):
259+
"""
260+
Return the exception that was set on this Task.
261+
262+
The exception (or None if no exception was set) is returned only if the Task is done.
263+
264+
If the Task has been cancelled, this method raises a CancelledError exception.
265+
266+
If the Task isn’t done yet, this method raises an InvalidStateError exception.
267+
"""
268+
if not self.done():
269+
raise InvalidStateError()
270+
271+
if isinstance(self.data, core.CancelledError):
272+
raise self.data
273+
274+
if isinstance(self.data, StopIteration):
275+
# If the data is a stop iteration we can assume this
276+
# was a successful run rather than any possible exception
277+
return None
278+
279+
if not isinstance(self.data, BaseException):
280+
# If the data is not any type of exception we can treat it as
281+
# something else we don't understand but not an exception.
282+
return None
283+
284+
return self.data
285+
286+
def cancelled(self) -> bool:
287+
"""
288+
Return True if the Task is cancelled.
289+
290+
The Task is cancelled when the cancellation was requested with cancel() and
291+
the wrapped coroutine propagated the CancelledError exception thrown into it.
292+
"""
293+
if not self.done():
294+
return False
295+
296+
return isinstance(self.data, core.CancelledError)

0 commit comments

Comments
 (0)