Fixed issue #4233.

Changed semantic of _fileio.FileIO's close()  method on file objects with closefd=False. The file descriptor is still kept open but the file object behaves like a closed file. The FileIO  object also got a new readonly attribute closefd.
Approved by Barry
This commit is contained in:
Christian Heimes 2008-11-05 19:30:32 +00:00
parent b37509b11b
commit ecc42a2b82
4 changed files with 41 additions and 15 deletions

View File

@ -213,8 +213,10 @@ I/O Base Classes
.. method:: close() .. method:: close()
Flush and close this stream. This method has no effect if the file is Flush and close this stream. This method has no effect if the file is
already closed. already closed. Once the file is closed, any operation on the file
(e.g. reading or writing) will raise an :exc:`IOError`. The internal
file descriptor isn't closed if *closefd* was False.
.. attribute:: closed .. attribute:: closed

View File

@ -272,6 +272,29 @@ class IOTest(unittest.TestCase):
self.assertRaises(ValueError, io.open, support.TESTFN, 'w', self.assertRaises(ValueError, io.open, support.TESTFN, 'w',
closefd=False) closefd=False)
def testReadClosed(self):
with io.open(support.TESTFN, "w") as f:
f.write("egg\n")
with io.open(support.TESTFN, "r") as f:
file = io.open(f.fileno(), "r", closefd=False)
self.assertEqual(file.read(), "egg\n")
file.seek(0)
file.close()
self.assertRaises(ValueError, file.read)
def test_no_closefd_with_filename(self):
# can't use closefd in combination with a file name
self.assertRaises(ValueError, io.open, support.TESTFN, "r", closefd=False)
def test_closefd_attr(self):
with io.open(support.TESTFN, "wb") as f:
f.write(b"egg\n")
with io.open(support.TESTFN, "r") as f:
self.assertEqual(f.buffer.raw.closefd, True)
file = io.open(f.fileno(), "r", closefd=False)
self.assertEqual(file.buffer.raw.closefd, False)
class MemorySeekTestMixin: class MemorySeekTestMixin:
def testInit(self): def testInit(self):
@ -1237,15 +1260,6 @@ class MiscIOTest(unittest.TestCase):
else: else:
self.assert_(issubclass(obj, io.IOBase)) self.assert_(issubclass(obj, io.IOBase))
def test_fileio_warnings(self):
with support.check_warnings() as w:
self.assertEqual(w.warnings, [])
self.assertRaises(TypeError, io.FileIO, [])
self.assertEqual(w.warnings, [])
self.assertRaises(ValueError, io.FileIO, "/some/invalid/name", "rt")
self.assertEqual(w.warnings, [])
def test_main(): def test_main():
support.run_unittest(IOTest, BytesIOTest, StringIOTest, support.run_unittest(IOTest, BytesIOTest, StringIOTest,
BufferedReaderTest, BufferedWriterTest, BufferedReaderTest, BufferedWriterTest,

View File

@ -15,6 +15,11 @@ What's New in Python 3.0 beta 5
Core and Builtins Core and Builtins
----------------- -----------------
- Issue #4233: Changed semantic of ``_fileio.FileIO``'s ``close()``
method on file objects with closefd=False. The file descriptor is still
kept open but the file object behaves like a closed file. The ``FileIO``
object also got a new readonly attribute ``closefd``.
- Issue #3626: On cygwin, starting python with a non-existent script name - Issue #3626: On cygwin, starting python with a non-existent script name
would not display anything if the file name is only 1 character long. would not display anything if the file name is only 1 character long.

View File

@ -61,10 +61,7 @@ static PyObject *
fileio_close(PyFileIOObject *self) fileio_close(PyFileIOObject *self)
{ {
if (!self->closefd) { if (!self->closefd) {
if (PyErr_WarnEx(PyExc_RuntimeWarning, self->fd = -1;
"Trying to close unclosable fd!", 3) < 0) {
return NULL;
}
Py_RETURN_NONE; Py_RETURN_NONE;
} }
errno = internal_close(self); errno = internal_close(self);
@ -820,6 +817,12 @@ get_closed(PyFileIOObject *self, void *closure)
return PyBool_FromLong((long)(self->fd < 0)); return PyBool_FromLong((long)(self->fd < 0));
} }
static PyObject *
get_closefd(PyFileIOObject *self, void *closure)
{
return PyBool_FromLong((long)(self->closefd));
}
static PyObject * static PyObject *
get_mode(PyFileIOObject *self, void *closure) get_mode(PyFileIOObject *self, void *closure)
{ {
@ -828,6 +831,8 @@ get_mode(PyFileIOObject *self, void *closure)
static PyGetSetDef fileio_getsetlist[] = { static PyGetSetDef fileio_getsetlist[] = {
{"closed", (getter)get_closed, NULL, "True if the file is closed"}, {"closed", (getter)get_closed, NULL, "True if the file is closed"},
{"closefd", (getter)get_closefd, NULL,
"True if the file descriptor will be closed"},
{"mode", (getter)get_mode, NULL, "String giving the file mode"}, {"mode", (getter)get_mode, NULL, "String giving the file mode"},
{0}, {0},
}; };