from testing_helpers import test_gc class C(object): def foo(self): print "inside foo()" def getWR(): c = C() wr = weakref.proxy(c) wr.attr = "test attr" print wr.attr, c.attr wr.foo() del c return wr wr = test_gc(getWR) try: wr.foo() except ReferenceError as e: print e try: print wr.attr except ReferenceError as e: print e try: wr.attr = "val2" except ReferenceError as e: print e
# Objects are allowed to resurrect other objects too, I guess from testing_helpers import test_gc class C(object): def __init__(self, x): self.x = x def __del__(self): global x x = self.x x = None def test(): c = C([]) test_gc(test) print x
import gc from testing_helpers import test_gc # This tests the edge case where a garbage collection gets triggered inside # a finalizer. Finalizers can allocate objects so this can definitely happen # in practice. indices = {} class GCCaller(object): def __del__(self): gc.collect() class ObjWithFinalizer(object): def __init__(self, index): self.index = index def __del__(self): global indices indices[self.index] = True def scope(): for _ in xrange(200): for i in xrange(20): obj = ObjWithFinalizer(i) caller = GCCaller() test_gc(scope)
from testing_helpers import test_gc # __del__ does not get called because it doesn't fallback to getattr # Note that this is an old-style class. class C: def __getattr__(self, name): def foo(): return 0 print name return foo def foo(): c = C() l = range(10) # This should cause __index__ to be printed because it fallbacks to getattr l[c] = 1 # Here, c goes out of scope. return test_gc(foo)
d = D() def scopeE(): e = E() def scopeF(): f = F() def scopeG(): g = G() def scopeH(): h = H() def scopeI(): i = I() test_gc(scopeC) test_gc(scopeD) test_gc(scopeE) test_gc(scopeF) test_gc(scopeG) test_gc(scopeH) test_gc(scopeI)
sys.stderr = Writer() strs = [] class C(object): def __init__(self, index): self.index = index def __del__(self): strs.append("never do this %d" % self.index) raise Exception("it's a bad idea") def test(): cs = [C(i) for i in range(10)] test_gc(test, 10) print sorted(strs) # Similarly for exceptions from weakref callbacks: import weakref called_callback = False def callback(ref): global called_callback if not called_callback: print "callback" called_callback = True raise ValueError()
class C(object): def foo(self): print "inside foo()" def getWR(): c = C() wr = weakref.proxy(c) wr.attr = "test attr" print wr.attr, c.attr wr.foo() del c return wr wr = test_gc(getWR) try: wr.foo() except ReferenceError as e: print e try: print wr.attr except ReferenceError as e: print e try: wr.attr = "val2" except ReferenceError as e: print e
class C(object): def __init__(self, index): self.index = index def __del__(self): strs.append("never do this %d" % self.index) raise Exception("it's a bad idea") def test(): cs = [C(i) for i in range(10)] test_gc(test, 10) print sorted(strs) # Similarly for exceptions from weakref callbacks: import weakref called_callback = False def callback(ref): global called_callback if not called_callback: print "callback" called_callback = True raise ValueError()
return increasing_lists def scope3(): decreasing_lists = [] for _ in xrange(number_of_attempts): decreasing_list = [] decreasing_lists.append(decreasing_list) objs = [ObjWithFinalizerAndRef(i, decreasing_list) for i in xrange(items_in_list)] for i in xrange(items_in_list - 1): objs[i+1].ref = objs[i] return decreasing_lists test_gc(scope1) print sorted(unordered_finalize.keys()) increasing_lists = test_gc(scope2, 25) decreasing_lists = test_gc(scope3, 25) for increasing_list in increasing_lists: if increasing_list == range(items_in_list): print "success! got " print increasing_list print "at least once" break for decreasing_list in decreasing_lists: decreasing_list.reverse() if decreasing_list == range(items_in_list): print "success! got "
decreasing_lists = [] for _ in xrange(number_of_attempts): decreasing_list = [] decreasing_lists.append(decreasing_list) objs = [ ObjWithFinalizerAndRef(i, decreasing_list) for i in xrange(items_in_list) ] for i in xrange(items_in_list - 1): objs[i + 1].ref = objs[i] return decreasing_lists test_gc(scope1) print sorted(unordered_finalize.keys()) increasing_lists = test_gc(scope2, 25) decreasing_lists = test_gc(scope3, 25) for increasing_list in increasing_lists: if increasing_list == range(items_in_list): print "success! got " print increasing_list print "at least once" break for decreasing_list in decreasing_lists: decreasing_list.reverse() if decreasing_list == range(items_in_list): print "success! got "
def scope_old3(): c3 = OldStyle(3) adverserial_weakref = weakref.ref(c3, retainer(c3)) def scope_new1(): c1 = NewStyle(1) return weakref.ref(c1, callback) def scope_new2(): c2 = NewStyle(2) return (weakref.ref(c2, callback), weakref.ref(c2, callback)) def scope_new3(): c3 = NewStyle(3) adverserial_weakref = weakref.ref(c3, retainer(c3)) print ">> Test old style" test_gc(scope_old1) test_gc(scope_old2) test_gc(scope_old3, 3) print ">> Test new style" test_gc(scope_new1) test_gc(scope_new2) test_gc(scope_new3, 3)
def weak_retainer(to_be_resurrected): def cb(wr): global saved_wr saved_wrs.append(to_be_resurrected()) print "staying alive~", wr, to_be_resurrected return cb def foo1(): c1 = C(1) c2 = C(2) wr1 = weakref.ref(c1, callback) wr2 = weakref.ref(c2, weak_retainer(wr1)) return (wr1, wr2) def foo2(): c3 = C(3) c4 = C(4) wr4 = weakref.ref(c4, callback) wr3 = weakref.ref(c3, weak_retainer(wr4)) return (wr3, wr4) wr1, wr2 = test_gc(foo1, 5) wr3, wr4 = test_gc(foo2, 5) print wr1(), wr2() print wr3(), wr4()
def scope_old2(): c2 = OldStyle(2) return (weakref.ref(c2, callback), weakref.ref(c2, callback)) def scope_old3(): c3 = OldStyle(3) adverserial_weakref = weakref.ref(c3, retainer(c3)) def scope_new1(): c1 = NewStyle(1) return weakref.ref(c1, callback) def scope_new2(): c2 = NewStyle(2) return (weakref.ref(c2, callback), weakref.ref(c2, callback)) def scope_new3(): c3 = NewStyle(3) adverserial_weakref = weakref.ref(c3, retainer(c3)) print ">> Test old style" test_gc(scope_old1) test_gc(scope_old2) test_gc(scope_old3, 3) print ">> Test new style" test_gc(scope_new1) test_gc(scope_new2) test_gc(scope_new3, 3)
def __init__(self, index): self.index = index saved_wrs = [] def weak_retainer(to_be_resurrected): def cb(wr): global saved_wr saved_wrs.append(to_be_resurrected()) print "staying alive~", wr, to_be_resurrected return cb def foo1(): c1 = C(1) c2 = C(2) wr1 = weakref.ref(c1, callback) wr2 = weakref.ref(c2, weak_retainer(wr1)) return (wr1, wr2) def foo2(): c3 = C(3) c4 = C(4) wr4 = weakref.ref(c4, callback) wr3 = weakref.ref(c3, weak_retainer(wr4)) return (wr3, wr4) wr1, wr2 = test_gc(foo1, 5) wr3, wr4 = test_gc(foo2, 5) print wr1(), wr2() print wr3(), wr4()
pass class H(C): pass class I(H, E): pass def scopeC(): c = C() def scopeD(): d = D() def scopeE(): e = E() def scopeF(): f = F() def scopeG(): g = G() def scopeH(): h = H() def scopeI(): i = I() test_gc(scopeC) test_gc(scopeD) test_gc(scopeE) test_gc(scopeF) test_gc(scopeG) test_gc(scopeH) test_gc(scopeI)