21
21
from . import core
22
22
23
23
24
+ class CancelledError (BaseException ):
25
+ """Injected into a task when calling `Task.cancel()`"""
26
+
27
+ pass
28
+
29
+
30
+ class InvalidStateError (Exception ):
31
+ """Can be raised in situations like setting a result value for a task object that already has a result value set."""
32
+
33
+ pass
34
+
35
+
24
36
# pairing-heap meld of 2 heaps; O(1)
25
37
def ph_meld (h1 , h2 ):
26
38
if h1 is None :
@@ -188,7 +200,7 @@ def done(self):
188
200
189
201
return not self .state
190
202
191
- def cancel (self ):
203
+ def cancel (self , msg = None ):
192
204
"""Cancel the task by injecting a ``CancelledError`` into it. The task
193
205
may or may not ignore this exception.
194
206
"""
@@ -211,5 +223,85 @@ def cancel(self):
211
223
# On the main running queue but scheduled in the future, so bring it forward to now.
212
224
core ._task_queue .remove (self )
213
225
core ._task_queue .push (self )
214
- self .data = core . CancelledError
226
+ self .data = CancelledError ( msg ) if msg else CancelledError ()
215
227
return True
228
+
229
+ def get_coro (self ):
230
+ return self .coro
231
+
232
+ def add_done_callback (self , callback ):
233
+ raise NotImplementedError ()
234
+
235
+ def remove_done_callback (self , callback ):
236
+ raise NotImplementedError ()
237
+
238
+ def set_result (self , result ):
239
+ raise RuntimeError ('Task does not support set_result operation' )
240
+
241
+ def result (self ):
242
+ """
243
+ Return the result of the Task.
244
+
245
+ 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.)
246
+
247
+ If the Task has been cancelled, this method raises a CancelledError exception.
248
+
249
+ If the Task’s result isn’t yet available, this method raises a InvalidStateError exception.
250
+
251
+ """
252
+ if not self .done ():
253
+ raise InvalidStateError ()
254
+
255
+ exception = self .exception ()
256
+
257
+ if exception is not None :
258
+ raise exception
259
+
260
+ if not isinstance (self .data , StopIteration ):
261
+ # If this isn't the case then we're in an odd state.
262
+ return None
263
+
264
+ return self .data .value
265
+
266
+ def set_exception (self , exception ):
267
+ raise RuntimeError ('Task does not support set_exception operation' )
268
+
269
+ def exception (self ):
270
+ """
271
+ Return the exception that was set on this Task.
272
+
273
+ The exception (or None if no exception was set) is returned only if the Task is done.
274
+
275
+ If the Task has been cancelled, this method raises a CancelledError exception.
276
+
277
+ If the Task isn’t done yet, this method raises an InvalidStateError exception.
278
+ """
279
+ if not self .done ():
280
+ raise InvalidStateError ()
281
+
282
+ if isinstance (self .data , core .CancelledError ):
283
+ raise self .data
284
+
285
+ if isinstance (self .data , StopIteration ):
286
+ # If the data is a stop iteration we can assume this
287
+ # was a successful run rather than any possible exception
288
+ return None
289
+
290
+ if not isinstance (self .data , BaseException ):
291
+ # If the data is not any type of exception we can treat it as
292
+ # something else we don't understand but not an exception.
293
+ return None
294
+
295
+ return self .data
296
+
297
+ def cancelled (self ) -> bool :
298
+ """
299
+ Return True if the Task is cancelled.
300
+
301
+ The Task is cancelled when the cancellation was requested with cancel() and
302
+ the wrapped coroutine propagated the CancelledError exception thrown into it.
303
+ """
304
+ if not self .done ():
305
+ return False
306
+
307
+ return isinstance (self .data , core .CancelledError )
0 commit comments