[Python-checkins] python/dist/src/Lib/test test_gc.py,1.25,1.26
tim_one@users.sourceforge.net
tim_one@users.sourceforge.net
Sat, 05 Apr 2003 16:11:41 -0800
Update of /cvsroot/python/python/dist/src/Lib/test
In directory sc8-pr-cvs1:/tmp/cvs-serv11222/python/Lib/test
Modified Files:
test_gc.py
Log Message:
Reworked move_finalizer_reachable() to create two distinct lists:
externally unreachable objects with finalizers, and externally unreachable
objects without finalizers reachable from such objects. This allows us
to call has_finalizer() at most once per object, and so limit the pain of
nasty getattr hooks. This fixes the failing "boom 2" example Jeremy
posted (a non-printing variant of which is now part of test_gc), via never
triggering the nasty part of its __getattr__ method.
Index: test_gc.py
===================================================================
RCS file: /cvsroot/python/python/dist/src/Lib/test/test_gc.py,v
retrieving revision 1.25
retrieving revision 1.26
diff -C2 -d -r1.25 -r1.26
*** test_gc.py 5 Apr 2003 17:46:04 -0000 1.25
--- test_gc.py 6 Apr 2003 00:11:38 -0000 1.26
***************
*** 254,258 ****
gc.disable()
! class C:
def __getattr__(self, someattribute):
del self.attr
--- 254,258 ----
gc.disable()
! class Boom:
def __getattr__(self, someattribute):
del self.attr
***************
*** 260,265 ****
def test_boom():
! a = C()
! b = C()
a.attr = b
b.attr = a
--- 260,265 ----
def test_boom():
! a = Boom()
! b = Boom()
a.attr = b
b.attr = a
***************
*** 268,272 ****
garbagelen = len(gc.garbage)
del a, b
! # a<->b are in a trash cycle now. Collection will invoke C.__getattr__
# (to see whether a and b have __del__ methods), and __getattr__ deletes
# the internal "attr" attributes as a side effect. That causes the
--- 268,272 ----
garbagelen = len(gc.garbage)
del a, b
! # a<->b are in a trash cycle now. Collection will invoke Boom.__getattr__
# (to see whether a and b have __del__ methods), and __getattr__ deletes
# the internal "attr" attributes as a side effect. That causes the
***************
*** 277,280 ****
--- 277,307 ----
expect(len(gc.garbage), garbagelen, "boom")
+ class Boom2:
+ def __init__(self):
+ self.x = 0
+
+ def __getattr__(self, someattribute):
+ self.x += 1
+ if self.x > 1:
+ del self.attr
+ raise AttributeError
+
+ def test_boom2():
+ a = Boom2()
+ b = Boom2()
+ a.attr = b
+ b.attr = a
+
+ gc.collect()
+ garbagelen = len(gc.garbage)
+ del a, b
+ # Much like test_boom(), except that __getattr__ doesn't break the
+ # cycle until the second time gc checks for __del__. As of 2.3b1,
+ # there isn't a second time, so this simply cleans up the trash cycle.
+ # We expect a, b, a.__dict__ and b.__dict__ (4 objects) to get reclaimed
+ # this way.
+ expect(gc.collect(), 4, "boom2")
+ expect(len(gc.garbage), garbagelen, "boom2")
+
def test_all():
gc.collect() # Delete 2nd generation garbage
***************
*** 296,299 ****
--- 323,327 ----
run_test("trashcan", test_trashcan)
run_test("boom", test_boom)
+ run_test("boom2", test_boom2)
def test():