Skip to content

Commit fd5116c

Browse files
authored
bpo-35950: Raise UnsupportedOperation in BufferedReader.truncate() (GH-18586)
The truncate() method of io.BufferedReader() should raise UnsupportedOperation when it is called on a read-only io.BufferedReader() instance. https://bugs.python.org/issue35950 Automerge-Triggered-By: @methane
1 parent d4d17fd commit fd5116c

File tree

4 files changed

+25
-5
lines changed

4 files changed

+25
-5
lines changed

Lib/_pyio.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -792,6 +792,9 @@ def tell(self):
792792
return pos
793793

794794
def truncate(self, pos=None):
795+
self._checkClosed()
796+
self._checkWritable()
797+
795798
# Flush the stream. We're mixing buffered I/O with lower-level I/O,
796799
# and a flush may be necessary to synch both views of the current
797800
# file state.

Lib/test/test_io.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1528,6 +1528,13 @@ def test_read_on_closed(self):
15281528
self.assertRaises(ValueError, b.peek)
15291529
self.assertRaises(ValueError, b.read1, 1)
15301530

1531+
def test_truncate_on_read_only(self):
1532+
rawio = self.MockFileIO(b"abc")
1533+
bufio = self.tp(rawio)
1534+
self.assertFalse(bufio.writable())
1535+
self.assertRaises(self.UnsupportedOperation, bufio.truncate)
1536+
self.assertRaises(self.UnsupportedOperation, bufio.truncate, 0)
1537+
15311538

15321539
class CBufferedReaderTest(BufferedReaderTest, SizeofTest):
15331540
tp = io.BufferedReader
@@ -2372,6 +2379,10 @@ def test_interleaved_readline_write(self):
23722379
# You can't construct a BufferedRandom over a non-seekable stream.
23732380
test_unseekable = None
23742381

2382+
# writable() returns True, so there's no point to test it over
2383+
# a writable stream.
2384+
test_truncate_on_read_only = None
2385+
23752386

23762387
class CBufferedRandomTest(BufferedRandomTest, SizeofTest):
23772388
tp = io.BufferedRandom
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Raise :exc:`io.UnsupportedOperation` in :meth:`io.BufferedReader.truncate`
2+
when it is called on a read-only :class:`io.BufferedReader` instance.

Modules/_io/bufferedio.c

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1315,15 +1315,19 @@ _io__Buffered_truncate_impl(buffered *self, PyObject *pos)
13151315
PyObject *res = NULL;
13161316

13171317
CHECK_INITIALIZED(self)
1318+
CHECK_CLOSED(self, "truncate of closed file")
1319+
if (!self->writable) {
1320+
return bufferediobase_unsupported("truncate");
1321+
}
13181322
if (!ENTER_BUFFERED(self))
13191323
return NULL;
13201324

1321-
if (self->writable) {
1322-
res = buffered_flush_and_rewind_unlocked(self);
1323-
if (res == NULL)
1324-
goto end;
1325-
Py_CLEAR(res);
1325+
res = buffered_flush_and_rewind_unlocked(self);
1326+
if (res == NULL) {
1327+
goto end;
13261328
}
1329+
Py_CLEAR(res);
1330+
13271331
res = PyObject_CallMethodOneArg(self->raw, _PyIO_str_truncate, pos);
13281332
if (res == NULL)
13291333
goto end;

0 commit comments

Comments
 (0)