Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit ecc42a2

Browse files
committed
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
1 parent b37509b commit ecc42a2

4 files changed

Lines changed: 41 additions & 15 deletions

File tree

Doc/library/io.rst

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -213,8 +213,10 @@ I/O Base Classes
213213

214214
.. method:: close()
215215

216-
Flush and close this stream. This method has no effect if the file is
217-
already closed.
216+
Flush and close this stream. This method has no effect if the file is
217+
already closed. Once the file is closed, any operation on the file
218+
(e.g. reading or writing) will raise an :exc:`IOError`. The internal
219+
file descriptor isn't closed if *closefd* was False.
218220

219221
.. attribute:: closed
220222

Lib/test/test_io.py

Lines changed: 23 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -272,6 +272,29 @@ def test_closefd(self):
272272
self.assertRaises(ValueError, io.open, support.TESTFN, 'w',
273273
closefd=False)
274274

275+
def testReadClosed(self):
276+
with io.open(support.TESTFN, "w") as f:
277+
f.write("egg\n")
278+
with io.open(support.TESTFN, "r") as f:
279+
file = io.open(f.fileno(), "r", closefd=False)
280+
self.assertEqual(file.read(), "egg\n")
281+
file.seek(0)
282+
file.close()
283+
self.assertRaises(ValueError, file.read)
284+
285+
def test_no_closefd_with_filename(self):
286+
# can't use closefd in combination with a file name
287+
self.assertRaises(ValueError, io.open, support.TESTFN, "r", closefd=False)
288+
289+
def test_closefd_attr(self):
290+
with io.open(support.TESTFN, "wb") as f:
291+
f.write(b"egg\n")
292+
with io.open(support.TESTFN, "r") as f:
293+
self.assertEqual(f.buffer.raw.closefd, True)
294+
file = io.open(f.fileno(), "r", closefd=False)
295+
self.assertEqual(file.buffer.raw.closefd, False)
296+
297+
275298
class MemorySeekTestMixin:
276299

277300
def testInit(self):
@@ -1237,15 +1260,6 @@ def testImport__all__(self):
12371260
else:
12381261
self.assert_(issubclass(obj, io.IOBase))
12391262

1240-
def test_fileio_warnings(self):
1241-
with support.check_warnings() as w:
1242-
self.assertEqual(w.warnings, [])
1243-
self.assertRaises(TypeError, io.FileIO, [])
1244-
self.assertEqual(w.warnings, [])
1245-
self.assertRaises(ValueError, io.FileIO, "/some/invalid/name", "rt")
1246-
self.assertEqual(w.warnings, [])
1247-
1248-
12491263
def test_main():
12501264
support.run_unittest(IOTest, BytesIOTest, StringIOTest,
12511265
BufferedReaderTest, BufferedWriterTest,

Misc/NEWS

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,11 @@ What's New in Python 3.0 beta 5
1515
Core and Builtins
1616
-----------------
1717

18+
- Issue #4233: Changed semantic of ``_fileio.FileIO``'s ``close()``
19+
method on file objects with closefd=False. The file descriptor is still
20+
kept open but the file object behaves like a closed file. The ``FileIO``
21+
object also got a new readonly attribute ``closefd``.
22+
1823
- Issue #3626: On cygwin, starting python with a non-existent script name
1924
would not display anything if the file name is only 1 character long.
2025

Modules/_fileio.c

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -61,10 +61,7 @@ static PyObject *
6161
fileio_close(PyFileIOObject *self)
6262
{
6363
if (!self->closefd) {
64-
if (PyErr_WarnEx(PyExc_RuntimeWarning,
65-
"Trying to close unclosable fd!", 3) < 0) {
66-
return NULL;
67-
}
64+
self->fd = -1;
6865
Py_RETURN_NONE;
6966
}
7067
errno = internal_close(self);
@@ -820,6 +817,12 @@ get_closed(PyFileIOObject *self, void *closure)
820817
return PyBool_FromLong((long)(self->fd < 0));
821818
}
822819

820+
static PyObject *
821+
get_closefd(PyFileIOObject *self, void *closure)
822+
{
823+
return PyBool_FromLong((long)(self->closefd));
824+
}
825+
823826
static PyObject *
824827
get_mode(PyFileIOObject *self, void *closure)
825828
{
@@ -828,6 +831,8 @@ get_mode(PyFileIOObject *self, void *closure)
828831

829832
static PyGetSetDef fileio_getsetlist[] = {
830833
{"closed", (getter)get_closed, NULL, "True if the file is closed"},
834+
{"closefd", (getter)get_closefd, NULL,
835+
"True if the file descriptor will be closed"},
831836
{"mode", (getter)get_mode, NULL, "String giving the file mode"},
832837
{0},
833838
};

0 commit comments

Comments
 (0)