From a565318b925e38f0fea99e17b63399f72e064605 Mon Sep 17 00:00:00 2001 From: Sam Bull Date: Sat, 11 Nov 2023 22:03:39 +0000 Subject: [PATCH 1/6] Use AppKey --- aiohttp_devtools/logs.py | 2 +- aiohttp_devtools/runserver/serve.py | 49 +++++++++++++++++++---------- aiohttp_devtools/runserver/watch.py | 4 +-- requirements.txt | 1 + setup.py | 2 +- tests/test_runserver_main.py | 8 ++--- tests/test_runserver_serve.py | 47 +++++++++++++-------------- tests/test_runserver_watch.py | 13 +++++--- 8 files changed, 70 insertions(+), 56 deletions(-) diff --git a/aiohttp_devtools/logs.py b/aiohttp_devtools/logs.py index 53683d26..3087d528 100644 --- a/aiohttp_devtools/logs.py +++ b/aiohttp_devtools/logs.py @@ -80,7 +80,7 @@ def formatMessage(self, record: logging.LogRecord) -> str: def formatException(self, ei: _Ei) -> str: sio = StringIO() - traceback.print_exception(*ei, file=sio) # type: ignore[misc] + traceback.print_exception(*ei, file=sio) stack = sio.getvalue() sio.close() if self.stream_is_tty and pyg_lexer: diff --git a/aiohttp_devtools/runserver/serve.py b/aiohttp_devtools/runserver/serve.py index 353bcce2..f5c36c2c 100644 --- a/aiohttp_devtools/runserver/serve.py +++ b/aiohttp_devtools/runserver/serve.py @@ -3,9 +3,10 @@ import json import mimetypes import sys +import warnings from errno import EADDRINUSE from pathlib import Path -from typing import Any, Iterator, Optional, NoReturn +from typing import Any, Iterator, NoReturn, Optional, Set, Tuple from aiohttp import WSMsgType, web from aiohttp.hdrs import LAST_MODIFIED, CONTENT_LENGTH @@ -23,19 +24,37 @@ from .log_handlers import AccessLogger from .utils import MutableValue +try: + from aiohttp_jinja2 import static_root_key +except ImportError: + static_root_key = None + LIVE_RELOAD_HOST_SNIPPET = '\n\n' LIVE_RELOAD_LOCAL_SNIPPET = b'\n\n' HOST = '0.0.0.0' +LIVERELOAD_SCRIPT = web.AppKey("LIVERELOAD_SCRIPT", bytes) +STATIC_PATH = web.AppKey("STATIC_PATH", str) +STATIC_URL = web.AppKey("STATIC_URL", str) +WS = web.AppKey("WS", Set[Tuple[web.WebSocketResponse, str]]) + def _set_static_url(app: web.Application, url: str) -> None: - app["static_root_url"] = MutableValue(url) + if static_root_key is None: # TODO: Remove fallback + with warnings.catch_warnings(): + app["static_root_url"] = MutableValue(url) + else: + app[static_root_key] = MutableValue(url) for subapp in app._subapps: _set_static_url(subapp, url) def _change_static_url(app: web.Application, url: str) -> None: - app["static_root_url"].change(url) + if static_root_key is None: # TODO: Remove fallback + with warnings.catch_warnings(): + app["static_root_url"].change(url) + else: + app[static_root_key].change(url) for subapp in app._subapps: _change_static_url(subapp, url) @@ -174,23 +193,20 @@ async def create_main_app(config: Config, app_factory: AppFactory) -> web.AppRun modify_main_app(app, config) await check_port_open(config.main_port) - return web.AppRunner(app, access_log_class=AccessLogger) + return web.AppRunner(app, access_log_class=AccessLogger, shutdown_timeout=0.1) async def start_main_app(runner: web.AppRunner, port: int) -> None: await runner.setup() - site = web.TCPSite(runner, host=HOST, port=port, shutdown_timeout=0.1) + site = web.TCPSite(runner, host=HOST, port=port) await site.start() -WS = 'websockets' - - async def src_reload(app: web.Application, path: Optional[str] = None) -> int: """ prompt each connected browser to reload by sending websocket message. - :param path: if supplied this must be a path relative to app['static_path'], + :param path: if supplied this must be a path relative to `static_path`, eg. reload of a single file is only supported for static resources. :return: number of sources reloaded """ @@ -200,7 +216,7 @@ async def src_reload(app: web.Application, path: Optional[str] = None) -> int: is_html = None if path: - path = str(Path(app['static_url']) / Path(path).relative_to(app['static_path'])) + path = str(Path(app[STATIC_URL]) / Path(path).relative_to(app[STATIC_PATH])) is_html = mimetypes.guess_type(path)[0] == 'text/html' reloads = 0 @@ -239,16 +255,15 @@ def create_auxiliary_app( *, static_path: Optional[str], static_url: str = "/", livereload: bool = True, browser_cache: bool = False) -> web.Application: app = web.Application() - app[WS] = set() - app.update( - static_path=static_path, - static_url=static_url, - ) + ws: Set[Tuple[web.WebSocketResponse, str]] = set() + app[STATIC_PATH] = static_path or "" + app[STATIC_URL] = static_url + app[WS] = ws app.on_shutdown.append(cleanup_aux_app) if livereload: lr_path = Path(__file__).resolve().parent / 'livereload.js' - app['livereload_script'] = lr_path.read_bytes() + app[LIVERELOAD_SCRIPT] = lr_path.read_bytes() app.router.add_route('GET', '/livereload.js', livereload_js) app.router.add_route('GET', '/livereload', websocket_handler) aux_logger.debug('enabling livereload on auxiliary app') @@ -271,7 +286,7 @@ async def livereload_js(request: web.Request) -> web.Response: if request.if_modified_since: raise HTTPNotModified() - lr_script = request.app['livereload_script'] + lr_script = request.app[LIVERELOAD_SCRIPT] return web.Response(body=lr_script, content_type='application/javascript', headers={LAST_MODIFIED: 'Fri, 01 Jan 2016 00:00:00 GMT'}) diff --git a/aiohttp_devtools/runserver/watch.py b/aiohttp_devtools/runserver/watch.py index be4e3a4a..fc8029af 100644 --- a/aiohttp_devtools/runserver/watch.py +++ b/aiohttp_devtools/runserver/watch.py @@ -14,7 +14,7 @@ from ..exceptions import AiohttpDevException from ..logs import rs_dft_logger as logger from .config import Config -from .serve import WS, serve_main_app, src_reload +from .serve import STATIC_PATH, WS, serve_main_app, src_reload class WatchTask: @@ -64,7 +64,7 @@ async def _run(self, live_checks: int = 150) -> None: try: self._start_dev_server() - static_path = str(self._app['static_path']) + static_path = self._app[STATIC_PATH] def is_static(changes: Iterable[Tuple[object, str]]) -> bool: return all(str(c[1]).startswith(static_path) for c in changes) diff --git a/requirements.txt b/requirements.txt index c1777a07..163d153a 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,4 +1,5 @@ aiohttp==3.8.5 +aiohttp-jinja2==1.6 click==8.1.7 coverage==7.3.2 devtools==0.12.2 diff --git a/setup.py b/setup.py index 298ec0bf..b0ba738d 100644 --- a/setup.py +++ b/setup.py @@ -63,7 +63,7 @@ aiohttp-devtools=aiohttp_devtools.cli:cli """, install_requires=[ - 'aiohttp>=3.8.0', + 'aiohttp>=3.9', 'click>=6.6', 'devtools>=0.6', 'Pygments>=2.2.0', diff --git a/tests/test_runserver_main.py b/tests/test_runserver_main.py index e1581ef0..2a826c84 100644 --- a/tests/test_runserver_main.py +++ b/tests/test_runserver_main.py @@ -9,8 +9,8 @@ from aiohttp_devtools.runserver import runserver from aiohttp_devtools.runserver.config import Config -from aiohttp_devtools.runserver.serve import (create_auxiliary_app, create_main_app, modify_main_app, src_reload, - start_main_app) +from aiohttp_devtools.runserver.serve import ( + WS, create_auxiliary_app, create_main_app, modify_main_app, src_reload, start_main_app) from .conftest import SIMPLE_APP, forked @@ -218,12 +218,12 @@ async def test_websocket_hello(aux_cli, smart_caplog): async def test_websocket_info(aux_cli, event_loop): - assert len(aux_cli.server.app['websockets']) == 0 + assert len(aux_cli.server.app[WS]) == 0 ws = await aux_cli.session.ws_connect(aux_cli.make_url('/livereload')) try: await ws.send_json({'command': 'info', 'url': 'foobar', 'plugins': 'bang'}) await asyncio.sleep(0.05) - assert len(aux_cli.server.app['websockets']) == 1 + assert len(aux_cli.server.app[WS]) == 1 finally: await ws.close() diff --git a/tests/test_runserver_serve.py b/tests/test_runserver_serve.py index dadeb7dc..31feb315 100644 --- a/tests/test_runserver_serve.py +++ b/tests/test_runserver_serve.py @@ -6,12 +6,15 @@ import pytest from aiohttp.web import Application, Request, Response +from aiohttp_jinja2 import static_root_key from pytest_toolbox import mktree from aiohttp_devtools.exceptions import AiohttpDevException from aiohttp_devtools.runserver.config import Config from aiohttp_devtools.runserver.log_handlers import fmt_size -from aiohttp_devtools.runserver.serve import check_port_open, cleanup_aux_app, modify_main_app, src_reload +from aiohttp_devtools.runserver.serve import ( + STATIC_PATH, STATIC_URL, WS, check_port_open, cleanup_aux_app, + modify_main_app, src_reload) from .conftest import SIMPLE_APP, create_future @@ -33,11 +36,9 @@ async def test_aux_reload(smart_caplog): aux_app = Application() ws = MagicMock() ws.send_str = MagicMock(return_value=create_future()) - aux_app.update( - websockets=[(ws, '/foo/bar')], - static_url='/static/', - static_path='/path/to/static_files/' - ) + aux_app[STATIC_PATH] = "/path/to/static_files/" + aux_app[STATIC_URL] = "/static/" + aux_app[WS] = set(((ws, '/foo/bar'),)) # type: ignore[misc] assert 1 == await src_reload(aux_app, '/path/to/static_files/the_file.js') assert ws.send_str.call_count == 1 send_obj = json.loads(ws.send_str.call_args[0][0]) @@ -55,11 +56,9 @@ async def test_aux_reload_no_path(): aux_app = Application() ws = MagicMock() ws.send_str = MagicMock(return_value=create_future()) - aux_app.update( - websockets=[(ws, '/foo/bar')], - static_url='/static/', - static_path='/path/to/static_files/' - ) + aux_app[STATIC_PATH] = "/path/to/static_files/" + aux_app[STATIC_URL] = "/static/" + aux_app[WS] = set(((ws, '/foo/bar'),)) # type: ignore[misc] assert 1 == await src_reload(aux_app) assert ws.send_str.call_count == 1 send_obj = json.loads(ws.send_str.call_args[0][0]) @@ -75,11 +74,9 @@ async def test_aux_reload_html_different(): aux_app = Application() ws = MagicMock() ws.send_str = MagicMock(return_value=create_future()) - aux_app.update( - websockets=[(ws, '/foo/bar')], - static_url='/static/', - static_path='/path/to/static_files/' - ) + aux_app[STATIC_PATH] = "/path/to/static_files/" + aux_app[STATIC_URL] = "/static/" + aux_app[WS] = set(((ws, '/foo/bar'),)) # type: ignore[misc] assert 0 == await src_reload(aux_app, '/path/to/static_files/foo/bar.html') assert ws.send_str.call_count == 0 @@ -89,11 +86,9 @@ async def test_aux_reload_runtime_error(smart_caplog): ws = MagicMock() ws.send_str = MagicMock(return_value=create_future()) ws.send_str = MagicMock(side_effect=RuntimeError('foobar')) - aux_app.update( - websockets=[(ws, '/foo/bar')], - static_url='/static/', - static_path='/path/to/static_files/' - ) + aux_app[STATIC_PATH] = "/path/to/static_files/" + aux_app[STATIC_URL] = "/static/" + aux_app[WS] = set(((ws, '/foo/bar'),)) # type: ignore[misc] assert 0 == await src_reload(aux_app) assert ws.send_str.call_count == 1 assert 'adev.server.aux ERROR: Error broadcasting change to /foo/bar, RuntimeError: foobar\n' == smart_caplog @@ -104,7 +99,7 @@ async def test_aux_cleanup(event_loop): aux_app.on_cleanup.append(cleanup_aux_app) ws = MagicMock() ws.close = MagicMock(return_value=create_future()) - aux_app['websockets'] = [(ws, '/foo/bar')] + aux_app[WS] = set(((ws, '/foo/bar'),)) # type: ignore[misc] aux_app.freeze() await aux_app.cleanup() assert ws.close.call_count == 1 @@ -144,8 +139,8 @@ def test_modify_main_app_all_off(tmpworkdir): modify_main_app(app, config) # type: ignore[arg-type] assert len(app.on_response_prepare) == 0 assert len(app.middlewares) == 0 - assert app['static_root_url'] == 'http://foobar.com:8001/static' - assert subapp["static_root_url"] == "http://foobar.com:8001/static" + assert app[static_root_key] == 'http://foobar.com:8001/static' + assert subapp[static_root_key] == "http://foobar.com:8001/static" assert app._debug is True @@ -158,8 +153,8 @@ def test_modify_main_app_all_on(tmpworkdir): modify_main_app(app, config) # type: ignore[arg-type] assert len(app.on_response_prepare) == 1 assert len(app.middlewares) == 2 - assert app['static_root_url'] == 'http://localhost:8001/static' - assert subapp['static_root_url'] == "http://localhost:8001/static" + assert app[static_root_key] == 'http://localhost:8001/static' + assert subapp[static_root_key] == "http://localhost:8001/static" assert app._debug is True diff --git a/tests/test_runserver_watch.py b/tests/test_runserver_watch.py index 4136f379..cf60b895 100644 --- a/tests/test_runserver_watch.py +++ b/tests/test_runserver_watch.py @@ -1,10 +1,12 @@ import asyncio from functools import partial +from typing import Set, Tuple from unittest.mock import MagicMock, call from aiohttp import ClientSession -from aiohttp.web import Application +from aiohttp.web import Application, WebSocketResponse +from aiohttp_devtools.runserver.serve import STATIC_PATH, WS from aiohttp_devtools.runserver.watch import AppTask, LiveReloadTask from .conftest import create_future @@ -39,7 +41,7 @@ async def test_single_file_change(event_loop, mocker): stop_mock = mocker.patch.object(app_task, "_stop_dev_server", autospec=True) app = MagicMock() await app_task.start(app) - d = {'static_path': '/path/to/'} + d = {STATIC_PATH: "/path/to/"} app.__getitem__.side_effect = d.__getitem__ assert app_task._task is not None await app_task._task @@ -79,13 +81,13 @@ async def test_python_no_server(event_loop, mocker): stop_mock = mocker.patch.object(app_task, "_stop_dev_server", autospec=True) mocker.patch.object(app_task, "_run", partial(app_task._run, live_checks=2)) app = Application() - app['static_path'] = '/path/to/' + app[STATIC_PATH] = "/path/to/" app.src_reload = MagicMock() mock_ws = MagicMock() f: asyncio.Future[int] = asyncio.Future() f.set_result(1) mock_ws.send_str = MagicMock(return_value=f) - app['websockets'] = [(mock_ws, '/')] + app[WS] = set(((mock_ws, '/'),)) # type: ignore[misc] await app_task.start(app) assert app_task._task is not None await app_task._task @@ -98,7 +100,8 @@ async def test_python_no_server(event_loop, mocker): async def test_reload_server_running(event_loop, aiohttp_client, mocker): app = Application() - app['websockets'] = [None] + ws: Set[Tuple[WebSocketResponse, str]] = set(((MagicMock(), "/foo"),)) + app[WS] = ws mock_src_reload = mocker.patch('aiohttp_devtools.runserver.watch.src_reload', return_value=create_future()) cli = await aiohttp_client(app) config = MagicMock() From 6e9f84b36a137af9cfb0b0aba65fc600bdd4f862 Mon Sep 17 00:00:00 2001 From: Sam Bull Date: Sun, 19 Nov 2023 14:27:55 +0000 Subject: [PATCH 2/6] Apply suggestions from code review --- requirements.txt | 2 +- setup.py | 2 +- tests/test_runserver_serve.py | 14 +++++++------- tests/test_runserver_watch.py | 2 +- 4 files changed, 10 insertions(+), 10 deletions(-) diff --git a/requirements.txt b/requirements.txt index 163d153a..e0676004 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,4 +1,4 @@ -aiohttp==3.8.5 +aiohttp==3.9.0 aiohttp-jinja2==1.6 click==8.1.7 coverage==7.3.2 diff --git a/setup.py b/setup.py index b0ba738d..db7c36b8 100644 --- a/setup.py +++ b/setup.py @@ -63,7 +63,7 @@ aiohttp-devtools=aiohttp_devtools.cli:cli """, install_requires=[ - 'aiohttp>=3.9', + "aiohttp>=3.9", 'click>=6.6', 'devtools>=0.6', 'Pygments>=2.2.0', diff --git a/tests/test_runserver_serve.py b/tests/test_runserver_serve.py index 31feb315..291a951b 100644 --- a/tests/test_runserver_serve.py +++ b/tests/test_runserver_serve.py @@ -38,7 +38,7 @@ async def test_aux_reload(smart_caplog): ws.send_str = MagicMock(return_value=create_future()) aux_app[STATIC_PATH] = "/path/to/static_files/" aux_app[STATIC_URL] = "/static/" - aux_app[WS] = set(((ws, '/foo/bar'),)) # type: ignore[misc] + aux_app[WS] = set(((ws, "/foo/bar"),)) # type: ignore[misc] assert 1 == await src_reload(aux_app, '/path/to/static_files/the_file.js') assert ws.send_str.call_count == 1 send_obj = json.loads(ws.send_str.call_args[0][0]) @@ -58,7 +58,7 @@ async def test_aux_reload_no_path(): ws.send_str = MagicMock(return_value=create_future()) aux_app[STATIC_PATH] = "/path/to/static_files/" aux_app[STATIC_URL] = "/static/" - aux_app[WS] = set(((ws, '/foo/bar'),)) # type: ignore[misc] + aux_app[WS] = set(((ws, "/foo/bar"),)) # type: ignore[misc] assert 1 == await src_reload(aux_app) assert ws.send_str.call_count == 1 send_obj = json.loads(ws.send_str.call_args[0][0]) @@ -76,7 +76,7 @@ async def test_aux_reload_html_different(): ws.send_str = MagicMock(return_value=create_future()) aux_app[STATIC_PATH] = "/path/to/static_files/" aux_app[STATIC_URL] = "/static/" - aux_app[WS] = set(((ws, '/foo/bar'),)) # type: ignore[misc] + aux_app[WS] = set(((ws, "/foo/bar"),)) # type: ignore[misc] assert 0 == await src_reload(aux_app, '/path/to/static_files/foo/bar.html') assert ws.send_str.call_count == 0 @@ -88,7 +88,7 @@ async def test_aux_reload_runtime_error(smart_caplog): ws.send_str = MagicMock(side_effect=RuntimeError('foobar')) aux_app[STATIC_PATH] = "/path/to/static_files/" aux_app[STATIC_URL] = "/static/" - aux_app[WS] = set(((ws, '/foo/bar'),)) # type: ignore[misc] + aux_app[WS] = set(((ws, "/foo/bar"),)) # type: ignore[misc] assert 0 == await src_reload(aux_app) assert ws.send_str.call_count == 1 assert 'adev.server.aux ERROR: Error broadcasting change to /foo/bar, RuntimeError: foobar\n' == smart_caplog @@ -99,7 +99,7 @@ async def test_aux_cleanup(event_loop): aux_app.on_cleanup.append(cleanup_aux_app) ws = MagicMock() ws.close = MagicMock(return_value=create_future()) - aux_app[WS] = set(((ws, '/foo/bar'),)) # type: ignore[misc] + aux_app[WS] = set(((ws, "/foo/bar"),)) # type: ignore[misc] aux_app.freeze() await aux_app.cleanup() assert ws.close.call_count == 1 @@ -139,7 +139,7 @@ def test_modify_main_app_all_off(tmpworkdir): modify_main_app(app, config) # type: ignore[arg-type] assert len(app.on_response_prepare) == 0 assert len(app.middlewares) == 0 - assert app[static_root_key] == 'http://foobar.com:8001/static' + assert app[static_root_key] == "http://foobar.com:8001/static" assert subapp[static_root_key] == "http://foobar.com:8001/static" assert app._debug is True @@ -153,7 +153,7 @@ def test_modify_main_app_all_on(tmpworkdir): modify_main_app(app, config) # type: ignore[arg-type] assert len(app.on_response_prepare) == 1 assert len(app.middlewares) == 2 - assert app[static_root_key] == 'http://localhost:8001/static' + assert app[static_root_key] == "http://localhost:8001/static" assert subapp[static_root_key] == "http://localhost:8001/static" assert app._debug is True diff --git a/tests/test_runserver_watch.py b/tests/test_runserver_watch.py index cf60b895..02edf5b2 100644 --- a/tests/test_runserver_watch.py +++ b/tests/test_runserver_watch.py @@ -87,7 +87,7 @@ async def test_python_no_server(event_loop, mocker): f: asyncio.Future[int] = asyncio.Future() f.set_result(1) mock_ws.send_str = MagicMock(return_value=f) - app[WS] = set(((mock_ws, '/'),)) # type: ignore[misc] + app[WS] = set(((mock_ws, "/"),)) # type: ignore[misc] await app_task.start(app) assert app_task._task is not None await app_task._task From a123ce2550bbe7da77d00594e4dccfd2acce851f Mon Sep 17 00:00:00 2001 From: Sam Bull Date: Sun, 19 Nov 2023 14:37:11 +0000 Subject: [PATCH 3/6] Update test_runserver_serve.py --- tests/test_runserver_serve.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/test_runserver_serve.py b/tests/test_runserver_serve.py index 291a951b..7f2bccef 100644 --- a/tests/test_runserver_serve.py +++ b/tests/test_runserver_serve.py @@ -1,7 +1,7 @@ import json import pathlib import socket -from typing import Dict +from typing import Any, Dict from unittest.mock import MagicMock import pytest @@ -115,7 +115,7 @@ def test_fmt_size_large(value, result): assert fmt_size(value) == result -class DummyApplication(Dict[str, object]): +class DummyApplication(Dict[web.AppKey[Any], object]): _debug = False def __init__(self): From acf29ce600581cc42a779d999510fc09ea3078be Mon Sep 17 00:00:00 2001 From: Sam Bull Date: Sun, 19 Nov 2023 14:37:41 +0000 Subject: [PATCH 4/6] Apply suggestions from code review --- aiohttp_devtools/logs.py | 2 +- aiohttp_devtools/runserver/serve.py | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/aiohttp_devtools/logs.py b/aiohttp_devtools/logs.py index 3087d528..53683d26 100644 --- a/aiohttp_devtools/logs.py +++ b/aiohttp_devtools/logs.py @@ -80,7 +80,7 @@ def formatMessage(self, record: logging.LogRecord) -> str: def formatException(self, ei: _Ei) -> str: sio = StringIO() - traceback.print_exception(*ei, file=sio) + traceback.print_exception(*ei, file=sio) # type: ignore[misc] stack = sio.getvalue() sio.close() if self.stream_is_tty and pyg_lexer: diff --git a/aiohttp_devtools/runserver/serve.py b/aiohttp_devtools/runserver/serve.py index f5c36c2c..1c9a5134 100644 --- a/aiohttp_devtools/runserver/serve.py +++ b/aiohttp_devtools/runserver/serve.py @@ -27,7 +27,7 @@ try: from aiohttp_jinja2 import static_root_key except ImportError: - static_root_key = None + static_root_key = None # type: ignore[assignment] LIVE_RELOAD_HOST_SNIPPET = '\n\n' LIVE_RELOAD_LOCAL_SNIPPET = b'\n\n' @@ -41,20 +41,20 @@ def _set_static_url(app: web.Application, url: str) -> None: if static_root_key is None: # TODO: Remove fallback - with warnings.catch_warnings(): + with warnings.catch_warnings(): # type: ignore[unreachable] app["static_root_url"] = MutableValue(url) else: - app[static_root_key] = MutableValue(url) + app[static_root_key] = MutableValue(url) # type: ignore[misc] for subapp in app._subapps: _set_static_url(subapp, url) def _change_static_url(app: web.Application, url: str) -> None: if static_root_key is None: # TODO: Remove fallback - with warnings.catch_warnings(): + with warnings.catch_warnings(): # type: ignore[unreachable] app["static_root_url"].change(url) else: - app[static_root_key].change(url) + app[static_root_key].change(url) # type: ignore[attr-defined] for subapp in app._subapps: _change_static_url(subapp, url) From 7fcc421748ccaaa6ba42381a1b5b8800bd03111d Mon Sep 17 00:00:00 2001 From: Sam Bull Date: Sun, 19 Nov 2023 14:39:53 +0000 Subject: [PATCH 5/6] Apply suggestions from code review --- tests/test_runserver_serve.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/test_runserver_serve.py b/tests/test_runserver_serve.py index 7f2bccef..774268bf 100644 --- a/tests/test_runserver_serve.py +++ b/tests/test_runserver_serve.py @@ -5,7 +5,7 @@ from unittest.mock import MagicMock import pytest -from aiohttp.web import Application, Request, Response +from aiohttp.web import Application, AppKey, Request, Response from aiohttp_jinja2 import static_root_key from pytest_toolbox import mktree @@ -115,7 +115,7 @@ def test_fmt_size_large(value, result): assert fmt_size(value) == result -class DummyApplication(Dict[web.AppKey[Any], object]): +class DummyApplication(Dict[AppKey[Any], object]): _debug = False def __init__(self): From 9f54a43595795b66529e5f59f233000f995de79b Mon Sep 17 00:00:00 2001 From: Sam Bull Date: Sun, 19 Nov 2023 14:46:11 +0000 Subject: [PATCH 6/6] Update test_runserver_serve.py --- tests/test_runserver_serve.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test_runserver_serve.py b/tests/test_runserver_serve.py index 774268bf..63e02bfa 100644 --- a/tests/test_runserver_serve.py +++ b/tests/test_runserver_serve.py @@ -122,7 +122,7 @@ def __init__(self): self.on_response_prepare = [] self.middlewares = [] self.router = MagicMock() - self['static_root_url'] = '/static/' + self[static_root_key] = '/static/' self._subapps = [] def add_subapp(self, path, app):