diff -r 815b88454e3e Lib/test/test_memoryio.py --- a/Lib/test/test_memoryio.py Fri Aug 31 17:14:31 2012 -0400 +++ b/Lib/test/test_memoryio.py Sun Sep 02 14:56:47 2012 +0100 @@ -347,6 +347,17 @@ memio = self.ioclass() memio.foo = 1 + def test_unusable_after_close(self): + # Test case for issue #15841 + memio = self.ioclass() + self.assertTrue(memio.readable()) + self.assertTrue(memio.writable()) + self.assertTrue(memio.seekable()) + memio.close() + self.assertFalse(memio.readable()) + self.assertFalse(memio.writable()) + self.assertFalse(memio.seekable()) + def test_pickling(self): buf = self.buftype("1234567890") memio = self.ioclass(buf) diff -r 815b88454e3e Modules/_io/bytesio.c --- a/Modules/_io/bytesio.c Fri Aug 31 17:14:31 2012 -0400 +++ b/Modules/_io/bytesio.c Sun Sep 02 14:56:47 2012 +0100 @@ -121,7 +121,7 @@ } /* 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,11 +171,22 @@ } } +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 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) { - Py_RETURN_TRUE; + if (self->buf) + Py_RETURN_TRUE; + Py_RETURN_FALSE; } PyDoc_STRVAR(flush_doc, @@ -867,9 +878,9 @@ }; 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 -r 815b88454e3e Modules/_io/stringio.c --- a/Modules/_io/stringio.c Fri Aug 31 17:14:31 2012 -0400 +++ b/Modules/_io/stringio.c Sun Sep 02 14:56:47 2012 +0100 @@ -760,10 +760,22 @@ } /* Properties and pseudo-properties */ + +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 IO object can be seeked."); + static PyObject * stringio_seekable(stringio *self, PyObject *args) { CHECK_INITIALIZED(self); + if (self->closed) + Py_RETURN_FALSE; Py_RETURN_TRUE; } @@ -771,6 +783,8 @@ stringio_readable(stringio *self, PyObject *args) { CHECK_INITIALIZED(self); + if (self->closed) + Py_RETURN_FALSE; Py_RETURN_TRUE; } @@ -778,6 +792,8 @@ stringio_writable(stringio *self, PyObject *args) { CHECK_INITIALIZED(self); + if (self->closed) + Py_RETURN_FALSE; Py_RETURN_TRUE; } @@ -956,9 +972,9 @@ {"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, seekable_doc}, + {"readable", (PyCFunction)stringio_readable, METH_NOARGS, readable_doc}, + {"writable", (PyCFunction)stringio_writable, METH_NOARGS, writable_doc}, {"__getstate__", (PyCFunction)stringio_getstate, METH_NOARGS}, {"__setstate__", (PyCFunction)stringio_setstate, METH_O},