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