Commit c5eec0e3 authored by Antoine Pitrou's avatar Antoine Pitrou

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

and io.StringIO objects now raise ValueError when the object has been closed.
Patch by Alessandro Moura.
parent 80f4553d
...@@ -883,12 +883,18 @@ class BytesIO(BufferedIOBase): ...@@ -883,12 +883,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
...@@ -1546,6 +1552,8 @@ class TextIOWrapper(TextIOBase): ...@@ -1546,6 +1552,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):
......
...@@ -328,9 +328,9 @@ class MemoryTestMixin: ...@@ -328,9 +328,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)
...@@ -649,7 +649,6 @@ class CBytesIOTest(PyBytesIOTest): ...@@ -649,7 +649,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
......
...@@ -602,6 +602,7 @@ Skip Montanaro ...@@ -602,6 +602,7 @@ Skip Montanaro
Paul Moore Paul Moore
Derek Morr Derek Morr
James A Morrison James A Morrison
Alessandro Moura
Pablo Mouzo Pablo Mouzo
Ruslan Mstoi Ruslan Mstoi
Sjoerd Mullender Sjoerd Mullender
......
...@@ -98,6 +98,10 @@ Core and Builtins ...@@ -98,6 +98,10 @@ Core and Builtins
Library Library
------- -------
- Issue #15841: The readable(), writable() and seekable() methods of
io.BytesIO and io.StringIO objects now raise ValueError when the object has
been closed. Patch by Alessandro Moura.
- Issue #12776,#11839: call argparse type function (specified by add_argument) - Issue #12776,#11839: call argparse type function (specified by add_argument)
only once. Before, the type function was called twice in the case where the only once. Before, the type function was called twice in the case where the
default was specified and the argument was given as well. This was default was specified and the argument was given as well. This was
......
...@@ -106,7 +106,7 @@ resize_buffer(bytesio *self, size_t size) ...@@ -106,7 +106,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)
{ {
...@@ -156,10 +156,20 @@ bytesio_get_closed(bytesio *self) ...@@ -156,10 +156,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;
} }
...@@ -827,9 +837,9 @@ static PyGetSetDef bytesio_getsetlist[] = { ...@@ -827,9 +837,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},
......
...@@ -632,10 +632,21 @@ stringio_init(stringio *self, PyObject *args, PyObject *kwds) ...@@ -632,10 +632,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;
} }
...@@ -643,6 +654,7 @@ static PyObject * ...@@ -643,6 +654,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;
} }
...@@ -650,6 +662,7 @@ static PyObject * ...@@ -650,6 +662,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;
} }
...@@ -817,9 +830,9 @@ static struct PyMethodDef stringio_methods[] = { ...@@ -817,9 +830,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