Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(668)

Side by Side Diff: pylib/gyp/ordered_dict.py

Issue 106233005: Add backported OrderedDict (Closed) Base URL: http://gyp.googlecode.com/svn/trunk
Patch Set: . Created 7 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« pylib/gyp/generator/msvs.py ('K') | « pylib/gyp/generator/msvs.py ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 # Unmodified from http://code.activestate.com/recipes/576693/
2 # This should be deleted once Py2.7 is available on all bots.
Nico 2013/12/13 17:54:18 , http://crbug.com/241769
scottmg 2013/12/13 17:56:29 Done.
3 # Linked from Python documentation here:
4 # http://docs.python.org/2/library/collections.html#collections.OrderedDict
5
6 # Backport of OrderedDict() class that runs on Python 2.4, 2.5, 2.6, 2.7 and pyp y.
7 # Passes Python2.7's test suite and incorporates all the latest updates.
8
9 try:
10 from thread import get_ident as _get_ident
11 except ImportError:
12 from dummy_thread import get_ident as _get_ident
13
14 try:
15 from _abcoll import KeysView, ValuesView, ItemsView
16 except ImportError:
17 pass
18
19
20 class OrderedDict(dict):
21 'Dictionary that remembers insertion order'
22 # An inherited dict maps keys to values.
23 # The inherited dict provides __getitem__, __len__, __contains__, and get.
24 # The remaining methods are order-aware.
25 # Big-O running times for all methods are the same as for regular dictionari es.
26
27 # The internal self.__map dictionary maps keys to links in a doubly linked l ist.
28 # The circular doubly linked list starts and ends with a sentinel element.
29 # The sentinel element never gets deleted (this simplifies the algorithm).
30 # Each link is stored as a list of length three: [PREV, NEXT, KEY].
31
32 def __init__(self, *args, **kwds):
33 '''Initialize an ordered dictionary. Signature is the same as for
34 regular dictionaries, but keyword arguments are not recommended
35 because their insertion order is arbitrary.
36
37 '''
38 if len(args) > 1:
39 raise TypeError('expected at most 1 arguments, got %d' % len(args))
40 try:
41 self.__root
42 except AttributeError:
43 self.__root = root = [] # sentinel node
44 root[:] = [root, root, None]
45 self.__map = {}
46 self.__update(*args, **kwds)
47
48 def __setitem__(self, key, value, dict_setitem=dict.__setitem__):
49 'od.__setitem__(i, y) <==> od[i]=y'
50 # Setting a new item creates a new link which goes at the end of the lin ked
51 # list, and the inherited dictionary is updated with the new key/value p air.
52 if key not in self:
53 root = self.__root
54 last = root[0]
55 last[1] = root[0] = self.__map[key] = [last, root, key]
56 dict_setitem(self, key, value)
57
58 def __delitem__(self, key, dict_delitem=dict.__delitem__):
59 'od.__delitem__(y) <==> del od[y]'
60 # Deleting an existing item uses self.__map to find the link which is
61 # then removed by updating the links in the predecessor and successor no des.
62 dict_delitem(self, key)
63 link_prev, link_next, key = self.__map.pop(key)
64 link_prev[1] = link_next
65 link_next[0] = link_prev
66
67 def __iter__(self):
68 'od.__iter__() <==> iter(od)'
69 root = self.__root
70 curr = root[1]
71 while curr is not root:
72 yield curr[2]
73 curr = curr[1]
74
75 def __reversed__(self):
76 'od.__reversed__() <==> reversed(od)'
77 root = self.__root
78 curr = root[0]
79 while curr is not root:
80 yield curr[2]
81 curr = curr[0]
82
83 def clear(self):
84 'od.clear() -> None. Remove all items from od.'
85 try:
86 for node in self.__map.itervalues():
87 del node[:]
88 root = self.__root
89 root[:] = [root, root, None]
90 self.__map.clear()
91 except AttributeError:
92 pass
93 dict.clear(self)
94
95 def popitem(self, last=True):
96 '''od.popitem() -> (k, v), return and remove a (key, value) pair.
97 Pairs are returned in LIFO order if last is true or FIFO order if false.
98
99 '''
100 if not self:
101 raise KeyError('dictionary is empty')
102 root = self.__root
103 if last:
104 link = root[0]
105 link_prev = link[0]
106 link_prev[1] = root
107 root[0] = link_prev
108 else:
109 link = root[1]
110 link_next = link[1]
111 root[1] = link_next
112 link_next[0] = root
113 key = link[2]
114 del self.__map[key]
115 value = dict.pop(self, key)
116 return key, value
117
118 # -- the following methods do not depend on the internal structure --
119
120 def keys(self):
121 'od.keys() -> list of keys in od'
122 return list(self)
123
124 def values(self):
125 'od.values() -> list of values in od'
126 return [self[key] for key in self]
127
128 def items(self):
129 'od.items() -> list of (key, value) pairs in od'
130 return [(key, self[key]) for key in self]
131
132 def iterkeys(self):
133 'od.iterkeys() -> an iterator over the keys in od'
134 return iter(self)
135
136 def itervalues(self):
137 'od.itervalues -> an iterator over the values in od'
138 for k in self:
139 yield self[k]
140
141 def iteritems(self):
142 'od.iteritems -> an iterator over the (key, value) items in od'
143 for k in self:
144 yield (k, self[k])
145
146 def update(*args, **kwds):
147 '''od.update(E, **F) -> None. Update od from dict/iterable E and F.
148
149 If E is a dict instance, does: for k in E: od[k] = E[k]
150 If E has a .keys() method, does: for k in E.keys(): od[k] = E[k]
151 Or if E is an iterable of items, does: for k, v in E: od[k] = v
152 In either case, this is followed by: for k, v in F.items(): od[k] = v
153
154 '''
155 if len(args) > 2:
156 raise TypeError('update() takes at most 2 positional '
157 'arguments (%d given)' % (len(args),))
158 elif not args:
159 raise TypeError('update() takes at least 1 argument (0 given)')
160 self = args[0]
161 # Make progressively weaker assumptions about "other"
162 other = ()
163 if len(args) == 2:
164 other = args[1]
165 if isinstance(other, dict):
166 for key in other:
167 self[key] = other[key]
168 elif hasattr(other, 'keys'):
169 for key in other.keys():
170 self[key] = other[key]
171 else:
172 for key, value in other:
173 self[key] = value
174 for key, value in kwds.items():
175 self[key] = value
176
177 __update = update # let subclasses override update without breaking __init_ _
178
179 __marker = object()
180
181 def pop(self, key, default=__marker):
182 '''od.pop(k[,d]) -> v, remove specified key and return the corresponding value.
183 If key is not found, d is returned if given, otherwise KeyError is raise d.
184
185 '''
186 if key in self:
187 result = self[key]
188 del self[key]
189 return result
190 if default is self.__marker:
191 raise KeyError(key)
192 return default
193
194 def setdefault(self, key, default=None):
195 'od.setdefault(k[,d]) -> od.get(k,d), also set od[k]=d if k not in od'
196 if key in self:
197 return self[key]
198 self[key] = default
199 return default
200
201 def __repr__(self, _repr_running={}):
202 'od.__repr__() <==> repr(od)'
203 call_key = id(self), _get_ident()
204 if call_key in _repr_running:
205 return '...'
206 _repr_running[call_key] = 1
207 try:
208 if not self:
209 return '%s()' % (self.__class__.__name__,)
210 return '%s(%r)' % (self.__class__.__name__, self.items())
211 finally:
212 del _repr_running[call_key]
213
214 def __reduce__(self):
215 'Return state information for pickling'
216 items = [[k, self[k]] for k in self]
217 inst_dict = vars(self).copy()
218 for k in vars(OrderedDict()):
219 inst_dict.pop(k, None)
220 if inst_dict:
221 return (self.__class__, (items,), inst_dict)
222 return self.__class__, (items,)
223
224 def copy(self):
225 'od.copy() -> a shallow copy of od'
226 return self.__class__(self)
227
228 @classmethod
229 def fromkeys(cls, iterable, value=None):
230 '''OD.fromkeys(S[, v]) -> New ordered dictionary with keys from S
231 and values equal to v (which defaults to None).
232
233 '''
234 d = cls()
235 for key in iterable:
236 d[key] = value
237 return d
238
239 def __eq__(self, other):
240 '''od.__eq__(y) <==> od==y. Comparison to another OD is order-sensitive
241 while comparison to a regular mapping is order-insensitive.
242
243 '''
244 if isinstance(other, OrderedDict):
245 return len(self)==len(other) and self.items() == other.items()
246 return dict.__eq__(self, other)
247
248 def __ne__(self, other):
249 return not self == other
250
251 # -- the following methods are only used in Python 2.7 --
252
253 def viewkeys(self):
254 "od.viewkeys() -> a set-like object providing a view on od's keys"
255 return KeysView(self)
256
257 def viewvalues(self):
258 "od.viewvalues() -> an object providing a view on od's values"
259 return ValuesView(self)
260
261 def viewitems(self):
262 "od.viewitems() -> a set-like object providing a view on od's items"
263 return ItemsView(self)
264
OLDNEW
« pylib/gyp/generator/msvs.py ('K') | « pylib/gyp/generator/msvs.py ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698