Guest User

xOrderedDict

a guest
Apr 25th, 2012
149
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 4.87 KB | None | 0 0
  1. #!/usr/bin/python
  2.  
  3. from _abcoll import *
  4. import types, collections
  5.  
  6. class xOrderedDict(dict, MutableMapping):
  7.     # dict object are NOT accepted as arguments because they are not order-preserving
  8.     # accepting OrderedDict, xOrderedDict, list of tuples
  9.     def __init__(self, *args):
  10.         self._K = []
  11.         if args: self.update(*args)
  12.     def __setitem__(self, key, value):
  13.         if key not in self: self._K.append(key)
  14.         dict.__setitem__(self, key, value)
  15.     def __delitem__(self, keys):
  16.         self.delete(*keys)
  17.     def __eq__(self, other):
  18.         if not isinstance(other, xOrderedDict): return False
  19.         if not MutableMapping.__eq__(self, other): return False
  20.         return self._K == other._K
  21.     def __ne__(self, other): return not self.__eq__(other)
  22.     def __iter__(self):
  23.         for key in self._K: yield key
  24.     def _get_before_index(self, before):
  25.         if before == [0]: return 0
  26.         elif before == [-1]: return -1
  27.         return self.indexof(before)
  28.     def _rawlistfromargs(self, *args):
  29.         raw = xOrderedDict()
  30.         for a in args:    
  31.             if isinstance(a, (types.TupleType, types.ListType)):
  32.                 for e in a: raw[e] = None
  33.             else: raw[a] = None
  34.         return raw
  35.     def _rawdictfromargs(self, *args):
  36.         raw = xOrderedDict()
  37.         for a in args:    
  38.             if isinstance(a, (collections.OrderedDict, xOrderedDict)): raw.update([ (k,v) for k,v in a.iteritems() ])
  39.             elif isinstance(a, types.ListType):
  40.                 for e in a: raw[e[0]] = e[1]
  41.             elif isinstance(a, types.TupleType): raw[a[0]] = a[1]
  42.             else: raise TypeError('Unsupported type: ' + str(type(a)))
  43.         return raw
  44.     def __repr__(self):
  45.         if not self: return '{}()'.format(self.__class__.__name__)
  46.         return '{}({!r})'.format(self.__class__.__name__, self.items())
  47.        
  48.     popitem = MutableMapping.popitem
  49.     pop = MutableMapping.pop
  50.     keys = MutableMapping.keys
  51.     values = MutableMapping.values
  52.     items = MutableMapping.items
  53.     iterkeys = MutableMapping.iterkeys
  54.     itervalues = MutableMapping.itervalues
  55.     iteritems = MutableMapping.iteritems
  56.     setdefault = MutableMapping.setdefault
  57.  
  58.     def clear(self):
  59.         dict.clear(self)
  60.         self._K = []
  61.     def indexof(self, key, *default):
  62.         if key in self: return self._K.index(key)
  63.         if len(default) > 1: raise AttributeError('indexof: extra argument(s) after [default]')
  64.         if not default: raise KeyError('[{0}] is not a valid key'.format(repr(key)))
  65.         else: return default[0]
  66.     def keyof(self, index, *default):
  67.         # index == -1: last key
  68.         if not isinstance(index, types.IntType): raise TypeError('list indices must be integers, not {0}'.format(type(index).__name__))
  69.         if index == -1: index = len(self._K) - 1
  70.         if index >=0 and index < len(self._K): return self._K[index]
  71.         if len(default) > 1: raise AttributeError('keyof: extra argument(s) after [default]')
  72.         if not default: raise IndexError('index ({0}) out of range'.format(index))
  73.         else: return default[0]
  74.     def update(self, *args):
  75.         MutableMapping.update(self, self._rawdictfromargs(*args))
  76.     def copy(self): return xOrderedDict(self)
  77.     def delete(self, *args):
  78.         raw = self._rawlistfromargs(*args)
  79.         unknowns = set(raw) - set(self)
  80.         if unknowns: raise KeyError('Invalid key(s): {!r}'.format(list(unknowns)))
  81.         for key in raw:
  82.             dict.__delitem__(self, key)
  83.             self._K.remove(key)
  84.     def insert(self, before, *args):
  85.         # if before is [-1] - append item(s) to end, if [0] - insert into beginning
  86.         idx = self._get_before_index(before)
  87.         raw = self._rawdictfromargs(*args)
  88.         intersect = set(self) & set(raw)
  89.         if intersect: raise KeyError('Duplicate key(s): {!r}'.format(list(intersect)))
  90.         for k,v in raw.iteritems():
  91.             dict.__setitem__(self, k, v)
  92.             if idx != -1:
  93.                 self._K.insert(idx, k)
  94.                 idx += 1
  95.             else: self._K.append(k)
  96.     def move(self, before, *args):
  97.         # if before is [-1] - move item(s) to end, if [0] - move into beginning
  98.         idx = self._get_before_index(before)
  99.         raw = self._rawlistfromargs(*args)
  100.         unknowns = set(raw) - set(self)
  101.         if unknowns: raise KeyError('Invalid key(s): {!r}'.format(list(unknowns)))
  102.         if idx != -1 and idx in [ self._K.index(k) for k in raw.iterkeys() ]:
  103.             raise KeyError('anchor element can not be moved')    
  104.         delta = 0
  105.         for k in raw.iterkeys():
  106.             i = self._K.index(k)
  107.             if idx != -1:
  108.                 if i < idx + delta: delta -= 1
  109.             del self._K[i]
  110.             if idx != -1:
  111.                 self._K.insert(idx+delta, k)
  112.                 delta += 1
  113.             else: self._K.append(k)
Advertisement
Add Comment
Please, Sign In to add comment