mirror of
https://github.com/Mikaela/Limnoria.git
synced 2024-11-26 20:59:27 +01:00
Add utils.structures.TruncatableSet.
This commit is contained in:
parent
7057112d2d
commit
94fbea6266
@ -454,5 +454,40 @@ class CacheDict(collections.MutableMapping):
|
|||||||
def __len__(self):
|
def __len__(self):
|
||||||
return len(self.d)
|
return len(self.d)
|
||||||
|
|
||||||
|
class TruncatableSet(collections.MutableSet):
|
||||||
|
"""A set that keeps track of the order of inserted elements so
|
||||||
|
the oldest can be removed."""
|
||||||
|
def __init__(self, iterable):
|
||||||
|
self._ordered_items = list(iterable)
|
||||||
|
self._items = set(self._ordered_items)
|
||||||
|
def __contains__(self, item):
|
||||||
|
return item in self._items
|
||||||
|
def __iter__(self):
|
||||||
|
return iter(self._items)
|
||||||
|
def __len__(self):
|
||||||
|
return len(self._items)
|
||||||
|
def add(self, item):
|
||||||
|
if item not in self._items:
|
||||||
|
self._items.add(item)
|
||||||
|
self._ordered_items.append(item)
|
||||||
|
def discard(self, item):
|
||||||
|
self._items.discard(item)
|
||||||
|
self._ordered_items.remove(item)
|
||||||
|
def truncate(self, size):
|
||||||
|
assert size >= 0
|
||||||
|
removed_size = len(self)-size
|
||||||
|
# I make two different cases depending on removed_size<size
|
||||||
|
# in order to make if faster if one is significantly bigger than the
|
||||||
|
# other.
|
||||||
|
if removed_size <= 0:
|
||||||
|
return
|
||||||
|
elif removed_size < size:
|
||||||
|
# If there are more kept items than removed items
|
||||||
|
for old_item in self._ordered_items[0:-size]:
|
||||||
|
self.discard(old_item)
|
||||||
|
self._ordered_items = self._ordered_items[-size:]
|
||||||
|
else:
|
||||||
|
self._ordered_items = self._ordered_items[-size:]
|
||||||
|
self._items = set(self._ordered_items)
|
||||||
|
|
||||||
# vim:set shiftwidth=4 softtabstop=4 expandtab textwidth=79:
|
# vim:set shiftwidth=4 softtabstop=4 expandtab textwidth=79:
|
||||||
|
@ -1133,6 +1133,26 @@ class TestCacheDict(SupyTestCase):
|
|||||||
self.failUnless(i in d)
|
self.failUnless(i in d)
|
||||||
self.failUnless(d[i] == i)
|
self.failUnless(d[i] == i)
|
||||||
|
|
||||||
|
class TestTruncatableSet(SupyTestCase):
|
||||||
|
def testBasics(self):
|
||||||
|
s = TruncatableSet(['foo', 'bar', 'baz', 'qux'])
|
||||||
|
self.assertEqual(s, {'foo', 'bar', 'baz', 'qux'})
|
||||||
|
self.failUnless('foo' in s)
|
||||||
|
self.failUnless('bar' in s)
|
||||||
|
self.failIf('quux' in s)
|
||||||
|
s.discard('baz')
|
||||||
|
self.failUnless('foo' in s)
|
||||||
|
self.failIf('baz' in s)
|
||||||
|
s.add('quux')
|
||||||
|
self.failUnless('quux' in s)
|
||||||
|
|
||||||
|
def testTruncate(self):
|
||||||
|
s = TruncatableSet(['foo', 'bar'])
|
||||||
|
s.add('baz')
|
||||||
|
s.add('qux')
|
||||||
|
s.truncate(3)
|
||||||
|
self.assertEqual(s, {'bar', 'baz', 'qux'})
|
||||||
|
|
||||||
|
|
||||||
# vim:set shiftwidth=4 softtabstop=4 expandtab textwidth=79:
|
# vim:set shiftwidth=4 softtabstop=4 expandtab textwidth=79:
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user