1*4882a593Smuzhiyun""" 2*4882a593SmuzhiyunBitBake 'Event' implementation 3*4882a593Smuzhiyun 4*4882a593SmuzhiyunClasses and functions for manipulating 'events' in the 5*4882a593SmuzhiyunBitBake build tools. 6*4882a593Smuzhiyun""" 7*4882a593Smuzhiyun 8*4882a593Smuzhiyun# Copyright (C) 2003, 2004 Chris Larson 9*4882a593Smuzhiyun# 10*4882a593Smuzhiyun# SPDX-License-Identifier: GPL-2.0-only 11*4882a593Smuzhiyun# 12*4882a593Smuzhiyun 13*4882a593Smuzhiyunimport ast 14*4882a593Smuzhiyunimport atexit 15*4882a593Smuzhiyunimport collections 16*4882a593Smuzhiyunimport logging 17*4882a593Smuzhiyunimport pickle 18*4882a593Smuzhiyunimport sys 19*4882a593Smuzhiyunimport threading 20*4882a593Smuzhiyunimport traceback 21*4882a593Smuzhiyun 22*4882a593Smuzhiyunimport bb.exceptions 23*4882a593Smuzhiyunimport bb.utils 24*4882a593Smuzhiyun 25*4882a593Smuzhiyun# This is the pid for which we should generate the event. This is set when 26*4882a593Smuzhiyun# the runqueue forks off. 27*4882a593Smuzhiyunworker_pid = 0 28*4882a593Smuzhiyunworker_fire = None 29*4882a593Smuzhiyun 30*4882a593Smuzhiyunlogger = logging.getLogger('BitBake.Event') 31*4882a593Smuzhiyun 32*4882a593Smuzhiyunclass Event(object): 33*4882a593Smuzhiyun """Base class for events""" 34*4882a593Smuzhiyun 35*4882a593Smuzhiyun def __init__(self): 36*4882a593Smuzhiyun self.pid = worker_pid 37*4882a593Smuzhiyun 38*4882a593Smuzhiyun 39*4882a593Smuzhiyunclass HeartbeatEvent(Event): 40*4882a593Smuzhiyun """Triggered at regular time intervals of 10 seconds. Other events can fire much more often 41*4882a593Smuzhiyun (runQueueTaskStarted when there are many short tasks) or not at all for long periods 42*4882a593Smuzhiyun of time (again runQueueTaskStarted, when there is just one long-running task), so this 43*4882a593Smuzhiyun event is more suitable for doing some task-independent work occasionally.""" 44*4882a593Smuzhiyun def __init__(self, time): 45*4882a593Smuzhiyun Event.__init__(self) 46*4882a593Smuzhiyun self.time = time 47*4882a593Smuzhiyun 48*4882a593SmuzhiyunRegistered = 10 49*4882a593SmuzhiyunAlreadyRegistered = 14 50*4882a593Smuzhiyun 51*4882a593Smuzhiyundef get_class_handlers(): 52*4882a593Smuzhiyun return _handlers 53*4882a593Smuzhiyun 54*4882a593Smuzhiyundef set_class_handlers(h): 55*4882a593Smuzhiyun global _handlers 56*4882a593Smuzhiyun _handlers = h 57*4882a593Smuzhiyun 58*4882a593Smuzhiyundef clean_class_handlers(): 59*4882a593Smuzhiyun return collections.OrderedDict() 60*4882a593Smuzhiyun 61*4882a593Smuzhiyun# Internal 62*4882a593Smuzhiyun_handlers = clean_class_handlers() 63*4882a593Smuzhiyun_ui_handlers = {} 64*4882a593Smuzhiyun_ui_logfilters = {} 65*4882a593Smuzhiyun_ui_handler_seq = 0 66*4882a593Smuzhiyun_event_handler_map = {} 67*4882a593Smuzhiyun_catchall_handlers = {} 68*4882a593Smuzhiyun_eventfilter = None 69*4882a593Smuzhiyun_uiready = False 70*4882a593Smuzhiyun_thread_lock = threading.Lock() 71*4882a593Smuzhiyun_thread_lock_enabled = False 72*4882a593Smuzhiyun 73*4882a593Smuzhiyunif hasattr(__builtins__, '__setitem__'): 74*4882a593Smuzhiyun builtins = __builtins__ 75*4882a593Smuzhiyunelse: 76*4882a593Smuzhiyun builtins = __builtins__.__dict__ 77*4882a593Smuzhiyun 78*4882a593Smuzhiyundef enable_threadlock(): 79*4882a593Smuzhiyun global _thread_lock_enabled 80*4882a593Smuzhiyun _thread_lock_enabled = True 81*4882a593Smuzhiyun 82*4882a593Smuzhiyundef disable_threadlock(): 83*4882a593Smuzhiyun global _thread_lock_enabled 84*4882a593Smuzhiyun _thread_lock_enabled = False 85*4882a593Smuzhiyun 86*4882a593Smuzhiyundef execute_handler(name, handler, event, d): 87*4882a593Smuzhiyun event.data = d 88*4882a593Smuzhiyun addedd = False 89*4882a593Smuzhiyun if 'd' not in builtins: 90*4882a593Smuzhiyun builtins['d'] = d 91*4882a593Smuzhiyun addedd = True 92*4882a593Smuzhiyun try: 93*4882a593Smuzhiyun ret = handler(event) 94*4882a593Smuzhiyun except (bb.parse.SkipRecipe, bb.BBHandledException): 95*4882a593Smuzhiyun raise 96*4882a593Smuzhiyun except Exception: 97*4882a593Smuzhiyun etype, value, tb = sys.exc_info() 98*4882a593Smuzhiyun logger.error("Execution of event handler '%s' failed" % name, 99*4882a593Smuzhiyun exc_info=(etype, value, tb.tb_next)) 100*4882a593Smuzhiyun raise 101*4882a593Smuzhiyun except SystemExit as exc: 102*4882a593Smuzhiyun if exc.code != 0: 103*4882a593Smuzhiyun logger.error("Execution of event handler '%s' failed" % name) 104*4882a593Smuzhiyun raise 105*4882a593Smuzhiyun finally: 106*4882a593Smuzhiyun del event.data 107*4882a593Smuzhiyun if addedd: 108*4882a593Smuzhiyun del builtins['d'] 109*4882a593Smuzhiyun 110*4882a593Smuzhiyundef fire_class_handlers(event, d): 111*4882a593Smuzhiyun if isinstance(event, logging.LogRecord): 112*4882a593Smuzhiyun return 113*4882a593Smuzhiyun 114*4882a593Smuzhiyun eid = str(event.__class__)[8:-2] 115*4882a593Smuzhiyun evt_hmap = _event_handler_map.get(eid, {}) 116*4882a593Smuzhiyun for name, handler in list(_handlers.items()): 117*4882a593Smuzhiyun if name in _catchall_handlers or name in evt_hmap: 118*4882a593Smuzhiyun if _eventfilter: 119*4882a593Smuzhiyun if not _eventfilter(name, handler, event, d): 120*4882a593Smuzhiyun continue 121*4882a593Smuzhiyun if d is not None and not name in (d.getVar("__BBHANDLERS_MC") or set()): 122*4882a593Smuzhiyun continue 123*4882a593Smuzhiyun execute_handler(name, handler, event, d) 124*4882a593Smuzhiyun 125*4882a593Smuzhiyunui_queue = [] 126*4882a593Smuzhiyun@atexit.register 127*4882a593Smuzhiyundef print_ui_queue(): 128*4882a593Smuzhiyun global ui_queue 129*4882a593Smuzhiyun """If we're exiting before a UI has been spawned, display any queued 130*4882a593Smuzhiyun LogRecords to the console.""" 131*4882a593Smuzhiyun logger = logging.getLogger("BitBake") 132*4882a593Smuzhiyun if not _uiready: 133*4882a593Smuzhiyun from bb.msg import BBLogFormatter 134*4882a593Smuzhiyun # Flush any existing buffered content 135*4882a593Smuzhiyun try: 136*4882a593Smuzhiyun sys.stdout.flush() 137*4882a593Smuzhiyun except: 138*4882a593Smuzhiyun pass 139*4882a593Smuzhiyun try: 140*4882a593Smuzhiyun sys.stderr.flush() 141*4882a593Smuzhiyun except: 142*4882a593Smuzhiyun pass 143*4882a593Smuzhiyun stdout = logging.StreamHandler(sys.stdout) 144*4882a593Smuzhiyun stderr = logging.StreamHandler(sys.stderr) 145*4882a593Smuzhiyun formatter = BBLogFormatter("%(levelname)s: %(message)s") 146*4882a593Smuzhiyun stdout.setFormatter(formatter) 147*4882a593Smuzhiyun stderr.setFormatter(formatter) 148*4882a593Smuzhiyun 149*4882a593Smuzhiyun # First check to see if we have any proper messages 150*4882a593Smuzhiyun msgprint = False 151*4882a593Smuzhiyun msgerrs = False 152*4882a593Smuzhiyun 153*4882a593Smuzhiyun # Should we print to stderr? 154*4882a593Smuzhiyun for event in ui_queue[:]: 155*4882a593Smuzhiyun if isinstance(event, logging.LogRecord) and event.levelno >= logging.WARNING: 156*4882a593Smuzhiyun msgerrs = True 157*4882a593Smuzhiyun break 158*4882a593Smuzhiyun 159*4882a593Smuzhiyun if msgerrs: 160*4882a593Smuzhiyun logger.addHandler(stderr) 161*4882a593Smuzhiyun else: 162*4882a593Smuzhiyun logger.addHandler(stdout) 163*4882a593Smuzhiyun 164*4882a593Smuzhiyun for event in ui_queue[:]: 165*4882a593Smuzhiyun if isinstance(event, logging.LogRecord): 166*4882a593Smuzhiyun if event.levelno > logging.DEBUG: 167*4882a593Smuzhiyun logger.handle(event) 168*4882a593Smuzhiyun msgprint = True 169*4882a593Smuzhiyun 170*4882a593Smuzhiyun # Nope, so just print all of the messages we have (including debug messages) 171*4882a593Smuzhiyun if not msgprint: 172*4882a593Smuzhiyun for event in ui_queue[:]: 173*4882a593Smuzhiyun if isinstance(event, logging.LogRecord): 174*4882a593Smuzhiyun logger.handle(event) 175*4882a593Smuzhiyun if msgerrs: 176*4882a593Smuzhiyun logger.removeHandler(stderr) 177*4882a593Smuzhiyun else: 178*4882a593Smuzhiyun logger.removeHandler(stdout) 179*4882a593Smuzhiyun ui_queue = [] 180*4882a593Smuzhiyun 181*4882a593Smuzhiyundef fire_ui_handlers(event, d): 182*4882a593Smuzhiyun global _thread_lock 183*4882a593Smuzhiyun global _thread_lock_enabled 184*4882a593Smuzhiyun 185*4882a593Smuzhiyun if not _uiready: 186*4882a593Smuzhiyun # No UI handlers registered yet, queue up the messages 187*4882a593Smuzhiyun ui_queue.append(event) 188*4882a593Smuzhiyun return 189*4882a593Smuzhiyun 190*4882a593Smuzhiyun if _thread_lock_enabled: 191*4882a593Smuzhiyun _thread_lock.acquire() 192*4882a593Smuzhiyun 193*4882a593Smuzhiyun errors = [] 194*4882a593Smuzhiyun for h in _ui_handlers: 195*4882a593Smuzhiyun #print "Sending event %s" % event 196*4882a593Smuzhiyun try: 197*4882a593Smuzhiyun if not _ui_logfilters[h].filter(event): 198*4882a593Smuzhiyun continue 199*4882a593Smuzhiyun # We use pickle here since it better handles object instances 200*4882a593Smuzhiyun # which xmlrpc's marshaller does not. Events *must* be serializable 201*4882a593Smuzhiyun # by pickle. 202*4882a593Smuzhiyun if hasattr(_ui_handlers[h].event, "sendpickle"): 203*4882a593Smuzhiyun _ui_handlers[h].event.sendpickle((pickle.dumps(event))) 204*4882a593Smuzhiyun else: 205*4882a593Smuzhiyun _ui_handlers[h].event.send(event) 206*4882a593Smuzhiyun except: 207*4882a593Smuzhiyun errors.append(h) 208*4882a593Smuzhiyun for h in errors: 209*4882a593Smuzhiyun del _ui_handlers[h] 210*4882a593Smuzhiyun 211*4882a593Smuzhiyun if _thread_lock_enabled: 212*4882a593Smuzhiyun _thread_lock.release() 213*4882a593Smuzhiyun 214*4882a593Smuzhiyundef fire(event, d): 215*4882a593Smuzhiyun """Fire off an Event""" 216*4882a593Smuzhiyun 217*4882a593Smuzhiyun # We can fire class handlers in the worker process context and this is 218*4882a593Smuzhiyun # desired so they get the task based datastore. 219*4882a593Smuzhiyun # UI handlers need to be fired in the server context so we defer this. They 220*4882a593Smuzhiyun # don't have a datastore so the datastore context isn't a problem. 221*4882a593Smuzhiyun 222*4882a593Smuzhiyun fire_class_handlers(event, d) 223*4882a593Smuzhiyun if worker_fire: 224*4882a593Smuzhiyun worker_fire(event, d) 225*4882a593Smuzhiyun else: 226*4882a593Smuzhiyun # If messages have been queued up, clear the queue 227*4882a593Smuzhiyun global _uiready, ui_queue 228*4882a593Smuzhiyun if _uiready and ui_queue: 229*4882a593Smuzhiyun for queue_event in ui_queue: 230*4882a593Smuzhiyun fire_ui_handlers(queue_event, d) 231*4882a593Smuzhiyun ui_queue = [] 232*4882a593Smuzhiyun fire_ui_handlers(event, d) 233*4882a593Smuzhiyun 234*4882a593Smuzhiyundef fire_from_worker(event, d): 235*4882a593Smuzhiyun fire_ui_handlers(event, d) 236*4882a593Smuzhiyun 237*4882a593Smuzhiyunnoop = lambda _: None 238*4882a593Smuzhiyundef register(name, handler, mask=None, filename=None, lineno=None, data=None): 239*4882a593Smuzhiyun """Register an Event handler""" 240*4882a593Smuzhiyun 241*4882a593Smuzhiyun if data is not None and data.getVar("BB_CURRENT_MC"): 242*4882a593Smuzhiyun mc = data.getVar("BB_CURRENT_MC") 243*4882a593Smuzhiyun name = '%s%s' % (mc.replace('-', '_'), name) 244*4882a593Smuzhiyun 245*4882a593Smuzhiyun # already registered 246*4882a593Smuzhiyun if name in _handlers: 247*4882a593Smuzhiyun if data is not None: 248*4882a593Smuzhiyun bbhands_mc = (data.getVar("__BBHANDLERS_MC") or set()) 249*4882a593Smuzhiyun bbhands_mc.add(name) 250*4882a593Smuzhiyun data.setVar("__BBHANDLERS_MC", bbhands_mc) 251*4882a593Smuzhiyun return AlreadyRegistered 252*4882a593Smuzhiyun 253*4882a593Smuzhiyun if handler is not None: 254*4882a593Smuzhiyun # handle string containing python code 255*4882a593Smuzhiyun if isinstance(handler, str): 256*4882a593Smuzhiyun tmp = "def %s(e):\n%s" % (name, handler) 257*4882a593Smuzhiyun try: 258*4882a593Smuzhiyun code = bb.methodpool.compile_cache(tmp) 259*4882a593Smuzhiyun if not code: 260*4882a593Smuzhiyun if filename is None: 261*4882a593Smuzhiyun filename = "%s(e)" % name 262*4882a593Smuzhiyun code = compile(tmp, filename, "exec", ast.PyCF_ONLY_AST) 263*4882a593Smuzhiyun if lineno is not None: 264*4882a593Smuzhiyun ast.increment_lineno(code, lineno-1) 265*4882a593Smuzhiyun code = compile(code, filename, "exec") 266*4882a593Smuzhiyun bb.methodpool.compile_cache_add(tmp, code) 267*4882a593Smuzhiyun except SyntaxError: 268*4882a593Smuzhiyun logger.error("Unable to register event handler '%s':\n%s", name, 269*4882a593Smuzhiyun ''.join(traceback.format_exc(limit=0))) 270*4882a593Smuzhiyun _handlers[name] = noop 271*4882a593Smuzhiyun return 272*4882a593Smuzhiyun env = {} 273*4882a593Smuzhiyun bb.utils.better_exec(code, env) 274*4882a593Smuzhiyun func = bb.utils.better_eval(name, env) 275*4882a593Smuzhiyun _handlers[name] = func 276*4882a593Smuzhiyun else: 277*4882a593Smuzhiyun _handlers[name] = handler 278*4882a593Smuzhiyun 279*4882a593Smuzhiyun if not mask or '*' in mask: 280*4882a593Smuzhiyun _catchall_handlers[name] = True 281*4882a593Smuzhiyun else: 282*4882a593Smuzhiyun for m in mask: 283*4882a593Smuzhiyun if _event_handler_map.get(m, None) is None: 284*4882a593Smuzhiyun _event_handler_map[m] = {} 285*4882a593Smuzhiyun _event_handler_map[m][name] = True 286*4882a593Smuzhiyun 287*4882a593Smuzhiyun if data is not None: 288*4882a593Smuzhiyun bbhands_mc = (data.getVar("__BBHANDLERS_MC") or set()) 289*4882a593Smuzhiyun bbhands_mc.add(name) 290*4882a593Smuzhiyun data.setVar("__BBHANDLERS_MC", bbhands_mc) 291*4882a593Smuzhiyun 292*4882a593Smuzhiyun return Registered 293*4882a593Smuzhiyun 294*4882a593Smuzhiyundef remove(name, handler, data=None): 295*4882a593Smuzhiyun """Remove an Event handler""" 296*4882a593Smuzhiyun if data is not None: 297*4882a593Smuzhiyun if data.getVar("BB_CURRENT_MC"): 298*4882a593Smuzhiyun mc = data.getVar("BB_CURRENT_MC") 299*4882a593Smuzhiyun name = '%s%s' % (mc.replace('-', '_'), name) 300*4882a593Smuzhiyun 301*4882a593Smuzhiyun _handlers.pop(name) 302*4882a593Smuzhiyun if name in _catchall_handlers: 303*4882a593Smuzhiyun _catchall_handlers.pop(name) 304*4882a593Smuzhiyun for event in _event_handler_map.keys(): 305*4882a593Smuzhiyun if name in _event_handler_map[event]: 306*4882a593Smuzhiyun _event_handler_map[event].pop(name) 307*4882a593Smuzhiyun 308*4882a593Smuzhiyun if data is not None: 309*4882a593Smuzhiyun bbhands_mc = (data.getVar("__BBHANDLERS_MC") or set()) 310*4882a593Smuzhiyun if name in bbhands_mc: 311*4882a593Smuzhiyun bbhands_mc.remove(name) 312*4882a593Smuzhiyun data.setVar("__BBHANDLERS_MC", bbhands_mc) 313*4882a593Smuzhiyun 314*4882a593Smuzhiyundef get_handlers(): 315*4882a593Smuzhiyun return _handlers 316*4882a593Smuzhiyun 317*4882a593Smuzhiyundef set_handlers(handlers): 318*4882a593Smuzhiyun global _handlers 319*4882a593Smuzhiyun _handlers = handlers 320*4882a593Smuzhiyun 321*4882a593Smuzhiyundef set_eventfilter(func): 322*4882a593Smuzhiyun global _eventfilter 323*4882a593Smuzhiyun _eventfilter = func 324*4882a593Smuzhiyun 325*4882a593Smuzhiyundef register_UIHhandler(handler, mainui=False): 326*4882a593Smuzhiyun bb.event._ui_handler_seq = bb.event._ui_handler_seq + 1 327*4882a593Smuzhiyun _ui_handlers[_ui_handler_seq] = handler 328*4882a593Smuzhiyun level, debug_domains = bb.msg.constructLogOptions() 329*4882a593Smuzhiyun _ui_logfilters[_ui_handler_seq] = UIEventFilter(level, debug_domains) 330*4882a593Smuzhiyun if mainui: 331*4882a593Smuzhiyun global _uiready 332*4882a593Smuzhiyun _uiready = _ui_handler_seq 333*4882a593Smuzhiyun return _ui_handler_seq 334*4882a593Smuzhiyun 335*4882a593Smuzhiyundef unregister_UIHhandler(handlerNum, mainui=False): 336*4882a593Smuzhiyun if mainui: 337*4882a593Smuzhiyun global _uiready 338*4882a593Smuzhiyun _uiready = False 339*4882a593Smuzhiyun if handlerNum in _ui_handlers: 340*4882a593Smuzhiyun del _ui_handlers[handlerNum] 341*4882a593Smuzhiyun return 342*4882a593Smuzhiyun 343*4882a593Smuzhiyundef get_uihandler(): 344*4882a593Smuzhiyun if _uiready is False: 345*4882a593Smuzhiyun return None 346*4882a593Smuzhiyun return _uiready 347*4882a593Smuzhiyun 348*4882a593Smuzhiyun# Class to allow filtering of events and specific filtering of LogRecords *before* we put them over the IPC 349*4882a593Smuzhiyunclass UIEventFilter(object): 350*4882a593Smuzhiyun def __init__(self, level, debug_domains): 351*4882a593Smuzhiyun self.update(None, level, debug_domains) 352*4882a593Smuzhiyun 353*4882a593Smuzhiyun def update(self, eventmask, level, debug_domains): 354*4882a593Smuzhiyun self.eventmask = eventmask 355*4882a593Smuzhiyun self.stdlevel = level 356*4882a593Smuzhiyun self.debug_domains = debug_domains 357*4882a593Smuzhiyun 358*4882a593Smuzhiyun def filter(self, event): 359*4882a593Smuzhiyun if isinstance(event, logging.LogRecord): 360*4882a593Smuzhiyun if event.levelno >= self.stdlevel: 361*4882a593Smuzhiyun return True 362*4882a593Smuzhiyun if event.name in self.debug_domains and event.levelno >= self.debug_domains[event.name]: 363*4882a593Smuzhiyun return True 364*4882a593Smuzhiyun return False 365*4882a593Smuzhiyun eid = str(event.__class__)[8:-2] 366*4882a593Smuzhiyun if self.eventmask and eid not in self.eventmask: 367*4882a593Smuzhiyun return False 368*4882a593Smuzhiyun return True 369*4882a593Smuzhiyun 370*4882a593Smuzhiyundef set_UIHmask(handlerNum, level, debug_domains, mask): 371*4882a593Smuzhiyun if not handlerNum in _ui_handlers: 372*4882a593Smuzhiyun return False 373*4882a593Smuzhiyun if '*' in mask: 374*4882a593Smuzhiyun _ui_logfilters[handlerNum].update(None, level, debug_domains) 375*4882a593Smuzhiyun else: 376*4882a593Smuzhiyun _ui_logfilters[handlerNum].update(mask, level, debug_domains) 377*4882a593Smuzhiyun return True 378*4882a593Smuzhiyun 379*4882a593Smuzhiyundef getName(e): 380*4882a593Smuzhiyun """Returns the name of a class or class instance""" 381*4882a593Smuzhiyun if getattr(e, "__name__", None) is None: 382*4882a593Smuzhiyun return e.__class__.__name__ 383*4882a593Smuzhiyun else: 384*4882a593Smuzhiyun return e.__name__ 385*4882a593Smuzhiyun 386*4882a593Smuzhiyunclass OperationStarted(Event): 387*4882a593Smuzhiyun """An operation has begun""" 388*4882a593Smuzhiyun def __init__(self, msg = "Operation Started"): 389*4882a593Smuzhiyun Event.__init__(self) 390*4882a593Smuzhiyun self.msg = msg 391*4882a593Smuzhiyun 392*4882a593Smuzhiyunclass OperationCompleted(Event): 393*4882a593Smuzhiyun """An operation has completed""" 394*4882a593Smuzhiyun def __init__(self, total, msg = "Operation Completed"): 395*4882a593Smuzhiyun Event.__init__(self) 396*4882a593Smuzhiyun self.total = total 397*4882a593Smuzhiyun self.msg = msg 398*4882a593Smuzhiyun 399*4882a593Smuzhiyunclass OperationProgress(Event): 400*4882a593Smuzhiyun """An operation is in progress""" 401*4882a593Smuzhiyun def __init__(self, current, total, msg = "Operation in Progress"): 402*4882a593Smuzhiyun Event.__init__(self) 403*4882a593Smuzhiyun self.current = current 404*4882a593Smuzhiyun self.total = total 405*4882a593Smuzhiyun self.msg = msg + ": %s/%s" % (current, total); 406*4882a593Smuzhiyun 407*4882a593Smuzhiyunclass ConfigParsed(Event): 408*4882a593Smuzhiyun """Configuration Parsing Complete""" 409*4882a593Smuzhiyun 410*4882a593Smuzhiyunclass MultiConfigParsed(Event): 411*4882a593Smuzhiyun """Multi-Config Parsing Complete""" 412*4882a593Smuzhiyun def __init__(self, mcdata): 413*4882a593Smuzhiyun self.mcdata = mcdata 414*4882a593Smuzhiyun Event.__init__(self) 415*4882a593Smuzhiyun 416*4882a593Smuzhiyunclass RecipeEvent(Event): 417*4882a593Smuzhiyun def __init__(self, fn): 418*4882a593Smuzhiyun self.fn = fn 419*4882a593Smuzhiyun Event.__init__(self) 420*4882a593Smuzhiyun 421*4882a593Smuzhiyunclass RecipePreFinalise(RecipeEvent): 422*4882a593Smuzhiyun """ Recipe Parsing Complete but not yet finalised""" 423*4882a593Smuzhiyun 424*4882a593Smuzhiyunclass RecipePostKeyExpansion(RecipeEvent): 425*4882a593Smuzhiyun """ Recipe Parsing Complete but not yet finalised""" 426*4882a593Smuzhiyun 427*4882a593Smuzhiyun 428*4882a593Smuzhiyunclass RecipeTaskPreProcess(RecipeEvent): 429*4882a593Smuzhiyun """ 430*4882a593Smuzhiyun Recipe Tasks about to be finalised 431*4882a593Smuzhiyun The list of tasks should be final at this point and handlers 432*4882a593Smuzhiyun are only able to change interdependencies 433*4882a593Smuzhiyun """ 434*4882a593Smuzhiyun def __init__(self, fn, tasklist): 435*4882a593Smuzhiyun self.fn = fn 436*4882a593Smuzhiyun self.tasklist = tasklist 437*4882a593Smuzhiyun Event.__init__(self) 438*4882a593Smuzhiyun 439*4882a593Smuzhiyunclass RecipeParsed(RecipeEvent): 440*4882a593Smuzhiyun """ Recipe Parsing Complete """ 441*4882a593Smuzhiyun 442*4882a593Smuzhiyunclass BuildBase(Event): 443*4882a593Smuzhiyun """Base class for bitbake build events""" 444*4882a593Smuzhiyun 445*4882a593Smuzhiyun def __init__(self, n, p, failures = 0): 446*4882a593Smuzhiyun self._name = n 447*4882a593Smuzhiyun self._pkgs = p 448*4882a593Smuzhiyun Event.__init__(self) 449*4882a593Smuzhiyun self._failures = failures 450*4882a593Smuzhiyun 451*4882a593Smuzhiyun def getPkgs(self): 452*4882a593Smuzhiyun return self._pkgs 453*4882a593Smuzhiyun 454*4882a593Smuzhiyun def setPkgs(self, pkgs): 455*4882a593Smuzhiyun self._pkgs = pkgs 456*4882a593Smuzhiyun 457*4882a593Smuzhiyun def getName(self): 458*4882a593Smuzhiyun return self._name 459*4882a593Smuzhiyun 460*4882a593Smuzhiyun def setName(self, name): 461*4882a593Smuzhiyun self._name = name 462*4882a593Smuzhiyun 463*4882a593Smuzhiyun def getFailures(self): 464*4882a593Smuzhiyun """ 465*4882a593Smuzhiyun Return the number of failed packages 466*4882a593Smuzhiyun """ 467*4882a593Smuzhiyun return self._failures 468*4882a593Smuzhiyun 469*4882a593Smuzhiyun pkgs = property(getPkgs, setPkgs, None, "pkgs property") 470*4882a593Smuzhiyun name = property(getName, setName, None, "name property") 471*4882a593Smuzhiyun 472*4882a593Smuzhiyunclass BuildInit(BuildBase): 473*4882a593Smuzhiyun """buildFile or buildTargets was invoked""" 474*4882a593Smuzhiyun def __init__(self, p=[]): 475*4882a593Smuzhiyun name = None 476*4882a593Smuzhiyun BuildBase.__init__(self, name, p) 477*4882a593Smuzhiyun 478*4882a593Smuzhiyunclass BuildStarted(BuildBase, OperationStarted): 479*4882a593Smuzhiyun """Event when builds start""" 480*4882a593Smuzhiyun def __init__(self, n, p, failures = 0): 481*4882a593Smuzhiyun OperationStarted.__init__(self, "Building Started") 482*4882a593Smuzhiyun BuildBase.__init__(self, n, p, failures) 483*4882a593Smuzhiyun 484*4882a593Smuzhiyunclass BuildCompleted(BuildBase, OperationCompleted): 485*4882a593Smuzhiyun """Event when builds have completed""" 486*4882a593Smuzhiyun def __init__(self, total, n, p, failures=0, interrupted=0): 487*4882a593Smuzhiyun if not failures: 488*4882a593Smuzhiyun OperationCompleted.__init__(self, total, "Building Succeeded") 489*4882a593Smuzhiyun else: 490*4882a593Smuzhiyun OperationCompleted.__init__(self, total, "Building Failed") 491*4882a593Smuzhiyun self._interrupted = interrupted 492*4882a593Smuzhiyun BuildBase.__init__(self, n, p, failures) 493*4882a593Smuzhiyun 494*4882a593Smuzhiyunclass DiskFull(Event): 495*4882a593Smuzhiyun """Disk full case build halted""" 496*4882a593Smuzhiyun def __init__(self, dev, type, freespace, mountpoint): 497*4882a593Smuzhiyun Event.__init__(self) 498*4882a593Smuzhiyun self._dev = dev 499*4882a593Smuzhiyun self._type = type 500*4882a593Smuzhiyun self._free = freespace 501*4882a593Smuzhiyun self._mountpoint = mountpoint 502*4882a593Smuzhiyun 503*4882a593Smuzhiyunclass DiskUsageSample: 504*4882a593Smuzhiyun def __init__(self, available_bytes, free_bytes, total_bytes): 505*4882a593Smuzhiyun # Number of bytes available to non-root processes. 506*4882a593Smuzhiyun self.available_bytes = available_bytes 507*4882a593Smuzhiyun # Number of bytes available to root processes. 508*4882a593Smuzhiyun self.free_bytes = free_bytes 509*4882a593Smuzhiyun # Total capacity of the volume. 510*4882a593Smuzhiyun self.total_bytes = total_bytes 511*4882a593Smuzhiyun 512*4882a593Smuzhiyunclass MonitorDiskEvent(Event): 513*4882a593Smuzhiyun """If BB_DISKMON_DIRS is set, then this event gets triggered each time disk space is checked. 514*4882a593Smuzhiyun Provides information about devices that are getting monitored.""" 515*4882a593Smuzhiyun def __init__(self, disk_usage): 516*4882a593Smuzhiyun Event.__init__(self) 517*4882a593Smuzhiyun # hash of device root path -> DiskUsageSample 518*4882a593Smuzhiyun self.disk_usage = disk_usage 519*4882a593Smuzhiyun 520*4882a593Smuzhiyunclass NoProvider(Event): 521*4882a593Smuzhiyun """No Provider for an Event""" 522*4882a593Smuzhiyun 523*4882a593Smuzhiyun def __init__(self, item, runtime=False, dependees=None, reasons=None, close_matches=None): 524*4882a593Smuzhiyun Event.__init__(self) 525*4882a593Smuzhiyun self._item = item 526*4882a593Smuzhiyun self._runtime = runtime 527*4882a593Smuzhiyun self._dependees = dependees 528*4882a593Smuzhiyun self._reasons = reasons 529*4882a593Smuzhiyun self._close_matches = close_matches 530*4882a593Smuzhiyun 531*4882a593Smuzhiyun def getItem(self): 532*4882a593Smuzhiyun return self._item 533*4882a593Smuzhiyun 534*4882a593Smuzhiyun def isRuntime(self): 535*4882a593Smuzhiyun return self._runtime 536*4882a593Smuzhiyun 537*4882a593Smuzhiyun def __str__(self): 538*4882a593Smuzhiyun msg = '' 539*4882a593Smuzhiyun if self._runtime: 540*4882a593Smuzhiyun r = "R" 541*4882a593Smuzhiyun else: 542*4882a593Smuzhiyun r = "" 543*4882a593Smuzhiyun 544*4882a593Smuzhiyun extra = '' 545*4882a593Smuzhiyun if not self._reasons: 546*4882a593Smuzhiyun if self._close_matches: 547*4882a593Smuzhiyun extra = ". Close matches:\n %s" % '\n '.join(sorted(set(self._close_matches))) 548*4882a593Smuzhiyun 549*4882a593Smuzhiyun if self._dependees: 550*4882a593Smuzhiyun msg = "Nothing %sPROVIDES '%s' (but %s %sDEPENDS on or otherwise requires it)%s" % (r, self._item, ", ".join(self._dependees), r, extra) 551*4882a593Smuzhiyun else: 552*4882a593Smuzhiyun msg = "Nothing %sPROVIDES '%s'%s" % (r, self._item, extra) 553*4882a593Smuzhiyun if self._reasons: 554*4882a593Smuzhiyun for reason in self._reasons: 555*4882a593Smuzhiyun msg += '\n' + reason 556*4882a593Smuzhiyun return msg 557*4882a593Smuzhiyun 558*4882a593Smuzhiyun 559*4882a593Smuzhiyunclass MultipleProviders(Event): 560*4882a593Smuzhiyun """Multiple Providers""" 561*4882a593Smuzhiyun 562*4882a593Smuzhiyun def __init__(self, item, candidates, runtime = False): 563*4882a593Smuzhiyun Event.__init__(self) 564*4882a593Smuzhiyun self._item = item 565*4882a593Smuzhiyun self._candidates = candidates 566*4882a593Smuzhiyun self._is_runtime = runtime 567*4882a593Smuzhiyun 568*4882a593Smuzhiyun def isRuntime(self): 569*4882a593Smuzhiyun """ 570*4882a593Smuzhiyun Is this a runtime issue? 571*4882a593Smuzhiyun """ 572*4882a593Smuzhiyun return self._is_runtime 573*4882a593Smuzhiyun 574*4882a593Smuzhiyun def getItem(self): 575*4882a593Smuzhiyun """ 576*4882a593Smuzhiyun The name for the to be build item 577*4882a593Smuzhiyun """ 578*4882a593Smuzhiyun return self._item 579*4882a593Smuzhiyun 580*4882a593Smuzhiyun def getCandidates(self): 581*4882a593Smuzhiyun """ 582*4882a593Smuzhiyun Get the possible Candidates for a PROVIDER. 583*4882a593Smuzhiyun """ 584*4882a593Smuzhiyun return self._candidates 585*4882a593Smuzhiyun 586*4882a593Smuzhiyun def __str__(self): 587*4882a593Smuzhiyun msg = "Multiple providers are available for %s%s (%s)" % (self._is_runtime and "runtime " or "", 588*4882a593Smuzhiyun self._item, 589*4882a593Smuzhiyun ", ".join(self._candidates)) 590*4882a593Smuzhiyun rtime = "" 591*4882a593Smuzhiyun if self._is_runtime: 592*4882a593Smuzhiyun rtime = "R" 593*4882a593Smuzhiyun msg += "\nConsider defining a PREFERRED_%sPROVIDER entry to match %s" % (rtime, self._item) 594*4882a593Smuzhiyun return msg 595*4882a593Smuzhiyun 596*4882a593Smuzhiyunclass ParseStarted(OperationStarted): 597*4882a593Smuzhiyun """Recipe parsing for the runqueue has begun""" 598*4882a593Smuzhiyun def __init__(self, total): 599*4882a593Smuzhiyun OperationStarted.__init__(self, "Recipe parsing Started") 600*4882a593Smuzhiyun self.total = total 601*4882a593Smuzhiyun 602*4882a593Smuzhiyunclass ParseCompleted(OperationCompleted): 603*4882a593Smuzhiyun """Recipe parsing for the runqueue has completed""" 604*4882a593Smuzhiyun def __init__(self, cached, parsed, skipped, masked, virtuals, errors, total): 605*4882a593Smuzhiyun OperationCompleted.__init__(self, total, "Recipe parsing Completed") 606*4882a593Smuzhiyun self.cached = cached 607*4882a593Smuzhiyun self.parsed = parsed 608*4882a593Smuzhiyun self.skipped = skipped 609*4882a593Smuzhiyun self.virtuals = virtuals 610*4882a593Smuzhiyun self.masked = masked 611*4882a593Smuzhiyun self.errors = errors 612*4882a593Smuzhiyun self.sofar = cached + parsed 613*4882a593Smuzhiyun 614*4882a593Smuzhiyunclass ParseProgress(OperationProgress): 615*4882a593Smuzhiyun """Recipe parsing progress""" 616*4882a593Smuzhiyun def __init__(self, current, total): 617*4882a593Smuzhiyun OperationProgress.__init__(self, current, total, "Recipe parsing") 618*4882a593Smuzhiyun 619*4882a593Smuzhiyun 620*4882a593Smuzhiyunclass CacheLoadStarted(OperationStarted): 621*4882a593Smuzhiyun """Loading of the dependency cache has begun""" 622*4882a593Smuzhiyun def __init__(self, total): 623*4882a593Smuzhiyun OperationStarted.__init__(self, "Loading cache Started") 624*4882a593Smuzhiyun self.total = total 625*4882a593Smuzhiyun 626*4882a593Smuzhiyunclass CacheLoadProgress(OperationProgress): 627*4882a593Smuzhiyun """Cache loading progress""" 628*4882a593Smuzhiyun def __init__(self, current, total): 629*4882a593Smuzhiyun OperationProgress.__init__(self, current, total, "Loading cache") 630*4882a593Smuzhiyun 631*4882a593Smuzhiyunclass CacheLoadCompleted(OperationCompleted): 632*4882a593Smuzhiyun """Cache loading is complete""" 633*4882a593Smuzhiyun def __init__(self, total, num_entries): 634*4882a593Smuzhiyun OperationCompleted.__init__(self, total, "Loading cache Completed") 635*4882a593Smuzhiyun self.num_entries = num_entries 636*4882a593Smuzhiyun 637*4882a593Smuzhiyunclass TreeDataPreparationStarted(OperationStarted): 638*4882a593Smuzhiyun """Tree data preparation started""" 639*4882a593Smuzhiyun def __init__(self): 640*4882a593Smuzhiyun OperationStarted.__init__(self, "Preparing tree data Started") 641*4882a593Smuzhiyun 642*4882a593Smuzhiyunclass TreeDataPreparationProgress(OperationProgress): 643*4882a593Smuzhiyun """Tree data preparation is in progress""" 644*4882a593Smuzhiyun def __init__(self, current, total): 645*4882a593Smuzhiyun OperationProgress.__init__(self, current, total, "Preparing tree data") 646*4882a593Smuzhiyun 647*4882a593Smuzhiyunclass TreeDataPreparationCompleted(OperationCompleted): 648*4882a593Smuzhiyun """Tree data preparation completed""" 649*4882a593Smuzhiyun def __init__(self, total): 650*4882a593Smuzhiyun OperationCompleted.__init__(self, total, "Preparing tree data Completed") 651*4882a593Smuzhiyun 652*4882a593Smuzhiyunclass DepTreeGenerated(Event): 653*4882a593Smuzhiyun """ 654*4882a593Smuzhiyun Event when a dependency tree has been generated 655*4882a593Smuzhiyun """ 656*4882a593Smuzhiyun 657*4882a593Smuzhiyun def __init__(self, depgraph): 658*4882a593Smuzhiyun Event.__init__(self) 659*4882a593Smuzhiyun self._depgraph = depgraph 660*4882a593Smuzhiyun 661*4882a593Smuzhiyunclass TargetsTreeGenerated(Event): 662*4882a593Smuzhiyun """ 663*4882a593Smuzhiyun Event when a set of buildable targets has been generated 664*4882a593Smuzhiyun """ 665*4882a593Smuzhiyun def __init__(self, model): 666*4882a593Smuzhiyun Event.__init__(self) 667*4882a593Smuzhiyun self._model = model 668*4882a593Smuzhiyun 669*4882a593Smuzhiyunclass ReachableStamps(Event): 670*4882a593Smuzhiyun """ 671*4882a593Smuzhiyun An event listing all stamps reachable after parsing 672*4882a593Smuzhiyun which the metadata may use to clean up stale data 673*4882a593Smuzhiyun """ 674*4882a593Smuzhiyun 675*4882a593Smuzhiyun def __init__(self, stamps): 676*4882a593Smuzhiyun Event.__init__(self) 677*4882a593Smuzhiyun self.stamps = stamps 678*4882a593Smuzhiyun 679*4882a593Smuzhiyunclass StaleSetSceneTasks(Event): 680*4882a593Smuzhiyun """ 681*4882a593Smuzhiyun An event listing setscene tasks which are 'stale' and will 682*4882a593Smuzhiyun be rerun. The metadata may use to clean up stale data. 683*4882a593Smuzhiyun tasks is a mapping of tasks and matching stale stamps. 684*4882a593Smuzhiyun """ 685*4882a593Smuzhiyun 686*4882a593Smuzhiyun def __init__(self, tasks): 687*4882a593Smuzhiyun Event.__init__(self) 688*4882a593Smuzhiyun self.tasks = tasks 689*4882a593Smuzhiyun 690*4882a593Smuzhiyunclass FilesMatchingFound(Event): 691*4882a593Smuzhiyun """ 692*4882a593Smuzhiyun Event when a list of files matching the supplied pattern has 693*4882a593Smuzhiyun been generated 694*4882a593Smuzhiyun """ 695*4882a593Smuzhiyun def __init__(self, pattern, matches): 696*4882a593Smuzhiyun Event.__init__(self) 697*4882a593Smuzhiyun self._pattern = pattern 698*4882a593Smuzhiyun self._matches = matches 699*4882a593Smuzhiyun 700*4882a593Smuzhiyunclass ConfigFilesFound(Event): 701*4882a593Smuzhiyun """ 702*4882a593Smuzhiyun Event when a list of appropriate config files has been generated 703*4882a593Smuzhiyun """ 704*4882a593Smuzhiyun def __init__(self, variable, values): 705*4882a593Smuzhiyun Event.__init__(self) 706*4882a593Smuzhiyun self._variable = variable 707*4882a593Smuzhiyun self._values = values 708*4882a593Smuzhiyun 709*4882a593Smuzhiyunclass ConfigFilePathFound(Event): 710*4882a593Smuzhiyun """ 711*4882a593Smuzhiyun Event when a path for a config file has been found 712*4882a593Smuzhiyun """ 713*4882a593Smuzhiyun def __init__(self, path): 714*4882a593Smuzhiyun Event.__init__(self) 715*4882a593Smuzhiyun self._path = path 716*4882a593Smuzhiyun 717*4882a593Smuzhiyunclass MsgBase(Event): 718*4882a593Smuzhiyun """Base class for messages""" 719*4882a593Smuzhiyun 720*4882a593Smuzhiyun def __init__(self, msg): 721*4882a593Smuzhiyun self._message = msg 722*4882a593Smuzhiyun Event.__init__(self) 723*4882a593Smuzhiyun 724*4882a593Smuzhiyunclass MsgDebug(MsgBase): 725*4882a593Smuzhiyun """Debug Message""" 726*4882a593Smuzhiyun 727*4882a593Smuzhiyunclass MsgNote(MsgBase): 728*4882a593Smuzhiyun """Note Message""" 729*4882a593Smuzhiyun 730*4882a593Smuzhiyunclass MsgWarn(MsgBase): 731*4882a593Smuzhiyun """Warning Message""" 732*4882a593Smuzhiyun 733*4882a593Smuzhiyunclass MsgError(MsgBase): 734*4882a593Smuzhiyun """Error Message""" 735*4882a593Smuzhiyun 736*4882a593Smuzhiyunclass MsgFatal(MsgBase): 737*4882a593Smuzhiyun """Fatal Message""" 738*4882a593Smuzhiyun 739*4882a593Smuzhiyunclass MsgPlain(MsgBase): 740*4882a593Smuzhiyun """General output""" 741*4882a593Smuzhiyun 742*4882a593Smuzhiyunclass LogExecTTY(Event): 743*4882a593Smuzhiyun """Send event containing program to spawn on tty of the logger""" 744*4882a593Smuzhiyun def __init__(self, msg, prog, sleep_delay, retries): 745*4882a593Smuzhiyun Event.__init__(self) 746*4882a593Smuzhiyun self.msg = msg 747*4882a593Smuzhiyun self.prog = prog 748*4882a593Smuzhiyun self.sleep_delay = sleep_delay 749*4882a593Smuzhiyun self.retries = retries 750*4882a593Smuzhiyun 751*4882a593Smuzhiyunclass LogHandler(logging.Handler): 752*4882a593Smuzhiyun """Dispatch logging messages as bitbake events""" 753*4882a593Smuzhiyun 754*4882a593Smuzhiyun def emit(self, record): 755*4882a593Smuzhiyun if record.exc_info: 756*4882a593Smuzhiyun etype, value, tb = record.exc_info 757*4882a593Smuzhiyun if hasattr(tb, 'tb_next'): 758*4882a593Smuzhiyun tb = list(bb.exceptions.extract_traceback(tb, context=3)) 759*4882a593Smuzhiyun # Need to turn the value into something the logging system can pickle 760*4882a593Smuzhiyun record.bb_exc_info = (etype, value, tb) 761*4882a593Smuzhiyun record.bb_exc_formatted = bb.exceptions.format_exception(etype, value, tb, limit=5) 762*4882a593Smuzhiyun value = str(value) 763*4882a593Smuzhiyun record.exc_info = None 764*4882a593Smuzhiyun fire(record, None) 765*4882a593Smuzhiyun 766*4882a593Smuzhiyun def filter(self, record): 767*4882a593Smuzhiyun record.taskpid = worker_pid 768*4882a593Smuzhiyun return True 769*4882a593Smuzhiyun 770*4882a593Smuzhiyunclass MetadataEvent(Event): 771*4882a593Smuzhiyun """ 772*4882a593Smuzhiyun Generic event that target for OE-Core classes 773*4882a593Smuzhiyun to report information during asynchronous execution 774*4882a593Smuzhiyun """ 775*4882a593Smuzhiyun def __init__(self, eventtype, eventdata): 776*4882a593Smuzhiyun Event.__init__(self) 777*4882a593Smuzhiyun self.type = eventtype 778*4882a593Smuzhiyun self._localdata = eventdata 779*4882a593Smuzhiyun 780*4882a593Smuzhiyunclass ProcessStarted(Event): 781*4882a593Smuzhiyun """ 782*4882a593Smuzhiyun Generic process started event (usually part of the initial startup) 783*4882a593Smuzhiyun where further progress events will be delivered 784*4882a593Smuzhiyun """ 785*4882a593Smuzhiyun def __init__(self, processname, total): 786*4882a593Smuzhiyun Event.__init__(self) 787*4882a593Smuzhiyun self.processname = processname 788*4882a593Smuzhiyun self.total = total 789*4882a593Smuzhiyun 790*4882a593Smuzhiyunclass ProcessProgress(Event): 791*4882a593Smuzhiyun """ 792*4882a593Smuzhiyun Generic process progress event (usually part of the initial startup) 793*4882a593Smuzhiyun """ 794*4882a593Smuzhiyun def __init__(self, processname, progress): 795*4882a593Smuzhiyun Event.__init__(self) 796*4882a593Smuzhiyun self.processname = processname 797*4882a593Smuzhiyun self.progress = progress 798*4882a593Smuzhiyun 799*4882a593Smuzhiyunclass ProcessFinished(Event): 800*4882a593Smuzhiyun """ 801*4882a593Smuzhiyun Generic process finished event (usually part of the initial startup) 802*4882a593Smuzhiyun """ 803*4882a593Smuzhiyun def __init__(self, processname): 804*4882a593Smuzhiyun Event.__init__(self) 805*4882a593Smuzhiyun self.processname = processname 806*4882a593Smuzhiyun 807*4882a593Smuzhiyunclass SanityCheck(Event): 808*4882a593Smuzhiyun """ 809*4882a593Smuzhiyun Event to run sanity checks, either raise errors or generate events as return status. 810*4882a593Smuzhiyun """ 811*4882a593Smuzhiyun def __init__(self, generateevents = True): 812*4882a593Smuzhiyun Event.__init__(self) 813*4882a593Smuzhiyun self.generateevents = generateevents 814*4882a593Smuzhiyun 815*4882a593Smuzhiyunclass SanityCheckPassed(Event): 816*4882a593Smuzhiyun """ 817*4882a593Smuzhiyun Event to indicate sanity check has passed 818*4882a593Smuzhiyun """ 819*4882a593Smuzhiyun 820*4882a593Smuzhiyunclass SanityCheckFailed(Event): 821*4882a593Smuzhiyun """ 822*4882a593Smuzhiyun Event to indicate sanity check has failed 823*4882a593Smuzhiyun """ 824*4882a593Smuzhiyun def __init__(self, msg, network_error=False): 825*4882a593Smuzhiyun Event.__init__(self) 826*4882a593Smuzhiyun self._msg = msg 827*4882a593Smuzhiyun self._network_error = network_error 828*4882a593Smuzhiyun 829*4882a593Smuzhiyunclass NetworkTest(Event): 830*4882a593Smuzhiyun """ 831*4882a593Smuzhiyun Event to run network connectivity tests, either raise errors or generate events as return status. 832*4882a593Smuzhiyun """ 833*4882a593Smuzhiyun def __init__(self, generateevents = True): 834*4882a593Smuzhiyun Event.__init__(self) 835*4882a593Smuzhiyun self.generateevents = generateevents 836*4882a593Smuzhiyun 837*4882a593Smuzhiyunclass NetworkTestPassed(Event): 838*4882a593Smuzhiyun """ 839*4882a593Smuzhiyun Event to indicate network test has passed 840*4882a593Smuzhiyun """ 841*4882a593Smuzhiyun 842*4882a593Smuzhiyunclass NetworkTestFailed(Event): 843*4882a593Smuzhiyun """ 844*4882a593Smuzhiyun Event to indicate network test has failed 845*4882a593Smuzhiyun """ 846*4882a593Smuzhiyun 847*4882a593Smuzhiyunclass FindSigInfoResult(Event): 848*4882a593Smuzhiyun """ 849*4882a593Smuzhiyun Event to return results from findSigInfo command 850*4882a593Smuzhiyun """ 851*4882a593Smuzhiyun def __init__(self, result): 852*4882a593Smuzhiyun Event.__init__(self) 853*4882a593Smuzhiyun self.result = result 854