Skip to content

Commit 8a695a4

Browse files
Reject closed file-like objects in session uploads
Co-authored-by: Shri Sukhani <shrisukhani@users.noreply.github.com>
1 parent 24e438b commit 8a695a4

3 files changed

Lines changed: 25 additions & 0 deletions

File tree

hyperbrowser/client/managers/async_manager/session.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,8 @@ async def upload_file(
134134
original_error=exc,
135135
) from exc
136136
elif callable(getattr(file_input, "read", None)):
137+
if getattr(file_input, "closed", False):
138+
raise HyperbrowserError("file_input file-like object must be open")
137139
files = {"file": file_input}
138140
response = await self._client.transport.post(
139141
self._client._build_url(f"/session/{id}/uploads"),

hyperbrowser/client/managers/sync_manager/session.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,8 @@ def upload_file(
126126
original_error=exc,
127127
) from exc
128128
elif callable(getattr(file_input, "read", None)):
129+
if getattr(file_input, "closed", False):
130+
raise HyperbrowserError("file_input file-like object must be open")
129131
files = {"file": file_input}
130132
response = self._client.transport.post(
131133
self._client._build_url(f"/session/{id}/uploads"),

tests/test_session_upload_file.py

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,15 @@ def test_sync_session_upload_file_rejects_non_callable_read_attribute():
148148
manager.upload_file("session_123", fake_file)
149149

150150

151+
def test_sync_session_upload_file_rejects_closed_file_like_object():
152+
manager = SyncSessionManager(_FakeClient(_SyncTransport()))
153+
closed_file_obj = io.BytesIO(b"content")
154+
closed_file_obj.close()
155+
156+
with pytest.raises(HyperbrowserError, match="file-like object must be open"):
157+
manager.upload_file("session_123", closed_file_obj)
158+
159+
151160
def test_async_session_upload_file_rejects_non_callable_read_attribute():
152161
manager = AsyncSessionManager(_FakeClient(_AsyncTransport()))
153162
fake_file = type("FakeFile", (), {"read": "not-callable"})()
@@ -159,6 +168,18 @@ async def run():
159168
asyncio.run(run())
160169

161170

171+
def test_async_session_upload_file_rejects_closed_file_like_object():
172+
manager = AsyncSessionManager(_FakeClient(_AsyncTransport()))
173+
closed_file_obj = io.BytesIO(b"content")
174+
closed_file_obj.close()
175+
176+
async def run():
177+
with pytest.raises(HyperbrowserError, match="file-like object must be open"):
178+
await manager.upload_file("session_123", closed_file_obj)
179+
180+
asyncio.run(run())
181+
182+
162183
def test_sync_session_upload_file_raises_hyperbrowser_error_for_missing_path(tmp_path):
163184
manager = SyncSessionManager(_FakeClient(_SyncTransport()))
164185
missing_path = tmp_path / "missing-file.txt"

0 commit comments

Comments
 (0)