fix(storage): close upload file handle when the request fails - #1586
fix(storage): close upload file handle when the request fails#1586chengwudi1 wants to merge 1 commit into
Conversation
49fc4ef to
ccc88c6
Compare
|
Hi! Friendly ping — the CI workflows (CI/CD, title check, SDK compliance) are |
|
Superseded by #1607, which credits you as co-author. Your diagnosis and your test coverage were both right — Two things came up while rebasing this onto 1. It no longer applied. #1577 landed in the meantime and rewrote the same block in 2. with open("big.bin", "rb") as f:
try:
client.storage.from_("bucket").upload("big.bin", f)
except StorageApiError:
f.seek(0) # ValueError: I/O operation on closed file
client.storage.from_("bucket").upload("big.bin", f)#1607 moves the close into One more thing your PR surfaced, worth its own issue: Thanks for the work here. |
What
Fixes #1575 — when
upload()/update()/upload_to_signed_url()fail, the file handle storage3 opened itself wasnever closed:
_requestclosed it after theexcept HTTPStatusErrorblock, so any non-2xx raisedStorageApiErrorstraight past it, leaking the handle (and emittingResourceWarning: unclosed file).How
Moved the close into a
finallyblock so it runs on both success and error paths. The condition is unchanged — stillonly
BufferedReaderhandles (i.e. only handles storage3 opened itself), so a caller-supplied stream is left alone._async/file_api.py: hand-written fix_sync/file_api.py: regenerated with unasync (from the_asyncsource), no unrelated changesTests
_sync/file_api.py: regenerated with unasync (from the_asyncsource), no unrelated changesTests
Added
tests/_async/test_file_api.pyandtests/_sync/test_file_api.py(3 tests each, mock-based — no network):upload closes the handle it opened on success (regression)
update closes the handle it opened on error
update closes the handle it opened on error
Verified: reverting only the source change fails the tests on
closenot being called. All 6 pass;ruff checkandVerified: reverting only the source change fails the tests on
closenot being called. All 6 pass;ruff checkandruff formatclean.Note: the diff on
file_api.pylooks larger than it is — wrapping the body intryreindents it. The onlybehavioural change is where the close happens.
Note: the diff on
file_api.pylooks larger than it is — wrapping the body intryreindents it. The onlybehavioural change is where the close happens.