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/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") 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()