|
2 | 2 |
|
3 | 3 | from __future__ import annotations
|
4 | 4 |
|
5 |
| -from asyncio import ensure_future, gather, shield, wait_for |
| 5 | +from asyncio import ( |
| 6 | + CancelledError, |
| 7 | + create_task, |
| 8 | + ensure_future, |
| 9 | + gather, |
| 10 | + shield, |
| 11 | + wait_for, |
| 12 | +) |
6 | 13 | from contextlib import suppress
|
7 | 14 | from copy import copy
|
8 | 15 | from typing import (
|
@@ -459,12 +466,23 @@ async def get_results() -> dict[str, Any]:
|
459 | 466 | field = awaitable_fields[0]
|
460 | 467 | results[field] = await results[field]
|
461 | 468 | else:
|
462 |
| - results.update( |
463 |
| - zip( |
464 |
| - awaitable_fields, |
465 |
| - await gather(*(results[field] for field in awaitable_fields)), |
466 |
| - ) |
467 |
| - ) |
| 469 | + tasks = { |
| 470 | + create_task(results[field]): field # type: ignore[arg-type] |
| 471 | + for field in awaitable_fields |
| 472 | + } |
| 473 | + |
| 474 | + try: |
| 475 | + awaited_results = await gather(*tasks) |
| 476 | + except Exception: |
| 477 | + # Cancel unfinished tasks before raising the exception |
| 478 | + for task in tasks: |
| 479 | + if not task.done(): |
| 480 | + task.cancel() |
| 481 | + await gather(*tasks, return_exceptions=True) |
| 482 | + raise |
| 483 | + |
| 484 | + results.update(zip(awaitable_fields, awaited_results)) |
| 485 | + |
468 | 486 | return results
|
469 | 487 |
|
470 | 488 | return get_results()
|
@@ -538,6 +556,10 @@ async def await_completed() -> Any:
|
538 | 556 | try:
|
539 | 557 | return await completed
|
540 | 558 | except Exception as raw_error:
|
| 559 | + # Before Python 3.8 CancelledError inherits Exception and |
| 560 | + # so gets caught here. |
| 561 | + if isinstance(raw_error, CancelledError): |
| 562 | + raise # pragma: no cover |
541 | 563 | self.handle_field_error(
|
542 | 564 | raw_error,
|
543 | 565 | return_type,
|
@@ -745,6 +767,10 @@ async def complete_awaitable_value(
|
745 | 767 | if self.is_awaitable(completed):
|
746 | 768 | completed = await completed
|
747 | 769 | except Exception as raw_error:
|
| 770 | + # Before Python 3.8 CancelledError inherits Exception and |
| 771 | + # so gets caught here. |
| 772 | + if isinstance(raw_error, CancelledError): |
| 773 | + raise # pragma: no cover |
748 | 774 | self.handle_field_error(
|
749 | 775 | raw_error, return_type, field_group, path, incremental_data_record
|
750 | 776 | )
|
|
0 commit comments