[pypy-svn] r78145 - in pypy/branch/fast-forward/pypy/module/_io: . test
afa at codespeak.net
afa at codespeak.net
Wed Oct 20 18:24:24 CEST 2010
Author: afa
Date: Wed Oct 20 18:24:22 2010
New Revision: 78145
Modified:
pypy/branch/fast-forward/pypy/module/_io/interp_iobase.py
pypy/branch/fast-forward/pypy/module/_io/test/test_io.py
Log:
Add finalizer for IOBase (and all subclasses)
Modified: pypy/branch/fast-forward/pypy/module/_io/interp_iobase.py
==============================================================================
--- pypy/branch/fast-forward/pypy/module/_io/interp_iobase.py (original)
+++ pypy/branch/fast-forward/pypy/module/_io/interp_iobase.py Wed Oct 20 18:24:22 2010
@@ -16,6 +16,7 @@
# XXX: IOBase thinks it has to maintain its own internal state in
# `__IOBase_closed` and call flush() by itself, but it is redundant
# with whatever behaviour a non-trivial derived class will implement.
+ self.space = space
self.__IOBase_closed = False
def _closed(self, space):
@@ -26,6 +27,20 @@
return True
return False
+ def __del__(self):
+ space = self.space
+ w_closed = space.findattr(self, space.wrap('closed'))
+ try:
+ # If `closed` doesn't exist or can't be evaluated as bool, then
+ # the object is probably in an unusable state, so ignore.
+ if w_closed is not None and not space.is_true(w_closed):
+ space.call_method(self, "close")
+ except OperationError:
+ # Silencing I/O errors is bad, but printing spurious tracebacks is
+ # equally as bad, and potentially more frequent (because of
+ # shutdown issues).
+ pass
+
def _CLOSED(self):
# Use this macro whenever you want to check the internal `closed`
# status of the IOBase object rather than the virtual `closed`
Modified: pypy/branch/fast-forward/pypy/module/_io/test/test_io.py
==============================================================================
--- pypy/branch/fast-forward/pypy/module/_io/test/test_io.py (original)
+++ pypy/branch/fast-forward/pypy/module/_io/test/test_io.py Wed Oct 20 18:24:22 2010
@@ -42,6 +42,25 @@
import _io
e = _io.UnsupportedOperation("seek")
+ def test_destructor(self):
+ import io
+ io.IOBase()
+
+ record = []
+ class MyIO(io.IOBase):
+ def __del__(self):
+ record.append(1)
+ super(MyIO, self).__del__()
+ def close(self):
+ record.append(2)
+ super(MyIO, self).close()
+ def flush(self):
+ record.append(3)
+ super(MyIO, self).flush()
+ MyIO()
+ import gc; gc.collect()
+ assert record == [1, 2, 3]
+
class AppTestOpen:
def setup_class(cls):
tmpfile = udir.join('tmpfile').ensure()
More information about the Pypy-commit
mailing list