Kaydet (Commit) 1d857453 authored tarafından Antoine Pitrou's avatar Antoine Pitrou

Issue #15841: The readable(), writable() and seekable() methods of BytesIO

and StringIO objects now raise ValueError when the object has been closed.
Patch by Alessandro Moura.
üst 397e5c98
...@@ -889,12 +889,18 @@ class BytesIO(BufferedIOBase): ...@@ -889,12 +889,18 @@ class BytesIO(BufferedIOBase):
return pos return pos
def readable(self): def readable(self):
if self.closed:
raise ValueError("I/O operation on closed file.")
return True return True
def writable(self): def writable(self):
if self.closed:
raise ValueError("I/O operation on closed file.")
return True return True
def seekable(self): def seekable(self):
if self.closed:
raise ValueError("I/O operation on closed file.")
return True return True
...@@ -1567,6 +1573,8 @@ class TextIOWrapper(TextIOBase): ...@@ -1567,6 +1573,8 @@ class TextIOWrapper(TextIOBase):
return self._buffer return self._buffer
def seekable(self): def seekable(self):
if self.closed:
raise ValueError("I/O operation on closed file.")
return self._seekable return self._seekable
def readable(self): def readable(self):
......
...@@ -318,9 +318,9 @@ class MemoryTestMixin: ...@@ -318,9 +318,9 @@ class MemoryTestMixin:
self.assertEqual(memio.isatty(), False) self.assertEqual(memio.isatty(), False)
self.assertEqual(memio.closed, False) self.assertEqual(memio.closed, False)
memio.close() memio.close()
self.assertEqual(memio.writable(), True) self.assertRaises(ValueError, memio.writable)
self.assertEqual(memio.readable(), True) self.assertRaises(ValueError, memio.readable)
self.assertEqual(memio.seekable(), True) self.assertRaises(ValueError, memio.seekable)
self.assertRaises(ValueError, memio.isatty) self.assertRaises(ValueError, memio.isatty)
self.assertEqual(memio.closed, True) self.assertEqual(memio.closed, True)
...@@ -665,7 +665,6 @@ class CBytesIOTest(PyBytesIOTest): ...@@ -665,7 +665,6 @@ class CBytesIOTest(PyBytesIOTest):
check(io.BytesIO(b'a'), basesize + 1 + 1 ) check(io.BytesIO(b'a'), basesize + 1 + 1 )
check(io.BytesIO(b'a' * 1000), basesize + 1000 + 1 ) check(io.BytesIO(b'a' * 1000), basesize + 1000 + 1 )
class CStringIOTest(PyStringIOTest): class CStringIOTest(PyStringIOTest):
ioclass = io.StringIO ioclass = io.StringIO
UnsupportedOperation = io.UnsupportedOperation UnsupportedOperation = io.UnsupportedOperation
......
...@@ -658,6 +658,7 @@ Skip Montanaro ...@@ -658,6 +658,7 @@ Skip Montanaro
Paul Moore Paul Moore
Derek Morr Derek Morr
James A Morrison James A Morrison
Alessandro Moura
Pablo Mouzo Pablo Mouzo
Mher Movsisyan Mher Movsisyan
Ruslan Mstoi Ruslan Mstoi
......
...@@ -115,6 +115,10 @@ Core and Builtins ...@@ -115,6 +115,10 @@ Core and Builtins
Library Library
------- -------
- Issue #15841: The readable(), writable() and seekable() methods of BytesIO
and StringIO objects now raise ValueError when the object has been closed.
Patch by Alessandro Moura.
- Issue #15509: webbrowser.UnixBrowser no longer passes empty arguments to - Issue #15509: webbrowser.UnixBrowser no longer passes empty arguments to
Popen when %action substitutions produce empty strings. Popen when %action substitutions produce empty strings.
......
...@@ -121,7 +121,7 @@ resize_buffer(bytesio *self, size_t size) ...@@ -121,7 +121,7 @@ resize_buffer(bytesio *self, size_t size)
} }
/* Internal routine for writing a string of bytes to the buffer of a BytesIO /* Internal routine for writing a string of bytes to the buffer of a BytesIO
object. Returns the number of bytes wrote, or -1 on error. */ object. Returns the number of bytes written, or -1 on error. */
static Py_ssize_t static Py_ssize_t
write_bytes(bytesio *self, const char *bytes, Py_ssize_t len) write_bytes(bytesio *self, const char *bytes, Py_ssize_t len)
{ {
...@@ -171,10 +171,20 @@ bytesio_get_closed(bytesio *self) ...@@ -171,10 +171,20 @@ bytesio_get_closed(bytesio *self)
} }
} }
PyDoc_STRVAR(readable_doc,
"readable() -> bool. Returns True if the IO object can be read.");
PyDoc_STRVAR(writable_doc,
"writable() -> bool. Returns True if the IO object can be written.");
PyDoc_STRVAR(seekable_doc,
"seekable() -> bool. Returns True if the IO object can be seeked.");
/* Generic getter for the writable, readable and seekable properties */ /* Generic getter for the writable, readable and seekable properties */
static PyObject * static PyObject *
return_true(bytesio *self) return_not_closed(bytesio *self)
{ {
CHECK_CLOSED(self);
Py_RETURN_TRUE; Py_RETURN_TRUE;
} }
...@@ -867,9 +877,9 @@ static PyGetSetDef bytesio_getsetlist[] = { ...@@ -867,9 +877,9 @@ static PyGetSetDef bytesio_getsetlist[] = {
}; };
static struct PyMethodDef bytesio_methods[] = { static struct PyMethodDef bytesio_methods[] = {
{"readable", (PyCFunction)return_true, METH_NOARGS, NULL}, {"readable", (PyCFunction)return_not_closed, METH_NOARGS, readable_doc},
{"seekable", (PyCFunction)return_true, METH_NOARGS, NULL}, {"seekable", (PyCFunction)return_not_closed, METH_NOARGS, seekable_doc},
{"writable", (PyCFunction)return_true, METH_NOARGS, NULL}, {"writable", (PyCFunction)return_not_closed, METH_NOARGS, writable_doc},
{"close", (PyCFunction)bytesio_close, METH_NOARGS, close_doc}, {"close", (PyCFunction)bytesio_close, METH_NOARGS, close_doc},
{"flush", (PyCFunction)bytesio_flush, METH_NOARGS, flush_doc}, {"flush", (PyCFunction)bytesio_flush, METH_NOARGS, flush_doc},
{"isatty", (PyCFunction)bytesio_isatty, METH_NOARGS, isatty_doc}, {"isatty", (PyCFunction)bytesio_isatty, METH_NOARGS, isatty_doc},
......
...@@ -650,10 +650,21 @@ stringio_init(stringio *self, PyObject *args, PyObject *kwds) ...@@ -650,10 +650,21 @@ stringio_init(stringio *self, PyObject *args, PyObject *kwds)
} }
/* Properties and pseudo-properties */ /* Properties and pseudo-properties */
PyDoc_STRVAR(stringio_readable_doc,
"readable() -> bool. Returns True if the IO object can be read.");
PyDoc_STRVAR(stringio_writable_doc,
"writable() -> bool. Returns True if the IO object can be written.");
PyDoc_STRVAR(stringio_seekable_doc,
"seekable() -> bool. Returns True if the IO object can be seeked.");
static PyObject * static PyObject *
stringio_seekable(stringio *self, PyObject *args) stringio_seekable(stringio *self, PyObject *args)
{ {
CHECK_INITIALIZED(self); CHECK_INITIALIZED(self);
CHECK_CLOSED(self);
Py_RETURN_TRUE; Py_RETURN_TRUE;
} }
...@@ -661,6 +672,7 @@ static PyObject * ...@@ -661,6 +672,7 @@ static PyObject *
stringio_readable(stringio *self, PyObject *args) stringio_readable(stringio *self, PyObject *args)
{ {
CHECK_INITIALIZED(self); CHECK_INITIALIZED(self);
CHECK_CLOSED(self);
Py_RETURN_TRUE; Py_RETURN_TRUE;
} }
...@@ -668,6 +680,7 @@ static PyObject * ...@@ -668,6 +680,7 @@ static PyObject *
stringio_writable(stringio *self, PyObject *args) stringio_writable(stringio *self, PyObject *args)
{ {
CHECK_INITIALIZED(self); CHECK_INITIALIZED(self);
CHECK_CLOSED(self);
Py_RETURN_TRUE; Py_RETURN_TRUE;
} }
...@@ -835,9 +848,9 @@ static struct PyMethodDef stringio_methods[] = { ...@@ -835,9 +848,9 @@ static struct PyMethodDef stringio_methods[] = {
{"seek", (PyCFunction)stringio_seek, METH_VARARGS, stringio_seek_doc}, {"seek", (PyCFunction)stringio_seek, METH_VARARGS, stringio_seek_doc},
{"write", (PyCFunction)stringio_write, METH_O, stringio_write_doc}, {"write", (PyCFunction)stringio_write, METH_O, stringio_write_doc},
{"seekable", (PyCFunction)stringio_seekable, METH_NOARGS}, {"seekable", (PyCFunction)stringio_seekable, METH_NOARGS, stringio_seekable_doc},
{"readable", (PyCFunction)stringio_readable, METH_NOARGS}, {"readable", (PyCFunction)stringio_readable, METH_NOARGS, stringio_readable_doc},
{"writable", (PyCFunction)stringio_writable, METH_NOARGS}, {"writable", (PyCFunction)stringio_writable, METH_NOARGS, stringio_writable_doc},
{"__getstate__", (PyCFunction)stringio_getstate, METH_NOARGS}, {"__getstate__", (PyCFunction)stringio_getstate, METH_NOARGS},
{"__setstate__", (PyCFunction)stringio_setstate, METH_O}, {"__setstate__", (PyCFunction)stringio_setstate, METH_O},
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment