Measured 2026-09-10, compiler 4d3d006cf973
p = "<tmp>/f.txt"
open(p, "w").write("DATA")
with open(p) as f:
print(repr(f.read())) # CPython: 'DATA' pxx: ''
q = "<tmp>/g.txt"
h = open(q, "w")
h.write("DATA2")
h.close()
with open(q) as f:
print(repr(f.read())) # CPython: 'DATA2' pxx: 'DATA2'
Two rows, one difference, and the second row is the control: the writer works. What is missing is the drain when the handle is dropped without a close.
Why no existing assertion can see it
Every file test in the tree closes what it opens — a with block, or an
explicit close() — which is correct style and is exactly why the defect
survives. A write-then-read-back is the only assertion class that can
observe this: the write itself succeeds, open() succeeds, the file EXISTS
afterwards with the right name and the right mode, and only its CONTENT is
wrong. An assertion on the return value of write would pass too.
Same structural blindness as a leak: the operation under test reports success and the damage is somewhere the success does not look.
The two candidate fixes
- Flush on finalisation. What CPython does. Needs the file object to have a destructor that runs when the last reference goes, which is a question about NilPy's object lifetime and not about files.
- Write through, no buffer.
pystdout_writealready does exactly this (IR_WRITE emits the syscall inline), so there is precedent — and it makesclose()cheap rather than load-bearing.
Option 2 removes the class instead of catching it, and the performance argument for a buffer has never been measured here.
Positive control for whoever takes it
The two-row program above, asserting 'DATA' on the FIRST row. A control that
only exercises the with spelling passes today and certifies the bug.