summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAntoine Pitrou <solipsis@pitrou.net>2012-09-05 18:13:48 (GMT)
committerAntoine Pitrou <solipsis@pitrou.net>2012-09-05 18:13:48 (GMT)
commit11946fbe804d99d26724e65dcb061cda6666c4e9 (patch)
tree33d3fac84bc13fdc95c9de2943d10641fe097a21
parente8677c038f94795f54de324e5d9235636c92afa0 (diff)
parent1d857453b7065dafdc34a72c1bbb2a993782b383 (diff)
downloadcpython-11946fbe804d99d26724e65dcb061cda6666c4e9.zip
cpython-11946fbe804d99d26724e65dcb061cda6666c4e9.tar.gz
cpython-11946fbe804d99d26724e65dcb061cda6666c4e9.tar.bz2
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.
-rw-r--r--Lib/_pyio.py8
-rw-r--r--Lib/test/test_memoryio.py7
-rw-r--r--Misc/ACKS1
-rw-r--r--Misc/NEWS4
-rw-r--r--Modules/_io/bytesio.c20
-rw-r--r--Modules/_io/stringio.c19
6 files changed, 47 insertions, 12 deletions
diff --git a/Lib/_pyio.py b/Lib/_pyio.py
index 387c585..fa77ec1 100644
--- a/Lib/_pyio.py
+++ b/Lib/_pyio.py
@@ -895,12 +895,18 @@ class BytesIO(BufferedIOBase):
return pos
def readable(self):
+ if self.closed:
+ raise ValueError("I/O operation on closed file.")
return True
def writable(self):
+ if self.closed:
+ raise ValueError("I/O operation on closed file.")
return True
def seekable(self):
+ if self.closed:
+ raise ValueError("I/O operation on closed file.")
return True
@@ -1562,6 +1568,8 @@ class TextIOWrapper(TextIOBase):
return self._buffer
def seekable(self):
+ if self.closed:
+ raise ValueError("I/O operation on closed file.")
return self._seekable
def readable(self):
diff --git a/Lib/test/test_memoryio.py b/Lib/test/test_memoryio.py
index 04ec8e7..e5db945 100644
--- a/Lib/test/test_memoryio.py
+++ b/Lib/test/test_memoryio.py
@@ -318,9 +318,9 @@ class MemoryTestMixin:
self.assertEqual(memio.isatty(), False)
self.assertEqual(memio.closed, False)
memio.close()
- self.assertEqual(memio.writable(), True)
- self.assertEqual(memio.readable(), True)
- self.assertEqual(memio.seekable(), True)
+ self.assertRaises(ValueError, memio.writable)
+ self.assertRaises(ValueError, memio.readable)
+ self.assertRaises(ValueError, memio.seekable)
self.assertRaises(ValueError, memio.isatty)
self.assertEqual(memio.closed, True)
@@ -665,7 +665,6 @@ class CBytesIOTest(PyBytesIOTest):
check(io.BytesIO(b'a'), basesize + 1 + 1 )
check(io.BytesIO(b'a' * 1000), basesize + 1000 + 1 )
-
class CStringIOTest(PyStringIOTest):
ioclass = io.StringIO
UnsupportedOperation = io.UnsupportedOperation
diff --git a/Misc/ACKS b/Misc/ACKS
index c6762c2..8af9f73 100644
--- a/Misc/ACKS
+++ b/Misc/ACKS
@@ -731,6 +731,7 @@ Paul Moore
Derek Morr
James A Morrison
Derek McTavish Mounce
+Alessandro Moura
Pablo Mouzo
Mher Movsisyan
Ruslan Mstoi
diff --git a/Misc/NEWS b/Misc/NEWS
index bc85305..aaf3aef 100644
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -21,6 +21,10 @@ Core and Builtins
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 #15447: Use subprocess.DEVNULL in webbrowser, instead of opening
os.devnull explicitly and leaving it open.
diff --git a/Modules/_io/bytesio.c b/Modules/_io/bytesio.c
index 3d027e2..20863af 100644
--- a/Modules/_io/bytesio.c
+++ b/Modules/_io/bytesio.c
@@ -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
- 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
write_bytes(bytesio *self, const char *bytes, Py_ssize_t len)
{
@@ -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 */
static PyObject *
-return_true(bytesio *self)
+return_not_closed(bytesio *self)
{
+ CHECK_CLOSED(self);
Py_RETURN_TRUE;
}
@@ -867,9 +877,9 @@ static PyGetSetDef bytesio_getsetlist[] = {
};
static struct PyMethodDef bytesio_methods[] = {
- {"readable", (PyCFunction)return_true, METH_NOARGS, NULL},
- {"seekable", (PyCFunction)return_true, METH_NOARGS, NULL},
- {"writable", (PyCFunction)return_true, METH_NOARGS, NULL},
+ {"readable", (PyCFunction)return_not_closed, METH_NOARGS, readable_doc},
+ {"seekable", (PyCFunction)return_not_closed, METH_NOARGS, seekable_doc},
+ {"writable", (PyCFunction)return_not_closed, METH_NOARGS, writable_doc},
{"close", (PyCFunction)bytesio_close, METH_NOARGS, close_doc},
{"flush", (PyCFunction)bytesio_flush, METH_NOARGS, flush_doc},
{"isatty", (PyCFunction)bytesio_isatty, METH_NOARGS, isatty_doc},
diff --git a/Modules/_io/stringio.c b/Modules/_io/stringio.c
index a1c31c0..9d73884 100644
--- a/Modules/_io/stringio.c
+++ b/Modules/_io/stringio.c
@@ -760,10 +760,21 @@ stringio_init(stringio *self, PyObject *args, PyObject *kwds)
}
/* 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 *
stringio_seekable(stringio *self, PyObject *args)
{
CHECK_INITIALIZED(self);
+ CHECK_CLOSED(self);
Py_RETURN_TRUE;
}
@@ -771,6 +782,7 @@ static PyObject *
stringio_readable(stringio *self, PyObject *args)
{
CHECK_INITIALIZED(self);
+ CHECK_CLOSED(self);
Py_RETURN_TRUE;
}
@@ -778,6 +790,7 @@ static PyObject *
stringio_writable(stringio *self, PyObject *args)
{
CHECK_INITIALIZED(self);
+ CHECK_CLOSED(self);
Py_RETURN_TRUE;
}
@@ -956,9 +969,9 @@ static struct PyMethodDef stringio_methods[] = {
{"seek", (PyCFunction)stringio_seek, METH_VARARGS, stringio_seek_doc},
{"write", (PyCFunction)stringio_write, METH_O, stringio_write_doc},
- {"seekable", (PyCFunction)stringio_seekable, METH_NOARGS},
- {"readable", (PyCFunction)stringio_readable, METH_NOARGS},
- {"writable", (PyCFunction)stringio_writable, METH_NOARGS},
+ {"seekable", (PyCFunction)stringio_seekable, METH_NOARGS, stringio_seekable_doc},
+ {"readable", (PyCFunction)stringio_readable, METH_NOARGS, stringio_readable_doc},
+ {"writable", (PyCFunction)stringio_writable, METH_NOARGS, stringio_writable_doc},
{"__getstate__", (PyCFunction)stringio_getstate, METH_NOARGS},
{"__setstate__", (PyCFunction)stringio_setstate, METH_O},