Author: Armin Rigo <[email protected]>
Branch: use-gc-del-3
Changeset: r84218:ea48aefe929c
Date: 2016-05-05 17:26 +0200
http://bitbucket.org/pypy/pypy/changeset/ea48aefe929c/

Log:    progress

diff --git a/pypy/interpreter/typedef.py b/pypy/interpreter/typedef.py
--- a/pypy/interpreter/typedef.py
+++ b/pypy/interpreter/typedef.py
@@ -24,6 +24,8 @@
         self.bases = bases
         self.heaptype = False
         self.hasdict = '__dict__' in rawdict
+        # no __del__: use an RPython _finalize_() method and register_finalizer
+        assert '__del__' not in rawdict
         self.weakrefable = '__weakref__' in rawdict
         self.doc = rawdict.pop('__doc__', None)
         for base in bases:
diff --git a/pypy/module/__builtin__/interp_classobj.py 
b/pypy/module/__builtin__/interp_classobj.py
--- a/pypy/module/__builtin__/interp_classobj.py
+++ b/pypy/module/__builtin__/interp_classobj.py
@@ -44,13 +44,12 @@
         self.bases_w = bases
         self.w_dict = w_dict
 
+    def has_user_del(self, space):
+        return self.lookup(space, '__del__') is not None
+
     def instantiate(self, space):
         cache = space.fromcache(Cache)
-        if self.lookup(space, '__del__') is not None:
-            w_inst = cache.cls_with_del(space, self)
-        else:
-            w_inst = cache.cls_without_del(space, self)
-        return w_inst
+        return cache.InstanceObjectCls(space, self)
 
     def getdict(self, space):
         return self.w_dict
@@ -132,9 +131,9 @@
                 self.setbases(space, w_value)
                 return
             elif name == "__del__":
-                if self.lookup(space, name) is None:
+                if not self.has_user_del(space):
                     msg = ("a __del__ method added to an existing class will "
-                           "not be called")
+                           "only be called on instances made from now on")
                     space.warn(space.wrap(msg), space.w_RuntimeWarning)
         space.setitem(self.w_dict, w_attr, w_value)
 
@@ -184,14 +183,10 @@
         if hasattr(space, 'is_fake_objspace'):
             # hack: with the fake objspace, we don't want to see typedef's
             # _getusercls() at all
-            self.cls_without_del = W_InstanceObject
-            self.cls_with_del = W_InstanceObject
             return
 
-        self.cls_without_del = _getusercls(
-                space, W_InstanceObject, False, reallywantdict=True)
-        self.cls_with_del = _getusercls(
-                space, W_InstanceObject, True, reallywantdict=True)
+        self.InstanceObjectCls = _getusercls(
+                space, W_InstanceObject, reallywantdict=True)
 
 
 def class_descr_call(space, w_self, __args__):
@@ -297,12 +292,15 @@
 class W_InstanceObject(W_Root):
     def __init__(self, space, w_class):
         # note that user_setup is overridden by the typedef.py machinery
+        self.space = space
         self.user_setup(space, space.gettypeobject(self.typedef))
         assert isinstance(w_class, W_ClassObject)
         self.w_class = w_class
+        if w_class.has_user_del(space):
+            space.finalizer_queue.register_finalizer(self)
 
     def user_setup(self, space, w_subtype):
-        self.space = space
+        pass
 
     def set_oldstyle_class(self, space, w_class):
         if w_class is None or not isinstance(w_class, W_ClassObject):
@@ -368,8 +366,7 @@
                 self.set_oldstyle_class(space, w_value)
                 return
             if name == '__del__' and w_meth is None:
-                cache = space.fromcache(Cache)
-                if (not isinstance(self, cache.cls_with_del)
+                if (not self.w_class.has_user_del(space)
                     and self.getdictvalue(space, '__del__') is None):
                     msg = ("a __del__ method added to an instance with no "
                            "__del__ in the class will not be called")
@@ -646,9 +643,8 @@
             raise oefmt(space.w_TypeError, "instance has no next() method")
         return space.call_function(w_func)
 
-    def descr_del(self, space):
-        # Note that this is called from executioncontext.UserDelAction
-        # via the space.userdel() method.
+    def _finalize_(self):
+        space = self.space
         w_func = self.getdictvalue(space, '__del__')
         if w_func is None:
             w_func = self.getattr_from_class(space, '__del__')
@@ -729,7 +725,6 @@
     __pow__ = interp2app(W_InstanceObject.descr_pow),
     __rpow__ = interp2app(W_InstanceObject.descr_rpow),
     next = interp2app(W_InstanceObject.descr_next),
-    __del__ = interp2app(W_InstanceObject.descr_del),
     __exit__ = interp2app(W_InstanceObject.descr_exit),
     __dict__ = dict_descr,
     **rawdict
diff --git a/rpython/rlib/rgc.py b/rpython/rlib/rgc.py
--- a/rpython/rlib/rgc.py
+++ b/rpython/rlib/rgc.py
@@ -440,14 +440,16 @@
         # Fetch and check the type of 'obj'
         objtyp = obj.__class__
         assert isinstance(objtyp, type), (
-            "to run register_finalizer() untranslated, "
-            "the object's class must be new-style")
+            "%r: to run register_finalizer() untranslated, "
+            "the object's class must be new-style" % (obj,))
         assert hasattr(obj, '__dict__'), (
-            "to run register_finalizer() untranslated, "
-            "the object must have a __dict__")
-        assert not hasattr(obj, '__slots__'), (
-            "to run register_finalizer() untranslated, "
-            "the object must not have __slots__")
+            "%r: to run register_finalizer() untranslated, "
+            "the object must have a __dict__" % (obj,))
+        assert (not hasattr(obj, '__slots__') or
+                type(obj).__slots__ == () or
+                type(obj).__slots__ == ('__weakref__',)), (
+            "%r: to run register_finalizer() untranslated, "
+            "the object must not have __slots__" % (obj,))
 
         # The first time, patch the method __del__ of the class, if
         # any, so that we can disable it on the original 'obj' and
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to