diff options
Diffstat (limited to 'bitbake/lib/bb/event.py')
| -rw-r--r-- | bitbake/lib/bb/event.py | 211 |
1 files changed, 98 insertions, 113 deletions
diff --git a/bitbake/lib/bb/event.py b/bitbake/lib/bb/event.py index 9d7341f878..7251d78715 100644 --- a/bitbake/lib/bb/event.py +++ b/bitbake/lib/bb/event.py | |||
| @@ -24,21 +24,18 @@ BitBake build tools. | |||
| 24 | 24 | ||
| 25 | import os, re | 25 | import os, re |
| 26 | import bb.utils | 26 | import bb.utils |
| 27 | import pickle | ||
| 28 | |||
| 29 | # This is the pid for which we should generate the event. This is set when | ||
| 30 | # the runqueue forks off. | ||
| 31 | worker_pid = 0 | ||
| 32 | worker_pipe = None | ||
| 27 | 33 | ||
| 28 | class Event: | 34 | class Event: |
| 29 | """Base class for events""" | 35 | """Base class for events""" |
| 30 | type = "Event" | ||
| 31 | |||
| 32 | def __init__(self, d): | ||
| 33 | self._data = d | ||
| 34 | |||
| 35 | def getData(self): | ||
| 36 | return self._data | ||
| 37 | |||
| 38 | def setData(self, data): | ||
| 39 | self._data = data | ||
| 40 | 36 | ||
| 41 | data = property(getData, setData, None, "data property") | 37 | def __init__(self): |
| 38 | self.pid = worker_pid | ||
| 42 | 39 | ||
| 43 | NotHandled = 0 | 40 | NotHandled = 0 |
| 44 | Handled = 1 | 41 | Handled = 1 |
| @@ -47,75 +44,83 @@ Registered = 10 | |||
| 47 | AlreadyRegistered = 14 | 44 | AlreadyRegistered = 14 |
| 48 | 45 | ||
| 49 | # Internal | 46 | # Internal |
| 50 | _handlers = [] | 47 | _handlers = {} |
| 51 | _handlers_dict = {} | 48 | _ui_handlers = {} |
| 49 | _ui_handler_seq = 0 | ||
| 52 | 50 | ||
| 53 | def tmpHandler(event): | 51 | def fire(event, d): |
| 54 | """Default handler for code events""" | 52 | """Fire off an Event""" |
| 55 | return NotHandled | ||
| 56 | 53 | ||
| 57 | def defaultTmpHandler(): | 54 | if worker_pid != 0: |
| 58 | tmp = "def tmpHandler(e):\n\t\"\"\"heh\"\"\"\n\treturn NotHandled" | 55 | worker_fire(event, d) |
| 59 | comp = bb.utils.better_compile(tmp, "tmpHandler(e)", "bb.event.defaultTmpHandler") | 56 | return |
| 60 | return comp | ||
| 61 | 57 | ||
| 62 | def fire(event): | 58 | for handler in _handlers: |
| 63 | """Fire off an Event""" | 59 | h = _handlers[handler] |
| 64 | for h in _handlers: | 60 | event.data = d |
| 65 | if type(h).__name__ == "code": | 61 | if type(h).__name__ == "code": |
| 66 | exec(h) | 62 | exec(h) |
| 67 | if tmpHandler(event) == Handled: | 63 | tmpHandler(event) |
| 68 | return Handled | ||
| 69 | else: | 64 | else: |
| 70 | if h(event) == Handled: | 65 | h(event) |
| 71 | return Handled | 66 | del event.data |
| 72 | return NotHandled | 67 | |
| 68 | errors = [] | ||
| 69 | for h in _ui_handlers: | ||
| 70 | #print "Sending event %s" % event | ||
| 71 | try: | ||
| 72 | # We use pickle here since it better handles object instances | ||
| 73 | # which xmlrpc's marshaller does not. Events *must* be serializable | ||
| 74 | # by pickle. | ||
| 75 | _ui_handlers[h].event.send((pickle.dumps(event))) | ||
| 76 | except: | ||
| 77 | errors.append(h) | ||
| 78 | for h in errors: | ||
| 79 | del _ui_handlers[h] | ||
| 80 | |||
| 81 | def worker_fire(event, d): | ||
| 82 | data = "<event>" + pickle.dumps(event) + "</event>" | ||
| 83 | if os.write(worker_pipe, data) != len (data): | ||
| 84 | print "Error sending event to server (short write)" | ||
| 85 | |||
| 86 | def fire_from_worker(event, d): | ||
| 87 | if not event.startswith("<event>") or not event.endswith("</event>"): | ||
| 88 | print "Error, not an event" | ||
| 89 | return | ||
| 90 | event = pickle.loads(event[7:-8]) | ||
| 91 | bb.event.fire(event, d) | ||
| 73 | 92 | ||
| 74 | def register(name, handler): | 93 | def register(name, handler): |
| 75 | """Register an Event handler""" | 94 | """Register an Event handler""" |
| 76 | 95 | ||
| 77 | # already registered | 96 | # already registered |
| 78 | if name in _handlers_dict: | 97 | if name in _handlers: |
| 79 | return AlreadyRegistered | 98 | return AlreadyRegistered |
| 80 | 99 | ||
| 81 | if handler is not None: | 100 | if handler is not None: |
| 82 | # handle string containing python code | 101 | # handle string containing python code |
| 83 | if type(handler).__name__ == "str": | 102 | if type(handler).__name__ == "str": |
| 84 | _registerCode(handler) | 103 | tmp = "def tmpHandler(e):\n%s" % handler |
| 104 | comp = bb.utils.better_compile(tmp, "tmpHandler(e)", "bb.event._registerCode") | ||
| 105 | _handlers[name] = comp | ||
| 85 | else: | 106 | else: |
| 86 | _handlers.append(handler) | 107 | _handlers[name] = handler |
| 87 | 108 | ||
| 88 | _handlers_dict[name] = 1 | ||
| 89 | return Registered | 109 | return Registered |
| 90 | 110 | ||
| 91 | def _registerCode(handlerStr): | ||
| 92 | """Register a 'code' Event. | ||
| 93 | Deprecated interface; call register instead. | ||
| 94 | |||
| 95 | Expects to be passed python code as a string, which will | ||
| 96 | be passed in turn to compile() and then exec(). Note that | ||
| 97 | the code will be within a function, so should have had | ||
| 98 | appropriate tabbing put in place.""" | ||
| 99 | tmp = "def tmpHandler(e):\n%s" % handlerStr | ||
| 100 | comp = bb.utils.better_compile(tmp, "tmpHandler(e)", "bb.event._registerCode") | ||
| 101 | # prevent duplicate registration | ||
| 102 | _handlers.append(comp) | ||
| 103 | |||
| 104 | def remove(name, handler): | 111 | def remove(name, handler): |
| 105 | """Remove an Event handler""" | 112 | """Remove an Event handler""" |
| 113 | _handlers.pop(name) | ||
| 106 | 114 | ||
| 107 | _handlers_dict.pop(name) | 115 | def register_UIHhandler(handler): |
| 108 | if type(handler).__name__ == "str": | 116 | bb.event._ui_handler_seq = bb.event._ui_handler_seq + 1 |
| 109 | return _removeCode(handler) | 117 | _ui_handlers[_ui_handler_seq] = handler |
| 110 | else: | 118 | return _ui_handler_seq |
| 111 | _handlers.remove(handler) | ||
| 112 | 119 | ||
| 113 | def _removeCode(handlerStr): | 120 | def unregister_UIHhandler(handlerNum): |
| 114 | """Remove a 'code' Event handler | 121 | if handlerNum in _ui_handlers: |
| 115 | Deprecated interface; call remove instead.""" | 122 | del _ui_handlers[handlerNum] |
| 116 | tmp = "def tmpHandler(e):\n%s" % handlerStr | 123 | return |
| 117 | comp = bb.utils.better_compile(tmp, "tmpHandler(e)", "bb.event._removeCode") | ||
| 118 | _handlers.remove(comp) | ||
| 119 | 124 | ||
| 120 | def getName(e): | 125 | def getName(e): |
| 121 | """Returns the name of a class or class instance""" | 126 | """Returns the name of a class or class instance""" |
| @@ -130,17 +135,17 @@ class ConfigParsed(Event): | |||
| 130 | class RecipeParsed(Event): | 135 | class RecipeParsed(Event): |
| 131 | """ Recipe Parsing Complete """ | 136 | """ Recipe Parsing Complete """ |
| 132 | 137 | ||
| 133 | def __init__(self, fn, d): | 138 | def __init__(self, fn): |
| 134 | self.fn = fn | 139 | self.fn = fn |
| 135 | Event.__init__(self, d) | 140 | Event.__init__(self) |
| 136 | 141 | ||
| 137 | class StampUpdate(Event): | 142 | class StampUpdate(Event): |
| 138 | """Trigger for any adjustment of the stamp files to happen""" | 143 | """Trigger for any adjustment of the stamp files to happen""" |
| 139 | 144 | ||
| 140 | def __init__(self, targets, stampfns, d): | 145 | def __init__(self, targets, stampfns): |
| 141 | self._targets = targets | 146 | self._targets = targets |
| 142 | self._stampfns = stampfns | 147 | self._stampfns = stampfns |
| 143 | Event.__init__(self, d) | 148 | Event.__init__(self) |
| 144 | 149 | ||
| 145 | def getStampPrefix(self): | 150 | def getStampPrefix(self): |
| 146 | return self._stampfns | 151 | return self._stampfns |
| @@ -151,29 +156,13 @@ class StampUpdate(Event): | |||
| 151 | stampPrefix = property(getStampPrefix) | 156 | stampPrefix = property(getStampPrefix) |
| 152 | targets = property(getTargets) | 157 | targets = property(getTargets) |
| 153 | 158 | ||
| 154 | class PkgBase(Event): | ||
| 155 | """Base class for package events""" | ||
| 156 | |||
| 157 | def __init__(self, t, d): | ||
| 158 | self._pkg = t | ||
| 159 | Event.__init__(self, d) | ||
| 160 | |||
| 161 | def getPkg(self): | ||
| 162 | return self._pkg | ||
| 163 | |||
| 164 | def setPkg(self, pkg): | ||
| 165 | self._pkg = pkg | ||
| 166 | |||
| 167 | pkg = property(getPkg, setPkg, None, "pkg property") | ||
| 168 | |||
| 169 | |||
| 170 | class BuildBase(Event): | 159 | class BuildBase(Event): |
| 171 | """Base class for bbmake run events""" | 160 | """Base class for bbmake run events""" |
| 172 | 161 | ||
| 173 | def __init__(self, n, p, c, failures = 0): | 162 | def __init__(self, n, p, failures = 0): |
| 174 | self._name = n | 163 | self._name = n |
| 175 | self._pkgs = p | 164 | self._pkgs = p |
| 176 | Event.__init__(self, c) | 165 | Event.__init__(self) |
| 177 | self._failures = failures | 166 | self._failures = failures |
| 178 | 167 | ||
| 179 | def getPkgs(self): | 168 | def getPkgs(self): |
| @@ -205,33 +194,8 @@ class BuildBase(Event): | |||
| 205 | cfg = property(getCfg, setCfg, None, "cfg property") | 194 | cfg = property(getCfg, setCfg, None, "cfg property") |
| 206 | 195 | ||
| 207 | 196 | ||
| 208 | class DepBase(PkgBase): | ||
| 209 | """Base class for dependency events""" | ||
| 210 | |||
| 211 | def __init__(self, t, data, d): | ||
| 212 | self._dep = d | ||
| 213 | PkgBase.__init__(self, t, data) | ||
| 214 | |||
| 215 | def getDep(self): | ||
| 216 | return self._dep | ||
| 217 | |||
| 218 | def setDep(self, dep): | ||
| 219 | self._dep = dep | ||
| 220 | |||
| 221 | dep = property(getDep, setDep, None, "dep property") | ||
| 222 | |||
| 223 | |||
| 224 | class PkgStarted(PkgBase): | ||
| 225 | """Package build started""" | ||
| 226 | 197 | ||
| 227 | 198 | ||
| 228 | class PkgFailed(PkgBase): | ||
| 229 | """Package build failed""" | ||
| 230 | |||
| 231 | |||
| 232 | class PkgSucceeded(PkgBase): | ||
| 233 | """Package build completed""" | ||
| 234 | |||
| 235 | 199 | ||
| 236 | class BuildStarted(BuildBase): | 200 | class BuildStarted(BuildBase): |
| 237 | """bbmake build run started""" | 201 | """bbmake build run started""" |
| @@ -241,18 +205,13 @@ class BuildCompleted(BuildBase): | |||
| 241 | """bbmake build run completed""" | 205 | """bbmake build run completed""" |
| 242 | 206 | ||
| 243 | 207 | ||
| 244 | class UnsatisfiedDep(DepBase): | ||
| 245 | """Unsatisfied Dependency""" | ||
| 246 | 208 | ||
| 247 | 209 | ||
| 248 | class RecursiveDep(DepBase): | ||
| 249 | """Recursive Dependency""" | ||
| 250 | |||
| 251 | class NoProvider(Event): | 210 | class NoProvider(Event): |
| 252 | """No Provider for an Event""" | 211 | """No Provider for an Event""" |
| 253 | 212 | ||
| 254 | def __init__(self, item, data,runtime=False): | 213 | def __init__(self, item, runtime=False): |
| 255 | Event.__init__(self, data) | 214 | Event.__init__(self) |
| 256 | self._item = item | 215 | self._item = item |
| 257 | self._runtime = runtime | 216 | self._runtime = runtime |
| 258 | 217 | ||
| @@ -265,8 +224,8 @@ class NoProvider(Event): | |||
| 265 | class MultipleProviders(Event): | 224 | class MultipleProviders(Event): |
| 266 | """Multiple Providers""" | 225 | """Multiple Providers""" |
| 267 | 226 | ||
| 268 | def __init__(self, item, candidates, data, runtime = False): | 227 | def __init__(self, item, candidates, runtime = False): |
| 269 | Event.__init__(self, data) | 228 | Event.__init__(self) |
| 270 | self._item = item | 229 | self._item = item |
| 271 | self._candidates = candidates | 230 | self._candidates = candidates |
| 272 | self._is_runtime = runtime | 231 | self._is_runtime = runtime |
| @@ -288,3 +247,29 @@ class MultipleProviders(Event): | |||
| 288 | Get the possible Candidates for a PROVIDER. | 247 | Get the possible Candidates for a PROVIDER. |
| 289 | """ | 248 | """ |
| 290 | return self._candidates | 249 | return self._candidates |
| 250 | |||
| 251 | class ParseProgress(Event): | ||
| 252 | """ | ||
| 253 | Parsing Progress Event | ||
| 254 | """ | ||
| 255 | |||
| 256 | def __init__(self, cached, parsed, skipped, masked, virtuals, errors, total): | ||
| 257 | Event.__init__(self) | ||
| 258 | self.cached = cached | ||
| 259 | self.parsed = parsed | ||
| 260 | self.skipped = skipped | ||
| 261 | self.virtuals = virtuals | ||
| 262 | self.masked = masked | ||
| 263 | self.errors = errors | ||
| 264 | self.sofar = cached + parsed | ||
| 265 | self.total = total | ||
| 266 | |||
| 267 | class DepTreeGenerated(Event): | ||
| 268 | """ | ||
| 269 | Event when a dependency tree has been generated | ||
| 270 | """ | ||
| 271 | |||
| 272 | def __init__(self, depgraph): | ||
| 273 | Event.__init__(self) | ||
| 274 | self._depgraph = depgraph | ||
| 275 | |||
