Skip to content

Commit 20c6535

Browse files
[3.11] gh-115059: Flush the underlying write buffer in io.BufferedRandom.read1() (GH-115163) (GH-115206)
(cherry picked from commit 846fd72) Co-authored-by: Serhiy Storchaka <[email protected]>
1 parent 5fc2f55 commit 20c6535

File tree

3 files changed

+63
-0
lines changed

3 files changed

+63
-0
lines changed

Lib/test/test_io.py

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2403,6 +2403,28 @@ def test_interleaved_read_write(self):
24032403
f.flush()
24042404
self.assertEqual(raw.getvalue(), b'a2c')
24052405

2406+
def test_read1_after_write(self):
2407+
with self.BytesIO(b'abcdef') as raw:
2408+
with self.tp(raw, 3) as f:
2409+
f.write(b"1")
2410+
self.assertEqual(f.read1(1), b'b')
2411+
f.flush()
2412+
self.assertEqual(raw.getvalue(), b'1bcdef')
2413+
with self.BytesIO(b'abcdef') as raw:
2414+
with self.tp(raw, 3) as f:
2415+
f.write(b"1")
2416+
self.assertEqual(f.read1(), b'bcd')
2417+
f.flush()
2418+
self.assertEqual(raw.getvalue(), b'1bcdef')
2419+
with self.BytesIO(b'abcdef') as raw:
2420+
with self.tp(raw, 3) as f:
2421+
f.write(b"1")
2422+
# XXX: read(100) returns different numbers of bytes
2423+
# in Python and C implementations.
2424+
self.assertEqual(f.read1(100)[:3], b'bcd')
2425+
f.flush()
2426+
self.assertEqual(raw.getvalue(), b'1bcdef')
2427+
24062428
def test_interleaved_readline_write(self):
24072429
with self.BytesIO(b'ab\ncdef\ng\n') as raw:
24082430
with self.tp(raw) as f:
@@ -2415,6 +2437,36 @@ def test_interleaved_readline_write(self):
24152437
f.flush()
24162438
self.assertEqual(raw.getvalue(), b'1b\n2def\n3\n')
24172439

2440+
def test_xxx(self):
2441+
with self.BytesIO(b'abcdefgh') as raw:
2442+
with self.tp(raw) as f:
2443+
f.write(b'123')
2444+
self.assertEqual(f.read(), b'defgh')
2445+
f.write(b'456')
2446+
f.flush()
2447+
self.assertEqual(raw.getvalue(), b'123defgh456')
2448+
with self.BytesIO(b'abcdefgh') as raw:
2449+
with self.tp(raw) as f:
2450+
f.write(b'123')
2451+
self.assertEqual(f.read(3), b'def')
2452+
f.write(b'456')
2453+
f.flush()
2454+
self.assertEqual(raw.getvalue(), b'123def456')
2455+
with self.BytesIO(b'abcdefgh') as raw:
2456+
with self.tp(raw) as f:
2457+
f.write(b'123')
2458+
self.assertEqual(f.read1(), b'defgh')
2459+
f.write(b'456')
2460+
f.flush()
2461+
self.assertEqual(raw.getvalue(), b'123defgh456')
2462+
with self.BytesIO(b'abcdefgh') as raw:
2463+
with self.tp(raw) as f:
2464+
f.write(b'123')
2465+
self.assertEqual(f.read1(3), b'def')
2466+
f.write(b'456')
2467+
f.flush()
2468+
self.assertEqual(raw.getvalue(), b'123def456')
2469+
24182470
# You can't construct a BufferedRandom over a non-seekable stream.
24192471
test_unseekable = None
24202472

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
:meth:`io.BufferedRandom.read1` now flushes the underlying write buffer.

Modules/_io/bufferedio.c

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -929,6 +929,16 @@ _io__Buffered_read1_impl(buffered *self, Py_ssize_t n)
929929
Py_DECREF(res);
930930
return NULL;
931931
}
932+
/* Flush the write buffer if necessary */
933+
if (self->writable) {
934+
PyObject *r = buffered_flush_and_rewind_unlocked(self);
935+
if (r == NULL) {
936+
LEAVE_BUFFERED(self)
937+
Py_DECREF(res);
938+
return NULL;
939+
}
940+
Py_DECREF(r);
941+
}
932942
_bufferedreader_reset_buf(self);
933943
r = _bufferedreader_raw_read(self, PyBytes_AS_STRING(res), n);
934944
LEAVE_BUFFERED(self)

0 commit comments

Comments
 (0)