Repository navigation
Conversation
Return independent read snapshots and reject mutation methods without changing writable store handles. Add binary/text, buffer, metadata, pickle and write-mode regression coverage. Fixes fsspec#2193 Assisted-by: OpenAI Codex <noreply@openai.com>
|
Took a careful look at this. The core problem is real and the enforcement surface is well chosen — overriding 1. The fix is asymmetric — writable handles still alias. The changelog says read-only opens mean "another open cannot change their mode", but m.pipe('/f', b'abc')
h1 = m.open('/f', 'r+b')
h2 = m.open('/f', 'ab')
h1.mode # -> 'ab', silently changed by opening h2
h1 is h2 # -> TrueBoth are writable so nothing raises today, but 2. This changes read visibility semantics, and I don't think it should be decided here. Snapshotting readers means an in-place write is no longer visible to an already-open reader: m.pipe('/f', b'AAA')
r = m.open('/f', 'rb')
w = m.open('/f', 'r+b'); w.seek(0); w.write(b'Z'); w.flush()
r.read()
# main: b'AA'
# this PR: b'AAA'Note main returns But it also moves Things I checked that are fine, so nobody goes chasing them:
Happy to see this land once the mode aliasing is settled and the semantics question has an answer. |
Assisted-by: OpenAI Codex
|
Thanks for the concrete checks. I reproduced both observations independently on this branch and on the original base
Commit Revalidation: 216 memory/backend tests passed; Ruff and the Sphinx HTML build with Assisted by OpenAI Codex under the submitting account's authorization. |
My choice is, that updates from other open handles should be immediately visible - they should share the same underlying buffer. The exact behaviour on local filesystems depends on the OS, so we are free to make the choice here. We should follow the normal posix behaviour, where mode "w" truncates and starts writing at position 0, but mode "a" (or "r+" etc) does not truncate and starts at the end. It is OK to write past the end of a BytesIO - it gets zero-filled. |
Address maintainer review on live read visibility while preserving transaction isolation and modification timestamps. Assisted-by: OpenAI Codex
|
Thanks @martindurant. Updated in 442ee75: each open now has its own cursor/mode over the same stored buffer, including writable handles. Existing readers observe ordinary writes and truncation immediately, and read-only buffer views remain read-only. The old snapshot design is removed. I merged af73c65 and retained its modification-time and transactional-append fixes. Transactional append/overwrite still publishes a replacement only at commit, so already-open handles keep the old buffer across that replacement. Added explicit coverage for both commit and rollback. One mode detail: r+b still starts at offset 0, matching existing upstream and builtin open; append modes start at EOF and write at the current EOF even after a seek. I kept the existing r+b contract rather than moving its initial cursor to EOF. Final memory/backend suite: 258 passed, also 258 against the installed wheel. Broader integration: 1,682 passed / 219 skipped / 11 xfailed, with the two invalid-Windows-filename failures independently reproduced on clean current upstream. Ruff, docs and clean packaging checks passed. The PR description now records the updated scope and limitations. |
Fixes #2193. Also addresses the shared-cursor behavior reported in #2199.
Current design (review follow-up, 2026-10-02)
Following @martindurant's request for live read visibility, this replaces the earlier read-snapshot proposal:
MemoryFilebuffer. Reads observe subsequent ordinary writes, truncation andwbreplacement contents without copying the file on open.write,writelines,truncateandcommit;getbuffer()exposes a read-only view of the shared buffer.r+bretains the existing offset-zero behavior (also the behavior of builtinopen);wtruncates, and seeking beyond EOF before writing zero-fills the gap.af73c65, retaining its modification-time fixes and private transactional append buffers. Transactional append/overwrite commit still publishes a replacement; handles opened before that commit retain their original buffer. Text wrappers can retain their normal read-ahead cache until a seek.MemoryFileconsumers in other backends remain supported.Validation
Dedicated Windows / CPython 3.13.15 environment:
|and raise WindowsWinError 123; the exact two failures reproduce on a clean export of current upstreamaf73c65(10 sibling cases pass). No existing skips or expectations were relaxed.AI assistance: implemented and validated with OpenAI Codex. The earlier snapshot-only design and its claims are superseded by this revision.