Skip to content

Commit

Permalink
Avoid logging exception from run_app() that is also raised (#8951) (#…
Browse files Browse the repository at this point in the history
…8975)

(cherry picked from commit 45d6e4f)
  • Loading branch information
Dreamsorcerer authored Sep 1, 2024
1 parent 87342c7 commit 1c1c0ea
Show file tree
Hide file tree
Showing 3 changed files with 28 additions and 5 deletions.
1 change: 1 addition & 0 deletions CHANGES/6807.bugfix.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Stopped logging exceptions from ``web.run_app()`` that would be raised regardless -- by :user:`Dreamsorcerer`.
13 changes: 9 additions & 4 deletions aiohttp/web.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import warnings
from argparse import ArgumentParser
from collections.abc import Iterable
from contextlib import suppress
from importlib import import_module
from typing import (
Any,
Expand Down Expand Up @@ -519,10 +520,14 @@ def run_app(
except (GracefulExit, KeyboardInterrupt): # pragma: no cover
pass
finally:
_cancel_tasks({main_task}, loop)
_cancel_tasks(asyncio.all_tasks(loop), loop)
loop.run_until_complete(loop.shutdown_asyncgens())
loop.close()
try:
main_task.cancel()
with suppress(asyncio.CancelledError):
loop.run_until_complete(main_task)
finally:
_cancel_tasks(asyncio.all_tasks(loop), loop)
loop.run_until_complete(loop.shutdown_asyncgens())
loop.close()


def main(argv: List[str]) -> None:
Expand Down
19 changes: 18 additions & 1 deletion tests/test_run_app.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
import subprocess
import sys
import time
from typing import Callable, NoReturn, Set
from typing import AsyncIterator, Callable, NoReturn, Set
from unittest import mock
from uuid import uuid4

Expand Down Expand Up @@ -906,6 +906,23 @@ async def init():
assert count == 3


def test_run_app_raises_exception(patched_loop: asyncio.AbstractEventLoop) -> None:
async def context(app: web.Application) -> AsyncIterator[None]:
raise RuntimeError("foo")
yield # pragma: no cover

app = web.Application()
app.cleanup_ctx.append(context)

with mock.patch.object(
patched_loop, "call_exception_handler", autospec=True, spec_set=True
) as m:
with pytest.raises(RuntimeError, match="foo"):
web.run_app(app, loop=patched_loop)

assert not m.called


class TestShutdown:
def raiser(self) -> NoReturn:
raise KeyboardInterrupt
Expand Down

0 comments on commit 1c1c0ea

Please sign in to comment.