Skip to content

Commit 0211f91

Browse files
[3.12] gh-115059: Flush the underlying write buffer in io.BufferedRandom.read1() (GH-115163) (GH-115205)
(cherry picked from commit 846fd72) Co-authored-by: Serhiy Storchaka <[email protected]>
1 parent 235c54f commit 0211f91

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
@@ -2506,6 +2506,28 @@ def test_interleaved_read_write(self):
25062506
f.flush()
25072507
self.assertEqual(raw.getvalue(), b'a2c')
25082508

2509+
def test_read1_after_write(self):
2510+
with self.BytesIO(b'abcdef') as raw:
2511+
with self.tp(raw, 3) as f:
2512+
f.write(b"1")
2513+
self.assertEqual(f.read1(1), b'b')
2514+
f.flush()
2515+
self.assertEqual(raw.getvalue(), b'1bcdef')
2516+
with self.BytesIO(b'abcdef') as raw:
2517+
with self.tp(raw, 3) as f:
2518+
f.write(b"1")
2519+
self.assertEqual(f.read1(), b'bcd')
2520+
f.flush()
2521+
self.assertEqual(raw.getvalue(), b'1bcdef')
2522+
with self.BytesIO(b'abcdef') as raw:
2523+
with self.tp(raw, 3) as f:
2524+
f.write(b"1")
2525+
# XXX: read(100) returns different numbers of bytes
2526+
# in Python and C implementations.
2527+
self.assertEqual(f.read1(100)[:3], b'bcd')
2528+
f.flush()
2529+
self.assertEqual(raw.getvalue(), b'1bcdef')
2530+
25092531
def test_interleaved_readline_write(self):
25102532
with self.BytesIO(b'ab\ncdef\ng\n') as raw:
25112533
with self.tp(raw) as f:
@@ -2518,6 +2540,36 @@ def test_interleaved_readline_write(self):
25182540
f.flush()
25192541
self.assertEqual(raw.getvalue(), b'1b\n2def\n3\n')
25202542

2543+
def test_xxx(self):
2544+
with self.BytesIO(b'abcdefgh') as raw:
2545+
with self.tp(raw) as f:
2546+
f.write(b'123')
2547+
self.assertEqual(f.read(), b'defgh')
2548+
f.write(b'456')
2549+
f.flush()
2550+
self.assertEqual(raw.getvalue(), b'123defgh456')
2551+
with self.BytesIO(b'abcdefgh') as raw:
2552+
with self.tp(raw) as f:
2553+
f.write(b'123')
2554+
self.assertEqual(f.read(3), b'def')
2555+
f.write(b'456')
2556+
f.flush()
2557+
self.assertEqual(raw.getvalue(), b'123def456')
2558+
with self.BytesIO(b'abcdefgh') as raw:
2559+
with self.tp(raw) as f:
2560+
f.write(b'123')
2561+
self.assertEqual(f.read1(), b'defgh')
2562+
f.write(b'456')
2563+
f.flush()
2564+
self.assertEqual(raw.getvalue(), b'123defgh456')
2565+
with self.BytesIO(b'abcdefgh') as raw:
2566+
with self.tp(raw) as f:
2567+
f.write(b'123')
2568+
self.assertEqual(f.read1(3), b'def')
2569+
f.write(b'456')
2570+
f.flush()
2571+
self.assertEqual(raw.getvalue(), b'123def456')
2572+
25212573
# You can't construct a BufferedRandom over a non-seekable stream.
25222574
test_unseekable = None
25232575

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
@@ -1015,6 +1015,16 @@ _io__Buffered_read1_impl(buffered *self, Py_ssize_t n)
10151015
Py_DECREF(res);
10161016
return NULL;
10171017
}
1018+
/* Flush the write buffer if necessary */
1019+
if (self->writable) {
1020+
PyObject *r = buffered_flush_and_rewind_unlocked(self);
1021+
if (r == NULL) {
1022+
LEAVE_BUFFERED(self)
1023+
Py_DECREF(res);
1024+
return NULL;
1025+
}
1026+
Py_DECREF(r);
1027+
}
10181028
_bufferedreader_reset_buf(self);
10191029
r = _bufferedreader_raw_read(self, PyBytes_AS_STRING(res), n);
10201030
LEAVE_BUFFERED(self)

0 commit comments

Comments
 (0)