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
This commit is contained in:
parent
d4d17fd2cf
commit
fd5116c0e7
|
@ -792,6 +792,9 @@ class _BufferedIOMixin(BufferedIOBase):
|
||||||
return pos
|
return pos
|
||||||
|
|
||||||
def truncate(self, pos=None):
|
def truncate(self, pos=None):
|
||||||
|
self._checkClosed()
|
||||||
|
self._checkWritable()
|
||||||
|
|
||||||
# Flush the stream. We're mixing buffered I/O with lower-level I/O,
|
# Flush the stream. We're mixing buffered I/O with lower-level I/O,
|
||||||
# and a flush may be necessary to synch both views of the current
|
# and a flush may be necessary to synch both views of the current
|
||||||
# file state.
|
# file state.
|
||||||
|
|
|
@ -1528,6 +1528,13 @@ class BufferedReaderTest(unittest.TestCase, CommonBufferedTests):
|
||||||
self.assertRaises(ValueError, b.peek)
|
self.assertRaises(ValueError, b.peek)
|
||||||
self.assertRaises(ValueError, b.read1, 1)
|
self.assertRaises(ValueError, b.read1, 1)
|
||||||
|
|
||||||
|
def test_truncate_on_read_only(self):
|
||||||
|
rawio = self.MockFileIO(b"abc")
|
||||||
|
bufio = self.tp(rawio)
|
||||||
|
self.assertFalse(bufio.writable())
|
||||||
|
self.assertRaises(self.UnsupportedOperation, bufio.truncate)
|
||||||
|
self.assertRaises(self.UnsupportedOperation, bufio.truncate, 0)
|
||||||
|
|
||||||
|
|
||||||
class CBufferedReaderTest(BufferedReaderTest, SizeofTest):
|
class CBufferedReaderTest(BufferedReaderTest, SizeofTest):
|
||||||
tp = io.BufferedReader
|
tp = io.BufferedReader
|
||||||
|
@ -2372,6 +2379,10 @@ class BufferedRandomTest(BufferedReaderTest, BufferedWriterTest):
|
||||||
# You can't construct a BufferedRandom over a non-seekable stream.
|
# You can't construct a BufferedRandom over a non-seekable stream.
|
||||||
test_unseekable = None
|
test_unseekable = None
|
||||||
|
|
||||||
|
# writable() returns True, so there's no point to test it over
|
||||||
|
# a writable stream.
|
||||||
|
test_truncate_on_read_only = None
|
||||||
|
|
||||||
|
|
||||||
class CBufferedRandomTest(BufferedRandomTest, SizeofTest):
|
class CBufferedRandomTest(BufferedRandomTest, SizeofTest):
|
||||||
tp = io.BufferedRandom
|
tp = io.BufferedRandom
|
||||||
|
|
|
@ -0,0 +1,2 @@
|
||||||
|
Raise :exc:`io.UnsupportedOperation` in :meth:`io.BufferedReader.truncate`
|
||||||
|
when it is called on a read-only :class:`io.BufferedReader` instance.
|
|
@ -1315,15 +1315,19 @@ _io__Buffered_truncate_impl(buffered *self, PyObject *pos)
|
||||||
PyObject *res = NULL;
|
PyObject *res = NULL;
|
||||||
|
|
||||||
CHECK_INITIALIZED(self)
|
CHECK_INITIALIZED(self)
|
||||||
|
CHECK_CLOSED(self, "truncate of closed file")
|
||||||
|
if (!self->writable) {
|
||||||
|
return bufferediobase_unsupported("truncate");
|
||||||
|
}
|
||||||
if (!ENTER_BUFFERED(self))
|
if (!ENTER_BUFFERED(self))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
if (self->writable) {
|
res = buffered_flush_and_rewind_unlocked(self);
|
||||||
res = buffered_flush_and_rewind_unlocked(self);
|
if (res == NULL) {
|
||||||
if (res == NULL)
|
goto end;
|
||||||
goto end;
|
|
||||||
Py_CLEAR(res);
|
|
||||||
}
|
}
|
||||||
|
Py_CLEAR(res);
|
||||||
|
|
||||||
res = PyObject_CallMethodOneArg(self->raw, _PyIO_str_truncate, pos);
|
res = PyObject_CallMethodOneArg(self->raw, _PyIO_str_truncate, pos);
|
||||||
if (res == NULL)
|
if (res == NULL)
|
||||||
goto end;
|
goto end;
|
||||||
|
|
Loading…
Reference in New Issue