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
2 changes: 1 addition & 1 deletion .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ repos:
- id: pyupgrade
args: ['--py37-plus']
- repo: https://github.com/PyCQA/flake8
rev: '7.1.2'
rev: '7.2.0'
hooks:
- id: flake8
additional_dependencies:
Expand Down
1 change: 1 addition & 0 deletions CHANGES/10672.bugfix.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Fixed :class:`multidict.CIMultiDict` being mutated when passed to :class:`aiohttp.web.Response` -- by :user:`bdraco`.
4 changes: 1 addition & 3 deletions aiohttp/web_response.py
Original file line number Diff line number Diff line change
Expand Up @@ -532,10 +532,8 @@ def __init__(

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")
Expand Down
2 changes: 1 addition & 1 deletion requirements/base.txt
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ gunicorn==23.0.0
# via -r requirements/base.in
idna==3.6
# via yarl
multidict==6.2.0
multidict==6.3.1
# via
# -r requirements/runtime-deps.in
# yarl
Expand Down
2 changes: 1 addition & 1 deletion requirements/constraints.txt
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ markupsafe==3.0.2
# via jinja2
mdurl==0.1.2
# via markdown-it-py
multidict==6.2.0
multidict==6.3.1
# via
# -r requirements/multidict.in
# -r requirements/runtime-deps.in
Expand Down
2 changes: 1 addition & 1 deletion requirements/cython.txt
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
#
cython==3.0.12
# via -r requirements/cython.in
multidict==6.2.0
multidict==6.3.1
# via -r requirements/multidict.in
typing-extensions==4.12.2
# via multidict
2 changes: 1 addition & 1 deletion requirements/dev.txt
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ markupsafe==3.0.2
# via jinja2
mdurl==0.1.2
# via markdown-it-py
multidict==6.2.0
multidict==6.3.1
# via
# -r requirements/runtime-deps.in
# yarl
Expand Down
2 changes: 1 addition & 1 deletion requirements/multidict.txt
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
#
# pip-compile --allow-unsafe --output-file=requirements/multidict.txt --resolver=backtracking --strip-extras requirements/multidict.in
#
multidict==6.2.0
multidict==6.3.1
# via -r requirements/multidict.in
typing-extensions==4.12.2
# via multidict
2 changes: 1 addition & 1 deletion requirements/runtime-deps.txt
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ frozenlist==1.5.0
# aiosignal
idna==3.6
# via yarl
multidict==6.2.0
multidict==6.3.1
# via
# -r requirements/runtime-deps.in
# yarl
Expand Down
2 changes: 1 addition & 1 deletion requirements/test.txt
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ markdown-it-py==3.0.0
# via rich
mdurl==0.1.2
# via markdown-it-py
multidict==6.2.0
multidict==6.3.1
# via
# -r requirements/runtime-deps.in
# yarl
Expand Down
3 changes: 1 addition & 2 deletions tests/test_client_ws_functional.py
Original file line number Diff line number Diff line change
Expand Up @@ -363,7 +363,6 @@ async def test_concurrent_close(aiohttp_client: AiohttpClient) -> None:
client_ws: Optional[aiohttp.ClientWebSocketResponse] = None

async def handler(request: web.Request) -> web.WebSocketResponse:
nonlocal client_ws
ws = web.WebSocketResponse()
await ws.prepare(request)

Expand Down Expand Up @@ -960,7 +959,7 @@ async def delayed_send_frame(
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)
Expand Down
1 change: 0 additions & 1 deletion tests/test_helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -378,7 +378,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):
Expand Down
14 changes: 13 additions & 1 deletion tests/test_web_response.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@

import aiosignal
import pytest
from multidict import CIMultiDict, CIMultiDictProxy
from multidict import CIMultiDict, CIMultiDictProxy, MultiDict

from aiohttp import HttpVersion, HttpVersion10, HttpVersion11, hdrs, web
from aiohttp.abc import AbstractStreamWriter
Expand Down Expand Up @@ -1384,3 +1384,15 @@ async def test_warn_large_cookie(buf: bytearray, writer: AbstractStreamWriter) -
assert match is not None
cookie = match.group(1)
assert len(cookie) == 4097


@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 = web.Response(body=b"answer", headers=headers)
await resp.prepare(req)
assert resp.content_length == 6
assert not headers
3 changes: 1 addition & 2 deletions tests/test_web_server.py
Original file line number Diff line number Diff line change
Expand Up @@ -384,7 +384,6 @@ async def test_handler_cancellation(unused_port_socket: socket.socket) -> None:
port = sock.getsockname()[1]

async def on_request(request: web.Request) -> web.Response:
nonlocal event
try:
await asyncio.sleep(10)
except asyncio.CancelledError:
Expand Down Expand Up @@ -427,7 +426,7 @@ async def test_no_handler_cancellation(unused_port_socket: socket.socket) -> Non
started = False

async def on_request(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()
Expand Down
Loading