(self, task)
| 226 | t.cancel() |
| 227 | |
| 228 | def _on_task_done(self, task): |
| 229 | self._tasks.discard(task) |
| 230 | |
| 231 | futures.future_discard_from_awaited_by(task, self._parent_task) |
| 232 | |
| 233 | if self._on_completed_fut is not None and not self._tasks: |
| 234 | if not self._on_completed_fut.done(): |
| 235 | self._on_completed_fut.set_result(True) |
| 236 | |
| 237 | if task.cancelled(): |
| 238 | return |
| 239 | |
| 240 | exc = task.exception() |
| 241 | if exc is None: |
| 242 | return |
| 243 | |
| 244 | self._errors.append(exc) |
| 245 | if self._is_base_error(exc) and self._base_error is None: |
| 246 | self._base_error = exc |
| 247 | |
| 248 | if self._parent_task.done(): |
| 249 | # Not sure if this case is possible, but we want to handle |
| 250 | # it anyways. |
| 251 | self._loop.call_exception_handler({ |
| 252 | 'message': f'Task {task!r} has errored out but its parent ' |
| 253 | f'task {self._parent_task} is already completed', |
| 254 | 'exception': exc, |
| 255 | 'task': task, |
| 256 | }) |
| 257 | return |
| 258 | |
| 259 | if not self._aborting and not self._parent_cancel_requested: |
| 260 | # If parent task *is not* being cancelled, it means that we want |
| 261 | # to manually cancel it to abort whatever is being run right now |
| 262 | # in the TaskGroup. But we want to mark parent task as |
| 263 | # "not cancelled" later in __aexit__. Example situation that |
| 264 | # we need to handle: |
| 265 | # |
| 266 | # async def foo(): |
| 267 | # try: |
| 268 | # async with TaskGroup() as g: |
| 269 | # g.create_task(crash_soon()) |
| 270 | # await something # <- this needs to be canceled |
| 271 | # # by the TaskGroup, e.g. |
| 272 | # # foo() needs to be cancelled |
| 273 | # except Exception: |
| 274 | # # Ignore any exceptions raised in the TaskGroup |
| 275 | # pass |
| 276 | # await something_else # this line has to be called |
| 277 | # # after TaskGroup is finished. |
| 278 | self._abort() |
| 279 | self._parent_cancel_requested = True |
| 280 | self._parent_task.cancel() |
nothing calls this directly
no test coverage detected