wxPython - Can you explain why I crash
Miki Tebeka
tebeka at cs.bgu.ac.il
Wed Apr 9 10:52:45 EDT 2003
Hello All,
I've written this little client. It used to work fine but now no
matter which button I press the application crash.
I'm running Python2.2 and wxPython 2.4.0.7
Any ideas?
10x.
Miki
--- ui.py ---
#!/usr/bin/env python
'''Compas client emulator UI'''
__author__ = 'Miki Tebeka <miki_tebeka at amat.com>'
__id__ = '$Id: ui.py,v 1.3 2003/03/06 14:20:15 MTebeka90603 Exp $'
# $Source: /u/CVSROOT/compass_client/ui.py,v $
from wxPython.wx import *
from os.path import isfile
from ConfigParser import ConfigParser
import client
# Ids
ID_GET_RECIPES = wxNewId()
ID_SELECT_RECIPE = wxNewId()
ID_GET_WAFERS = wxNewId()
ID_LOAD = wxNewId()
ID_UNLOAD = wxNewId()
ID_RUN = wxNewId()
ID_STOP = wxNewId()
ID_DISCONNECT = wxNewId()
ID_CONNECT = wxNewId()
ID_LAST_ERROR = wxNewId()
ID_STATUSBAR = wxNewId()
ID_SELECT_ALIGN = wxNewId()
# Connection messages
CONNECTED = 'Connected'
DISONNECTED = 'Disconnected'
class CompassClient(wxFrame):
'''Client frame'''
def __init__(self):
# No resizable border
wxFrame.__init__(self, None, -1, 'CompassSim',
style=wxDEFAULT_FRAME_STYLE &
(~wxRESIZE_BORDER))
self.CreateStatusBar(1, 0, ID_STATUSBAR)
self.GetStatusBar().SetFieldsCount(2)
# Get mouse click on task bar
EVT_LEFT_DOWN(self.GetStatusBar(), self.last_error)
sizer = wxBoxSizer(wxVERTICAL)
# Recipe list
t = wxStaticText(self, -1, 'Recipes:')
sizer.Add(t)
self.recipes = wxListBox(self, -1)
sizer.Add(self.recipes, 0, wxEXPAND)
hsizer = wxBoxSizer(wxHORIZONTAL)
self.add_button(ID_GET_RECIPES, 'Read Data', self.get_recipes,
hsizer)
self.add_button(ID_SELECT_RECIPE, 'Select',
self.select_recipe, \
hsizer)
sizer.Add(hsizer)
self.add_sep(sizer)
# Wafer List
t = wxStaticText(self, -1, 'Wafers:')
sizer.Add(t)
self.wafers = wxListBox(self, -1, style=wxLB_EXTENDED)
sizer.Add(self.wafers, 0, wxEXPAND)
# Load / Unload
hsizer = wxBoxSizer(wxHORIZONTAL)
self.add_button(ID_LOAD, 'Load', self.load, hsizer)
self.add_button(ID_UNLOAD, 'Unload', self.unload, hsizer)
sizer.Add(hsizer)
# Run / Stop
self.add_sep(sizer)
hsizer = wxBoxSizer(wxHORIZONTAL)
self.add_button(ID_RUN, 'Run', self.run, hsizer)
self.add_button(ID_STOP, 'Stop', self.stop, hsizer)
sizer.Add(hsizer)
self.times = wxSpinCtrl(self, -1, size=(75,-1))
self.times.SetRange(1, 999999)
self.times.SetValue(1)
sizer.Add(self.times)
self.add_sep(sizer)
# Connect / Quit
hsizer = wxBoxSizer(wxHORIZONTAL)
self.add_button(ID_CONNECT, 'Connect', self.connect, hsizer)
self.add_button(-1, 'Quit', lambda e: self.Close(1), hsizer)
sizer.Add(hsizer)
# Auto resize
self.SetSizer(sizer)
self.SetAutoLayout(1)
sizer.Fit(self)
self.connect(None)
def status(self, success):
'''Status of last commands'''
if success:
self.SetStatusText('OK', 1)
else:
self.SetStatusText('Error', 1)
def busy(self):
'''Busy state'''
self.SetCursor(wxHOURGLASS_CURSOR)
def idle(self):
'''Idle state'''
self.SetCursor(wxSTANDARD_CURSOR)
def add_button(self, id, title, func, sizer, center = 0):
'''Add a button to sizer'''
b = wxButton(self, id, title)
EVT_BUTTON(self, id, func)
if center:
sizer.Add(b, 0, wxALIGN_CENTER)
else:
sizer.Add(b)
def add_sep(self, sizer):
'''Add a seperator to sizer'''
sizer.Add(0, 5, 0, wxEXPAND)
def error(self, msg):
'''Show error message'''
dlg = wxMessageDialog(self, msg, 'Error', \
wxOK | wxICON_EXCLAMATION)
dlg.ShowModal()
dlg.Destroy()
def last_error(self, e):
'''Show last error'''
err = client.LAST_ERROR
if not err:
err = 'Unknown Error'
dlg = wxMessageDialog(self, err, 'Last Error', \
wxOK | wxICON_INFORMATION)
dlg.ShowModal()
dlg.Destroy()
def get_recipes(self, e):
'''Get recipe list'''
print 'get_recipes'
try:
self.busy()
if not client.get_lot_data():
self.status(0)
return
recipes = client.get_recipe_list()
if not recipes:
self.status(0)
return
# Update listbox
self.recipes.Clear()
for recipe in recipes:
self.recipes.Append(recipe)
self.status(1)
finally:
self.idle()
def select_recipe(self, e):
'''Select a recipe'''
try:
self.busy()
if self.recipes.GetCount() == 0:
self.error('No Recipes')
return
if not client.select_recipe(self.recipes.GetStringSelection()):
self.status(0)
return
wafers = client.get_wafer_list()
if not wafers:
self.status(0)
return
# Update listbox
self.wafers.Clear()
for wafer in wafers:
self.wafers.Append(wafer)
self.status(1)
finally:
self.idle()
def _load(self, wafer):
# set_alignment_parameters must bee called before load
# Image must have /work/wf prefix (see stub_functions.cpp
AlignData)
params = ['/work/wf/coarse.img', 'TIFF', # Name and format
'1.634888', '1.660389', # Pixel size
'-264.066777', '-9704.485647', # Center to Coarse
'-24.486192', '-21.873070', # Coarse to fine
'-21.873070', '5.359366', # Corner to Fine
'1'] # Unpatterned
if not client.set_alignment_parameters(*params):
client.LAST_ERROR = "Can't set alignment data"
return 0
return client.load(wafer)
def load(self, e):
'''Load wafer'''
try:
self.busy()
if self.wafers.GetCount() == 0:
self.error('No Wafers')
return
if len(self.wafers.GetSelections()) != 1:
self.error('Please select only one wafer')
return
wafer = self.wafers.GetString(self.wafers.GetSelections()[0])
self.status(self._load(wafer))
finally:
self.idle()
def unload(self, e):
'''Unload wafer'''
try:
self.busy()
self.status(client.unload())
finally:
self.idle()
def run(self, e):
'''Run process for given number of iterations'''
try:
self.busy()
wafers = map(lambda i: self.wafers.GetString(i), \
self.wafers.GetSelections())
for t in range(self.times.GetValue()):
for wafer in wafers:
if not self._load(wafer):
self.status(0)
return
if not client.start_process():
self.status(0)
return
if not client.unload():
self.status(0)
return
self.status(1)
finally:
self.idle()
def stop(self, e):
'''Stop process'''
try:
self.busy()
self.status(client.stop())
finally:
self.idle()
def connect(self, e):
'''Connect to tcp server'''
try:
self.busy()
if not client.connect():
self.connected = 0
self.SetStatusText(DISONNECTED)
return
self.SetStatusText(CONNECTED)
finally:
self.idle()
def main():
app = wxPySimpleApp()
frame = CompassClient()
frame.Show(1)
app.MainLoop()
# Main
if __name__ == '__main__':
main()
--- ui.py ---
--- client.py ---
'''Compas client emulator'''
__author__ = 'Miki Tebeka <miki_tebeka at amat.com>'
__id__ = '$Id: client.py,v 1.5 2003/03/06 14:20:15 MTebeka90603 Exp $'
# $Source: /u/CVSROOT/compass_client/client.py,v $
from socket import error as SocketError, socket, AF_INET, SOCK_STREAM
import re
from xml.dom.minidom import parseString
from sys import exit
SOCKET = None # Global socket
HOST = 'localhost' # Host name
PORT = 3333 # Port
LAST_ERROR = '' # Last error
def header(name):
'''Create header xml'''
return '<Header To="BEE" From="WF" Type="Request" Name="%s"/>' %
name
def connect():
'''Connect to tcp server'''
global SOCKET, LAST_ERROR
SOCKET = socket(AF_INET, SOCK_STREAM)
try:
SOCKET.connect((HOST, PORT))
return 1
except SocketError, e:
LAST_ERROR = str(e)
SOCKET = None
return 0
def disconnect():
global SOCKET
SOCKET = None
def is_connected():
global SOCKET
return SOCKET != None
def _send(msg):
'''send "len msg"'''
SOCKET.sendall('%d %s' % (len(msg), msg))
# Regular expressions
NUM_RE = re.compile('\d')
WS_RE = re.compile('\s')
def _read():
'''Read message. Return error + extra'''
size = ''
while 1:
d = SOCKET.recv(1)
if not NUM_RE.match(d):
break
size += d
return _parse_respone(SOCKET.recv(int(size)))
class Error:
'''Error class'''
def __init__(self, value = 0, message = ''):
self.value = value # Error value
self.message = message # Error message
def __repr__(self):
return 'Error (%d): %s' % (self.value, self.message)
def ok(self):
'''True not error occured'''
return self.value == 0
def _parse_respone(msg):
'''Parse a respone. Return error + extra'''
global LAST_ERROR
doc = parseString(msg)
datanode = doc.getElementsByTagName('Data')[0]
assert(len(datanode.childNodes) in [1,2])
errnode = None
for node in datanode.childNodes:
if node.nodeName == 'Error':
errnode = node
datanode.removeChild(node)
break
assert(errnode)
attrs = errnode.attributes
err = Error(int(attrs['ErrNum'].value), attrs['ErrText'].value)
LAST_ERROR = err.message
if len(datanode.childNodes):
extra = datanode.childNodes[0]
else:
extra = None
return err, extra
def _simple_cmd(msg):
'''Simple command'''
if not SOCKET:
return 0
_send(msg)
err, extra = _read()
return err.ok()
def _list_cmd(msg):
'''Command that returns a list'''
if not SOCKET:
return 0
_send(msg)
err, extra = _read()
if not err.ok():
return []
else:
return map(lambda n: n.nodeValue, extra.attributes.values())
def _state_cmd(msg):
'''Command that returns a state'''
if not SOCKET:
return 0
_send(msg)
err, extra = _read()
if not err.ok():
return -1
return int(extra.attributes['Value'].nodeValue)
# Interface functions
def get_lot_data():
'''Get lot data'''
return _simple_cmd(header('GetLotData'))
def get_recipe_list():
'''Get recipe list'''
print 'get_recipe_list'
return _list_cmd(header('GetRecipeList'))
def select_recipe(recipe):
'''Select a recipe'''
msg = header('SelectRecipe')
msg += '<Data><Recipe Name="%s"/></Data>' % recipe
return _simple_cmd(msg)
def get_wafer_list():
'''Get wafer list'''
return _list_cmd(header('GetWafersList'))
def set_alignment_parameters(*params):
'''Set alignment parameters'''
assert(len(params) == 11)
msg = header('AlignData') + '''
<Data>
<CoarseImage Name="%s" Format="%s"/>
<CoarsePixelSize psX="%s" psY="%s"/>
<CenterToCoarse CntrToCrsX="%s" CntrToCrsY="%s"/>
<CoarseToFine CrsToFineX="%s" CrsToFineY="%s"/>
<CornerToFine CrnToFineX="%s" CrnToFineY="%s"/>
<WaferType UnPatternedWafer="%s"/>
</Data>''' % params
return _simple_cmd(msg)
def prepare_to_load(slot):
'''Prepare to load'''
msg = header('PrepareToLoad')
msg += '<Data><Slot SlotID="%s"/></Data>' % slot
return _simple_cmd(msg)
def load_ended():
'''Load ended'''
return _simple_cmd(header('LoadEnded'))
def load(slot):
'''Load sequence'''
if not prepare_to_load(slot):
return 0
return load_ended()
def start_process():
'''Start process'''
return _simple_cmd(header('StartProcess'))
def prepare_to_unload():
'''Prepare to unload'''
return _simple_cmd(header('PrepareToUnload'))
def unload_ended():
'''Unload ended'''
return _simple_cmd(header('UnloadEnded'))
def unload():
'''Unload sequence'''
if not prepare_to_unload():
return 0
return unload_ended()
def get_state():
'''Get state'''
return _state_cmd(header('GetState'))
def get_vacuum_state():
'''Get vacuum state'''
return _state_cmd(header('GetVacuumState'))
def stop():
'''Stop'''
return _simple_cmd(header('bee_stop_process'))
--- client.py ---
More information about the Python-list
mailing list