Try to import Python's OrderedDict

There is an OrderedDict in Python 2.7+.
The try order is now as follows:
* OrderedDict from Python's collections module
* OrderedDict from the jsonencode module (dependency)
* OrderedDict from the ordereddict module (pypi package)
* our own OrderedDict
This commit is contained in:
Laurent Bachelier 2011-04-23 23:44:45 +02:00
commit 5ac2de43d7

View file

@ -19,108 +19,114 @@
try: try:
from ordereddict import OrderedDict from collections import OrderedDict
except: except ImportError:
## {{{ http://code.activestate.com/recipes/576693/ (r6) try:
from UserDict import DictMixin from simplejson import OrderedDict
except ImportError:
try:
from ordereddict import OrderedDict
except ImportError:
## {{{ http://code.activestate.com/recipes/576693/ (r6)
from UserDict import DictMixin
class OrderedDict(dict, DictMixin): class OrderedDict(dict, DictMixin):
def __init__(self, *args, **kwds): def __init__(self, *args, **kwds):
if len(args) > 1: if len(args) > 1:
raise TypeError('expected at most 1 arguments, got %d' % len(args)) raise TypeError('expected at most 1 arguments, got %d' % len(args))
try: try:
self.__end self.__end
except AttributeError: except AttributeError:
self.clear() self.clear()
self.update(*args, **kwds) self.update(*args, **kwds)
def clear(self): def clear(self):
self.__end = end = [] self.__end = end = []
end += [None, end, end] # sentinel node for doubly linked list end += [None, end, end] # sentinel node for doubly linked list
self.__map = {} # key --> [key, prev, next] self.__map = {} # key --> [key, prev, next]
dict.clear(self) dict.clear(self)
def __setitem__(self, key, value): def __setitem__(self, key, value):
if key not in self: if key not in self:
end = self.__end end = self.__end
curr = end[1] curr = end[1]
curr[2] = end[1] = self.__map[key] = [key, curr, end] curr[2] = end[1] = self.__map[key] = [key, curr, end]
dict.__setitem__(self, key, value) dict.__setitem__(self, key, value)
def __delitem__(self, key): def __delitem__(self, key):
dict.__delitem__(self, key) dict.__delitem__(self, key)
key, prev, next = self.__map.pop(key) key, prev, next = self.__map.pop(key)
prev[2] = next prev[2] = next
next[1] = prev next[1] = prev
def __iter__(self): def __iter__(self):
end = self.__end end = self.__end
curr = end[2] curr = end[2]
while curr is not end: while curr is not end:
yield curr[0] yield curr[0]
curr = curr[2] curr = curr[2]
def __reversed__(self): def __reversed__(self):
end = self.__end end = self.__end
curr = end[1] curr = end[1]
while curr is not end: while curr is not end:
yield curr[0] yield curr[0]
curr = curr[1] curr = curr[1]
def popitem(self, last=True): def popitem(self, last=True):
if not self: if not self:
raise KeyError('dictionary is empty') raise KeyError('dictionary is empty')
if last: if last:
key = reversed(self).next() key = reversed(self).next()
else: else:
key = iter(self).next() key = iter(self).next()
value = self.pop(key) value = self.pop(key)
return key, value return key, value
def __reduce__(self): def __reduce__(self):
items = [[k, self[k]] for k in self] items = [[k, self[k]] for k in self]
tmp = self.__map, self.__end tmp = self.__map, self.__end
del self.__map, self.__end del self.__map, self.__end
inst_dict = vars(self).copy() inst_dict = vars(self).copy()
self.__map, self.__end = tmp self.__map, self.__end = tmp
if inst_dict: if inst_dict:
return (self.__class__, (items,), inst_dict) return (self.__class__, (items,), inst_dict)
return self.__class__, (items,) return self.__class__, (items,)
def keys(self): def keys(self):
return list(self) return list(self)
setdefault = DictMixin.setdefault setdefault = DictMixin.setdefault
update = DictMixin.update update = DictMixin.update
pop = DictMixin.pop pop = DictMixin.pop
values = DictMixin.values values = DictMixin.values
items = DictMixin.items items = DictMixin.items
iterkeys = DictMixin.iterkeys iterkeys = DictMixin.iterkeys
itervalues = DictMixin.itervalues itervalues = DictMixin.itervalues
iteritems = DictMixin.iteritems iteritems = DictMixin.iteritems
def __repr__(self): def __repr__(self):
if not self: if not self:
return '%s()' % (self.__class__.__name__,) return '%s()' % (self.__class__.__name__,)
return '%s(%r)' % (self.__class__.__name__, self.items()) return '%s(%r)' % (self.__class__.__name__, self.items())
def copy(self): def copy(self):
return self.__class__(self) return self.__class__(self)
@classmethod @classmethod
def fromkeys(cls, iterable, value=None): def fromkeys(cls, iterable, value=None):
d = cls() d = cls()
for key in iterable: for key in iterable:
d[key] = value d[key] = value
return d return d
def __eq__(self, other): def __eq__(self, other):
if isinstance(other, OrderedDict): if isinstance(other, OrderedDict):
return len(self)==len(other) and self.items() == other.items() return len(self)==len(other) and self.items() == other.items()
return dict.__eq__(self, other) return dict.__eq__(self, other)
def __ne__(self, other): def __ne__(self, other):
return not self == other return not self == other
## end of http://code.activestate.com/recipes/576693/ }}} ## end of http://code.activestate.com/recipes/576693/ }}}