[pypy-svn] r49755 - in pypy/branch/interplevel-oldstyle-classes/pypy/module/__builtin__: . test
cfbolz at codespeak.net
cfbolz at codespeak.net
Fri Dec 14 01:06:58 CET 2007
Author: cfbolz
Date: Fri Dec 14 01:06:57 2007
New Revision: 49755
Modified:
pypy/branch/interplevel-oldstyle-classes/pypy/module/__builtin__/interp_classobj.py
pypy/branch/interplevel-oldstyle-classes/pypy/module/__builtin__/test/test_classobj.py
Log:
support for __del__. not quite elegant, but works.
Modified: pypy/branch/interplevel-oldstyle-classes/pypy/module/__builtin__/interp_classobj.py
==============================================================================
--- pypy/branch/interplevel-oldstyle-classes/pypy/module/__builtin__/interp_classobj.py (original)
+++ pypy/branch/interplevel-oldstyle-classes/pypy/module/__builtin__/interp_classobj.py Fri Dec 14 01:06:57 2007
@@ -44,7 +44,7 @@
self.name = space.str_w(w_name)
self.bases_w = bases
self.w_dict = w_dict
-
+
def getdict(self):
return self.w_dict
@@ -144,7 +144,10 @@
return space.call_function(w_descr_get, w_value, space.w_None, self)
def descr_call(self, space, __args__):
- w_inst = W_InstanceObject(space, self)
+ if self.lookup(space, space.wrap('__del__')) is not None:
+ w_inst = W_InstanceObjectWithDel(space, self)
+ else:
+ w_inst = W_InstanceObject(space, self)
w_init = w_inst.getattr(space, space.wrap('__init__'), False)
if w_init is not None:
w_result = space.call_args(w_init, __args__)
@@ -274,6 +277,7 @@
assert isinstance(w_class, W_ClassObject)
self.w_class = w_class
self.w_dict = w_dict
+ self.space = space
def getdict(self):
return self.w_dict
@@ -669,3 +673,28 @@
**rawdict
)
+class W_InstanceObjectWithDel(W_InstanceObject):
+ # XXX this is code duplication from pypy.interpreter.typedef
+ # find a way to prevent this.
+ def __del__(self):
+
+ lifeline = self.getweakref()
+ if lifeline is not None:
+ # Clear all weakrefs to this object before we call
+ # the app-level __del__. We detach the lifeline
+ # first: if the app-level __del__ tries to use
+ # weakrefs again, they won't reuse the broken
+ # (already-cleared) ones from this lifeline.
+ self.setweakref(self.space, None)
+ lifeline.clear_all_weakrefs()
+ try:
+ self.descr_del()
+ except OperationError, e:
+ e.write_unraisable(self.space, 'method __del__ of ', self)
+ e.clear(self.space) # break up reference cycles
+
+ def descr_del(self):
+ space = self.space
+ w_func = self.getattr(space, space.wrap('__del__'), False)
+ if w_func is not None:
+ space.call_function(w_func)
Modified: pypy/branch/interplevel-oldstyle-classes/pypy/module/__builtin__/test/test_classobj.py
==============================================================================
--- pypy/branch/interplevel-oldstyle-classes/pypy/module/__builtin__/test/test_classobj.py (original)
+++ pypy/branch/interplevel-oldstyle-classes/pypy/module/__builtin__/test/test_classobj.py Fri Dec 14 01:06:57 2007
@@ -577,3 +577,24 @@
a = type(a).__new__(type(a), A, {'c': 2})
assert a.b == 1
assert a.c == 2
+
+ def test_del(self):
+ import gc
+ l = []
+ class A:
+ def __del__(self):
+ l.append(1)
+ a = A()
+ a = None
+ gc.collect()
+ gc.collect()
+ gc.collect()
+ assert l == [1]
+ class B(A):
+ pass
+ b = B()
+ b = None
+ gc.collect()
+ gc.collect()
+ gc.collect()
+ assert l == [1, 1]
More information about the Pypy-commit
mailing list