Skip to content

Commit d5f2123

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

File tree

2 files changed

+83
-2
lines changed

2 files changed

+83
-2
lines changed

asyncio/core.py

+10
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

@@ -285,6 +291,10 @@ def run_until_complete(main_task=None):
285291
_task_queue.push_head(t)
286292
# Save return value of coro to pass up to caller.
287293
t.data = er
294+
if isinstance(er, StopIteration):
295+
t._result = er.value
296+
else:
297+
t._exception = er
288298
elif t.state is None:
289299
# Task is already finished and nothing await'ed on the task,
290300
# so call the exception handler.

asyncio/task.py

+73-2
Original file line numberDiff line numberDiff line change
@@ -145,6 +145,9 @@ class Task:
145145
"""
146146

147147
def __init__(self, coro, globals=None):
148+
self._exception = None
149+
self._result = None
150+
148151
self.coro = coro # Coroutine of this Task
149152
self.data = None # General data for queue it is waiting on
150153
self.state = True # None, False, True, a callable, or a TaskQueue instance
@@ -188,7 +191,7 @@ def done(self):
188191

189192
return not self.state
190193

191-
def cancel(self):
194+
def cancel(self, msg=None):
192195
"""Cancel the task by injecting a ``CancelledError`` into it. The task
193196
may or may not ignore this exception.
194197
"""
@@ -211,5 +214,73 @@ def cancel(self):
211214
# On the main running queue but scheduled in the future, so bring it forward to now.
212215
core._task_queue.remove(self)
213216
core._task_queue.push(self)
214-
self.data = core.CancelledError
217+
cancelled_error = core.CancelledError(msg)
218+
self.data = cancelled_error
219+
self._exception = cancelled_error
215220
return True
221+
222+
def get_coro(self):
223+
return self.coro
224+
225+
def add_done_callback(self, callback):
226+
raise NotImplementedError()
227+
228+
def remove_done_callback(self, callback):
229+
raise NotImplementedError()
230+
231+
def set_result(self, result):
232+
raise RuntimeError('Task does not support set_result operation')
233+
234+
def result(self):
235+
"""
236+
Return the result of the Task.
237+
238+
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.)
239+
240+
If the Task has been cancelled, this method raises a CancelledError exception.
241+
242+
If the Task’s result isn’t yet available, this method raises a InvalidStateError exception.
243+
244+
"""
245+
if not self.done():
246+
raise InvalidStateError()
247+
248+
exception = self.exception()
249+
250+
if exception is not None:
251+
raise exception
252+
253+
return self._result
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._exception, core.CancelledError):
272+
raise self._exception
273+
274+
return self._exception
275+
276+
def cancelled(self) -> bool:
277+
"""
278+
Return True if the Task is cancelled.
279+
280+
The Task is cancelled when the cancellation was requested with cancel() and
281+
the wrapped coroutine propagated the CancelledError exception thrown into it.
282+
"""
283+
if not self.done():
284+
return False
285+
286+
return isinstance(self._exception, core.CancelledError)

0 commit comments

Comments
 (0)