summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChristopher Larson <chris_larson@mentor.com>2012-09-10 22:23:19 +0000
committerRichard Purdie <richard.purdie@linuxfoundation.org>2012-09-20 10:29:33 +0100
commit749f4f67444c7be7fe7aac0189776fd540975e09 (patch)
tree68454bc7a1583e3d49cb99d54cbd14d949f824d2
parentf57392590a95ac5812e3cc7a2bb6751fdc34a7df (diff)
downloadpoky-749f4f67444c7be7fe7aac0189776fd540975e09.tar.gz
bitbake: compat, event: use OrderedDict from py2.7 for the event handlers
This ensures that our event handlers get run in registration order, making the behavior more deterministic. I pulled in the python2.7 OrderedDict to avoid essentially reimplementing a version of it ourselves, figuring we can drop it when we bump our required python version next. (Bitbake rev: 44aa0b0537d3fbd1272015e7677948f84d8c0607) Signed-off-by: Christopher Larson <chris_larson@mentor.com> Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
-rw-r--r--bitbake/lib/bb/compat.py213
-rw-r--r--bitbake/lib/bb/event.py3
2 files changed, 215 insertions, 1 deletions
diff --git a/bitbake/lib/bb/compat.py b/bitbake/lib/bb/compat.py
index c6978fccc5..1466da2379 100644
--- a/bitbake/lib/bb/compat.py
+++ b/bitbake/lib/bb/compat.py
@@ -1,5 +1,11 @@
1"""Code pulled from future python versions, here for compatibility""" 1"""Code pulled from future python versions, here for compatibility"""
2 2
3from collections import MutableMapping, KeysView, ValuesView, ItemsView
4try:
5 from thread import get_ident as _get_ident
6except ImportError:
7 from dummy_thread import get_ident as _get_ident
8
3def total_ordering(cls): 9def total_ordering(cls):
4 """Class decorator that fills in missing ordering methods""" 10 """Class decorator that fills in missing ordering methods"""
5 convert = { 11 convert = {
@@ -26,3 +32,210 @@ def total_ordering(cls):
26 opfunc.__doc__ = getattr(int, opname).__doc__ 32 opfunc.__doc__ = getattr(int, opname).__doc__
27 setattr(cls, opname, opfunc) 33 setattr(cls, opname, opfunc)
28 return cls 34 return cls
35
36class OrderedDict(dict):
37 'Dictionary that remembers insertion order'
38 # An inherited dict maps keys to values.
39 # The inherited dict provides __getitem__, __len__, __contains__, and get.
40 # The remaining methods are order-aware.
41 # Big-O running times for all methods are the same as regular dictionaries.
42
43 # The internal self.__map dict maps keys to links in a doubly linked list.
44 # The circular doubly linked list starts and ends with a sentinel element.
45 # The sentinel element never gets deleted (this simplifies the algorithm).
46 # Each link is stored as a list of length three: [PREV, NEXT, KEY].
47
48 def __init__(self, *args, **kwds):
49 '''Initialize an ordered dictionary. The signature is the same as
50 regular dictionaries, but keyword arguments are not recommended because
51 their insertion order is arbitrary.
52
53 '''
54 if len(args) > 1:
55 raise TypeError('expected at most 1 arguments, got %d' % len(args))
56 try:
57 self.__root
58 except AttributeError:
59 self.__root = root = [] # sentinel node
60 root[:] = [root, root, None]
61 self.__map = {}
62 self.__update(*args, **kwds)
63
64 def __setitem__(self, key, value, PREV=0, NEXT=1, dict_setitem=dict.__setitem__):
65 'od.__setitem__(i, y) <==> od[i]=y'
66 # Setting a new item creates a new link at the end of the linked list,
67 # and the inherited dictionary is updated with the new key/value pair.
68 if key not in self:
69 root = self.__root
70 last = root[PREV]
71 last[NEXT] = root[PREV] = self.__map[key] = [last, root, key]
72 dict_setitem(self, key, value)
73
74 def __delitem__(self, key, PREV=0, NEXT=1, dict_delitem=dict.__delitem__):
75 'od.__delitem__(y) <==> del od[y]'
76 # Deleting an existing item uses self.__map to find the link which gets
77 # removed by updating the links in the predecessor and successor nodes.
78 dict_delitem(self, key)
79 link_prev, link_next, key = self.__map.pop(key)
80 link_prev[NEXT] = link_next
81 link_next[PREV] = link_prev
82
83 def __iter__(self):
84 'od.__iter__() <==> iter(od)'
85 # Traverse the linked list in order.
86 NEXT, KEY = 1, 2
87 root = self.__root
88 curr = root[NEXT]
89 while curr is not root:
90 yield curr[KEY]
91 curr = curr[NEXT]
92
93 def __reversed__(self):
94 'od.__reversed__() <==> reversed(od)'
95 # Traverse the linked list in reverse order.
96 PREV, KEY = 0, 2
97 root = self.__root
98 curr = root[PREV]
99 while curr is not root:
100 yield curr[KEY]
101 curr = curr[PREV]
102
103 def clear(self):
104 'od.clear() -> None. Remove all items from od.'
105 for node in self.__map.itervalues():
106 del node[:]
107 root = self.__root
108 root[:] = [root, root, None]
109 self.__map.clear()
110 dict.clear(self)
111
112 # -- the following methods do not depend on the internal structure --
113
114 def keys(self):
115 'od.keys() -> list of keys in od'
116 return list(self)
117
118 def values(self):
119 'od.values() -> list of values in od'
120 return [self[key] for key in self]
121
122 def items(self):
123 'od.items() -> list of (key, value) pairs in od'
124 return [(key, self[key]) for key in self]
125
126 def iterkeys(self):
127 'od.iterkeys() -> an iterator over the keys in od'
128 return iter(self)
129
130 def itervalues(self):
131 'od.itervalues -> an iterator over the values in od'
132 for k in self:
133 yield self[k]
134
135 def iteritems(self):
136 'od.iteritems -> an iterator over the (key, value) pairs in od'
137 for k in self:
138 yield (k, self[k])
139
140 update = MutableMapping.update
141
142 __update = update # let subclasses override update without breaking __init__
143
144 __marker = object()
145
146 def pop(self, key, default=__marker):
147 '''od.pop(k[,d]) -> v, remove specified key and return the corresponding
148 value. If key is not found, d is returned if given, otherwise KeyError
149 is raised.
150
151 '''
152 if key in self:
153 result = self[key]
154 del self[key]
155 return result
156 if default is self.__marker:
157 raise KeyError(key)
158 return default
159
160 def setdefault(self, key, default=None):
161 'od.setdefault(k[,d]) -> od.get(k,d), also set od[k]=d if k not in od'
162 if key in self:
163 return self[key]
164 self[key] = default
165 return default
166
167 def popitem(self, last=True):
168 '''od.popitem() -> (k, v), return and remove a (key, value) pair.
169 Pairs are returned in LIFO order if last is true or FIFO order if false.
170
171 '''
172 if not self:
173 raise KeyError('dictionary is empty')
174 key = next(reversed(self) if last else iter(self))
175 value = self.pop(key)
176 return key, value
177
178 def __repr__(self, _repr_running={}):
179 'od.__repr__() <==> repr(od)'
180 call_key = id(self), _get_ident()
181 if call_key in _repr_running:
182 return '...'
183 _repr_running[call_key] = 1
184 try:
185 if not self:
186 return '%s()' % (self.__class__.__name__,)
187 return '%s(%r)' % (self.__class__.__name__, self.items())
188 finally:
189 del _repr_running[call_key]
190
191 def __reduce__(self):
192 'Return state information for pickling'
193 items = [[k, self[k]] for k in self]
194 inst_dict = vars(self).copy()
195 for k in vars(OrderedDict()):
196 inst_dict.pop(k, None)
197 if inst_dict:
198 return (self.__class__, (items,), inst_dict)
199 return self.__class__, (items,)
200
201 def copy(self):
202 'od.copy() -> a shallow copy of od'
203 return self.__class__(self)
204
205 @classmethod
206 def fromkeys(cls, iterable, value=None):
207 '''OD.fromkeys(S[, v]) -> New ordered dictionary with keys from S.
208 If not specified, the value defaults to None.
209
210 '''
211 self = cls()
212 for key in iterable:
213 self[key] = value
214 return self
215
216 def __eq__(self, other):
217 '''od.__eq__(y) <==> od==y. Comparison to another OD is order-sensitive
218 while comparison to a regular mapping is order-insensitive.
219
220 '''
221 if isinstance(other, OrderedDict):
222 return len(self)==len(other) and self.items() == other.items()
223 return dict.__eq__(self, other)
224
225 def __ne__(self, other):
226 'od.__ne__(y) <==> od!=y'
227 return not self == other
228
229 # -- the following methods support python 3.x style dictionary views --
230
231 def viewkeys(self):
232 "od.viewkeys() -> a set-like object providing a view on od's keys"
233 return KeysView(self)
234
235 def viewvalues(self):
236 "od.viewvalues() -> an object providing a view on od's values"
237 return ValuesView(self)
238
239 def viewitems(self):
240 "od.viewitems() -> a set-like object providing a view on od's items"
241 return ItemsView(self)
diff --git a/bitbake/lib/bb/event.py b/bitbake/lib/bb/event.py
index ab62d4d055..7ee28fcfcb 100644
--- a/bitbake/lib/bb/event.py
+++ b/bitbake/lib/bb/event.py
@@ -32,6 +32,7 @@ import logging
32import atexit 32import atexit
33import traceback 33import traceback
34import bb.utils 34import bb.utils
35import bb.compat
35 36
36# This is the pid for which we should generate the event. This is set when 37# This is the pid for which we should generate the event. This is set when
37# the runqueue forks off. 38# the runqueue forks off.
@@ -53,7 +54,7 @@ Registered = 10
53AlreadyRegistered = 14 54AlreadyRegistered = 14
54 55
55# Internal 56# Internal
56_handlers = {} 57_handlers = bb.compat.OrderedDict()
57_ui_handlers = {} 58_ui_handlers = {}
58_ui_handler_seq = 0 59_ui_handler_seq = 0
59 60