bpo-35950: Raise UnsupportedOperation in BufferedReader.truncate() (GH-18586)
https://github.com/python/cpython/commit/fd5116c0e77aec05f67fb24f10562ac9206... commit: fd5116c0e77aec05f67fb24f10562ac920648035 branch: master author: Berker Peksag <berker.peksag@gmail.com> committer: GitHub <noreply@github.com> date: 2020-02-21T09:57:26-08:00 summary: 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 files: A Misc/NEWS.d/next/Library/2020-02-21-02-42-41.bpo-35950.9G3-wl.rst M Lib/_pyio.py M Lib/test/test_io.py M Modules/_io/bufferedio.c diff --git a/Lib/_pyio.py b/Lib/_pyio.py index 4c2414672ed56..8eaa114c07c91 100644 --- a/Lib/_pyio.py +++ b/Lib/_pyio.py @@ -792,6 +792,9 @@ def tell(self): return pos def truncate(self, pos=None): + self._checkClosed() + self._checkWritable() + # 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 # file state. diff --git a/Lib/test/test_io.py b/Lib/test/test_io.py index 0bfa4d249e9a6..c27dfd96bc00d 100644 --- a/Lib/test/test_io.py +++ b/Lib/test/test_io.py @@ -1528,6 +1528,13 @@ def test_read_on_closed(self): self.assertRaises(ValueError, b.peek) 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): tp = io.BufferedReader @@ -2372,6 +2379,10 @@ def test_interleaved_readline_write(self): # You can't construct a BufferedRandom over a non-seekable stream. 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): tp = io.BufferedRandom diff --git a/Misc/NEWS.d/next/Library/2020-02-21-02-42-41.bpo-35950.9G3-wl.rst b/Misc/NEWS.d/next/Library/2020-02-21-02-42-41.bpo-35950.9G3-wl.rst new file mode 100644 index 0000000000000..92e3b2399238e --- /dev/null +++ b/Misc/NEWS.d/next/Library/2020-02-21-02-42-41.bpo-35950.9G3-wl.rst @@ -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. diff --git a/Modules/_io/bufferedio.c b/Modules/_io/bufferedio.c index 6f55577813c9f..a09082c84f8a2 100644 --- a/Modules/_io/bufferedio.c +++ b/Modules/_io/bufferedio.c @@ -1315,15 +1315,19 @@ _io__Buffered_truncate_impl(buffered *self, PyObject *pos) PyObject *res = NULL; CHECK_INITIALIZED(self) + CHECK_CLOSED(self, "truncate of closed file") + if (!self->writable) { + return bufferediobase_unsupported("truncate"); + } if (!ENTER_BUFFERED(self)) return NULL; - if (self->writable) { - res = buffered_flush_and_rewind_unlocked(self); - if (res == NULL) - goto end; - Py_CLEAR(res); + res = buffered_flush_and_rewind_unlocked(self); + if (res == NULL) { + goto end; } + Py_CLEAR(res); + res = PyObject_CallMethodOneArg(self->raw, _PyIO_str_truncate, pos); if (res == NULL) goto end;
participants (1)
-
Berker Peksag