Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion src/async_kernel/pending.py
Original file line number Diff line number Diff line change
Expand Up @@ -206,6 +206,7 @@ class PendingGroup(PendingTracker, anyio.AsyncContextManagerMixin):
_cancel_scope: anyio.CancelScope
_cancelled: str | None = None
_leaving_context: bool = False
_failed: Fixed[Self, list[Pending]] = Fixed(list)
cancellation_timeout = 10
"The maximum time to wait for cancelled pending to be done."

Expand Down Expand Up @@ -236,7 +237,9 @@ async def __asynccontextmanager__(self) -> AsyncGenerator[Self]:
self.cancel(f"An error occurred: {e!r}")
raise
if self._cancelled is not None:
raise PendingCancelled(self._cancelled)
exceptions = [e for pen in self._failed if isinstance(e := pen.exception(), Exception)]
msg = "One or more exceptions occurred in this context!"
raise ExceptionGroup(msg, exceptions)
finally:
self._leaving_context = True
self._stop_tracking(token)
Expand All @@ -261,6 +264,7 @@ def on_pending_done(self, pen: Pending) -> None:
try:
self._pending.remove(pen)
if self._active and (not pen.cancelled() and (pen.exception())):
self._failed.append(pen)
self.cancel(f"Exception in member: {pen}")
except KeyError:
pass
Expand Down
12 changes: 5 additions & 7 deletions tests/test_pending.py
Original file line number Diff line number Diff line change
Expand Up @@ -420,14 +420,14 @@ async def add_when_cancelled():
assert not pm.active

async def test_wait_exception(self, caller: Caller):
with pytest.raises(PendingCancelled): # noqa: PT012
with pytest.raises(ExceptionGroup): # noqa: PT012
async with PendingGroup():
pen = caller.call_soon(anyio.sleep_forever)
Pending(PendingGroup).set_exception(RuntimeError("stop"))
assert pen.cancelled() # pyright: ignore[reportPossiblyUnboundVariable]

async def test_cancelled_by_pending(self, caller: Caller):
with pytest.raises(PendingCancelled): # noqa: PT012
with pytest.raises(ExceptionGroup): # noqa: PT012
async with PendingGroup() as pg:
assert caller.call_soon(lambda: 1 / 0) in pg.pending
await anyio.sleep_forever()
Expand Down Expand Up @@ -473,11 +473,9 @@ async def test_nested(self, caller: Caller):
assert pen.cancelled() # pyright: ignore[reportPossiblyUnboundVariable]

async def test_nested_raises(self, caller: Caller):
with pytest.raises(PendingCancelled, match="division by zero"): # noqa: PT012
async with caller.create_pending_group() as pg1:
async with pg1.caller.create_pending_group() as pg2:
pen = pg2.caller.call_soon(lambda: 1 / 0)

with pytest.raises(ExceptionGroup):
async with caller.create_pending_group() as pg1, pg1.caller.create_pending_group() as pg2:
pen = pg2.caller.call_soon(lambda: 1 / 0)
assert pen.exception() # pyright: ignore[reportPossiblyUnboundVariable]

async def test_queue(self, caller: Caller):
Expand Down
Loading