Committing the patch in issue 2965, so that weakref dicts have a closer

interface to normal dictionaries.  keys(), values() and items() still return
iterators instead of views, but that can be fixed later (or not).
This commit is contained in:
Barry Warsaw 2008-09-04 01:42:51 +00:00
parent 6ecc5c1980
commit ecaab837b6
3 changed files with 23 additions and 57 deletions

View File

@ -152,14 +152,9 @@ references that will cause the garbage collector to keep the keys around longer
than needed. than needed.
.. method:: WeakKeyDictionary.iterkeyrefs()
Return an :term:`iterator` that yields the weak references to the keys.
.. method:: WeakKeyDictionary.keyrefs() .. method:: WeakKeyDictionary.keyrefs()
Return a list of weak references to the keys. Return an :term:`iterator` that yields the weak references to the keys.
.. class:: WeakValueDictionary([dict]) .. class:: WeakValueDictionary([dict])
@ -176,18 +171,13 @@ than needed.
magic" (as a side effect of garbage collection). magic" (as a side effect of garbage collection).
:class:`WeakValueDictionary` objects have the following additional methods. :class:`WeakValueDictionary` objects have the following additional methods.
These method have the same issues as the :meth:`iterkeyrefs` and :meth:`keyrefs` These method have the same issues as the and :meth:`keyrefs` method of
methods of :class:`WeakKeyDictionary` objects. :class:`WeakKeyDictionary` objects.
.. method:: WeakValueDictionary.itervaluerefs()
Return an :term:`iterator` that yields the weak references to the values.
.. method:: WeakValueDictionary.valuerefs() .. method:: WeakValueDictionary.valuerefs()
Return a list of weak references to the values. Return an :term:`iterator` that yields the weak references to the values.
.. class:: WeakSet([elements]) .. class:: WeakSet([elements])
@ -290,7 +280,7 @@ the referent is accessed::
def __init__(self, ob, callback=None, **annotations): def __init__(self, ob, callback=None, **annotations):
super(ExtendedRef, self).__init__(ob, callback) super(ExtendedRef, self).__init__(ob, callback)
self.__counter = 0 self.__counter = 0
for k, v in annotations.iteritems(): for k, v in annotations.items():
setattr(self, k, v) setattr(self, k, v)
def __call__(self): def __call__(self):

View File

@ -790,8 +790,8 @@ class MappingTestCase(TestBase):
self.assertEqual(weakref.getweakrefcount(o), 1) self.assertEqual(weakref.getweakrefcount(o), 1)
self.assert_(o is dict[o.arg], self.assert_(o is dict[o.arg],
"wrong object returned by weak dict!") "wrong object returned by weak dict!")
items1 = dict.items() items1 = list(dict.items())
items2 = dict.copy().items() items2 = list(dict.copy().items())
items1.sort() items1.sort()
items2.sort() items2.sort()
self.assertEqual(items1, items2, self.assertEqual(items1, items2,
@ -856,8 +856,8 @@ class MappingTestCase(TestBase):
# Test iterkeyrefs() # Test iterkeyrefs()
objects2 = list(objects) objects2 = list(objects)
self.assertEqual(len(list(dict.iterkeyrefs())), len(objects)) self.assertEqual(len(list(dict.keyrefs())), len(objects))
for wr in dict.iterkeyrefs(): for wr in dict.keyrefs():
ob = wr() ob = wr()
self.assert_(ob in dict) self.assert_(ob in dict)
self.assert_(ob in dict) self.assert_(ob in dict)
@ -892,28 +892,28 @@ class MappingTestCase(TestBase):
def check_iters(self, dict): def check_iters(self, dict):
# item iterator: # item iterator:
items = dict.items() items = list(dict.items())
for item in dict.items(): for item in dict.items():
items.remove(item) items.remove(item)
self.assert_(len(items) == 0, "items() did not touch all items") self.assertFalse(items, "items() did not touch all items")
# key iterator, via __iter__(): # key iterator, via __iter__():
keys = list(dict.keys()) keys = list(dict.keys())
for k in dict: for k in dict:
keys.remove(k) keys.remove(k)
self.assert_(len(keys) == 0, "__iter__() did not touch all keys") self.assertFalse(keys, "__iter__() did not touch all keys")
# key iterator, via iterkeys(): # key iterator, via iterkeys():
keys = list(dict.keys()) keys = list(dict.keys())
for k in dict.keys(): for k in dict.keys():
keys.remove(k) keys.remove(k)
self.assert_(len(keys) == 0, "iterkeys() did not touch all keys") self.assertFalse(keys, "iterkeys() did not touch all keys")
# value iterator: # value iterator:
values = list(dict.values()) values = list(dict.values())
for v in dict.values(): for v in dict.values():
values.remove(v) values.remove(v)
self.assert_(len(values) == 0, self.assertFalse(values,
"itervalues() did not touch all values") "itervalues() did not touch all values")
def test_make_weak_keyed_dict_from_dict(self): def test_make_weak_keyed_dict_from_dict(self):
@ -1030,7 +1030,7 @@ class MappingTestCase(TestBase):
self.assertEqual(len(d), 2) self.assertEqual(len(d), 2)
del d[o1] del d[o1]
self.assertEqual(len(d), 1) self.assertEqual(len(d), 1)
self.assertEqual(d.keys(), [o2]) self.assertEqual(list(d.keys()), [o2])
def test_weak_valued_delitem(self): def test_weak_valued_delitem(self):
d = weakref.WeakValueDictionary() d = weakref.WeakValueDictionary()
@ -1041,7 +1041,7 @@ class MappingTestCase(TestBase):
self.assertEqual(len(d), 2) self.assertEqual(len(d), 2)
del d['something'] del d['something']
self.assertEqual(len(d), 1) self.assertEqual(len(d), 1)
self.assert_(d.items() == [('something else', o2)]) self.assert_(list(d.items()) == [('something else', o2)])
def test_weak_keyed_bad_delitem(self): def test_weak_keyed_bad_delitem(self):
d = weakref.WeakKeyDictionary() d = weakref.WeakKeyDictionary()
@ -1082,7 +1082,7 @@ class MappingTestCase(TestBase):
d[o] = o.value d[o] = o.value
del o # now the only strong references to keys are in objs del o # now the only strong references to keys are in objs
# Find the order in which iterkeys sees the keys. # Find the order in which iterkeys sees the keys.
objs = d.keys() objs = list(d.keys())
# Reverse it, so that the iteration implementation of __delitem__ # Reverse it, so that the iteration implementation of __delitem__
# has to keep looping to find the first object we delete. # has to keep looping to find the first object we delete.
objs.reverse() objs.reverse()

View File

@ -106,13 +106,13 @@ class WeakValueDictionary(collections.MutableMapping):
L.append((key, o)) L.append((key, o))
return L return L
def iteritems(self): def items(self):
for wr in self.data.values(): for wr in self.data.values():
value = wr() value = wr()
if value is not None: if value is not None:
yield wr.key, value yield wr.key, value
def iterkeys(self): def keys(self):
return iter(self.data.keys()) return iter(self.data.keys())
def __iter__(self): def __iter__(self):
@ -130,7 +130,7 @@ class WeakValueDictionary(collections.MutableMapping):
""" """
return self.data.values() return self.data.values()
def itervalues(self): def values(self):
for wr in self.data.values(): for wr in self.data.values():
obj = wr() obj = wr()
if obj is not None: if obj is not None:
@ -186,14 +186,6 @@ class WeakValueDictionary(collections.MutableMapping):
""" """
return self.data.values() return self.data.values()
def values(self):
L = []
for wr in self.data.values():
o = wr()
if o is not None:
L.append(o)
return L
class KeyedRef(ref): class KeyedRef(ref):
"""Specialized reference that includes a key corresponding to the value. """Specialized reference that includes a key corresponding to the value.
@ -270,20 +262,12 @@ class WeakKeyDictionary(collections.MutableMapping):
return wr in self.data return wr in self.data
def items(self): def items(self):
L = []
for key, value in self.data.items():
o = key()
if o is not None:
L.append((o, value))
return L
def iteritems(self):
for wr, value in self.data.items(): for wr, value in self.data.items():
key = wr() key = wr()
if key is not None: if key is not None:
yield key, value yield key, value
def iterkeyrefs(self): def keyrefs(self):
"""Return an iterator that yields the weak references to the keys. """Return an iterator that yields the weak references to the keys.
The references are not guaranteed to be 'live' at the time The references are not guaranteed to be 'live' at the time
@ -295,7 +279,7 @@ class WeakKeyDictionary(collections.MutableMapping):
""" """
return self.data.keys() return self.data.keys()
def iterkeys(self): def keys(self):
for wr in self.data.keys(): for wr in self.data.keys():
obj = wr() obj = wr()
if obj is not None: if obj is not None:
@ -304,7 +288,7 @@ class WeakKeyDictionary(collections.MutableMapping):
def __iter__(self): def __iter__(self):
return iter(self.keys()) return iter(self.keys())
def itervalues(self): def values(self):
return iter(self.data.values()) return iter(self.data.values())
def keyrefs(self): def keyrefs(self):
@ -319,14 +303,6 @@ class WeakKeyDictionary(collections.MutableMapping):
""" """
return self.data.keys() return self.data.keys()
def keys(self):
L = []
for wr in self.data.keys():
o = wr()
if o is not None:
L.append(o)
return L
def popitem(self): def popitem(self):
while 1: while 1:
key, value = self.data.popitem() key, value = self.data.popitem()