@@ -111,7 +111,11 @@ def __getstate__(self):
111
111
def __setstate__ (self ,data_dict ):
112
112
self .__dict__ = data_dict
113
113
# turn the normal dictionary back into a dictionary with weak values
114
- self ._parents = {k :weakref .ref (v )
114
+ # The extra lambda is to provide a callback to remove dead
115
+ # weakrefs from the dictionary when garbage collection is done.
116
+ self ._parents = {k :weakref .ref (v ,lambda ref ,sid = k ,
117
+ target = self ._parents :
118
+ target .pop (sid ))
115
119
for k ,v in self ._parents .items ()if v is not None }
116
120
117
121
def __copy__ (self ,* args ):
@@ -169,7 +173,12 @@ def set_children(self, *children):
169
173
# parents are destroyed, references from the children won't
170
174
# keep them alive.
171
175
for child in children :
172
- child ._parents [id (self )]= weakref .ref (self )
176
+ # Use weak references so this dictionary won't keep obsolete nodes
177
+ # alive; the callback deletes the dictionary entry. This is a
178
+ # performance improvement over using WeakValueDictionary.
179
+ ref = weakref .ref (self ,lambda ref ,sid = id (self ),
180
+ target = child ._parents :target .pop (sid ))
181
+ child ._parents [id (self )]= ref
173
182
174
183
if DEBUG :
175
184
_set_children = set_children