Home | History | Annotate | Download | only in simplejson
      1 """Drop-in replacement for collections.OrderedDict by Raymond Hettinger
      2 
      3 http://code.activestate.com/recipes/576693/
      4 
      5 """
      6 from UserDict import DictMixin
      7 
      8 # Modified from original to support Python 2.4, see
      9 # http://code.google.com/p/simplejson/issues/detail?id=53
     10 try:
     11     all
     12 except NameError:
     13     def all(seq):
     14         for elem in seq:
     15             if not elem:
     16                 return False
     17         return True
     18 
     19 class OrderedDict(dict, DictMixin):
     20 
     21     def __init__(self, *args, **kwds):
     22         if len(args) > 1:
     23             raise TypeError('expected at most 1 arguments, got %d' % len(args))
     24         try:
     25             self.__end
     26         except AttributeError:
     27             self.clear()
     28         self.update(*args, **kwds)
     29 
     30     def clear(self):
     31         self.__end = end = []
     32         end += [None, end, end]         # sentinel node for doubly linked list
     33         self.__map = {}                 # key --> [key, prev, next]
     34         dict.clear(self)
     35 
     36     def __setitem__(self, key, value):
     37         if key not in self:
     38             end = self.__end
     39             curr = end[1]
     40             curr[2] = end[1] = self.__map[key] = [key, curr, end]
     41         dict.__setitem__(self, key, value)
     42 
     43     def __delitem__(self, key):
     44         dict.__delitem__(self, key)
     45         key, prev, next = self.__map.pop(key)
     46         prev[2] = next
     47         next[1] = prev
     48 
     49     def __iter__(self):
     50         end = self.__end
     51         curr = end[2]
     52         while curr is not end:
     53             yield curr[0]
     54             curr = curr[2]
     55 
     56     def __reversed__(self):
     57         end = self.__end
     58         curr = end[1]
     59         while curr is not end:
     60             yield curr[0]
     61             curr = curr[1]
     62 
     63     def popitem(self, last=True):
     64         if not self:
     65             raise KeyError('dictionary is empty')
     66         # Modified from original to support Python 2.4, see
     67         # http://code.google.com/p/simplejson/issues/detail?id=53
     68         if last:
     69             key = reversed(self).next()
     70         else:
     71             key = iter(self).next()
     72         value = self.pop(key)
     73         return key, value
     74 
     75     def __reduce__(self):
     76         items = [[k, self[k]] for k in self]
     77         tmp = self.__map, self.__end
     78         del self.__map, self.__end
     79         inst_dict = vars(self).copy()
     80         self.__map, self.__end = tmp
     81         if inst_dict:
     82             return (self.__class__, (items,), inst_dict)
     83         return self.__class__, (items,)
     84 
     85     def keys(self):
     86         return list(self)
     87 
     88     setdefault = DictMixin.setdefault
     89     update = DictMixin.update
     90     pop = DictMixin.pop
     91     values = DictMixin.values
     92     items = DictMixin.items
     93     iterkeys = DictMixin.iterkeys
     94     itervalues = DictMixin.itervalues
     95     iteritems = DictMixin.iteritems
     96 
     97     def __repr__(self):
     98         if not self:
     99             return '%s()' % (self.__class__.__name__,)
    100         return '%s(%r)' % (self.__class__.__name__, self.items())
    101 
    102     def copy(self):
    103         return self.__class__(self)
    104 
    105     @classmethod
    106     def fromkeys(cls, iterable, value=None):
    107         d = cls()
    108         for key in iterable:
    109             d[key] = value
    110         return d
    111 
    112     def __eq__(self, other):
    113         if isinstance(other, OrderedDict):
    114             return len(self)==len(other) and \
    115                    all(p==q for p, q in  zip(self.items(), other.items()))
    116         return dict.__eq__(self, other)
    117 
    118     def __ne__(self, other):
    119         return not self == other
    120