diff --git a/rfswarm.py b/rfswarm.py index 559399cc1..285785878 100644 --- a/rfswarm.py +++ b/rfswarm.py @@ -18,6 +18,7 @@ import sys import os import glob +import configparser import hashlib import lzma import base64 @@ -270,6 +271,9 @@ class RFSwarmGUI(tk.Frame): tabs = None + config = None + gui_ini = None + # #000000 = Black defcolours = ['#000000'] @@ -327,6 +331,16 @@ def __init__(self, master=None): # Grid.columnconfigure(root, 0, weight=1) root.protocol("WM_DELETE_WINDOW", self.on_closing) + self.config = configparser.ConfigParser() + scrdir = os.path.dirname(__file__) + print("RFSwarmAgent: __init__: scrdir: ", scrdir) + self.gui_ini = os.path.join(scrdir, "RFSwarmGUI.ini") + if os.path.isfile(self.gui_ini): + print("RFSwarmAgent: __init__: agentini: ", self.gui_ini) + self.config.read(self.gui_ini) + else: + self.saveini() + tk.Frame.__init__(self, root) self.grid(row=0, column=0, sticky="nsew") self.columnconfigure(0, weight=1) @@ -340,6 +354,10 @@ def __init__(self, master=None): self.dbthread.start() + def saveini(self): + with open(self.gui_ini, 'w') as configfile: # save + self.config.write(configfile) + # def mainloop(self): # pass @@ -361,6 +379,8 @@ def on_closing(self): print("on_closing: Join DB Thread") self.dbthread.join() + print("on_closing: Save ini File") + self.saveini() print("on_closing: exit") exit() @@ -390,6 +410,14 @@ def BuildUI(self): def BuildPlan(self, p): + if 'Plan' not in self.config: + self.config['Plan'] = {} + self.saveini() + + if 'LastDir' not in self.config['Plan']: + self.config['Plan']['LastDir'] = self.dir_path + self.saveini() + p.columnconfigure(0, weight=2) p.rowconfigure(0, weight=1) # p.rowconfigure(1, weight=1) @@ -447,6 +475,23 @@ def BuildPlan(self, p): def BuildRun(self, r): + if 'Run' not in self.config: + self.config['Run'] = {} + self.saveini() + + if 'display_index' not in self.config['Run']: + self.config['Run']['display_index'] = str(False) + self.saveini() + + if 'display_iteration' not in self.config['Run']: + self.config['Run']['display_iteration'] = str(False) + self.saveini() + + if 'display_sequence' not in self.config['Run']: + self.config['Run']['display_sequence'] = str(False) + self.saveini() + + rg = ttk.Frame(r) rg.grid(column=0, row=1, sticky="nsew") rgbar = ttk.Frame(rg) @@ -455,36 +500,36 @@ def BuildRun(self, r): # # run info bar # - # usr = ttk.Label(rgbar, text="Unique by:") #, borderwidth=2, relief="raised") - # usr.grid(column=11, row=0, sticky="nsew") # , rowspan=2 - # - # # gblist = ["script_index", "iteration", "sequence"] - # if "display_index" not in self.display_run: - # self.display_run['display_index'] = tk.BooleanVar() - # self.display_run['display_index'].set(False) - # usr = ttk.Label(rgbar, text=" Index ") #, borderwidth=2, relief="raised") - # usr.grid(column=10, row=1, sticky="nsew") - # # chk = tk.Checkbutton(rgbar, text="Index", variable=self.display_run['display_index'], onvalue=1, offvalue=0) #, height = 2, width = 10) - # chk = tk.Checkbutton(rgbar, variable=self.display_run['display_index'], onvalue=True, offvalue=False) #, height = 2, width = 10) - # chk.grid(column=10, row=2, sticky="nsew") - # - # if "display_iteration" not in self.display_run: - # self.display_run['display_iteration'] = tk.BooleanVar() - # self.display_run['display_iteration'].set(False) - # usr = ttk.Label(rgbar, text=" Iteration ") #, borderwidth=2, relief="raised") - # usr.grid(column=11, row=1, sticky="nsew") - # # chk = tk.Checkbutton(rgbar, text="Iteration", variable=self.display_run['display_iteration'], onvalue=1, offvalue=0) #, height = 2, width = 10) - # chk = tk.Checkbutton(rgbar, variable=self.display_run['display_iteration'], onvalue=True, offvalue=False) #, height = 2, width = 10) - # chk.grid(column=11, row=2, sticky="nsew") - # - # if "display_sequence" not in self.display_run: - # self.display_run['display_sequence'] = tk.BooleanVar() - # self.display_run['display_sequence'].set(False) - # usr = ttk.Label(rgbar, text=" Sequence ") #, borderwidth=2, relief="raised") - # usr.grid(column=12, row=1, sticky="nsew") - # # chk = tk.Checkbutton(rgbar, text="Sequence", variable=self.display_run['display_sequence'], onvalue=1, offvalue=0) #, height = 2, width = 10) - # chk = tk.Checkbutton(rgbar, variable=self.display_run['display_sequence'], onvalue=True, offvalue=False) #, height = 2, width = 10) - # chk.grid(column=12, row=2, sticky="nsew") + usr = ttk.Label(rgbar, text="Unique by:") #, borderwidth=2, relief="raised") + usr.grid(column=11, row=0, sticky="nsew") # , rowspan=2 + + # gblist = ["script_index", "iteration", "sequence"] + if "display_index" not in self.display_run: + self.display_run['display_index'] = tk.BooleanVar() + self.display_run['display_index'].set(self.str2bool(self.config['Run']['display_index'])) + usr = ttk.Label(rgbar, text=" Index ") #, borderwidth=2, relief="raised") + usr.grid(column=10, row=1, sticky="nsew") + # chk = tk.Checkbutton(rgbar, text="Index", variable=self.display_run['display_index'], onvalue=1, offvalue=0) #, height = 2, width = 10) + chk = tk.Checkbutton(rgbar, variable=self.display_run['display_index'], onvalue=True, offvalue=False, command=self.delayed_UpdateRunStats_bg) #, height = 2, width = 10) + chk.grid(column=10, row=2, sticky="nsew") + + if "display_iteration" not in self.display_run: + self.display_run['display_iteration'] = tk.BooleanVar() + self.display_run['display_iteration'].set(self.str2bool(self.config['Run']['display_iteration'])) + usr = ttk.Label(rgbar, text=" Iteration ") #, borderwidth=2, relief="raised") + usr.grid(column=11, row=1, sticky="nsew") + # chk = tk.Checkbutton(rgbar, text="Iteration", variable=self.display_run['display_iteration'], onvalue=1, offvalue=0) #, height = 2, width = 10) + chk = tk.Checkbutton(rgbar, variable=self.display_run['display_iteration'], onvalue=True, offvalue=False, command=self.delayed_UpdateRunStats_bg) #, height = 2, width = 10) + chk.grid(column=11, row=2, sticky="nsew") + + if "display_sequence" not in self.display_run: + self.display_run['display_sequence'] = tk.BooleanVar() + self.display_run['display_sequence'].set(self.str2bool(self.config['Run']['display_sequence'])) + usr = ttk.Label(rgbar, text=" Sequence ") #, borderwidth=2, relief="raised") + usr.grid(column=12, row=1, sticky="nsew") + # chk = tk.Checkbutton(rgbar, text="Sequence", variable=self.display_run['display_sequence'], onvalue=1, offvalue=0) #, height = 2, width = 10) + chk = tk.Checkbutton(rgbar, variable=self.display_run['display_sequence'], onvalue=True, offvalue=False, command=self.delayed_UpdateRunStats_bg) #, height = 2, width = 10) + chk.grid(column=12, row=2, sticky="nsew") if "start_time" not in self.display_run: self.display_run['start_time'] = tk.StringVar() @@ -988,105 +1033,145 @@ def get_next_agent(self): else: return None + def delayed_UpdateRunStats_bg(self): + + display_index = self.display_run['display_index'].get() + if display_index != self.str2bool(self.config['Run']['display_index']): + self.config['Run']['display_index'] = str(display_index) + self.saveini() + + display_iteration = self.display_run['display_iteration'].get() + if display_iteration != self.str2bool(self.config['Run']['display_iteration']): + self.config['Run']['display_iteration'] = str(display_iteration) + self.saveini() + + display_sequence = self.display_run['display_sequence'].get() + if display_sequence != self.str2bool(self.config['Run']['display_sequence']): + self.config['Run']['display_sequence'] = str(display_sequence) + self.saveini() + + time_elapsed = int(time.time()) - self.rungridupdate + if (time_elapsed>5): + ut = threading.Thread(target=self.delayed_UpdateRunStats) + ut.start() + def delayed_UpdateRunStats(self): - time.sleep(5) - # queue sqls so UpdateRunStats should have the results - - # TODO: to query the percentile value we'll need to create an aggregate class - # https://docs.python.org/2/library/sqlite3.html#sqlite3.Connection.create_aggregate - - gblist = [] - # if self.display_run['display_index'].get(): - # gblist.append("script_index") - # if self.display_run['display_iteration'].get(): - # gblist.append("iteration") - # if self.display_run['display_sequence'].get(): - # gblist.append("sequence") - - gblist.append("result_name") - # print("delayed_UpdateRunStats: gblist:", gblist) - # gblist = ["result_name"] - # gblist = ["sequence", "result_name"] - # gblist = ["script_index", "result_name"] - # gblist = ["script_index", "iteration", "sequence", "result_name"] - gbcols = ", ".join(gblist) - - # print("delayed_UpdateRunStats: gbcols:", gbcols) - - - sql = "SELECT " - if len(gblist)>0: - sql += gbcols - sql += ", " - sql += "result_name, " - sql += "result, " - sql += "count(*) 'count', " - sql += "round(min(elapsed_time),3) 'min', " - sql += "round(avg(elapsed_time),3) 'avg', " - sql += "round(max(elapsed_time),3) 'max' " - sql += "FROM Results " - sql += "WHERE result = 'PASS' " - sql += "GROUP BY " - sql += gbcols - - # round(-4.535,2); - - # sql = """SELECT - # script_index, - # sequence, - # result_name, - # result, - # count(*) 'count', - # min(elapsed_time) 'min', - # avg(elapsed_time) 'avg', - # max(elapsed_time) 'max' - # FROM Results - # WHERE result = 'PASS' - # GROUP BY script_index, sequence, result_name""" - - # print("delayed_UpdateRunStats: sql:", sql) - - self.dbqueue["Read"].append({"SQL": sql, "KEY": "RunStats_Pass"}) - - sql = "SELECT " - if len(gblist)>0: - sql += gbcols - sql += ", " - sql += "result_name, " - sql += "result, " - sql += "count(*) 'count' " - sql += "FROM Results " - sql += "WHERE result <> 'PASS' " - sql += "GROUP BY " - sql += gbcols - - # sql = """SELECT - # script_index, - # sequence, - # result_name, - # result, - # count(*) 'count' - # FROM Results - # WHERE result <> 'PASS' - # GROUP BY script_index, - # sequence, - # result_name""" - - # print("delayed_UpdateRunStats: sql:", sql) - - self.dbqueue["Read"].append({"SQL": sql, "KEY": "RunStats_NotPass"}) - - time.sleep(1) - self.UpdateRunStats() + time_elapsed = int(time.time()) - self.rungridupdate + if (time_elapsed>5): + # queue sqls so UpdateRunStats should have the results + + # TODO: to query the percentile value we'll need to create an aggregate class + # https://docs.python.org/2/library/sqlite3.html#sqlite3.Connection.create_aggregate + + gblist = [] + display_index = self.display_run['display_index'].get() + # print("delayed_UpdateRunStats: display_index:", display_index, " config[Run][display_index]:", self.config['Run']['display_index'], " bool(config[Run][display_index]):", self.str2bool(self.config['Run']['display_index'])) + if display_index != self.str2bool(self.config['Run']['display_index']): + self.config['Run']['display_index'] = str(display_index) + self.saveini() + if display_index: + gblist.append("script_index") + + display_iteration = self.display_run['display_iteration'].get() + if display_iteration != self.str2bool(self.config['Run']['display_iteration']): + self.config['Run']['display_iteration'] = str(display_iteration) + self.saveini() + if display_iteration: + gblist.append("iteration") + + display_sequence = self.display_run['display_sequence'].get() + if display_sequence != self.str2bool(self.config['Run']['display_sequence']): + self.config['Run']['display_sequence'] = str(display_sequence) + self.saveini() + if display_sequence: + gblist.append("sequence") + + gblist.append("result_name") + # print("delayed_UpdateRunStats: gblist:", gblist) + # gblist = ["result_name"] + # gblist = ["sequence", "result_name"] + # gblist = ["script_index", "result_name"] + # gblist = ["script_index", "iteration", "sequence", "result_name"] + gbcols = ", ".join(gblist) + + # print("delayed_UpdateRunStats: gbcols:", gbcols) + + + sql = "SELECT " + if len(gblist)>0: + sql += gbcols + sql += ", " + sql += "result_name, " + sql += "result, " + sql += "count(*) 'count', " + sql += "round(min(elapsed_time),3) 'min', " + sql += "round(avg(elapsed_time),3) 'avg', " + sql += "round(max(elapsed_time),3) 'max' " + sql += "FROM Results " + sql += "WHERE result = 'PASS' " + if len(gblist)>0: + sql += "GROUP BY " + sql += gbcols + + # round(-4.535,2); + + # sql = """SELECT + # script_index, + # sequence, + # result_name, + # result, + # count(*) 'count', + # min(elapsed_time) 'min', + # avg(elapsed_time) 'avg', + # max(elapsed_time) 'max' + # FROM Results + # WHERE result = 'PASS' + # GROUP BY script_index, sequence, result_name""" + + # print("delayed_UpdateRunStats: sql:", sql) + + self.dbqueue["Read"].append({"SQL": sql, "KEY": "RunStats_Pass"}) + + sql = "SELECT " + if len(gblist)>0: + sql += gbcols + sql += ", " + sql += "result_name, " + sql += "result, " + sql += "count(*) 'count' " + sql += "FROM Results " + sql += "WHERE result <> 'PASS' " + sql += "GROUP BY " + sql += gbcols + + # sql = """SELECT + # script_index, + # sequence, + # result_name, + # result, + # count(*) 'count' + # FROM Results + # WHERE result <> 'PASS' + # GROUP BY script_index, + # sequence, + # result_name""" + + # print("delayed_UpdateRunStats: sql:", sql) + + self.dbqueue["Read"].append({"SQL": sql, "KEY": "RunStats_NotPass"}) + + time.sleep(1) + self.UpdateRunStats() def UpdateRunStats(self): rnum = 0 removestat = [] - stm = time.localtime(self.robot_schedule["Start"]) - self.display_run['start_time'].set(" {} ".format(time.strftime("%H:%M:%S", stm))) - etm = time.gmtime(int(time.time()) - self.robot_schedule["Start"]) - self.display_run['elapsed_time'].set(" {} ".format(time.strftime("%H:%M:%S", etm))) + if "Start" in self.robot_schedule: + stm = time.localtime(self.robot_schedule["Start"]) + self.display_run['start_time'].set(" {} ".format(time.strftime("%H:%M:%S", stm))) + etm = time.gmtime(int(time.time()) - self.robot_schedule["Start"]) + self.display_run['elapsed_time'].set(" {} ".format(time.strftime("%H:%M:%S", etm))) time_elapsed = int(time.time()) - self.rungridupdate if (time_elapsed>5): @@ -1128,19 +1213,43 @@ def UpdateRunStats(self): colno += 1 + colno += -1 grdcols = self.rungrid.grid_size()[0]-1 + # print("UpdateRunStats: grdcols:", grdcols, " colno:",colno) + if grdcols>colno: + # print("UpdateRunStats: need to remove columns grdcols:", grdcols, " colno:",colno) + c = grdcols + while c>colno: + # print("UpdateRunStats: need to remove rows c:", c, " colno:",colno) + relmts = self.rungrid.grid_slaves(row=None, column=c) + # print(relmts) + for elmt in relmts: + elmt.destroy() + c += -1 + + + datarows = len(self.dbqueue["ReadResult"]["RunStats_Pass"]) + grdrows = self.rungrid.grid_size()[1]-1 + # print("UpdateRunStats: grdrows:", grdrows, " > datarows:",datarows) + if grdrows>datarows: + # print("UpdateRunStats: need to remove rows grdrows:", grdrows, " > datarows:",datarows) + r = grdrows + while r>datarows: + # print("UpdateRunStats: need to remove rows r:", r, " > datarows:",datarows) + relmts = self.rungrid.grid_slaves(row=r, column=None) + # print(relmts) + for elmt in relmts: + elmt.destroy() + r += -1 + rowno = 1 for row in self.dbqueue["ReadResult"]["RunStats_Pass"]: newrow = False - grdrows = self.agenttgrid.grid_size()[1] + grdrows = self.rungrid.grid_size()[1] # print("UpdateRunStats: grdrows:", grdrows) if rowno not in self.display_run["rows"]: self.display_run["rows"][rowno] = {} - newrow = True - if rowno>grdrows: - newrow = True - # print("UpdateRunStats: newrow:", newrow) colno = 0 newcell = False @@ -1148,12 +1257,15 @@ def UpdateRunStats(self): # print("UpdateRunStats: colno:", colno, "col:", col) # print("UpdateRunStats: row[col]:", row[col]) if colno>len(self.display_run["rows"][rowno])-1: - newcell = True self.display_run["rows"][rowno][colno] = tk.StringVar() self.display_run["rows"][rowno][colno].set(" {} ".format(row[col])) - if newrow or newcell: + relmts = self.rungrid.grid_slaves(row=rowno, column=colno) + # print("UpdateRunStats: relmts:", relmts) + + # if newrow or newcell: + if len(relmts) < 1: usr = ttk.Label(self.rungrid, textvariable=self.display_run["rows"][rowno][colno], borderwidth=2, relief="groove") usr.grid(column=colno, row=rowno, sticky="nsew") @@ -1162,22 +1274,7 @@ def UpdateRunStats(self): rowno += 1 - # self.display_run["columns"] - # self.display_agents[rnum]["Agent"] = tk.StringVar() - - # usr = ttk.Label(self.rungrid, textvariable=self.display_run["columns"][colno], borderwidth=2, relief="groove") - # usr = ttk.Label(self.rungrid, text=" Status ", borderwidth=2, relief="raised") - - # self.display_run - # self.display_run["columns"] = self.dbqueue["ReadResult"][0].keys() - # for col in self.display_run["columns"]: - # usr = ttk.Label(self.agenttgrid, text=" Status ", borderwidth=2, relief="raised") - # usr.grid(column=0, row=0, sticky="nsew") - # self.rungrid - # grdrows = self.agenttgrid.grid_size()[1]-1 - - # if rnum>0: ut = threading.Thread(target=self.delayed_UpdateRunStats) ut.start() @@ -1462,7 +1559,7 @@ def sr_file_validate(self, r): # print(fg) # print(fg[1].get()) # root.filename = tkFileDialog.askopenfilename(initialdir = "/",title = "Select file",filetypes = (("jpeg files","*.jpg"),("all files","*.*"))) - scriptfile = str(tkf.askopenfilename(initialdir=self.lastdir, title = "Select Robot Framework File", filetypes = (("Robot Framework","*.robot"),("all files","*.*")))) + scriptfile = str(tkf.askopenfilename(initialdir=self.config['Plan']['LastDir'], title = "Select Robot Framework File", filetypes = (("Robot Framework","*.robot"),("all files","*.*")))) # print("scriptfile:", scriptfile) if len(scriptfile)>0: fg[1].configure(state='normal') @@ -1484,7 +1581,8 @@ def sr_file_validate(self, r): t = threading.Thread(target=self.find_dependancies, args=(script_hash, )) t.start() - self.lastdir = os.path.dirname(scriptfile) + self.config['Plan']['LastDir'] = os.path.dirname(scriptfile) + self.saveini() self.sr_test_genlist(r) else: fg[1].configure(state='normal') @@ -2135,6 +2233,13 @@ def register_result(self, AgentName, result_name, result, elapsed_time, start_ti ut = threading.Thread(target=self.delayed_UpdateRunStats) ut.start() + + def str2bool(self, instr): + # print("str2bool: instr:", instr) + if instr in ["True", "true", "TRUE", "YES", "yes", "Yes", "1"]: + return True + return False + rfs = RFSwarmGUI() print("Robot Framework Swarm: Run GUI") rfs.master.title('Robot Framework Swarm')