+++ /dev/null
-# Copyright (c) 2006-2009 Nathan Binkert <nate@binkert.org>
-# All rights reserved.
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions are
-# met: redistributions of source code must retain the above copyright
-# notice, this list of conditions and the following disclaimer;
-# redistributions in binary form must reproduce the above copyright
-# notice, this list of conditions and the following disclaimer in the
-# documentation and/or other materials provided with the distribution;
-# neither the name of the copyright holders nor the names of its
-# contributors may be used to endorse or promote products derived from
-# this software without specific prior written permission.
-#
-# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-from __future__ import print_function
-from __future__ import absolute_import
-
-from bisect import bisect_left, bisect_right
-
-class SortedDict(dict):
- def _get_sorted(self):
- return getattr(self, '_sorted', sorted)
- def _set_sorted(self, val):
- self._sorted = val
- self._del_keys()
- sorted = property(_get_sorted, _set_sorted)
-
- @property
- def _keys(self):
- try:
- return self._sorted_keys
- except AttributeError:
- _sorted_keys = self.sorted(dict.keys(self))
- self._sorted_keys = _sorted_keys
- return _sorted_keys
-
- def _left_eq(self, key):
- index = self._left_ge(self, key)
- if self._keys[index] != key:
- raise KeyError(key)
- return index
-
- def _right_eq(self, key):
- index = self._right_le(self, key)
- if self._keys[index] != key:
- raise KeyError(key)
- return index
-
- def _right_lt(self, key):
- index = bisect_left(self._keys, key)
- if index:
- return index - 1
- raise KeyError(key)
-
- def _right_le(self, key):
- index = bisect_right(self._keys, key)
- if index:
- return index - 1
- raise KeyError(key)
-
- def _left_gt(self, key):
- index = bisect_right(self._keys, key)
- if index != len(self._keys):
- return index
- raise KeyError(key)
-
- def _left_ge(self, key):
- index = bisect_left(self._keys, key)
- if index != len(self._keys):
- return index
- raise KeyError(key)
-
- def _del_keys(self):
- try:
- del self._sorted_keys
- except AttributeError:
- pass
-
- def __repr__(self):
- return 'SortedDict({%s})' % ', '.join('%r: %r' % item
- for item in self.items())
- def __setitem__(self, key, item):
- dict.__setitem__(self, key, item)
- self._del_keys()
-
- def __delitem__(self, key):
- dict.__delitem__(self, key)
- self._del_keys()
-
- def clear(self):
- self.data.clear()
- self._del_keys()
-
- def copy(self):
- t = type(self)
- return t(self)
-
- def keys(self):
- return self._keys
-
- def values(self):
- for k in self._keys:
- yield self[k]
-
- def items(self):
- for k in self._keys:
- yield k, self[k]
-
- def keyrange(self, start=None, end=None, inclusive=False):
- if start is not None:
- start = self._left_ge(start)
-
- if end is not None:
- if inclusive:
- end = self._right_le(end)
- else:
- end = self._right_lt(end)
-
- return iter(self._keys[start:end+1])
-
- def valuerange(self, *args, **kwargs):
- for k in self.keyrange(*args, **kwargs):
- yield self[k]
-
- def itemrange(self, *args, **kwargs):
- for k in self.keyrange(*args, **kwargs):
- yield k, self[k]
-
- def update(self, *args, **kwargs):
- dict.update(self, *args, **kwargs)
- self._del_keys()
-
- def setdefault(self, key, _failobj=None):
- try:
- return self[key]
- except KeyError:
- self[key] = _failobj
-
- def pop(self, key, *args):
- try:
- dict.pop(self, key)
- self._del_keys()
- except KeyError:
- if not args:
- raise
- return args[0]
-
- def popitem(self):
- try:
- key = self._keys[0]
- self._del_keys()
- except IndexError:
- raise KeyError('popitem(): dictionary is empty')
- else:
- return key, dict.pop(self, key)
-
- @classmethod
- def fromkeys(cls, seq, value=None):
- d = cls()
- for key in seq:
- d[key] = value
- return d
-
-if __name__ == '__main__':
- def display(d):
- print(d)
- print(list(d.keys()))
- print(list(d.keys()))
- print(list(d.values()))
- print(list(d.values()))
- print(list(d.items()))
- print(list(d.items()))
-
- d = SortedDict(x=24,e=5,j=4,b=2,z=26,d=4)
- display(d)
-
- print('popitem', d.popitem())
- display(d)
-
- print('pop j')
- d.pop('j')
- display(d)
-
- d.setdefault('a', 1)
- d.setdefault('g', 7)
- d.setdefault('_')
- display(d)
-
- d.update({'b' : 2, 'h' : 8})
- display(d)
-
- del d['x']
- display(d)
- d['y'] = 26
- display(d)
-
- print(repr(d))
-
- print(d.copy())
-
- for k,v in d.itemrange('d', 'z', inclusive=True):
- print(k, v)