[Python-checkins] r68754 - in python/branches/io-c: Lib/test/test_io.py Modules/_bufferedio.c Modules/_fileio.c Modules/_iobase.c Modules/_iomodule.h Modules/_textio.c
antoine.pitrou
python-checkins at python.org
Mon Jan 19 00:51:08 CET 2009
Author: antoine.pitrou
Date: Mon Jan 19 00:51:08 2009
New Revision: 68754
Log:
Remove IOBase.__del__ and replace it with custom code with tp_dealloc
Modified:
python/branches/io-c/Lib/test/test_io.py
python/branches/io-c/Modules/_bufferedio.c
python/branches/io-c/Modules/_fileio.c
python/branches/io-c/Modules/_iobase.c
python/branches/io-c/Modules/_iomodule.h
python/branches/io-c/Modules/_textio.c
Modified: python/branches/io-c/Lib/test/test_io.py
==============================================================================
--- python/branches/io-c/Lib/test/test_io.py (original)
+++ python/branches/io-c/Lib/test/test_io.py Mon Jan 19 00:51:08 2009
@@ -338,6 +338,29 @@
del f
self.assertEqual(record, [1, 2, 3])
+ def test_IOBase_destructor(self):
+ record = []
+ class MyIO(io.IOBase):
+ def __init__(self):
+ pass
+ def __del__(self):
+ record.append(1)
+ try:
+ f = io.IOBase.__del__
+ except AttributeError:
+ pass
+ else:
+ f(self)
+ def close(self):
+ record.append(2)
+ io.IOBase.close(self)
+ def flush(self):
+ record.append(3)
+ io.IOBase.flush(self)
+ f = MyIO()
+ del f
+ self.assertEqual(record, [1, 2, 3])
+
def test_close_flushes(self):
f = io.open(support.TESTFN, "wb")
f.write(b"xxx")
Modified: python/branches/io-c/Modules/_bufferedio.c
==============================================================================
--- python/branches/io-c/Modules/_bufferedio.c (original)
+++ python/branches/io-c/Modules/_bufferedio.c Mon Jan 19 00:51:08 2009
@@ -285,26 +285,9 @@
static void
BufferedObject_dealloc(BufferedObject *self)
{
- PyObject *res;
- /* XXX this is inelegant */
- if (Py_TYPE(self)->tp_del == NULL) {
- PyObject *tp, *v, *tb;
- PyErr_Fetch(&tp, &v, &tb);
- /* We need to resurrect the object as calling close() can invoke
- arbitrary code. */
- ((PyObject *) self)->ob_refcnt++;
- res = PyObject_CallMethodObjArgs((PyObject *) self, _PyIO_str_close,
- NULL);
- if (res == NULL) {
- /* XXX dump exception on terminal?
- But IOBase.__del__ prefers to remain silent... */
- PyErr_Clear();
- }
- Py_XDECREF(res);
- PyErr_Restore(tp, v, tb);
- if (--((PyObject *) self)->ob_refcnt != 0)
- return;
- }
+ if (_PyIOBase_finalize((PyObject *) self) < 0)
+ return;
+ self->ok = 0;
if (self->weakreflist != NULL)
PyObject_ClearWeakRefs((PyObject *)self);
Py_CLEAR(self->raw);
@@ -342,15 +325,18 @@
/* Flush the stream. We're mixing buffered I/O with lower-level I/O,
* and a flush may be necessary to synch both views of the current
- * file state.
+ * file state.
*/
res = PyObject_CallMethodObjArgs(self->raw, _PyIO_str_flush, NULL);
if (res == NULL)
return NULL;
Py_DECREF(res);
- if (pos == Py_None)
+ if (pos == Py_None) {
pos = PyObject_CallMethod(self->raw, "tell", NULL);
+ if (pos == NULL)
+ return NULL;
+ }
else
Py_INCREF(pos);
Modified: python/branches/io-c/Modules/_fileio.c
==============================================================================
--- python/branches/io-c/Modules/_fileio.c (original)
+++ python/branches/io-c/Modules/_fileio.c Mon Jan 19 00:51:08 2009
@@ -335,16 +335,11 @@
static void
fileio_dealloc(PyFileIOObject *self)
{
+ if (_PyIOBase_finalize((PyObject *) self) < 0)
+ return;
if (self->weakreflist != NULL)
PyObject_ClearWeakRefs((PyObject *) self);
-
- if (self->fd >= 0 && self->closefd) {
- if(internal_close(self))
- PyErr_WriteUnraisable((PyObject*)self);
- }
-
Py_CLEAR(self->dict);
-
Py_TYPE(self)->tp_free((PyObject *)self);
}
Modified: python/branches/io-c/Modules/_iobase.c
==============================================================================
--- python/branches/io-c/Modules/_iobase.c (original)
+++ python/branches/io-c/Modules/_iobase.c Mon Jan 19 00:51:08 2009
@@ -178,26 +178,48 @@
/* Destructor */
-static PyObject *
-IOBase_del(PyObject *self, PyObject *args)
+int
+_PyIOBase_finalize(PyObject *self)
{
- PyObject *res = NULL;
- if (IOBase_closed(self))
- Py_RETURN_NONE;
- res = PyObject_CallMethodObjArgs(self, _PyIO_str_close, NULL);
- if (res == NULL) {
- /* At program exit time, it's possible that globals have already been
- * deleted, and then the close() call might fail. Since there's
- * nothing we can do about such failures and they annoy the end
- * users, we suppress the traceback.
- *
- * XXX: this function can be called at other times and what if the
- * error is genuine?
- */
+ PyObject *res;
+ PyObject *tp, *v, *tb;
+ int closed = 1;
+ PyErr_Fetch(&tp, &v, &tb);
+ /* We need to resurrect the object as calling close() can invoke
+ arbitrary code. */
+ ((PyObject *) self)->ob_refcnt++;
+ /* The object could already be in an usable state, so we'll take any
+ error as meaning "stop, nothing to see here". */
+ res = PyObject_GetAttr(self, _PyIO_str_closed);
+ if (res == NULL)
PyErr_Clear();
+ else {
+ closed = PyObject_IsTrue(res);
+ Py_DECREF(res);
+ if (closed == -1)
+ PyErr_Clear();
}
- Py_XDECREF(res);
- Py_RETURN_NONE;
+ if (closed == 0) {
+ res = PyObject_CallMethodObjArgs((PyObject *) self, _PyIO_str_close,
+ NULL);
+ if (res == NULL) {
+ /* XXX dump exception on terminal?
+ But IOBase.__del__ prefers to remain silent... */
+ PyErr_Clear();
+ }
+ Py_XDECREF(res);
+ }
+ PyErr_Restore(tp, v, tb);
+ if (--((PyObject *) self)->ob_refcnt != 0)
+ return -1;
+ return 0;
+}
+
+static void
+IOBase_dealloc(PyObject *self)
+{
+ if (_PyIOBase_finalize(self) == 0)
+ Py_TYPE(self)->tp_free(self);
}
/* Inquiry methods */
@@ -588,7 +610,6 @@
{"fileno", IOBase_fileno, METH_NOARGS, IOBase_fileno_doc},
{"isatty", IOBase_isatty, METH_NOARGS, IOBase_isatty_doc},
- {"__del__", IOBase_del, METH_NOARGS},
{"__enter__", IOBase_enter, METH_NOARGS},
{"__exit__", IOBase_exit, METH_VARARGS},
@@ -610,7 +631,7 @@
"IOBase", /*tp_name*/
0, /*tp_basicsize*/
0, /*tp_itemsize*/
- 0, /*tp_dealloc*/
+ IOBase_dealloc, /*tp_dealloc*/
0, /*tp_print*/
0, /*tp_getattr*/
0, /*tp_setattr*/
Modified: python/branches/io-c/Modules/_iomodule.h
==============================================================================
--- python/branches/io-c/Modules/_iomodule.h (original)
+++ python/branches/io-c/Modules/_iomodule.h Mon Jan 19 00:51:08 2009
@@ -25,6 +25,12 @@
extern PyObject* PyIOExc_UnsupportedOperation;
+/* Helper for finalization.
+ This function will revive an object ready to be deallocated and try to
+ close() it. It returns 0 if the object can be destroyed, or -1 if it
+ is alive again. */
+extern int _PyIOBase_finalize(PyObject *self);
+
#define DEFAULT_BUFFER_SIZE (8 * 1024) /* bytes */
typedef struct {
@@ -36,7 +42,6 @@
} PyBlockingIOErrorObject;
PyObject *PyExc_BlockingIOError;
-
/*
* Offset type for positioning.
*/
Modified: python/branches/io-c/Modules/_textio.c
==============================================================================
--- python/branches/io-c/Modules/_textio.c (original)
+++ python/branches/io-c/Modules/_textio.c Mon Jan 19 00:51:08 2009
@@ -782,26 +782,8 @@
static void
TextIOWrapper_dealloc(PyTextIOWrapperObject *self)
{
- PyObject *res;
- /* XXX this is inelegant */
- if (Py_TYPE(self)->tp_del == NULL && self->ok) {
- PyObject *tp, *v, *tb;
- PyErr_Fetch(&tp, &v, &tb);
- /* We need to resurrect the object as calling close() can invoke
- arbitrary code. */
- ((PyObject *) self)->ob_refcnt++;
- res = PyObject_CallMethodObjArgs((PyObject *) self, _PyIO_str_close,
- NULL);
- if (res == NULL) {
- /* XXX dump exception on terminal?
- But IOBase.__del__ prefers to remain silent... */
- PyErr_Clear();
- }
- Py_XDECREF(res);
- PyErr_Restore(tp, v, tb);
- if (--((PyObject *) self)->ob_refcnt != 0)
- return;
- }
+ if (_PyIOBase_finalize((PyObject *) self) < 0)
+ return;
self->ok = 0;
Py_CLEAR(self->buffer);
Py_CLEAR(self->encoding);
More information about the Python-checkins
mailing list