mirror of
https://github.com/python/cpython.git
synced 2025-08-03 08:34:29 +00:00
Address SF bug 519621: slots weren't traversed by GC.
While I was at it, I added a tp_clear handler and changed the tp_dealloc handler to use the clear_slots helper for the tp_clear handler. Also tightened the rules for slot names: they must now be proper identifiers (ignoring the dirty little fact that <ctype.h> is locale sensitive). Also set mp->flags = READONLY for the __weakref__ pseudo-slot. Most of this is a 2.2 bugfix candidate; I'll apply it there myself.
This commit is contained in:
parent
e22bc1e841
commit
9923ffe2c0
3 changed files with 194 additions and 49 deletions
|
@ -1060,6 +1060,45 @@ def slots():
|
|||
vereq(x.b, 2)
|
||||
vereq(x.c, 3)
|
||||
|
||||
# Make sure slot names are proper identifiers
|
||||
try:
|
||||
class C(object):
|
||||
__slots__ = [None]
|
||||
except TypeError:
|
||||
pass
|
||||
else:
|
||||
raise TestFailed, "[None] slots not caught"
|
||||
try:
|
||||
class C(object):
|
||||
__slots__ = ["foo bar"]
|
||||
except TypeError:
|
||||
pass
|
||||
else:
|
||||
raise TestFailed, "['foo bar'] slots not caught"
|
||||
try:
|
||||
class C(object):
|
||||
__slots__ = ["foo\0bar"]
|
||||
except TypeError:
|
||||
pass
|
||||
else:
|
||||
raise TestFailed, "['foo\\0bar'] slots not caught"
|
||||
try:
|
||||
class C(object):
|
||||
__slots__ = ["1"]
|
||||
except TypeError:
|
||||
pass
|
||||
else:
|
||||
raise TestFailed, "['1'] slots not caught"
|
||||
try:
|
||||
class C(object):
|
||||
__slots__ = [""]
|
||||
except TypeError:
|
||||
pass
|
||||
else:
|
||||
raise TestFailed, "[''] slots not caught"
|
||||
class C(object):
|
||||
__slots__ = ["a", "a_b", "_a", "A0123456789Z"]
|
||||
|
||||
# Test leaks
|
||||
class Counted(object):
|
||||
counter = 0 # counts the number of instances alive
|
||||
|
@ -1094,6 +1133,18 @@ def slots():
|
|||
del x
|
||||
vereq(Counted.counter, 0)
|
||||
|
||||
# Test cyclical leaks [SF bug 519621]
|
||||
class F(object):
|
||||
__slots__ = ['a', 'b']
|
||||
log = []
|
||||
s = F()
|
||||
s.a = [Counted(), s]
|
||||
vereq(Counted.counter, 1)
|
||||
s = None
|
||||
import gc
|
||||
gc.collect()
|
||||
vereq(Counted.counter, 0)
|
||||
|
||||
def dynamics():
|
||||
if verbose: print "Testing class attribute propagation..."
|
||||
class D(object):
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue