From 322656596abfd772b0573731a78676f4a16f2d34 Mon Sep 17 00:00:00 2001 From: Amaury Forgeot d'Arc Date: Thu, 20 Nov 2008 23:34:31 +0000 Subject: 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 Backport of r67106 from the py3k branch --- Doc/library/io.rst | 6 ++++-- Lib/test/test_io.py | 24 ++++++++++++++++++++++++ Misc/NEWS | 5 +++++ Modules/_fileio.c | 13 +++++++++---- 4 files changed, 42 insertions(+), 6 deletions(-) diff --git a/Doc/library/io.rst b/Doc/library/io.rst index 18df0e0..25d5f16 100644 --- a/Doc/library/io.rst +++ b/Doc/library/io.rst @@ -214,8 +214,10 @@ I/O Base Classes .. method:: close() - Flush and close this stream. This method has no effect if the file is - already closed. + Flush and close this stream. This method has no effect if the file is + 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 diff --git a/Lib/test/test_io.py b/Lib/test/test_io.py index 378d994..c9bd38d 100644 --- a/Lib/test/test_io.py +++ b/Lib/test/test_io.py @@ -272,6 +272,30 @@ class IOTest(unittest.TestCase): self.assertRaises(ValueError, io.open, test_support.TESTFN, 'w', closefd=False) + def testReadClosed(self): + with io.open(test_support.TESTFN, "w") as f: + f.write("egg\n") + with io.open(test_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, test_support.TESTFN, "r", closefd=False) + + def test_closefd_attr(self): + with io.open(test_support.TESTFN, "wb") as f: + f.write(b"egg\n") + with io.open(test_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: def testInit(self): diff --git a/Misc/NEWS b/Misc/NEWS index c97f6b3..7e6787a 100644 --- a/Misc/NEWS +++ b/Misc/NEWS @@ -12,6 +12,11 @@ What's New in Python 2.7 alpha 1 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 #4348: Some bytearray methods returned that didn't cause any change to the bytearray, returned the same bytearray instead of a copy. diff --git a/Modules/_fileio.c b/Modules/_fileio.c index 49bc29c..b9310f3 100644 --- a/Modules/_fileio.c +++ b/Modules/_fileio.c @@ -61,10 +61,7 @@ static PyObject * fileio_close(PyFileIOObject *self) { if (!self->closefd) { - if (PyErr_WarnEx(PyExc_RuntimeWarning, - "Trying to close unclosable fd!", 3) < 0) { - return NULL; - } + self->fd = -1; Py_RETURN_NONE; } errno = internal_close(self); @@ -821,6 +818,12 @@ get_closed(PyFileIOObject *self, void *closure) } static PyObject * +get_closefd(PyFileIOObject *self, void *closure) +{ + return PyBool_FromLong((long)(self->closefd)); +} + +static PyObject * get_mode(PyFileIOObject *self, void *closure) { return PyString_FromString(mode_string(self)); @@ -828,6 +831,8 @@ get_mode(PyFileIOObject *self, void *closure) static PyGetSetDef fileio_getsetlist[] = { {"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"}, {0}, }; -- cgit v0.12