[pypy-commit] pypy use-gc-del-3: Use @rgc.must_be_light_finalizer on classes
arigo
pypy.commits at gmail.com
Thu May 5 09:18:32 EDT 2016
Author: Armin Rigo <arigo at tunes.org>
Branch: use-gc-del-3
Changeset: r84214:b00c736dfd7c
Date: 2016-05-05 10:19 +0200
http://bitbucket.org/pypy/pypy/changeset/b00c736dfd7c/
Log: Use @rgc.must_be_light_finalizer on classes
diff --git a/rpython/annotator/classdesc.py b/rpython/annotator/classdesc.py
--- a/rpython/annotator/classdesc.py
+++ b/rpython/annotator/classdesc.py
@@ -579,6 +579,14 @@
if cls not in FORCE_ATTRIBUTES_INTO_CLASSES:
self.all_enforced_attrs = [] # no attribute allowed
+ if (getattr(cls, '_must_be_light_finalizer_', False) and
+ hasattr(cls, '__del__') and
+ not getattr(cls.__del__, '_must_be_light_finalizer_', False)):
+ raise AnnotatorError(
+ "Class %r is in a class hierarchy with "
+ "_must_be_light_finalizer_ = True, but it has a "
+ "destructor without @rgc.must_be_light_finalizer" % (cls,))
+
def add_source_attribute(self, name, value, mixin=False):
if isinstance(value, property):
# special case for property object
diff --git a/rpython/annotator/test/test_annrpython.py b/rpython/annotator/test/test_annrpython.py
--- a/rpython/annotator/test/test_annrpython.py
+++ b/rpython/annotator/test/test_annrpython.py
@@ -4584,6 +4584,32 @@
e = py.test.raises(Exception, a.build_types, f, [])
assert str(e.value) == "Don't know how to represent Ellipsis"
+ def test_must_be_light_finalizer(self):
+ from rpython.rlib import rgc
+ @rgc.must_be_light_finalizer
+ class A(object):
+ pass
+ class B(A):
+ def __del__(self):
+ pass
+ class C(A):
+ @rgc.must_be_light_finalizer
+ def __del__(self):
+ pass
+ class D(object):
+ def __del__(self):
+ pass
+ def fb():
+ B()
+ def fc():
+ C()
+ def fd():
+ D()
+ a = self.RPythonAnnotator()
+ a.build_types(fc, [])
+ a.build_types(fd, [])
+ py.test.raises(AnnotatorError, a.build_types, fb, [])
+
def g(n):
return [0, 1, 2, n]
diff --git a/rpython/rlib/rgc.py b/rpython/rlib/rgc.py
--- a/rpython/rlib/rgc.py
+++ b/rpython/rlib/rgc.py
@@ -362,6 +362,16 @@
return func
def must_be_light_finalizer(func):
+ """Mark a __del__ method as being a destructor, calling only a limited
+ set of operations. See pypy/doc/discussion/finalizer-order.rst.
+
+ If you use the same decorator on a class, this class and all its
+ subclasses are only allowed to have __del__ methods which are
+ similarly decorated (or no __del__ at all). It prevents a class
+ hierarchy from having destructors in some parent classes, which are
+ overridden in subclasses with (non-light, old-style) finalizers.
+ (This case is the original motivation for FinalizerQueue.)
+ """
func._must_be_light_finalizer_ = True
return func
More information about the pypy-commit
mailing list