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
6 changes: 1 addition & 5 deletions aiohttp/payload.py
Original file line number Diff line number Diff line change
Expand Up @@ -557,11 +557,7 @@ def size(self) -> Optional[int]:
# By storing the start position, we ensure the size calculation always
# returns the correct total size for any subsequent use.
if self._start_position is None:
try:
self._start_position = self._value.tell()
except (OSError, AttributeError):
# Can't get position, can't determine size
return None
self._start_position = self._value.tell()

# Return the total size from the start position
# This ensures Content-Length is correct even after reading
Expand Down
114 changes: 57 additions & 57 deletions requirements/constraints.txt

Large diffs are not rendered by default.

104 changes: 52 additions & 52 deletions requirements/dev.txt

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions requirements/lint.txt
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ markdown-it-py==3.0.0
# via rich
mdurl==0.1.2
# via markdown-it-py
mypy==1.16.1 ; implementation_name == "cpython"
mypy==1.17.0 ; implementation_name == "cpython"
# via -r requirements/lint.in
mypy-extensions==1.1.0
# via mypy
Expand Down Expand Up @@ -86,7 +86,7 @@ pytest-mock==3.14.1
# via -r requirements/lint.in
python-dateutil==2.9.0.post0
# via freezegun
python-on-whales==0.77.0
python-on-whales==0.78.0
# via -r requirements/lint.in
pyyaml==6.0.2
# via pre-commit
Expand Down
28 changes: 14 additions & 14 deletions requirements/test.txt
Original file line number Diff line number Diff line change
Expand Up @@ -5,19 +5,19 @@
# pip-compile --allow-unsafe --output-file=requirements/test.txt --resolver=backtracking --strip-extras requirements/test.in
#
aiodns==3.5.0
# via -r /home/dependabot/dependabot-updater/tmp/20250715-1382-lngh7e/dependabot_20250715-1382-a7k872/requirements/runtime-deps.in
# via -r /home/dependabot/dependabot-updater/tmp/20250715-1384-v0sr9j/dependabot_20250715-1384-mw23m4/requirements/runtime-deps.in
aiohappyeyeballs==2.6.1
# via -r /home/dependabot/dependabot-updater/tmp/20250715-1382-lngh7e/dependabot_20250715-1382-a7k872/requirements/runtime-deps.in
# via -r /home/dependabot/dependabot-updater/tmp/20250715-1384-v0sr9j/dependabot_20250715-1384-mw23m4/requirements/runtime-deps.in
aiosignal==1.4.0
# via -r /home/dependabot/dependabot-updater/tmp/20250715-1382-lngh7e/dependabot_20250715-1382-a7k872/requirements/runtime-deps.in
# via -r /home/dependabot/dependabot-updater/tmp/20250715-1384-v0sr9j/dependabot_20250715-1384-mw23m4/requirements/runtime-deps.in
annotated-types==0.7.0
# via pydantic
async-timeout==5.0.1 ; python_version < "3.11"
# via -r /home/dependabot/dependabot-updater/tmp/20250715-1382-lngh7e/dependabot_20250715-1382-a7k872/requirements/runtime-deps.in
# via -r /home/dependabot/dependabot-updater/tmp/20250715-1384-v0sr9j/dependabot_20250715-1384-mw23m4/requirements/runtime-deps.in
blockbuster==1.5.25
# via -r requirements/test.in
brotli==1.1.0 ; platform_python_implementation == "CPython"
# via -r /home/dependabot/dependabot-updater/tmp/20250715-1382-lngh7e/dependabot_20250715-1382-a7k872/requirements/runtime-deps.in
# via -r /home/dependabot/dependabot-updater/tmp/20250715-1384-v0sr9j/dependabot_20250715-1384-mw23m4/requirements/runtime-deps.in
cffi==1.17.1
# via
# cryptography
Expand All @@ -41,10 +41,10 @@ freezegun==1.5.3
# via -r requirements/test.in
frozenlist==1.7.0
# via
# -r /home/dependabot/dependabot-updater/tmp/20250715-1382-lngh7e/dependabot_20250715-1382-a7k872/requirements/runtime-deps.in
# -r /home/dependabot/dependabot-updater/tmp/20250715-1384-v0sr9j/dependabot_20250715-1384-mw23m4/requirements/runtime-deps.in
# aiosignal
gunicorn==23.0.0
# via -r /home/dependabot/dependabot-updater/tmp/20250715-1382-lngh7e/dependabot_20250715-1382-a7k872/requirements/base.in
# via -r /home/dependabot/dependabot-updater/tmp/20250715-1384-v0sr9j/dependabot_20250715-1384-mw23m4/requirements/base.in
idna==3.6
# via
# trustme
Expand All @@ -59,9 +59,9 @@ mdurl==0.1.2
# via markdown-it-py
multidict==6.6.3
# via
# -r /home/dependabot/dependabot-updater/tmp/20250715-1382-lngh7e/dependabot_20250715-1382-a7k872/requirements/runtime-deps.in
# -r /home/dependabot/dependabot-updater/tmp/20250715-1384-v0sr9j/dependabot_20250715-1384-mw23m4/requirements/runtime-deps.in
# yarl
mypy==1.16.1 ; implementation_name == "cpython"
mypy==1.17.0 ; implementation_name == "cpython"
# via -r requirements/test.in
mypy-extensions==1.1.0
# via mypy
Expand All @@ -79,7 +79,7 @@ pluggy==1.6.0
# pytest-cov
propcache==0.3.2
# via
# -r /home/dependabot/dependabot-updater/tmp/20250715-1382-lngh7e/dependabot_20250715-1382-a7k872/requirements/runtime-deps.in
# -r /home/dependabot/dependabot-updater/tmp/20250715-1384-v0sr9j/dependabot_20250715-1384-mw23m4/requirements/runtime-deps.in
# yarl
proxy-py==2.4.10
# via -r requirements/test.in
Expand Down Expand Up @@ -112,7 +112,7 @@ pytest-xdist==3.8.0
# via -r requirements/test.in
python-dateutil==2.9.0.post0
# via freezegun
python-on-whales==0.77.0
python-on-whales==0.78.0
# via -r requirements/test.in
rich==14.0.0
# via pytest-codspeed
Expand Down Expand Up @@ -141,12 +141,12 @@ typing-extensions==4.14.1
typing-inspection==0.4.1
# via pydantic
uvloop==0.21.0 ; platform_system != "Windows" and implementation_name == "cpython"
# via -r /home/dependabot/dependabot-updater/tmp/20250715-1382-lngh7e/dependabot_20250715-1382-a7k872/requirements/base.in
# via -r /home/dependabot/dependabot-updater/tmp/20250715-1384-v0sr9j/dependabot_20250715-1384-mw23m4/requirements/base.in
wait-for-it==2.3.0
# via -r requirements/test.in
yarl==1.20.1
# via -r /home/dependabot/dependabot-updater/tmp/20250715-1382-lngh7e/dependabot_20250715-1382-a7k872/requirements/runtime-deps.in
# via -r /home/dependabot/dependabot-updater/tmp/20250715-1384-v0sr9j/dependabot_20250715-1384-mw23m4/requirements/runtime-deps.in
zlib-ng==0.5.1
# via -r requirements/test.in
zstandard==0.23.0 ; platform_python_implementation == "CPython" and python_version < "3.14"
# via -r /home/dependabot/dependabot-updater/tmp/20250715-1382-lngh7e/dependabot_20250715-1382-a7k872/requirements/runtime-deps.in
# via -r /home/dependabot/dependabot-updater/tmp/20250715-1384-v0sr9j/dependabot_20250715-1384-mw23m4/requirements/runtime-deps.in
6 changes: 3 additions & 3 deletions tests/test_client_functional.py
Original file line number Diff line number Diff line change
Expand Up @@ -4910,7 +4910,7 @@ async def final_handler(request: web.Request) -> web.Response:
client = await aiohttp_client(app)

payload_data = b"buffered reader payload"
buffer = io.BufferedReader(io.BytesIO(payload_data)) # type: ignore[arg-type]
buffer = io.BufferedReader(io.BytesIO(payload_data))
payload = BufferedReaderPayload(buffer)

resp = await client.post("/redirect", data=payload)
Expand Down Expand Up @@ -5369,8 +5369,8 @@ async def test_file_upload_307_308_redirect(
) -> None:
"""Test that file uploads work correctly with 307/308 redirects.

This demonstrates the bug where file payloads get incorrect Content-Length
on redirect because the file position isn't reset.
This verifies that file payloads maintain correct Content-Length
on redirect by properly handling the file position.
"""
received_bodies: list[bytes] = []

Expand Down
16 changes: 8 additions & 8 deletions tests/test_client_request.py
Original file line number Diff line number Diff line change
Expand Up @@ -1191,7 +1191,7 @@ async def _mock_write_bytes(
async def test_data_file(
loop: asyncio.AbstractEventLoop, buf: bytearray, conn: mock.Mock
) -> None:
with io.BufferedReader(io.BytesIO(b"*" * 2)) as file_handle: # type: ignore[arg-type]
with io.BufferedReader(io.BytesIO(b"*" * 2)) as file_handle:
req = ClientRequest(
"POST",
URL("http://python.org/"),
Expand Down Expand Up @@ -1804,7 +1804,7 @@ async def test_warn_if_unclosed_payload_via_body_setter(

# First set a payload that needs manual closing (autoclose=False)
file_payload = payload.BufferedReaderPayload(
io.BufferedReader(io.BytesIO(b"test data")), # type: ignore[arg-type]
io.BufferedReader(io.BytesIO(b"test data")),
encoding="utf-8",
)
req.body = file_payload
Expand Down Expand Up @@ -1851,7 +1851,7 @@ async def test_no_warn_for_consumed_payload_via_body_setter(

# Create a payload that needs manual closing
file_payload = payload.BufferedReaderPayload(
io.BufferedReader(io.BytesIO(b"test data")), # type: ignore[arg-type]
io.BufferedReader(io.BytesIO(b"test data")),
encoding="utf-8",
)
req.body = file_payload
Expand Down Expand Up @@ -1881,7 +1881,7 @@ async def test_warn_if_unclosed_payload_via_update_body_from_data(

# First set a payload that needs manual closing
file_payload = payload.BufferedReaderPayload(
io.BufferedReader(io.BytesIO(b"initial data")), # type: ignore[arg-type]
io.BufferedReader(io.BytesIO(b"initial data")),
encoding="utf-8",
)
req.update_body_from_data(file_payload)
Expand All @@ -1907,11 +1907,11 @@ async def test_warn_via_update_with_file_payload(
req = make_request("POST", "http://python.org/")

# First create a file-like object that results in BufferedReaderPayload
buffered1 = io.BufferedReader(io.BytesIO(b"file content 1")) # type: ignore[arg-type]
buffered1 = io.BufferedReader(io.BytesIO(b"file content 1"))
req.update_body_from_data(buffered1)

# Second update should warn about the first payload
buffered2 = io.BufferedReader(io.BytesIO(b"file content 2")) # type: ignore[arg-type]
buffered2 = io.BufferedReader(io.BytesIO(b"file content 2"))

with pytest.warns(
ResourceWarning,
Expand Down Expand Up @@ -2101,7 +2101,7 @@ async def test_warn_stacklevel_points_to_user_code(

# First set a payload that needs manual closing (autoclose=False)
file_payload = payload.BufferedReaderPayload(
io.BufferedReader(io.BytesIO(b"test data")), # type: ignore[arg-type]
io.BufferedReader(io.BytesIO(b"test data")),
encoding="utf-8",
)
req.body = file_payload
Expand Down Expand Up @@ -2139,7 +2139,7 @@ async def test_warn_stacklevel_update_body_from_data(

# First set a payload that needs manual closing (autoclose=False)
file_payload = payload.BufferedReaderPayload(
io.BufferedReader(io.BytesIO(b"test data")), # type: ignore[arg-type]
io.BufferedReader(io.BytesIO(b"test data")),
encoding="utf-8",
)
req.update_body_from_data(file_payload)
Expand Down
13 changes: 6 additions & 7 deletions tests/test_payload.py
Original file line number Diff line number Diff line change
Expand Up @@ -874,7 +874,7 @@ async def test_string_io_payload_reusability() -> None:
async def test_buffered_reader_payload_reusability() -> None:
"""Test that BufferedReaderPayload can be written and read multiple times."""
data = b"test buffered reader payload"
buffer = io.BufferedReader(io.BytesIO(data)) # type: ignore[arg-type]
buffer = io.BufferedReader(io.BytesIO(data))
p = payload.BufferedReaderPayload(buffer)

# First write_with_length
Expand Down Expand Up @@ -1281,8 +1281,9 @@ def open_file() -> TextIO:
async def test_iobase_payload_size_after_reading(tmp_path: Path) -> None:
"""Test that IOBasePayload.size returns correct size after file has been read.

This demonstrates the bug where size calculation doesn't account for
the current file position, causing issues with 307/308 redirects.
This verifies that size calculation properly accounts for the initial
file position, which is critical for 307/308 redirects where the same
payload instance is reused.
"""
# Create a test file with known content
test_file = tmp_path / "test.txt"
Expand All @@ -1304,14 +1305,12 @@ async def test_iobase_payload_size_after_reading(tmp_path: Path) -> None:
assert len(writer.buffer) == expected_size

# Second size check - should still return full file size
# but currently returns 0 because file position is at EOF
assert p.size == expected_size # This assertion fails!
assert p.size == expected_size

# Attempting to write again should write the full content
# but currently writes nothing because file is at EOF
writer2 = BufferWriter()
await p.write(writer2)
assert len(writer2.buffer) == expected_size # This also fails!
assert len(writer2.buffer) == expected_size
finally:
await asyncio.to_thread(f.close)

Expand Down
2 changes: 1 addition & 1 deletion tests/test_web_response.py
Original file line number Diff line number Diff line change
Expand Up @@ -1106,7 +1106,7 @@ def read(self, size: int = -1) -> bytes:
(io.StringIO("test"), "test"),
(io.TextIOWrapper(io.BytesIO(b"test")), "test"),
(io.BytesIO(b"test"), "test"),
(io.BufferedReader(io.BytesIO(b"test")), "test"), # type: ignore[arg-type]
(io.BufferedReader(io.BytesIO(b"test")), "test"),
(async_iter(), None),
(BodyPartReader(b"x", CIMultiDictProxy(CIMultiDict()), mock.Mock()), None),
(
Expand Down
Loading