fix(core): preserve read-only write failures during Windows cleanup - #217
Conversation
Clear the read-only attribute only on the failed write temporary file. Log cleanup failures without masking the original exception. Add native Windows regression and writable overwrite coverage for issue phasespace-labs#216.
|
Merged — thank you. This is the scope you proposed on #169, built exactly as described. The test is the part I want to name. Asserting The read-only sentinel is better than the obvious test. "No One thing worth having on the record: on POSIX the re-raise inside the inner handler now lands in the outer And thank you for how you reported the validation. You named the platform and interpreter, scoped the claim to the checks you actually ran, and flagged that |
Fixes #216.
A failed overwrite of a read-only destination on Windows can also fail to unlink the temporary file whose mode was copied from that destination. Cleanup then strands the temporary file and masks the original replacement exception.
This change retries deletion after making only that temporary file writable on Windows. Cleanup errors are logged and the original write exception is re-raised. The successful-write path and pre-rename mode-copy order stay unchanged; the destination is never made writable.
The native Windows regression uses the real
os.replace, captures its exception, and asserts that the exact same object is raised to the caller. It checks unchanged destination content and mode, preservation of an unrelated read-only temporary-file sentinel, and removal of only the write's temporary file. Additional tests cover exact UTF-8 bytes and mode for writable overwrites, plus cleanup failures that must be logged without masking the original error.Validation on native Windows / CPython 3.11.15:
d4379d87d7f13f041ef3ddeca18cab2751ee471b: 3 failed, 1 passed.test_atomic_write_directory_fsync_failure_propagates_and_cleans_temp, also fails on unchanged upstream: it expects a directory fsync error while Windows skips directory fsync. No broader-suite green claim is intended.ruff check palinode/ tests/ scripts/: passed.bandit -r palinode/ -ll: passed.Full suite not rerun; unrelated native process-liveness tests remain outside this case. Changelog entry is under the existing Unreleased / Fixed heading.
Commands for reproduction: