From d5eb044f1a2a8c3fdcb79ba3d59a36a4bf864a5d Mon Sep 17 00:00:00 2001 From: Giulio Leone Date: Sat, 28 Feb 2026 22:13:46 +0100 Subject: [PATCH 1/2] perf: use deque for FormData.add_fields() queue (#12166) --- aiohttp/formdata.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/aiohttp/formdata.py b/aiohttp/formdata.py index 8e9157f8e07..50dae68244f 100644 --- a/aiohttp/formdata.py +++ b/aiohttp/formdata.py @@ -1,4 +1,5 @@ import io +from collections import deque from collections.abc import Iterable from typing import Any from urllib.parse import urlencode @@ -81,10 +82,10 @@ def add_field( self._fields.append((type_options, headers, value)) def add_fields(self, *fields: Any) -> None: - to_add = list(fields) + to_add: deque[Any] = deque(fields) while to_add: - rec = to_add.pop(0) + rec = to_add.popleft() if isinstance(rec, io.IOBase): k = guess_filename(rec, "unknown") From 2d03bc45722f4153c2a993f084ecac04023d54c4 Mon Sep 17 00:00:00 2001 From: Rodrigo Nogueira Date: Sat, 28 Feb 2026 18:43:28 -0300 Subject: [PATCH 2/2] Fix test_data_file race condition on Python 3.14 free-threaded (#12170) --- CHANGES/12170.misc.rst | 1 + tests/test_client_request.py | 13 ++++++++++++- 2 files changed, 13 insertions(+), 1 deletion(-) create mode 100644 CHANGES/12170.misc.rst diff --git a/CHANGES/12170.misc.rst b/CHANGES/12170.misc.rst new file mode 100644 index 00000000000..23c63db50e9 --- /dev/null +++ b/CHANGES/12170.misc.rst @@ -0,0 +1 @@ +Fixed race condition in ``test_data_file`` on Python 3.14 free-threaded builds -- by :user:`rodrigobnogueira`. diff --git a/tests/test_client_request.py b/tests/test_client_request.py index fc693fc16c3..054496e6748 100644 --- a/tests/test_client_request.py +++ b/tests/test_client_request.py @@ -1352,7 +1352,18 @@ async def test_data_file( assert isinstance(req.body, payload.BufferedReaderPayload) assert req.headers["TRANSFER-ENCODING"] == "chunked" - resp = await req._send(conn) + original_write_bytes = req._write_bytes + + async def _mock_write_bytes( + writer: AbstractStreamWriter, conn: mock.Mock, content_length: int | None + ) -> None: + # Ensure the task is scheduled so _writer isn't None + await asyncio.sleep(0) + await original_write_bytes(writer, conn, content_length) + + with mock.patch.object(req, "_write_bytes", _mock_write_bytes): + resp = await req._send(conn) + assert asyncio.isfuture(req._writer) await resp.wait_for_close()