class Interpreter_thread(Thread): """The threaded interpreter.""" def __init__(self): """Initialise the object.""" # Set up the thread object. Thread.__init__(self) # Set the thread to be daemonic so that relax can exit. self.daemon = True # Create a queue object for the user function calls. self._queue = Queue() # The list of user functions still in the queue. self._uf_list = [] # A flag for exiting the thread. self._exit = False def empty(self): """Is the queue empty?""" # Execution is locked. if status.exec_lock.locked(): return False # There are still queued calls. elif len(self._uf_list): return False # The queue is empty. else: return True def exit(self): """Cause the thread to exit once all currently queued user functions are processed.""" # First set the flag. self._exit = True # Then queue a dummy user function. self._queue.put([None, None, None]) def join(self): """Wrapper method for the Queue.join() method.""" # Join the queue. self._queue.join() def queue(self, fn, *args, **kwds): """Queue up a user function for asynchronous execution. @param fn: The user function as a string. @type fn: str @param args: The user function arguments. @type args: any arguments @param kwds: The user function keyword arguments. @type kwds: any keyword arguments """ # Add the user function name to the list. self._uf_list.append(repr(fn)) # Place the user function and its args onto the queue. self._queue.put([fn, args, kwds]) def run(self): """Execute the thread.""" # Loop until told to exit. while not self._exit: # Get the user function from the queue. fn, args, kwds = self._queue.get() # No user function. if fn == None: continue # Execution lock. status.exec_lock.acquire('gui', mode='interpreter thread') # Execute the user function, catching errors (the nested try-except statements within the try-finally statements are for Python 2.4 and earlier support). try: try: fn(*args, **kwds) # Catch all RelaxErrors. except AllRelaxErrors: instance = sys.exc_info()[1] # Display a dialog with the error. wx.CallAfter(gui_raise, instance, raise_flag=False) # Handle all other errors. except: # Print the exception. print_exc() # Release the lock. finally: # Signal that the queue item has been processed. self._queue.task_done() # Release the execution lock. status.exec_lock.release() # Remove the user function from the list. self._uf_list.pop(self._uf_list.index(repr(fn))) # Notify all observers that a user function has completed. status.observers.gui_uf.notify()