Statistics
| Branch: | Tag: | Revision:

root / kamaki / clients / utils / ordereddict.py @ c6ebe715

History | View | Annotate | Download (10.2 kB)

1 e3f01d64 Stavros Sachtouris
# Copyright 2012-2013 GRNET S.A. All rights reserved.
2 b4368e33 Stavros Sachtouris
#
3 b4368e33 Stavros Sachtouris
# Redistribution and use in source and binary forms, with or
4 b4368e33 Stavros Sachtouris
# without modification, are permitted provided that the following
5 b4368e33 Stavros Sachtouris
# conditions are met:
6 b4368e33 Stavros Sachtouris
#
7 b4368e33 Stavros Sachtouris
#   1. Redistributions of source code must retain the above
8 b4368e33 Stavros Sachtouris
#      copyright notice, this list of conditions and the following
9 b4368e33 Stavros Sachtouris
#      disclaimer.
10 b4368e33 Stavros Sachtouris
#
11 b4368e33 Stavros Sachtouris
#   2. Redistributions in binary form must reproduce the above
12 b4368e33 Stavros Sachtouris
#      copyright notice, this list of conditions and the following
13 b4368e33 Stavros Sachtouris
#      disclaimer in the documentation and/or other materials
14 b4368e33 Stavros Sachtouris
#      provided with the distribution.
15 b4368e33 Stavros Sachtouris
#
16 b4368e33 Stavros Sachtouris
# THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS
17 b4368e33 Stavros Sachtouris
# OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 b4368e33 Stavros Sachtouris
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19 b4368e33 Stavros Sachtouris
# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR
20 b4368e33 Stavros Sachtouris
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 b4368e33 Stavros Sachtouris
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 b4368e33 Stavros Sachtouris
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
23 b4368e33 Stavros Sachtouris
# USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
24 b4368e33 Stavros Sachtouris
# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 b4368e33 Stavros Sachtouris
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
26 b4368e33 Stavros Sachtouris
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27 b4368e33 Stavros Sachtouris
# POSSIBILITY OF SUCH DAMAGE.
28 b4368e33 Stavros Sachtouris
#
29 b4368e33 Stavros Sachtouris
# The views and conclusions contained in the software and
30 b4368e33 Stavros Sachtouris
# documentation are those of the authors and should not be
31 b4368e33 Stavros Sachtouris
# interpreted as representing official policies, either expressed
32 b4368e33 Stavros Sachtouris
# or implied, of GRNET S.A.
33 b4368e33 Stavros Sachtouris
34 b4368e33 Stavros Sachtouris
# Backport of OrderedDict() class that runs on Python 2.4, 2.5, 2.6, 2.7 and
35 b4368e33 Stavros Sachtouris
# pypy. Passes Python2.7's test suite and incorporates all the latest updates.
36 54069d1b Stavros Sachtouris
37 54069d1b Stavros Sachtouris
try:
38 54069d1b Stavros Sachtouris
    from thread import get_ident as _get_ident
39 54069d1b Stavros Sachtouris
except ImportError:
40 54069d1b Stavros Sachtouris
    from dummy_thread import get_ident as _get_ident
41 54069d1b Stavros Sachtouris
42 54069d1b Stavros Sachtouris
try:
43 54069d1b Stavros Sachtouris
    from _abcoll import KeysView, ValuesView, ItemsView
44 54069d1b Stavros Sachtouris
except ImportError:
45 54069d1b Stavros Sachtouris
    pass
46 54069d1b Stavros Sachtouris
47 54069d1b Stavros Sachtouris
48 54069d1b Stavros Sachtouris
class OrderedDict(dict):
49 6764f588 Stavros Sachtouris
    """Dictionary that remembers insertion order
50 6764f588 Stavros Sachtouris
    An inherited dict maps keys to values.
51 6764f588 Stavros Sachtouris
    The inherited dict provides __getitem__, __len__, __contains__, and get.
52 6764f588 Stavros Sachtouris
    The remaining methods are order-aware.
53 6764f588 Stavros Sachtouris
    Big-O running times for all methods are the same as for regular
54 6764f588 Stavros Sachtouris
    dictionaries.
55 6764f588 Stavros Sachtouris
    The internal self.__map dictionary maps keys to links in a doubly linked
56 6764f588 Stavros Sachtouris
    list.
57 6764f588 Stavros Sachtouris
    The circular doubly linked list starts and ends with a sentinel element.
58 6764f588 Stavros Sachtouris
    The sentinel element never gets deleted (this simplifies the algorithm).
59 6764f588 Stavros Sachtouris
    Each link is stored as a list of length three:  [PREV, NEXT, KEY].
60 6764f588 Stavros Sachtouris
    """
61 54069d1b Stavros Sachtouris
62 54069d1b Stavros Sachtouris
    def __init__(self, *args, **kwds):
63 54069d1b Stavros Sachtouris
        '''Initialize an ordered dictionary.  Signature is the same as for
64 54069d1b Stavros Sachtouris
        regular dictionaries, but keyword arguments are not recommended
65 54069d1b Stavros Sachtouris
        because their insertion order is arbitrary.
66 54069d1b Stavros Sachtouris

67 54069d1b Stavros Sachtouris
        '''
68 54069d1b Stavros Sachtouris
        if len(args) > 1:
69 54069d1b Stavros Sachtouris
            raise TypeError('expected at most 1 arguments, got %d' % len(args))
70 54069d1b Stavros Sachtouris
        try:
71 54069d1b Stavros Sachtouris
            self.__root
72 54069d1b Stavros Sachtouris
        except AttributeError:
73 54069d1b Stavros Sachtouris
            self.__root = root = []                     # sentinel node
74 54069d1b Stavros Sachtouris
            root[:] = [root, root, None]
75 54069d1b Stavros Sachtouris
            self.__map = {}
76 54069d1b Stavros Sachtouris
        self.__update(*args, **kwds)
77 54069d1b Stavros Sachtouris
78 54069d1b Stavros Sachtouris
    def __setitem__(self, key, value, dict_setitem=dict.__setitem__):
79 54069d1b Stavros Sachtouris
        'od.__setitem__(i, y) <==> od[i]=y'
80 b4368e33 Stavros Sachtouris
        # Setting a new item creates a new link which goes at the end of the
81 b4368e33 Stavros Sachtouris
        # linked
82 b4368e33 Stavros Sachtouris
        # list, and the inherited dictionary is updated with the new key/value
83 b4368e33 Stavros Sachtouris
        # pair.
84 54069d1b Stavros Sachtouris
        if key not in self:
85 54069d1b Stavros Sachtouris
            root = self.__root
86 54069d1b Stavros Sachtouris
            last = root[0]
87 54069d1b Stavros Sachtouris
            last[1] = root[0] = self.__map[key] = [last, root, key]
88 54069d1b Stavros Sachtouris
        dict_setitem(self, key, value)
89 54069d1b Stavros Sachtouris
90 54069d1b Stavros Sachtouris
    def __delitem__(self, key, dict_delitem=dict.__delitem__):
91 54069d1b Stavros Sachtouris
        'od.__delitem__(y) <==> del od[y]'
92 54069d1b Stavros Sachtouris
        # Deleting an existing item uses self.__map to find the link which is
93 b4368e33 Stavros Sachtouris
        # then removed by updating the links in the predecessor and successor
94 b4368e33 Stavros Sachtouris
        # nodes.
95 54069d1b Stavros Sachtouris
        dict_delitem(self, key)
96 54069d1b Stavros Sachtouris
        link_prev, link_next, key = self.__map.pop(key)
97 54069d1b Stavros Sachtouris
        link_prev[1] = link_next
98 54069d1b Stavros Sachtouris
        link_next[0] = link_prev
99 54069d1b Stavros Sachtouris
100 54069d1b Stavros Sachtouris
    def __iter__(self):
101 54069d1b Stavros Sachtouris
        'od.__iter__() <==> iter(od)'
102 54069d1b Stavros Sachtouris
        root = self.__root
103 54069d1b Stavros Sachtouris
        curr = root[1]
104 54069d1b Stavros Sachtouris
        while curr is not root:
105 54069d1b Stavros Sachtouris
            yield curr[2]
106 54069d1b Stavros Sachtouris
            curr = curr[1]
107 54069d1b Stavros Sachtouris
108 54069d1b Stavros Sachtouris
    def __reversed__(self):
109 54069d1b Stavros Sachtouris
        'od.__reversed__() <==> reversed(od)'
110 54069d1b Stavros Sachtouris
        root = self.__root
111 54069d1b Stavros Sachtouris
        curr = root[0]
112 54069d1b Stavros Sachtouris
        while curr is not root:
113 54069d1b Stavros Sachtouris
            yield curr[2]
114 54069d1b Stavros Sachtouris
            curr = curr[0]
115 54069d1b Stavros Sachtouris
116 54069d1b Stavros Sachtouris
    def clear(self):
117 54069d1b Stavros Sachtouris
        'od.clear() -> None.  Remove all items from od.'
118 54069d1b Stavros Sachtouris
        try:
119 54069d1b Stavros Sachtouris
            for node in self.__map.itervalues():
120 54069d1b Stavros Sachtouris
                del node[:]
121 54069d1b Stavros Sachtouris
            root = self.__root
122 54069d1b Stavros Sachtouris
            root[:] = [root, root, None]
123 54069d1b Stavros Sachtouris
            self.__map.clear()
124 54069d1b Stavros Sachtouris
        except AttributeError:
125 54069d1b Stavros Sachtouris
            pass
126 54069d1b Stavros Sachtouris
        dict.clear(self)
127 54069d1b Stavros Sachtouris
128 54069d1b Stavros Sachtouris
    def popitem(self, last=True):
129 6764f588 Stavros Sachtouris
        """od.popitem() -> (k, v), return and remove a (key, value) pair.
130 6764f588 Stavros Sachtouris
        Pairs are returned in LIFO order if last is true or FIFO order if
131 6764f588 Stavros Sachtouris
        false.
132 6764f588 Stavros Sachtouris
        """
133 54069d1b Stavros Sachtouris
134 54069d1b Stavros Sachtouris
        if not self:
135 54069d1b Stavros Sachtouris
            raise KeyError('dictionary is empty')
136 54069d1b Stavros Sachtouris
        root = self.__root
137 54069d1b Stavros Sachtouris
        if last:
138 54069d1b Stavros Sachtouris
            link = root[0]
139 54069d1b Stavros Sachtouris
            link_prev = link[0]
140 54069d1b Stavros Sachtouris
            link_prev[1] = root
141 54069d1b Stavros Sachtouris
            root[0] = link_prev
142 54069d1b Stavros Sachtouris
        else:
143 54069d1b Stavros Sachtouris
            link = root[1]
144 54069d1b Stavros Sachtouris
            link_next = link[1]
145 54069d1b Stavros Sachtouris
            root[1] = link_next
146 54069d1b Stavros Sachtouris
            link_next[0] = root
147 54069d1b Stavros Sachtouris
        key = link[2]
148 54069d1b Stavros Sachtouris
        del self.__map[key]
149 54069d1b Stavros Sachtouris
        value = dict.pop(self, key)
150 54069d1b Stavros Sachtouris
        return key, value
151 54069d1b Stavros Sachtouris
152 54069d1b Stavros Sachtouris
    # -- the following methods do not depend on the internal structure --
153 54069d1b Stavros Sachtouris
154 54069d1b Stavros Sachtouris
    def keys(self):
155 54069d1b Stavros Sachtouris
        'od.keys() -> list of keys in od'
156 54069d1b Stavros Sachtouris
        return list(self)
157 54069d1b Stavros Sachtouris
158 54069d1b Stavros Sachtouris
    def values(self):
159 54069d1b Stavros Sachtouris
        'od.values() -> list of values in od'
160 54069d1b Stavros Sachtouris
        return [self[key] for key in self]
161 54069d1b Stavros Sachtouris
162 54069d1b Stavros Sachtouris
    def items(self):
163 54069d1b Stavros Sachtouris
        'od.items() -> list of (key, value) pairs in od'
164 54069d1b Stavros Sachtouris
        return [(key, self[key]) for key in self]
165 54069d1b Stavros Sachtouris
166 54069d1b Stavros Sachtouris
    def iterkeys(self):
167 54069d1b Stavros Sachtouris
        'od.iterkeys() -> an iterator over the keys in od'
168 54069d1b Stavros Sachtouris
        return iter(self)
169 54069d1b Stavros Sachtouris
170 54069d1b Stavros Sachtouris
    def itervalues(self):
171 54069d1b Stavros Sachtouris
        'od.itervalues -> an iterator over the values in od'
172 54069d1b Stavros Sachtouris
        for k in self:
173 54069d1b Stavros Sachtouris
            yield self[k]
174 54069d1b Stavros Sachtouris
175 54069d1b Stavros Sachtouris
    def iteritems(self):
176 54069d1b Stavros Sachtouris
        'od.iteritems -> an iterator over the (key, value) items in od'
177 54069d1b Stavros Sachtouris
        for k in self:
178 54069d1b Stavros Sachtouris
            yield (k, self[k])
179 54069d1b Stavros Sachtouris
180 54069d1b Stavros Sachtouris
    def update(*args, **kwds):
181 54069d1b Stavros Sachtouris
        '''od.update(E, **F) -> None.  Update od from dict/iterable E and F.
182 54069d1b Stavros Sachtouris

183 54069d1b Stavros Sachtouris
        If E is a dict instance, does:           for k in E: od[k] = E[k]
184 b4368e33 Stavros Sachtouris
        If E has a .keys() method, does:         for k in E.keys(): od[k]=E[k]
185 54069d1b Stavros Sachtouris
        Or if E is an iterable of items, does:   for k, v in E: od[k] = v
186 b4368e33 Stavros Sachtouris
        In either case, this is followed by:     for k, v in F.items(): od[k]=v
187 54069d1b Stavros Sachtouris

188 54069d1b Stavros Sachtouris
        '''
189 54069d1b Stavros Sachtouris
        if len(args) > 2:
190 54069d1b Stavros Sachtouris
            raise TypeError('update() takes at most 2 positional '
191 54069d1b Stavros Sachtouris
                            'arguments (%d given)' % (len(args),))
192 54069d1b Stavros Sachtouris
        elif not args:
193 54069d1b Stavros Sachtouris
            raise TypeError('update() takes at least 1 argument (0 given)')
194 54069d1b Stavros Sachtouris
        self = args[0]
195 54069d1b Stavros Sachtouris
        # Make progressively weaker assumptions about "other"
196 54069d1b Stavros Sachtouris
        other = ()
197 54069d1b Stavros Sachtouris
        if len(args) == 2:
198 54069d1b Stavros Sachtouris
            other = args[1]
199 54069d1b Stavros Sachtouris
        if isinstance(other, dict):
200 54069d1b Stavros Sachtouris
            for key in other:
201 54069d1b Stavros Sachtouris
                self[key] = other[key]
202 54069d1b Stavros Sachtouris
        elif hasattr(other, 'keys'):
203 54069d1b Stavros Sachtouris
            for key in other.keys():
204 54069d1b Stavros Sachtouris
                self[key] = other[key]
205 54069d1b Stavros Sachtouris
        else:
206 54069d1b Stavros Sachtouris
            for key, value in other:
207 54069d1b Stavros Sachtouris
                self[key] = value
208 54069d1b Stavros Sachtouris
        for key, value in kwds.items():
209 54069d1b Stavros Sachtouris
            self[key] = value
210 54069d1b Stavros Sachtouris
211 6764f588 Stavros Sachtouris
    #  let subclasses override update without breaking __init__
212 6764f588 Stavros Sachtouris
    __update = update
213 54069d1b Stavros Sachtouris
214 54069d1b Stavros Sachtouris
    __marker = object()
215 54069d1b Stavros Sachtouris
216 54069d1b Stavros Sachtouris
    def pop(self, key, default=__marker):
217 6764f588 Stavros Sachtouris
        """od.pop(k[,d]) -> v, remove specified key and return the
218 6764f588 Stavros Sachtouris
        corresponding value. If key is not found, d is returned if given,
219 6764f588 Stavros Sachtouris
        otherwise KeyError is raised.
220 6764f588 Stavros Sachtouris
        """
221 54069d1b Stavros Sachtouris
        if key in self:
222 54069d1b Stavros Sachtouris
            result = self[key]
223 54069d1b Stavros Sachtouris
            del self[key]
224 54069d1b Stavros Sachtouris
            return result
225 54069d1b Stavros Sachtouris
        if default is self.__marker:
226 54069d1b Stavros Sachtouris
            raise KeyError(key)
227 54069d1b Stavros Sachtouris
        return default
228 54069d1b Stavros Sachtouris
229 54069d1b Stavros Sachtouris
    def setdefault(self, key, default=None):
230 6764f588 Stavros Sachtouris
        """od.setdefault(k[,d]) -> od.get(k,d), also set od[k]=d if k not in
231 6764f588 Stavros Sachtouris
        od
232 6764f588 Stavros Sachtouris
        """
233 54069d1b Stavros Sachtouris
        if key in self:
234 54069d1b Stavros Sachtouris
            return self[key]
235 54069d1b Stavros Sachtouris
        self[key] = default
236 54069d1b Stavros Sachtouris
        return default
237 54069d1b Stavros Sachtouris
238 54069d1b Stavros Sachtouris
    def __repr__(self, _repr_running={}):
239 6764f588 Stavros Sachtouris
        """od.__repr__() <==> repr(od)"""
240 54069d1b Stavros Sachtouris
        call_key = id(self), _get_ident()
241 54069d1b Stavros Sachtouris
        if call_key in _repr_running:
242 54069d1b Stavros Sachtouris
            return '...'
243 54069d1b Stavros Sachtouris
        _repr_running[call_key] = 1
244 54069d1b Stavros Sachtouris
        try:
245 54069d1b Stavros Sachtouris
            if not self:
246 54069d1b Stavros Sachtouris
                return '%s()' % (self.__class__.__name__,)
247 54069d1b Stavros Sachtouris
            return '%s(%r)' % (self.__class__.__name__, self.items())
248 54069d1b Stavros Sachtouris
        finally:
249 54069d1b Stavros Sachtouris
            del _repr_running[call_key]
250 54069d1b Stavros Sachtouris
251 54069d1b Stavros Sachtouris
    def __reduce__(self):
252 6764f588 Stavros Sachtouris
        """Return state information for pickling"""
253 54069d1b Stavros Sachtouris
        items = [[k, self[k]] for k in self]
254 54069d1b Stavros Sachtouris
        inst_dict = vars(self).copy()
255 54069d1b Stavros Sachtouris
        for k in vars(OrderedDict()):
256 54069d1b Stavros Sachtouris
            inst_dict.pop(k, None)
257 54069d1b Stavros Sachtouris
        if inst_dict:
258 54069d1b Stavros Sachtouris
            return (self.__class__, (items,), inst_dict)
259 54069d1b Stavros Sachtouris
        return self.__class__, (items,)
260 54069d1b Stavros Sachtouris
261 54069d1b Stavros Sachtouris
    def copy(self):
262 6764f588 Stavros Sachtouris
        """od.copy() -> a shallow copy of od"""
263 54069d1b Stavros Sachtouris
        return self.__class__(self)
264 54069d1b Stavros Sachtouris
265 54069d1b Stavros Sachtouris
    @classmethod
266 54069d1b Stavros Sachtouris
    def fromkeys(cls, iterable, value=None):
267 6764f588 Stavros Sachtouris
        """OD.fromkeys(S[, v]) -> New ordered dictionary with keys from S
268 54069d1b Stavros Sachtouris
        and values equal to v (which defaults to None).
269 6764f588 Stavros Sachtouris
        """
270 54069d1b Stavros Sachtouris
        d = cls()
271 54069d1b Stavros Sachtouris
        for key in iterable:
272 54069d1b Stavros Sachtouris
            d[key] = value
273 54069d1b Stavros Sachtouris
        return d
274 54069d1b Stavros Sachtouris
275 54069d1b Stavros Sachtouris
    def __eq__(self, other):
276 6764f588 Stavros Sachtouris
        """od.__eq__(y) <==> od==y.  Comparison to another OD is
277 6764f588 Stavros Sachtouris
        order-sensitive while comparison to a regular mapping is
278 6764f588 Stavros Sachtouris
        order-insensitive.
279 6764f588 Stavros Sachtouris
        """
280 54069d1b Stavros Sachtouris
        if isinstance(other, OrderedDict):
281 6764f588 Stavros Sachtouris
            return len(self) == len(other) and self.items() == other.items()
282 54069d1b Stavros Sachtouris
        return dict.__eq__(self, other)
283 54069d1b Stavros Sachtouris
284 54069d1b Stavros Sachtouris
    def __ne__(self, other):
285 54069d1b Stavros Sachtouris
        return not self == other
286 54069d1b Stavros Sachtouris
287 54069d1b Stavros Sachtouris
    # -- the following methods are only used in Python 2.7 --
288 54069d1b Stavros Sachtouris
289 54069d1b Stavros Sachtouris
    def viewkeys(self):
290 54069d1b Stavros Sachtouris
        "od.viewkeys() -> a set-like object providing a view on od's keys"
291 54069d1b Stavros Sachtouris
        return KeysView(self)
292 54069d1b Stavros Sachtouris
293 54069d1b Stavros Sachtouris
    def viewvalues(self):
294 54069d1b Stavros Sachtouris
        "od.viewvalues() -> an object providing a view on od's values"
295 54069d1b Stavros Sachtouris
        return ValuesView(self)
296 54069d1b Stavros Sachtouris
297 54069d1b Stavros Sachtouris
    def viewitems(self):
298 54069d1b Stavros Sachtouris
        "od.viewitems() -> a set-like object providing a view on od's items"
299 54069d1b Stavros Sachtouris
        return ItemsView(self)