Statistics
| Branch: | Tag: | Revision:

root / kamaki / clients / commissioning / utils / ordereddict.py @ 34f48ce0

History | View | Annotate | Download (10.2 kB)

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

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

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

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