dictutil: remove unused ValueOrderedDict
This commit is contained in:
parent
4f493b1a03
commit
61b85dbf78
|
@ -1407,11 +1407,6 @@ class DictUtil(unittest.TestCase):
|
|||
self.failUnless(filter(lambda x: x is 3, d.iterkeys()))
|
||||
d[fake3] = 8
|
||||
|
||||
def test_all(self):
|
||||
self._help_test_eq_but_notis(dictutil.ValueOrderedDict)
|
||||
self._help_test_nonempty_dict(dictutil.ValueOrderedDict)
|
||||
self._help_test_eq_but_notis(dictutil.ValueOrderedDict)
|
||||
|
||||
def test_dict_of_sets(self):
|
||||
ds = dictutil.DictOfSets()
|
||||
ds.add(1, "a")
|
||||
|
@ -1470,68 +1465,6 @@ class DictUtil(unittest.TestCase):
|
|||
dictutil.del_if_present(d, 3)
|
||||
self.failUnlessEqual(d, {2: "b"})
|
||||
|
||||
def test_valueordereddict(self):
|
||||
d = dictutil.ValueOrderedDict()
|
||||
d["a"] = 3
|
||||
d["b"] = 2
|
||||
d["c"] = 1
|
||||
|
||||
self.failUnlessEqual(d, {"a": 3, "b": 2, "c": 1})
|
||||
self.failUnlessEqual(d.items(), [("c", 1), ("b", 2), ("a", 3)])
|
||||
self.failUnlessEqual(d.values(), [1, 2, 3])
|
||||
self.failUnlessEqual(d.keys(), ["c", "b", "a"])
|
||||
self.failUnlessEqual(repr(d), "<ValueOrderedDict {c: 1, b: 2, a: 3}>")
|
||||
self.failUnlessEqual(str(d), "<ValueOrderedDict {c: 1, b: 2, a: 3}>")
|
||||
# str() is supposed to only show the first 16 entries
|
||||
large_d = dictutil.ValueOrderedDict()
|
||||
for i in range(20):
|
||||
large_d["k%d" % i] = i
|
||||
large_d_repr = ("<ValueOrderedDict {%s, ...}>" %
|
||||
", ".join(["k%d: %d" % (i, i) for i in range(16)]))
|
||||
self.failUnlessEqual(str(large_d), large_d_repr)
|
||||
|
||||
def eq(a, b):
|
||||
return a == b
|
||||
self.failIf(d == {"a": 4})
|
||||
self.failUnless(d != {"a": 4})
|
||||
|
||||
x = d.setdefault("d", 0)
|
||||
self.failUnlessEqual(x, 0)
|
||||
self.failUnlessEqual(d["d"], 0)
|
||||
x = d.setdefault("d", -1)
|
||||
self.failUnlessEqual(x, 0)
|
||||
self.failUnlessEqual(d["d"], 0)
|
||||
|
||||
x = d.remove("e", "default", False)
|
||||
self.failUnlessEqual(x, "default")
|
||||
self.failUnlessRaises(KeyError, d.remove, "e", "default", True)
|
||||
x = d.remove("d", 5)
|
||||
self.failUnlessEqual(x, 0)
|
||||
|
||||
x = d.__getitem__("c")
|
||||
self.failUnlessEqual(x, 1)
|
||||
x = d.__getitem__("e", "default", False)
|
||||
self.failUnlessEqual(x, "default")
|
||||
self.failUnlessRaises(KeyError, d.__getitem__, "e", "default", True)
|
||||
|
||||
self.failUnlessEqual(d.popitem(), ("c", 1))
|
||||
self.failUnlessEqual(d.popitem(), ("b", 2))
|
||||
self.failUnlessEqual(d.popitem(), ("a", 3))
|
||||
self.failUnlessRaises(KeyError, d.popitem)
|
||||
|
||||
d = dictutil.ValueOrderedDict({"a": 3, "b": 2, "c": 1})
|
||||
x = d.pop("d", "default", False)
|
||||
self.failUnlessEqual(x, "default")
|
||||
self.failUnlessRaises(KeyError, d.pop, "d", "default", True)
|
||||
x = d.pop("b")
|
||||
self.failUnlessEqual(x, 2)
|
||||
self.failUnlessEqual(d.items(), [("c", 1), ("a", 3)])
|
||||
|
||||
d = dictutil.ValueOrderedDict({"a": 3, "b": 2, "c": 1})
|
||||
x = d.pop_from_list(1) # pop the second item, b/2
|
||||
self.failUnlessEqual(x, "b")
|
||||
self.failUnlessEqual(d.items(), [("c", 1), ("a", 3)])
|
||||
|
||||
def test_auxdict(self):
|
||||
d = dictutil.AuxValueDict()
|
||||
# we put the serialized form in the auxdata
|
||||
|
|
|
@ -2,11 +2,6 @@
|
|||
Tools to mess with dicts.
|
||||
"""
|
||||
|
||||
import operator
|
||||
from bisect import bisect_left, insort_left
|
||||
|
||||
from allmydata.util.assertutil import _assert, precondition
|
||||
|
||||
def move(k, d1, d2, strict=False):
|
||||
"""
|
||||
Move item with key k from d1 to d2.
|
||||
|
@ -58,271 +53,6 @@ def del_if_present(d, k):
|
|||
if d.has_key(k):
|
||||
del d[k]
|
||||
|
||||
class ValueOrderedDict:
|
||||
"""
|
||||
Note: this implementation assumes that the values do not mutate and change
|
||||
their sort order. That is, it stores the values in a sorted list and
|
||||
as items are added and removed from the dict, it makes updates to the list
|
||||
which will keep the list sorted. But if a value that is currently sitting
|
||||
in the list changes its sort order, then the internal consistency of this
|
||||
object will be lost.
|
||||
|
||||
If that happens, and if assertion checking is turned on, then you will get
|
||||
an assertion failure the very next time you try to do anything with this
|
||||
ValueOrderedDict. However, those internal consistency checks are very slow
|
||||
and almost certainly unacceptable to leave turned on in production code.
|
||||
"""
|
||||
class ItemIterator:
|
||||
def __init__(self, c):
|
||||
self.c = c
|
||||
self.i = 0
|
||||
def __iter__(self):
|
||||
return self
|
||||
def next(self):
|
||||
precondition(self.i <= len(self.c.l), "The iterated ValueOrderedDict doesn't have this many elements. Most likely this is because someone altered the contents of the ValueOrderedDict while the iteration was in progress.", self.i, self.c)
|
||||
precondition((self.i == len(self.c.l)) or self.c.d.has_key(self.c.l[self.i][1]), "The iterated ValueOrderedDict doesn't have this key. Most likely this is because someone altered the contents of the ValueOrderedDict while the iteration was in progress.", self.i, (self.i < len(self.c.l)) and self.c.l[self.i], self.c)
|
||||
if self.i == len(self.c.l):
|
||||
raise StopIteration
|
||||
le = self.c.l[self.i]
|
||||
self.i += 1
|
||||
return (le[1], le[0],)
|
||||
|
||||
def iteritems(self):
|
||||
return ValueOrderedDict.ItemIterator(self)
|
||||
|
||||
def items(self):
|
||||
return zip(map(operator.__getitem__, self.l, [1]*len(self.l)), map(operator.__getitem__, self.l, [0]*len(self.l)))
|
||||
|
||||
def values(self):
|
||||
return map(operator.__getitem__, self.l, [0]*len(self.l))
|
||||
|
||||
def keys(self):
|
||||
return map(operator.__getitem__, self.l, [1]*len(self.l))
|
||||
|
||||
class KeyIterator:
|
||||
def __init__(self, c):
|
||||
self.c = c
|
||||
self.i = 0
|
||||
def __iter__(self):
|
||||
return self
|
||||
def next(self):
|
||||
precondition(self.i <= len(self.c.l), "The iterated ValueOrderedDict doesn't have this many elements. Most likely this is because someone altered the contents of the ValueOrderedDict while the iteration was in progress.", self.i, self.c)
|
||||
precondition((self.i == len(self.c.l)) or self.c.d.has_key(self.c.l[self.i][1]), "The iterated ValueOrderedDict doesn't have this key. Most likely this is because someone altered the contents of the ValueOrderedDict while the iteration was in progress.", self.i, (self.i < len(self.c.l)) and self.c.l[self.i], self.c)
|
||||
if self.i == len(self.c.l):
|
||||
raise StopIteration
|
||||
le = self.c.l[self.i]
|
||||
self.i += 1
|
||||
return le[1]
|
||||
|
||||
def iterkeys(self):
|
||||
return ValueOrderedDict.KeyIterator(self)
|
||||
|
||||
class ValueIterator:
|
||||
def __init__(self, c):
|
||||
self.c = c
|
||||
self.i = 0
|
||||
def __iter__(self):
|
||||
return self
|
||||
def next(self):
|
||||
precondition(self.i <= len(self.c.l), "The iterated ValueOrderedDict doesn't have this many elements. Most likely this is because someone altered the contents of the ValueOrderedDict while the iteration was in progress.", self.i, self.c)
|
||||
precondition((self.i == len(self.c.l)) or self.c.d.has_key(self.c.l[self.i][1]), "The iterated ValueOrderedDict doesn't have this key. Most likely this is because someone altered the contents of the ValueOrderedDict while the iteration was in progress.", self.i, (self.i < len(self.c.l)) and self.c.l[self.i], self.c)
|
||||
if self.i == len(self.c.l):
|
||||
raise StopIteration
|
||||
le = self.c.l[self.i]
|
||||
self.i += 1
|
||||
return le[0]
|
||||
|
||||
def itervalues(self):
|
||||
return ValueOrderedDict.ValueIterator(self)
|
||||
|
||||
def __init__(self, initialdata={}):
|
||||
self.d = {} # k: key, v: val
|
||||
self.l = [] # sorted list of tuples of (val, key,)
|
||||
self.update(initialdata)
|
||||
assert self._assert_invariants()
|
||||
|
||||
def __len__(self):
|
||||
return len(self.l)
|
||||
|
||||
def __repr_n__(self, n=None):
|
||||
s = ["{",]
|
||||
try:
|
||||
iter = self.iteritems()
|
||||
x = iter.next()
|
||||
s.append(str(x[0])); s.append(": "); s.append(str(x[1]))
|
||||
i = 1
|
||||
while (n is None) or (i < n):
|
||||
i += 1
|
||||
x = iter.next()
|
||||
s.append(", ");
|
||||
s.append(str(x[0])); s.append(": "); s.append(str(x[1]))
|
||||
# if we get here, we're truncating the repr, so make that clear
|
||||
s.append(", ...")
|
||||
except StopIteration:
|
||||
pass
|
||||
s.append("}")
|
||||
return ''.join(s)
|
||||
|
||||
def __repr__(self):
|
||||
return "<%s %s>" % (self.__class__.__name__, self.__repr_n__(),)
|
||||
|
||||
def __str__(self):
|
||||
return "<%s %s>" % (self.__class__.__name__, self.__repr_n__(16),)
|
||||
|
||||
def __eq__(self, other):
|
||||
for (k, v,) in other.iteritems():
|
||||
if not self.d.has_key(k) or self.d[k] != v:
|
||||
return False
|
||||
return True
|
||||
|
||||
def __ne__(self, other):
|
||||
return not self.__eq__(other)
|
||||
|
||||
def _assert_invariants(self):
|
||||
iter = self.l.__iter__()
|
||||
try:
|
||||
oldx = iter.next()
|
||||
while True:
|
||||
x = iter.next()
|
||||
# self.l is required to be sorted
|
||||
_assert(x >= oldx, x, oldx)
|
||||
# every element of self.l is required to appear in self.d
|
||||
_assert(self.d.has_key(x[1]), x)
|
||||
oldx =x
|
||||
except StopIteration:
|
||||
pass
|
||||
for (k, v,) in self.d.iteritems():
|
||||
i = bisect_left(self.l, (v, k,))
|
||||
while (self.l[i][0] is not v) or (self.l[i][1] is not k):
|
||||
i += 1
|
||||
_assert(i < len(self.l), i, len(self.l), k, v, self.l)
|
||||
_assert(self.l[i][0] is v, i, v, l=self.l, d=self.d)
|
||||
_assert(self.l[i][1] is k, i, k, l=self.l, d=self.d)
|
||||
return True
|
||||
|
||||
def insert(self, key, val=None):
|
||||
assert self._assert_invariants()
|
||||
result = self.__setitem__(key, val)
|
||||
assert self._assert_invariants()
|
||||
return result
|
||||
|
||||
def setdefault(self, key, default=None):
|
||||
assert self._assert_invariants()
|
||||
if not self.has_key(key):
|
||||
self[key] = default
|
||||
assert self._assert_invariants()
|
||||
return self[key]
|
||||
|
||||
def __setitem__(self, key, val=None):
|
||||
assert self._assert_invariants()
|
||||
if self.d.has_key(key):
|
||||
oldval = self.d[key]
|
||||
if oldval != val:
|
||||
# re-sort
|
||||
i = bisect_left(self.l, (oldval, key,))
|
||||
while (self.l[i][0] is not oldval) or (self.l[i][1] is not key):
|
||||
i += 1
|
||||
self.l.pop(i)
|
||||
insort_left(self.l, (val, key,))
|
||||
elif oldval is not val:
|
||||
# replace
|
||||
i = bisect_left(self.l, (oldval, key,))
|
||||
while (self.l[i][0] is not oldval) or (self.l[i][1] is not key):
|
||||
i += 1
|
||||
self.l[i] = (val, key,)
|
||||
else:
|
||||
insort_left(self.l, (val, key,))
|
||||
|
||||
self.d[key] = val
|
||||
assert self._assert_invariants()
|
||||
return val
|
||||
|
||||
def remove(self, key, default=None, strictkey=True):
|
||||
assert self._assert_invariants()
|
||||
result = self.__delitem__(key, default, strictkey)
|
||||
assert self._assert_invariants()
|
||||
return result
|
||||
|
||||
def __getitem__(self, key, default=None, strictkey=True):
|
||||
if not self.d.has_key(key):
|
||||
if strictkey:
|
||||
raise KeyError, key
|
||||
else:
|
||||
return default
|
||||
return self.d[key]
|
||||
|
||||
def __delitem__(self, key, default=None, strictkey=True):
|
||||
"""
|
||||
@param strictkey: True if you want a KeyError in the case that
|
||||
key is not there, False if you want a reference to default
|
||||
in the case that key is not there
|
||||
@param default: the object to return if key is not there; This
|
||||
is ignored if strictkey.
|
||||
|
||||
@return: the object removed or default if there is not item by
|
||||
that key and strictkey is False
|
||||
"""
|
||||
assert self._assert_invariants()
|
||||
if self.d.has_key(key):
|
||||
val = self.d.pop(key)
|
||||
i = bisect_left(self.l, (val, key,))
|
||||
while (self.l[i][0] is not val) or (self.l[i][1] is not key):
|
||||
i += 1
|
||||
self.l.pop(i)
|
||||
assert self._assert_invariants()
|
||||
return val
|
||||
elif strictkey:
|
||||
assert self._assert_invariants()
|
||||
raise KeyError, key
|
||||
else:
|
||||
assert self._assert_invariants()
|
||||
return default
|
||||
|
||||
def clear(self):
|
||||
assert self._assert_invariants()
|
||||
self.d.clear()
|
||||
del self.l[:]
|
||||
assert self._assert_invariants()
|
||||
|
||||
def update(self, otherdict):
|
||||
"""
|
||||
@return: self
|
||||
"""
|
||||
assert self._assert_invariants()
|
||||
for (k, v,) in otherdict.iteritems():
|
||||
self.insert(k, v)
|
||||
assert self._assert_invariants()
|
||||
return self
|
||||
|
||||
def has_key(self, key):
|
||||
assert self._assert_invariants()
|
||||
return self.d.has_key(key)
|
||||
|
||||
def popitem(self):
|
||||
if not self.l:
|
||||
raise KeyError, 'popitem(): dictionary is empty'
|
||||
le = self.l.pop(0)
|
||||
del self.d[le[1]]
|
||||
return (le[1], le[0],)
|
||||
|
||||
def pop(self, k, default=None, strictkey=False):
|
||||
if not self.d.has_key(k):
|
||||
if strictkey:
|
||||
raise KeyError, k
|
||||
else:
|
||||
return default
|
||||
v = self.d.pop(k)
|
||||
i = bisect_left(self.l, (v, k,))
|
||||
while (self.l[i][0] is not v) or (self.l[i][1] is not k):
|
||||
i += 1
|
||||
self.l.pop(i)
|
||||
return v
|
||||
|
||||
def pop_from_list(self, i=0):
|
||||
le = self.l.pop(i)
|
||||
del self.d[le[1]]
|
||||
return le[1]
|
||||
|
||||
class AuxValueDict(dict):
|
||||
"""I behave like a regular dict, but each key is associated with two
|
||||
values: the main value, and an auxilliary one. Setting the main value
|
||||
|
|
Loading…
Reference in New Issue