|
@@ -1,286 +0,0 @@
|
|
|
-# _compat.py -- For dealing with python2.4 oddness
|
|
|
-# Copyright (C) 2008 Canonical Ltd.
|
|
|
-#
|
|
|
-# This program is free software; you can redistribute it and/or
|
|
|
-# modify it under the terms of the GNU General Public License
|
|
|
-# as published by the Free Software Foundation; version 2
|
|
|
-# of the License or (at your option) a later version.
|
|
|
-#
|
|
|
-# This program is distributed in the hope that it will be useful,
|
|
|
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
-# GNU General Public License for more details.
|
|
|
-#
|
|
|
-# You should have received a copy of the GNU General Public License
|
|
|
-# along with this program; if not, write to the Free Software
|
|
|
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
|
|
-# MA 02110-1301, USA.
|
|
|
-
|
|
|
-"""Misc utilities to work with python <2.7.
|
|
|
-
|
|
|
-These utilities can all be deleted when dulwich decides it wants to stop
|
|
|
-support for python <2.7.
|
|
|
-"""
|
|
|
-
|
|
|
-# Backport of OrderedDict() class that runs on Python 2.4, 2.5, 2.6, 2.7 and
|
|
|
-# pypy. Passes Python2.7's test suite and incorporates all the latest updates.
|
|
|
-# Copyright (C) Raymond Hettinger, MIT license
|
|
|
-
|
|
|
-try:
|
|
|
- from thread import get_ident as _get_ident
|
|
|
-except ImportError:
|
|
|
- from dummy_thread import get_ident as _get_ident
|
|
|
-
|
|
|
-try:
|
|
|
- from _abcoll import KeysView, ValuesView, ItemsView
|
|
|
-except ImportError:
|
|
|
- pass
|
|
|
-
|
|
|
-class OrderedDict(dict):
|
|
|
- 'Dictionary that remembers insertion order'
|
|
|
- # An inherited dict maps keys to values.
|
|
|
- # The inherited dict provides __getitem__, __len__, __contains__, and get.
|
|
|
- # The remaining methods are order-aware.
|
|
|
- # Big-O running times for all methods are the same as for regular
|
|
|
- # dictionaries.
|
|
|
-
|
|
|
- # The internal self.__map dictionary maps keys to links in a doubly linked
|
|
|
- # list. The circular doubly linked list starts and ends with a sentinel
|
|
|
- # element. The sentinel element never gets deleted (this simplifies the
|
|
|
- # algorithm). Each link is stored as a list of length three: [PREV, NEXT,
|
|
|
- # KEY].
|
|
|
-
|
|
|
- def __init__(self, *args, **kwds):
|
|
|
- '''Initialize an ordered dictionary. Signature is the same as for
|
|
|
- regular dictionaries, but keyword arguments are not recommended
|
|
|
- because their insertion order is arbitrary.
|
|
|
-
|
|
|
- '''
|
|
|
- if len(args) > 1:
|
|
|
- raise TypeError('expected at most 1 arguments, got %d' % len(args))
|
|
|
- try:
|
|
|
- self.__root
|
|
|
- except AttributeError:
|
|
|
- self.__root = root = [] # sentinel node
|
|
|
- root[:] = [root, root, None]
|
|
|
- self.__map = {}
|
|
|
- self.__update(*args, **kwds)
|
|
|
-
|
|
|
- def __setitem__(self, key, value, dict_setitem=dict.__setitem__):
|
|
|
- 'od.__setitem__(i, y) <==> od[i]=y'
|
|
|
- # Setting a new item creates a new link which goes at the end of the
|
|
|
- # linked list, and the inherited dictionary is updated with the new
|
|
|
- # key/value pair.
|
|
|
- if key not in self:
|
|
|
- root = self.__root
|
|
|
- last = root[0]
|
|
|
- last[1] = root[0] = self.__map[key] = [last, root, key]
|
|
|
- dict_setitem(self, key, value)
|
|
|
-
|
|
|
- def __delitem__(self, key, dict_delitem=dict.__delitem__):
|
|
|
- 'od.__delitem__(y) <==> del od[y]'
|
|
|
- # Deleting an existing item uses self.__map to find the link which is
|
|
|
- # then removed by updating the links in the predecessor and successor
|
|
|
- # nodes.
|
|
|
- dict_delitem(self, key)
|
|
|
- link_prev, link_next, key = self.__map.pop(key)
|
|
|
- link_prev[1] = link_next
|
|
|
- link_next[0] = link_prev
|
|
|
-
|
|
|
- def __iter__(self):
|
|
|
- 'od.__iter__() <==> iter(od)'
|
|
|
- root = self.__root
|
|
|
- curr = root[1]
|
|
|
- while curr is not root:
|
|
|
- yield curr[2]
|
|
|
- curr = curr[1]
|
|
|
-
|
|
|
- def __reversed__(self):
|
|
|
- 'od.__reversed__() <==> reversed(od)'
|
|
|
- root = self.__root
|
|
|
- curr = root[0]
|
|
|
- while curr is not root:
|
|
|
- yield curr[2]
|
|
|
- curr = curr[0]
|
|
|
-
|
|
|
- def clear(self):
|
|
|
- 'od.clear() -> None. Remove all items from od.'
|
|
|
- try:
|
|
|
- for node in self.__map.itervalues():
|
|
|
- del node[:]
|
|
|
- root = self.__root
|
|
|
- root[:] = [root, root, None]
|
|
|
- self.__map.clear()
|
|
|
- except AttributeError:
|
|
|
- pass
|
|
|
- dict.clear(self)
|
|
|
-
|
|
|
- def popitem(self, last=True):
|
|
|
- """od.popitem() -> (k, v), return and remove a (key, value) pair.
|
|
|
- Pairs are returned in LIFO order if last is true or FIFO order if false.
|
|
|
-
|
|
|
- """
|
|
|
- if not self:
|
|
|
- raise KeyError('dictionary is empty')
|
|
|
- root = self.__root
|
|
|
- if last:
|
|
|
- link = root[0]
|
|
|
- link_prev = link[0]
|
|
|
- link_prev[1] = root
|
|
|
- root[0] = link_prev
|
|
|
- else:
|
|
|
- link = root[1]
|
|
|
- link_next = link[1]
|
|
|
- root[1] = link_next
|
|
|
- link_next[0] = root
|
|
|
- key = link[2]
|
|
|
- del self.__map[key]
|
|
|
- value = dict.pop(self, key)
|
|
|
- return key, value
|
|
|
-
|
|
|
- # -- the following methods do not depend on the internal structure --
|
|
|
-
|
|
|
- def keys(self):
|
|
|
- """'od.keys() -> list of keys in od"""
|
|
|
- return list(self)
|
|
|
-
|
|
|
- def values(self):
|
|
|
- """od.values() -> list of values in od"""
|
|
|
- return [self[key] for key in self]
|
|
|
-
|
|
|
- def items(self):
|
|
|
- """od.items() -> list of (key, value) pairs in od"""
|
|
|
- return [(key, self[key]) for key in self]
|
|
|
-
|
|
|
- def iterkeys(self):
|
|
|
- """od.iterkeys() -> an iterator over the keys in od"""
|
|
|
- return iter(self)
|
|
|
-
|
|
|
- def itervalues(self):
|
|
|
- """od.itervalues -> an iterator over the values in od"""
|
|
|
- for k in self:
|
|
|
- yield self[k]
|
|
|
-
|
|
|
- def iteritems(self):
|
|
|
- """od.iteritems -> an iterator over the (key, value) items in od"""
|
|
|
- for k in self:
|
|
|
- yield (k, self[k])
|
|
|
-
|
|
|
- def update(*args, **kwds):
|
|
|
- """od.update(E, F) -> None. Update od from dict/iterable E and F.
|
|
|
-
|
|
|
- If E is a dict instance, does: for k in E: od[k] = E[k]
|
|
|
- If E has a .keys() method, does: for k in E.keys(): od[k] = E[k]
|
|
|
- Or if E is an iterable of items, does: for k, v in E: od[k] = v
|
|
|
- In either case, this is followed by: for k, v in F.items(): od[k] = v
|
|
|
- """
|
|
|
- if len(args) > 2:
|
|
|
- raise TypeError('update() takes at most 2 positional '
|
|
|
- 'arguments (%d given)' % (len(args),))
|
|
|
- elif not args:
|
|
|
- raise TypeError('update() takes at least 1 argument (0 given)')
|
|
|
- self = args[0]
|
|
|
- # Make progressively weaker assumptions about "other"
|
|
|
- other = ()
|
|
|
- if len(args) == 2:
|
|
|
- other = args[1]
|
|
|
- if isinstance(other, dict):
|
|
|
- for key in other:
|
|
|
- self[key] = other[key]
|
|
|
- elif hasattr(other, 'keys'):
|
|
|
- for key in other.keys():
|
|
|
- self[key] = other[key]
|
|
|
- else:
|
|
|
- for key, value in other:
|
|
|
- self[key] = value
|
|
|
- for key, value in kwds.items():
|
|
|
- self[key] = value
|
|
|
-
|
|
|
- __update = update # let subclasses override update without breaking
|
|
|
- # __init__
|
|
|
-
|
|
|
- __marker = object()
|
|
|
-
|
|
|
- def pop(self, key, default=__marker):
|
|
|
- """od.pop(k[,d]) -> v, remove specified key and return the corresponding value.
|
|
|
- If key is not found, d is returned if given, otherwise KeyError is raised.
|
|
|
-
|
|
|
- """
|
|
|
- if key in self:
|
|
|
- result = self[key]
|
|
|
- del self[key]
|
|
|
- return result
|
|
|
- if default is self.__marker:
|
|
|
- raise KeyError(key)
|
|
|
- return default
|
|
|
-
|
|
|
- def setdefault(self, key, default=None):
|
|
|
- 'od.setdefault(k[,d]) -> od.get(k,d), also set od[k]=d if k not in od'
|
|
|
- if key in self:
|
|
|
- return self[key]
|
|
|
- self[key] = default
|
|
|
- return default
|
|
|
-
|
|
|
- def __repr__(self, _repr_running={}):
|
|
|
- 'od.__repr__() <==> repr(od)'
|
|
|
- call_key = id(self), _get_ident()
|
|
|
- if call_key in _repr_running:
|
|
|
- return '...'
|
|
|
- _repr_running[call_key] = 1
|
|
|
- try:
|
|
|
- if not self:
|
|
|
- return '%s()' % (self.__class__.__name__,)
|
|
|
- return '%s(%r)' % (self.__class__.__name__, self.items())
|
|
|
- finally:
|
|
|
- del _repr_running[call_key]
|
|
|
-
|
|
|
- def __reduce__(self):
|
|
|
- 'Return state information for pickling'
|
|
|
- items = [[k, self[k]] for k in self]
|
|
|
- inst_dict = vars(self).copy()
|
|
|
- for k in vars(OrderedDict()):
|
|
|
- inst_dict.pop(k, None)
|
|
|
- if inst_dict:
|
|
|
- return (self.__class__, (items,), inst_dict)
|
|
|
- return self.__class__, (items,)
|
|
|
-
|
|
|
- def copy(self):
|
|
|
- 'od.copy() -> a shallow copy of od'
|
|
|
- return self.__class__(self)
|
|
|
-
|
|
|
- @classmethod
|
|
|
- def fromkeys(cls, iterable, value=None):
|
|
|
- '''OD.fromkeys(S[, v]) -> New ordered dictionary with keys from S
|
|
|
- and values equal to v (which defaults to None).
|
|
|
-
|
|
|
- '''
|
|
|
- d = cls()
|
|
|
- for key in iterable:
|
|
|
- d[key] = value
|
|
|
- return d
|
|
|
-
|
|
|
- def __eq__(self, other):
|
|
|
- '''od.__eq__(y) <==> od==y. Comparison to another OD is order-sensitive
|
|
|
- while comparison to a regular mapping is order-insensitive.
|
|
|
-
|
|
|
- '''
|
|
|
- if isinstance(other, OrderedDict):
|
|
|
- return len(self)==len(other) and self.items() == other.items()
|
|
|
- return dict.__eq__(self, other)
|
|
|
-
|
|
|
- def __ne__(self, other):
|
|
|
- return not self == other
|
|
|
-
|
|
|
- # -- the following methods are only used in Python 2.7 --
|
|
|
-
|
|
|
- def viewkeys(self):
|
|
|
- "od.viewkeys() -> a set-like object providing a view on od's keys"
|
|
|
- return KeysView(self)
|
|
|
-
|
|
|
- def viewvalues(self):
|
|
|
- "od.viewvalues() -> an object providing a view on od's values"
|
|
|
- return ValuesView(self)
|
|
|
-
|
|
|
- def viewitems(self):
|
|
|
- "od.viewitems() -> a set-like object providing a view on od's items"
|
|
|
- return ItemsView(self)
|