Skip to content

Commit 6114679

Browse files
committed
SF bug #1012315: weakref.WeakValueDictionary should override .has_key()
* Check the found object for a None value during a contains/has_key lookup. Perhaps it will help the OP who is likely suffering from an occassional GC or threading object deletion after self.data is checked. * Complete the previous patch by removing the unnecessary indirection for weak dict iterators. Makes the code cleaner and more readable.
1 parent 3a3817f commit 6114679

File tree

1 file changed

+36
-31
lines changed

1 file changed

+36
-31
lines changed

Lib/weakref.py

Lines changed: 36 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,20 @@ def __getitem__(self, key):
5757
else:
5858
return o
5959

60+
def __contains__(self, key):
61+
try:
62+
o = self.data[key]()
63+
except KeyError:
64+
return False
65+
return o is not None
66+
67+
def has_key(self, key):
68+
try:
69+
o = self.data[key]()
70+
except KeyError:
71+
return False
72+
return o is not None
73+
6074
def __repr__(self):
6175
return "<WeakValueDictionary at %s>" % id(self)
6276

@@ -93,14 +107,22 @@ def items(self):
93107
return L
94108

95109
def iteritems(self):
96-
return WeakValuedItemIterator(self)
110+
for wr in self.data.itervalues():
111+
value = wr()
112+
if value is not None:
113+
yield wr.key, value
97114

98115
def iterkeys(self):
99116
return self.data.iterkeys()
100-
__iter__ = iterkeys
117+
118+
def __iter__(self):
119+
return self.data.iterkeys()
101120

102121
def itervalues(self):
103-
return WeakValuedValueIterator(self)
122+
for wr in self.data.itervalues():
123+
obj = wr()
124+
if obj is not None:
125+
yield obj
104126

105127
def popitem(self):
106128
while 1:
@@ -236,11 +258,19 @@ def items(self):
236258
return L
237259

238260
def iteritems(self):
239-
return WeakKeyedItemIterator(self)
261+
for wr, value in self.data.iteritems():
262+
key = wr()
263+
if key is not None:
264+
yield key, value
240265

241266
def iterkeys(self):
242-
return WeakKeyedKeyIterator(self)
243-
__iter__ = iterkeys
267+
for wr in self.data.iterkeys():
268+
obj = wr()
269+
if obj is not None:
270+
yield obj
271+
272+
def __iter__(self):
273+
return self.iterkeys()
244274

245275
def itervalues(self):
246276
return self.data.itervalues()
@@ -275,28 +305,3 @@ def update(self, dict=None, **kwargs):
275305
d[ref(key, self._remove)] = value
276306
if len(kwargs):
277307
self.update(kwargs)
278-
279-
280-
def WeakKeyedKeyIterator(weakdict):
281-
for wr in weakdict.data.iterkeys():
282-
obj = wr()
283-
if obj is not None:
284-
yield obj
285-
286-
def WeakKeyedItemIterator(weakdict):
287-
for wr, value in weakdict.data.iteritems():
288-
key = wr()
289-
if key is not None:
290-
yield key, value
291-
292-
def WeakValuedValueIterator(weakdict):
293-
for wr in weakdict.data.itervalues():
294-
obj = wr()
295-
if obj is not None:
296-
yield obj
297-
298-
def WeakValuedItemIterator(weakdict):
299-
for wr in weakdict.data.itervalues():
300-
value = wr()
301-
if value is not None:
302-
yield wr.key, value

0 commit comments

Comments
 (0)