1*4882a593Smuzhiyun#!/usr/bin/env python3 2*4882a593Smuzhiyun# 3*4882a593Smuzhiyun# Copyright (C) 2014 Alex Damian 4*4882a593Smuzhiyun# 5*4882a593Smuzhiyun# SPDX-License-Identifier: GPL-2.0-only 6*4882a593Smuzhiyun# 7*4882a593Smuzhiyun# This file re-uses code spread throughout other Bitbake source files. 8*4882a593Smuzhiyun# As such, all other copyrights belong to their own right holders. 9*4882a593Smuzhiyun# 10*4882a593Smuzhiyun 11*4882a593Smuzhiyun""" 12*4882a593SmuzhiyunThis command takes a filename as a single parameter. The filename is read 13*4882a593Smuzhiyunas a build eventlog, and the ToasterUI is used to process events in the file 14*4882a593Smuzhiyunand log data in the database 15*4882a593Smuzhiyun""" 16*4882a593Smuzhiyun 17*4882a593Smuzhiyunimport os 18*4882a593Smuzhiyunimport sys 19*4882a593Smuzhiyunimport json 20*4882a593Smuzhiyunimport pickle 21*4882a593Smuzhiyunimport codecs 22*4882a593Smuzhiyunimport warnings 23*4882a593Smuzhiyunwarnings.simplefilter("default") 24*4882a593Smuzhiyun 25*4882a593Smuzhiyunfrom collections import namedtuple 26*4882a593Smuzhiyun 27*4882a593Smuzhiyun# mangle syspath to allow easy import of modules 28*4882a593Smuzhiyunfrom os.path import join, dirname, abspath 29*4882a593Smuzhiyunsys.path.insert(0, join(dirname(dirname(abspath(__file__))), 'lib')) 30*4882a593Smuzhiyun 31*4882a593Smuzhiyunimport bb.cooker 32*4882a593Smuzhiyunfrom bb.ui import toasterui 33*4882a593Smuzhiyun 34*4882a593Smuzhiyunclass EventPlayer: 35*4882a593Smuzhiyun """Emulate a connection to a bitbake server.""" 36*4882a593Smuzhiyun 37*4882a593Smuzhiyun def __init__(self, eventfile, variables): 38*4882a593Smuzhiyun self.eventfile = eventfile 39*4882a593Smuzhiyun self.variables = variables 40*4882a593Smuzhiyun self.eventmask = [] 41*4882a593Smuzhiyun 42*4882a593Smuzhiyun def waitEvent(self, _timeout): 43*4882a593Smuzhiyun """Read event from the file.""" 44*4882a593Smuzhiyun line = self.eventfile.readline().strip() 45*4882a593Smuzhiyun if not line: 46*4882a593Smuzhiyun return 47*4882a593Smuzhiyun try: 48*4882a593Smuzhiyun event_str = json.loads(line)['vars'].encode('utf-8') 49*4882a593Smuzhiyun event = pickle.loads(codecs.decode(event_str, 'base64')) 50*4882a593Smuzhiyun event_name = "%s.%s" % (event.__module__, event.__class__.__name__) 51*4882a593Smuzhiyun if event_name not in self.eventmask: 52*4882a593Smuzhiyun return 53*4882a593Smuzhiyun return event 54*4882a593Smuzhiyun except ValueError as err: 55*4882a593Smuzhiyun print("Failed loading ", line) 56*4882a593Smuzhiyun raise err 57*4882a593Smuzhiyun 58*4882a593Smuzhiyun def runCommand(self, command_line): 59*4882a593Smuzhiyun """Emulate running a command on the server.""" 60*4882a593Smuzhiyun name = command_line[0] 61*4882a593Smuzhiyun 62*4882a593Smuzhiyun if name == "getVariable": 63*4882a593Smuzhiyun var_name = command_line[1] 64*4882a593Smuzhiyun variable = self.variables.get(var_name) 65*4882a593Smuzhiyun if variable: 66*4882a593Smuzhiyun return variable['v'], None 67*4882a593Smuzhiyun return None, "Missing variable %s" % var_name 68*4882a593Smuzhiyun 69*4882a593Smuzhiyun elif name == "getAllKeysWithFlags": 70*4882a593Smuzhiyun dump = {} 71*4882a593Smuzhiyun flaglist = command_line[1] 72*4882a593Smuzhiyun for key, val in self.variables.items(): 73*4882a593Smuzhiyun try: 74*4882a593Smuzhiyun if not key.startswith("__"): 75*4882a593Smuzhiyun dump[key] = { 76*4882a593Smuzhiyun 'v': val['v'], 77*4882a593Smuzhiyun 'history' : val['history'], 78*4882a593Smuzhiyun } 79*4882a593Smuzhiyun for flag in flaglist: 80*4882a593Smuzhiyun dump[key][flag] = val[flag] 81*4882a593Smuzhiyun except Exception as err: 82*4882a593Smuzhiyun print(err) 83*4882a593Smuzhiyun return (dump, None) 84*4882a593Smuzhiyun 85*4882a593Smuzhiyun elif name == 'setEventMask': 86*4882a593Smuzhiyun self.eventmask = command_line[-1] 87*4882a593Smuzhiyun return True, None 88*4882a593Smuzhiyun 89*4882a593Smuzhiyun else: 90*4882a593Smuzhiyun raise Exception("Command %s not implemented" % command_line[0]) 91*4882a593Smuzhiyun 92*4882a593Smuzhiyun def getEventHandle(self): 93*4882a593Smuzhiyun """ 94*4882a593Smuzhiyun This method is called by toasterui. 95*4882a593Smuzhiyun The return value is passed to self.runCommand but not used there. 96*4882a593Smuzhiyun """ 97*4882a593Smuzhiyun pass 98*4882a593Smuzhiyun 99*4882a593Smuzhiyundef main(argv): 100*4882a593Smuzhiyun with open(argv[-1]) as eventfile: 101*4882a593Smuzhiyun # load variables from the first line 102*4882a593Smuzhiyun variables = json.loads(eventfile.readline().strip())['allvariables'] 103*4882a593Smuzhiyun 104*4882a593Smuzhiyun params = namedtuple('ConfigParams', ['observe_only'])(True) 105*4882a593Smuzhiyun player = EventPlayer(eventfile, variables) 106*4882a593Smuzhiyun 107*4882a593Smuzhiyun return toasterui.main(player, player, params) 108*4882a593Smuzhiyun 109*4882a593Smuzhiyun# run toaster ui on our mock bitbake class 110*4882a593Smuzhiyunif __name__ == "__main__": 111*4882a593Smuzhiyun if len(sys.argv) != 2: 112*4882a593Smuzhiyun print("Usage: %s <event file>" % os.path.basename(sys.argv[0])) 113*4882a593Smuzhiyun sys.exit(1) 114*4882a593Smuzhiyun 115*4882a593Smuzhiyun sys.exit(main(sys.argv)) 116