#!/usr/bin/env python
""" tkinter use example with ecflow
from a NCEP request, while overview was part of CDP commands
"""
import Tkinter as tki
import ecflow as ec
from threading import Thread
import Queue, sys, time, os, pwd
from scrolledlist import ScrolledList
# thanks to NMT
# from=http://infohost.nmt.edu/tcc/help/lang/python/examples/scrolledlist/
# firefox $from ; wget $from/scrolledlist.py
PROGRAM_NAME = "ecflowview-overview"
BUTTON_FONT = ('times', 12)
MONO_FONT = ('lucidatypewriter', 14, 'bold')
DEBUG = 0
COLORS = { "aborted": "red",
"active": "green",
"submitted": "cyan",
"complete": "yellow",
"suspended": "orange",
"queued": "blue",
"unknwon": "grey" }
class Label(object):
""" a class to encapsulate what was a global variable"""
inst = None
def __init__(self, item):
Label.inst = item
@classmethod
def update(cls):
if Label.inst is None: return
Label.inst.set(time.strftime(
"%a, %d %b %Y %H:%M:%S"))
class MenuBar(tki.Frame):
def __init__(self, parent):
tki.Frame.__init__(self, parent)
self.__helpButton = self.__createHelp()
self.__helpButton.grid(row=0, column=3)
self.__updateButton = tki.Button(
self, text='Update',
font= BUTTON_FONT,
command= parent.update)
self.__updateButton.grid(row=0, column=2)
def __createHelp(self):
mb = tki.Menubutton(self, font=BUTTON_FONT,
relief= tki.RAISED,
text= 'Help')
menu = tki.Menu(mb)
mb['menu'] = menu
url = "https://software.ecmwf.int/wiki/display/ECFLOW/Documentation"
def url1(): self.__url(url= url)
def url2(): self.__url(url="http://effbot.org/tkinterbook/")
menu.add_command(command= url1, label="confluence tutorial?")
menu.add_command(command= url2, label="tkinter?")
return mb
def __url(self, url=None):
if url is None: return
os.system("firefox " + url)
class TaskList(tki.Frame):
NAME_WIDTH = 40
NAME_LINES = 80
def __init__(self, parent, kind):
tki.Frame.__init__(self, parent)
self.__kind = kind
self.__callback = None
self.__label = tki.Label(self, font=BUTTON_FONT,
background= COLORS[kind],
text= kind)
self.__label.grid(row=0, column=0, sticky= tki.W)
self.__scrolledList = ScrolledList(
self,
width= self.NAME_WIDTH,
height= self.NAME_LINES,
callback= self.__callback)
self.__scrolledList.grid(row=1, column=0)
def insert(self, path):
self.__scrolledList.append(path)
def clear(self):
self.__scrolledList.clear()
running = [True]
class PaceKeeper():
PACE = 60
def __init__(self, item, queue):
thr = Thread(target=self.process,
args=(queue, running))
self._item = item
thr.start()
def process(self, queue, running):
while running:
queue.put(self._item.update)
time.sleep(self.PACE)
def run(self): self.update()
def update(self, verbose=False):
while True:
print time.clock()
self._item.update()
time.sleep(self.PACE)
class Client(object):
""" a class to focus on client-ecFlow-server comm"""
def __init__(self, one="local-localhost@31415"):
try: nick, hhh = one.split("-")
except: hhh = one; nick = None
try: host, port = hhh.split("@")
except: host = "localhost"; port = 31415
if nick is None: self.nick = "%s@%d" % (host, port)
print "# client creation", nick, host, port
self.nick = nick
self.client = ec.Client(host, port)
def process(self, win):
Label.update()
self.client.sync_local()
defs = self.client.get_defs()
if defs is None: print("# %s-%: empty content" % (
self.host, self.port))
Label.update()
for suite in defs.suites:
self.process_nc(suite, win)
def process_nc(self, node, win):
for item in node.nodes:
if isinstance(item, ec.Task):
self.process_node(item, win)
else: self.process_nc(item, win)
def process_node(self, node, wins):
for kind, win in wins.items():
status = "%s" % node.get_state()
if status != kind: continue
win.insert("%s:%s" % (self.nick, node.get_abs_node_path()))
# print self.nick, node.get_abs_node_path(), status
class Application(tki.Frame):
def __init__(self, master=None, client=None, queue=None):
tki.Frame.__init__(self, master)
if client is None:
self.__clients = [ Client("localhost@31415"), ]
elif type(client) == set:
self.__clients = client
else: self.__clients = [ client ]
self.__queue = queue
width = 640
height = 780
self.canvas = tki.Canvas(width=width, height=height, bg='black')
self.grid()
self.createWidgets()
self.canvas.after(50, self.check_queue)
def createWidgets(self):
rowx = 1
glob = Label(tki.StringVar(self))
root = self
self.__menuBar = MenuBar(root)
self.__menuBar.grid(row=0, column=0,
sticky=tki.W)
self.label = tki.Label(root,
textvariable=Label.inst)
self.label.grid(row=0, column=2,
sticky=tki.E)
self.__wins = dict()
rowx += 1
colx = 0
kinds = ("active", "aborted", "submitted")
for kind in kinds:
self.__wins[kind] = TaskList(root, kind)
self.__wins[kind].grid(row=rowx, column= colx,
sticky=tki.S + tki.E + tki.W)
colx += 1
self.update()
def check_queue(self):
try:
self.__queue.get(block=False)
except Queue.Empty:
pass
else:
self.update()
self.canvas.after(50, self.check_queue)
def update(self):
Label.update()
for kind, win in self.__wins.items():
win.clear()
for client in self.__clients:
if type(client) == list:
for clt in client:
clt.process(self.__wins)
else:
try: client.process(self.__wins)
except: pass
pass
def get_username():
return pwd.getpwuid( os.getuid() )[ 0 ]
def get_uid():
return pwd.getpwnam(get_username()).pw_uid
if __name__ == '__main__':
try: port = 1500 + int(get_uid())
except: port = 31415
if len(sys.argv) == 0:
clients = [ Client("localhost%d" % port) ]
else:
clients = []
for num in xrange(1, len(sys.argv)):
clients.append( Client(sys.argv[num]) )
queue = Queue.Queue()
# app = AppSms(host, port, queue)
app = Application(client= clients, queue= queue)
app.master.title(PROGRAM_NAME)
app.columnconfigure(0, weight=1)
app.rowconfigure(0, weight=1)
PaceKeeper(app, queue)
app.mainloop()
|