diff options
| author | Piotr Ożarowski <piotr@debian.org> | 2025-04-05 14:44:31 +0200 |
|---|---|---|
| committer | git-ubuntu importer <ubuntu-devel-discuss@lists.ubuntu.com> | 2025-04-13 16:44:19 +0000 |
| commit | 04a71ac1321e4607c7d0966bff7539fd65270dae (patch) | |
| tree | 058817d69156f746d899203bf4f5799bb3321aa6 | |
| parent | 69a6f8ee84fe67115d0c2a9cb73c15baf0c2edc2 (diff) | |
| parent | 3fc943c06bff7a459a7e2946b3b919081677b04c (diff) | |
3.11.16-1 (patches applied)applied/3.11.16-1applied/ubuntu/questing-proposedapplied/ubuntu/questing
Imported using git-ubuntu import.
| -rw-r--r-- | CHANGES.rst | 27 | ||||
| -rw-r--r-- | PKG-INFO | 2 | ||||
| -rw-r--r-- | aiohttp.egg-info/PKG-INFO | 2 | ||||
| -rw-r--r-- | aiohttp/__init__.py | 2 | ||||
| -rw-r--r-- | aiohttp/pytest_plugin.py | 6 | ||||
| -rw-r--r-- | aiohttp/web_response.py | 4 | ||||
| -rw-r--r-- | aiohttp/web_urldispatcher.py | 8 | ||||
| -rw-r--r-- | aiohttp/worker.py | 5 | ||||
| -rw-r--r-- | debian/changelog | 6 | ||||
| -rw-r--r-- | tests/test_client_ws_functional.py | 3 | ||||
| -rw-r--r-- | tests/test_helpers.py | 1 | ||||
| -rw-r--r-- | tests/test_web_response.py | 14 | ||||
| -rw-r--r-- | tests/test_web_server.py | 3 |
13 files changed, 64 insertions, 19 deletions
diff --git a/CHANGES.rst b/CHANGES.rst index c2654b9..00d728e 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -10,6 +10,33 @@ .. towncrier release notes start +3.11.16 (2025-04-01) +==================== + +Bug fixes +--------- + +- Replaced deprecated ``asyncio.iscoroutinefunction`` with its counterpart from ``inspect`` + -- by :user:`layday`. + + + *Related issues and pull requests on GitHub:* + :issue:`10634`. + + + +- Fixed :class:`multidict.CIMultiDict` being mutated when passed to :class:`aiohttp.web.Response` -- by :user:`bdraco`. + + + *Related issues and pull requests on GitHub:* + :issue:`10672`. + + + + +---- + + 3.11.15 (2025-03-31) ==================== @@ -1,6 +1,6 @@ Metadata-Version: 2.4 Name: aiohttp -Version: 3.11.15 +Version: 3.11.16 Summary: Async http client/server framework (asyncio) Home-page: https://github.com/aio-libs/aiohttp Maintainer: aiohttp team <team@aiohttp.org> diff --git a/aiohttp.egg-info/PKG-INFO b/aiohttp.egg-info/PKG-INFO index 55bbb90..78bb74b 100644 --- a/aiohttp.egg-info/PKG-INFO +++ b/aiohttp.egg-info/PKG-INFO @@ -1,6 +1,6 @@ Metadata-Version: 2.4 Name: aiohttp -Version: 3.11.15 +Version: 3.11.16 Summary: Async http client/server framework (asyncio) Home-page: https://github.com/aio-libs/aiohttp Maintainer: aiohttp team <team@aiohttp.org> diff --git a/aiohttp/__init__.py b/aiohttp/__init__.py index aba86dc..93b06c7 100644 --- a/aiohttp/__init__.py +++ b/aiohttp/__init__.py @@ -1,4 +1,4 @@ -__version__ = "3.11.15" +__version__ = "3.11.16" from typing import TYPE_CHECKING, Tuple diff --git a/aiohttp/pytest_plugin.py b/aiohttp/pytest_plugin.py index 7ce60fa..21d6ea7 100644 --- a/aiohttp/pytest_plugin.py +++ b/aiohttp/pytest_plugin.py @@ -98,7 +98,7 @@ def pytest_fixture_setup(fixturedef): # type: ignore[no-untyped-def] if inspect.isasyncgenfunction(func): # async generator fixture is_async_gen = True - elif asyncio.iscoroutinefunction(func): + elif inspect.iscoroutinefunction(func): # regular async fixture is_async_gen = False else: @@ -200,14 +200,14 @@ def _passthrough_loop_context(loop, fast=False): # type: ignore[no-untyped-def] def pytest_pycollect_makeitem(collector, name, obj): # type: ignore[no-untyped-def] """Fix pytest collecting for coroutines.""" - if collector.funcnamefilter(name) and asyncio.iscoroutinefunction(obj): + if collector.funcnamefilter(name) and inspect.iscoroutinefunction(obj): return list(collector._genfunctions(name, obj)) def pytest_pyfunc_call(pyfuncitem): # type: ignore[no-untyped-def] """Run coroutines in an event loop instead of a normal function call.""" fast = pyfuncitem.config.getoption("--aiohttp-fast") - if asyncio.iscoroutinefunction(pyfuncitem.function): + if inspect.iscoroutinefunction(pyfuncitem.function): existing_loop = pyfuncitem.funcargs.get( "proactor_loop" ) or pyfuncitem.funcargs.get("loop", None) diff --git a/aiohttp/web_response.py b/aiohttp/web_response.py index e498a90..367ac6e 100644 --- a/aiohttp/web_response.py +++ b/aiohttp/web_response.py @@ -629,10 +629,8 @@ class Response(StreamResponse): if headers is None: real_headers: CIMultiDict[str] = CIMultiDict() - elif not isinstance(headers, CIMultiDict): - real_headers = CIMultiDict(headers) else: - real_headers = headers # = cast('CIMultiDict[str]', headers) + real_headers = CIMultiDict(headers) if content_type is not None and "charset" in content_type: raise ValueError("charset must not be in content_type argument") diff --git a/aiohttp/web_urldispatcher.py b/aiohttp/web_urldispatcher.py index 6443c50..28ae251 100644 --- a/aiohttp/web_urldispatcher.py +++ b/aiohttp/web_urldispatcher.py @@ -180,8 +180,8 @@ class AbstractRoute(abc.ABC): if expect_handler is None: expect_handler = _default_expect_handler - assert asyncio.iscoroutinefunction( - expect_handler + assert inspect.iscoroutinefunction(expect_handler) or ( + sys.version_info < (3, 14) and asyncio.iscoroutinefunction(expect_handler) ), f"Coroutine is expected, got {expect_handler!r}" method = method.upper() @@ -189,7 +189,9 @@ class AbstractRoute(abc.ABC): raise ValueError(f"{method} is not allowed HTTP method") assert callable(handler), handler - if asyncio.iscoroutinefunction(handler): + if inspect.iscoroutinefunction(handler) or ( + sys.version_info < (3, 14) and asyncio.iscoroutinefunction(handler) + ): pass elif inspect.isgeneratorfunction(handler): warnings.warn( diff --git a/aiohttp/worker.py b/aiohttp/worker.py index 8ed121a..f7281bf 100644 --- a/aiohttp/worker.py +++ b/aiohttp/worker.py @@ -1,6 +1,7 @@ """Async gunicorn worker for aiohttp.web""" import asyncio +import inspect import os import re import signal @@ -71,7 +72,9 @@ class GunicornWebWorker(base.Worker): # type: ignore[misc,no-any-unimported] runner = None if isinstance(self.wsgi, Application): app = self.wsgi - elif asyncio.iscoroutinefunction(self.wsgi): + elif inspect.iscoroutinefunction(self.wsgi) or ( + sys.version_info < (3, 14) and asyncio.iscoroutinefunction(self.wsgi) + ): wsgi = await self.wsgi() if isinstance(wsgi, web.AppRunner): runner = wsgi diff --git a/debian/changelog b/debian/changelog index 7712d16..aa64486 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,9 @@ +python-aiohttp (3.11.16-1) unstable; urgency=medium + + * New upstream release + + -- Piotr Ożarowski <piotr@debian.org> Sat, 05 Apr 2025 14:44:31 +0200 + python-aiohttp (3.11.15-1) unstable; urgency=medium * Team upload. diff --git a/tests/test_client_ws_functional.py b/tests/test_client_ws_functional.py index 54cd5e9..0ca57ab 100644 --- a/tests/test_client_ws_functional.py +++ b/tests/test_client_ws_functional.py @@ -315,7 +315,6 @@ async def test_concurrent_close(aiohttp_client) -> None: client_ws = None async def handler(request): - nonlocal client_ws ws = web.WebSocketResponse() await ws.prepare(request) @@ -936,7 +935,7 @@ async def test_close_websocket_while_ping_inflight( message: bytes, opcode: int, compress: Optional[int] = None ) -> None: assert opcode == WSMsgType.PING - nonlocal cancelled, ping_started + nonlocal cancelled ping_started.set_result(None) try: await asyncio.sleep(1) diff --git a/tests/test_helpers.py b/tests/test_helpers.py index 2a83032..a343cbd 100644 --- a/tests/test_helpers.py +++ b/tests/test_helpers.py @@ -351,7 +351,6 @@ async def test_timer_context_timeout_does_swallow_cancellation() -> None: ctx = helpers.TimerContext(loop) async def task_with_timeout() -> None: - nonlocal ctx new_task = asyncio.current_task() assert new_task is not None with pytest.raises(asyncio.TimeoutError): diff --git a/tests/test_web_response.py b/tests/test_web_response.py index 0591426..9576916 100644 --- a/tests/test_web_response.py +++ b/tests/test_web_response.py @@ -10,7 +10,7 @@ from unittest import mock import aiosignal import pytest -from multidict import CIMultiDict, CIMultiDictProxy +from multidict import CIMultiDict, CIMultiDictProxy, MultiDict from re_assert import Matches from aiohttp import HttpVersion, HttpVersion10, HttpVersion11, hdrs @@ -1479,3 +1479,15 @@ class TestJSONResponse: def test_content_type_is_overrideable(self) -> None: resp = json_response({"foo": 42}, content_type="application/vnd.json+api") assert "application/vnd.json+api" == resp.content_type + + +@pytest.mark.parametrize("loose_header_type", (MultiDict, CIMultiDict, dict)) +async def test_passing_cimultidict_to_web_response_not_mutated( + loose_header_type: type, +) -> None: + req = make_request("GET", "/") + headers = loose_header_type({}) + resp = Response(body=b"answer", headers=headers) + await resp.prepare(req) + assert resp.content_length == 6 + assert not headers diff --git a/tests/test_web_server.py b/tests/test_web_server.py index 9098ef9..d2f1341 100644 --- a/tests/test_web_server.py +++ b/tests/test_web_server.py @@ -347,7 +347,6 @@ async def test_handler_cancellation(unused_port_socket: socket.socket) -> None: port = sock.getsockname()[1] async def on_request(_: web.Request) -> web.Response: - nonlocal event try: await asyncio.sleep(10) except asyncio.CancelledError: @@ -389,7 +388,7 @@ async def test_no_handler_cancellation(unused_port_socket: socket.socket) -> Non started = False async def on_request(_: web.Request) -> web.Response: - nonlocal done_event, started, timeout_event + nonlocal started started = True await asyncio.wait_for(timeout_event.wait(), timeout=5) done_event.set() |
