diff --git a/IPython/gui/wx/ipython_interactive_shell.py b/IPython/gui/wx/ipython_interactive_shell.py index 70a0815..9cbe948 100644 --- a/IPython/gui/wx/ipython_interactive_shell.py +++ b/IPython/gui/wx/ipython_interactive_shell.py @@ -55,9 +55,8 @@ class _Helper(object): #helper.output.write = self.doc.append return pydoc.help(*args, **kwds) - - -class IterableIPShell(Thread): + +class IterableIPShell(object): ''' Create an IPython instance inside a dedicated thread. Does not start a blocking event loop, instead allow single iterations. @@ -70,7 +69,7 @@ class IterableIPShell(Thread): def __init__(self,argv =[],user_ns={},user_global_ns=None, cin=None, cout=None, cerr=None, - exit_handler=None,time_loop = 0.1): + ask_exit_handler=None, do_exit_handler=None, time_loop = 0.1): ''' @param argv: Command line options for IPython @type argv: list @@ -89,7 +88,6 @@ class IterableIPShell(Thread): @param time_loop: Define the sleep time between two thread's loop @type int ''' - Thread.__init__(self) #first we redefine in/out/error functions of IPython if cin: @@ -127,7 +125,11 @@ class IterableIPShell(Thread): IPython.iplib.raw_input_original = self._raw_input #we replace the ipython default exit command by our method self._IP.exit = self._setAskExit - + #we modify Exit and Quit Magic + ip = IPython.ipapi.get() + ip.expose_magic('Exit', self._setDoExit) + ip.expose_magic('Quit', self._setDoExit) + sys.excepthook = excepthook self._iter_more = 0 @@ -136,9 +138,6 @@ class IterableIPShell(Thread): self._prompt = str(self._IP.outputcache.prompt1).strip() #thread working vars - self._terminate = False - self._time_loop = time_loop - self._do_execute = False self._line_to_execute = '' #vars that will be checked by GUI loop to handle thread states... @@ -152,46 +151,30 @@ class IterableIPShell(Thread): self._IP.user_ns['help'] = _Helper(self._pager_help) #----------------------- Thread management section ---------------------- - def run (self): - """ - Thread main loop - The thread will run until self._terminate will be set to True via shutdown() function - Command processing can be interrupted with Instance.raise_exc(KeyboardInterrupt) call in the - GUI thread. - """ - while(not self._terminate): - try: - if self._do_execute: - self._doc_text = None - self._help_text = None - self._execute() - self._do_execute = False - self._afterExecute() #used for uper class to generate event after execution - - except KeyboardInterrupt: - pass - - time.sleep(self._time_loop) - - def shutdown(self): - """ - Shutdown the tread - """ - self._terminate = True - def doExecute(self,line): """ Tell the thread to process the 'line' command """ - self._do_execute = True + self._line_to_execute = line + class CodeExecutor(Thread): + def __init__(self,instance,after): + Thread.__init__(self) + self.instance = instance + self._afterExecute=after + def run(self): + try: + self.instance._doc_text = None + self.instance._help_text = None + self.instance._execute() + self._afterExecute() #used for uper class to generate event after execution + + except KeyboardInterrupt: + pass + + self.ce = CodeExecutor(self,self._afterExecute) + self.ce.start() - def isExecuteDone(self): - """ - Returns the processing state - """ - return not self._do_execute - #----------------------- IPython management section ---------------------- def getAskExit(self): ''' @@ -360,10 +343,17 @@ class IterableIPShell(Thread): def _setAskExit(self): ''' - set the _ask_exit variable that can be cjhecked by GUI to see if + set the _ask_exit variable that can be checked by GUI to see if IPython request an exit handling ''' self._ask_exit = True + + def _setDoExit(self, toto, arg): + ''' + set the _do_exit variable that can be checked by GUI to see if + IPython do a direct exit of the app + ''' + self._do_exit = True def _getHistoryMaxIndex(self): ''' @@ -378,7 +368,7 @@ class IterableIPShell(Thread): ''' Get's the command string of the current history level. - @return: Historic command string. + @return: Historic command stri @rtype: string ''' rv = self._IP.input_hist_raw[self._history_level].strip('\n') diff --git a/IPython/gui/wx/ipython_view.py b/IPython/gui/wx/ipython_view.py index 7dee619..293ec61 100644 --- a/IPython/gui/wx/ipython_view.py +++ b/IPython/gui/wx/ipython_view.py @@ -51,24 +51,27 @@ class WxIterableIPShell(IterableIPShell): def __init__(self,wx_instance, argv=[],user_ns={},user_global_ns=None, cin=None, cout=None, cerr=None, - exit_handler=None,time_loop = 0.1): + ask_exit_handler=None,do_exit_handler=None,time_loop = 0.1): - user_ns['addGUIShortcut'] = self.addGUIShortcut + #user_ns['addGUIShortcut'] = self.addGUIShortcut IterableIPShell.__init__(self,argv,user_ns,user_global_ns, cin, cout, cerr, - exit_handler,time_loop) + ask_exit_handler, do_exit_handler, time_loop) # This creates a new Event class and a EVT binder function (self.IPythonAskExitEvent, EVT_IP_ASK_EXIT) = wx.lib.newevent.NewEvent() + (self.IPythonDoExitEvent, EVT_IP_DO_EXIT) = wx.lib.newevent.NewEvent() (self.IPythonAddButtonEvent, EVT_IP_ADD_BUTTON_EXIT) = wx.lib.newevent.NewEvent() (self.IPythonExecuteDoneEvent, EVT_IP_EXECUTE_DONE) = wx.lib.newevent.NewEvent() - wx_instance.Bind(EVT_IP_ASK_EXIT, wx_instance.exit_handler) + wx_instance.Bind(EVT_IP_ASK_EXIT, wx_instance.ask_exit_handler) + wx_instance.Bind(EVT_IP_DO_EXIT, wx_instance.do_exit_handler) wx_instance.Bind(EVT_IP_ADD_BUTTON_EXIT, wx_instance.add_button_handler) wx_instance.Bind(EVT_IP_EXECUTE_DONE, wx_instance.evtStateExecuteDone) self.wx_instance = wx_instance - self._IP.exit = self._AskExit + self._IP.ask_exit = self._AskExit + self._IP.do_exit = self._DoExit def addGUIShortcut(self,text,func): evt = self.IPythonAddButtonEvent(button_info={'text':text,'func':self.wx_instance.doExecuteLine(func)}) @@ -78,6 +81,10 @@ class WxIterableIPShell(IterableIPShell): evt = self.IPythonAskExitEvent() wx.PostEvent(self.wx_instance, evt) + def _DoExit(self): + evt = self.IPythonDoExitEvent() + wx.PostEvent(self.wx_instance, evt) + def _afterExecute(self): evt = self.IPythonExecuteDoneEvent() wx.PostEvent(self.wx_instance, evt) @@ -464,7 +471,7 @@ class WxIPythonViewPanel(wx.Panel): I've choosed to derivate from a wx.Panel because it seems to be ore usefull Any idea to make it more 'genric' welcomed. ''' - def __init__(self,parent,exit_handler=None,intro=None, + def __init__(self,parent,ask_exit_handler=None,do_exit_handler=None,intro=None, background_color="BLACK",add_button_handler=None): ''' Initialize. @@ -478,14 +485,14 @@ class WxIPythonViewPanel(wx.Panel): self.cout = StringIO() self.add_button_handler = add_button_handler - self.exit_handler = exit_handler + self.ask_exit_handler = ask_exit_handler + self.do_exit_handler = do_exit_handler self.IP = WxIterableIPShell(self, cout=self.cout,cerr=self.cout, - exit_handler = exit_handler, + ask_exit_handler = ask_exit_handler, + do_exit_handler = do_exit_handler, time_loop = 0.1) - self.IP.start() - ### IPython wx console view instanciation ### #If user didn't defined an intro text, we create one for him #If you really wnat an empty intrp just call wxIPythonViewPanel with intro='' @@ -537,8 +544,6 @@ class WxIPythonViewPanel(wx.Panel): #self.Bind(wx.EVT_IDLE, self.runStateMachine) def __del__(self): - self.IP.shutdown() - self.IP.join() WxConsoleView.__del__() #---------------------------- IPython Thread Management --------------------------------------- @@ -701,7 +706,7 @@ class WxIPythonViewPanel(wx.Panel): if event.Modifiers == wx.MOD_CONTROL: if self.cur_state == 'WAIT_END_OF_EXECUTION': #we raise an exception inside the IPython thread container - self.IP.raise_exc(KeyboardInterrupt) + self.IP.ce.raise_exc(KeyboardInterrupt) return if event.KeyCode == wx.WXK_RETURN: