##// END OF EJS Templates
revised threading model....
ldufrechou -
Show More
@@ -55,9 +55,8 b' class _Helper(object):'
55
55
56 #helper.output.write = self.doc.append
56 #helper.output.write = self.doc.append
57 return pydoc.help(*args, **kwds)
57 return pydoc.help(*args, **kwds)
58
58
59
59 class IterableIPShell(object):
60 class IterableIPShell(Thread):
61 '''
60 '''
62 Create an IPython instance inside a dedicated thread.
61 Create an IPython instance inside a dedicated thread.
63 Does not start a blocking event loop, instead allow single iterations.
62 Does not start a blocking event loop, instead allow single iterations.
@@ -70,7 +69,7 b' class IterableIPShell(Thread):'
70 def __init__(self,argv
69 def __init__(self,argv
71 =[],user_ns={},user_global_ns=None,
70 =[],user_ns={},user_global_ns=None,
72 cin=None, cout=None, cerr=None,
71 cin=None, cout=None, cerr=None,
73 exit_handler=None,time_loop = 0.1):
72 ask_exit_handler=None, do_exit_handler=None, time_loop = 0.1):
74 '''
73 '''
75 @param argv: Command line options for IPython
74 @param argv: Command line options for IPython
76 @type argv: list
75 @type argv: list
@@ -89,7 +88,6 b' class IterableIPShell(Thread):'
89 @param time_loop: Define the sleep time between two thread's loop
88 @param time_loop: Define the sleep time between two thread's loop
90 @type int
89 @type int
91 '''
90 '''
92 Thread.__init__(self)
93
91
94 #first we redefine in/out/error functions of IPython
92 #first we redefine in/out/error functions of IPython
95 if cin:
93 if cin:
@@ -127,7 +125,11 b' class IterableIPShell(Thread):'
127 IPython.iplib.raw_input_original = self._raw_input
125 IPython.iplib.raw_input_original = self._raw_input
128 #we replace the ipython default exit command by our method
126 #we replace the ipython default exit command by our method
129 self._IP.exit = self._setAskExit
127 self._IP.exit = self._setAskExit
130
128 #we modify Exit and Quit Magic
129 ip = IPython.ipapi.get()
130 ip.expose_magic('Exit', self._setDoExit)
131 ip.expose_magic('Quit', self._setDoExit)
132
131 sys.excepthook = excepthook
133 sys.excepthook = excepthook
132
134
133 self._iter_more = 0
135 self._iter_more = 0
@@ -136,9 +138,6 b' class IterableIPShell(Thread):'
136 self._prompt = str(self._IP.outputcache.prompt1).strip()
138 self._prompt = str(self._IP.outputcache.prompt1).strip()
137
139
138 #thread working vars
140 #thread working vars
139 self._terminate = False
140 self._time_loop = time_loop
141 self._do_execute = False
142 self._line_to_execute = ''
141 self._line_to_execute = ''
143
142
144 #vars that will be checked by GUI loop to handle thread states...
143 #vars that will be checked by GUI loop to handle thread states...
@@ -152,46 +151,30 b' class IterableIPShell(Thread):'
152 self._IP.user_ns['help'] = _Helper(self._pager_help)
151 self._IP.user_ns['help'] = _Helper(self._pager_help)
153
152
154 #----------------------- Thread management section ----------------------
153 #----------------------- Thread management section ----------------------
155 def run (self):
156 """
157 Thread main loop
158 The thread will run until self._terminate will be set to True via shutdown() function
159 Command processing can be interrupted with Instance.raise_exc(KeyboardInterrupt) call in the
160 GUI thread.
161 """
162 while(not self._terminate):
163 try:
164 if self._do_execute:
165 self._doc_text = None
166 self._help_text = None
167 self._execute()
168 self._do_execute = False
169 self._afterExecute() #used for uper class to generate event after execution
170
171 except KeyboardInterrupt:
172 pass
173
174 time.sleep(self._time_loop)
175
176 def shutdown(self):
177 """
178 Shutdown the tread
179 """
180 self._terminate = True
181
182 def doExecute(self,line):
154 def doExecute(self,line):
183 """
155 """
184 Tell the thread to process the 'line' command
156 Tell the thread to process the 'line' command
185 """
157 """
186 self._do_execute = True
158
187 self._line_to_execute = line
159 self._line_to_execute = line
160 class CodeExecutor(Thread):
161 def __init__(self,instance,after):
162 Thread.__init__(self)
163 self.instance = instance
164 self._afterExecute=after
165 def run(self):
166 try:
167 self.instance._doc_text = None
168 self.instance._help_text = None
169 self.instance._execute()
170 self._afterExecute() #used for uper class to generate event after execution
171
172 except KeyboardInterrupt:
173 pass
174
175 self.ce = CodeExecutor(self,self._afterExecute)
176 self.ce.start()
188
177
189 def isExecuteDone(self):
190 """
191 Returns the processing state
192 """
193 return not self._do_execute
194
195 #----------------------- IPython management section ----------------------
178 #----------------------- IPython management section ----------------------
196 def getAskExit(self):
179 def getAskExit(self):
197 '''
180 '''
@@ -360,10 +343,17 b' class IterableIPShell(Thread):'
360
343
361 def _setAskExit(self):
344 def _setAskExit(self):
362 '''
345 '''
363 set the _ask_exit variable that can be cjhecked by GUI to see if
346 set the _ask_exit variable that can be checked by GUI to see if
364 IPython request an exit handling
347 IPython request an exit handling
365 '''
348 '''
366 self._ask_exit = True
349 self._ask_exit = True
350
351 def _setDoExit(self, toto, arg):
352 '''
353 set the _do_exit variable that can be checked by GUI to see if
354 IPython do a direct exit of the app
355 '''
356 self._do_exit = True
367
357
368 def _getHistoryMaxIndex(self):
358 def _getHistoryMaxIndex(self):
369 '''
359 '''
@@ -378,7 +368,7 b' class IterableIPShell(Thread):'
378 '''
368 '''
379 Get's the command string of the current history level.
369 Get's the command string of the current history level.
380
370
381 @return: Historic command string.
371 @return: Historic command stri
382 @rtype: string
372 @rtype: string
383 '''
373 '''
384 rv = self._IP.input_hist_raw[self._history_level].strip('\n')
374 rv = self._IP.input_hist_raw[self._history_level].strip('\n')
@@ -51,24 +51,27 b' class WxIterableIPShell(IterableIPShell):'
51 def __init__(self,wx_instance,
51 def __init__(self,wx_instance,
52 argv=[],user_ns={},user_global_ns=None,
52 argv=[],user_ns={},user_global_ns=None,
53 cin=None, cout=None, cerr=None,
53 cin=None, cout=None, cerr=None,
54 exit_handler=None,time_loop = 0.1):
54 ask_exit_handler=None,do_exit_handler=None,time_loop = 0.1):
55
55
56 user_ns['addGUIShortcut'] = self.addGUIShortcut
56 #user_ns['addGUIShortcut'] = self.addGUIShortcut
57 IterableIPShell.__init__(self,argv,user_ns,user_global_ns,
57 IterableIPShell.__init__(self,argv,user_ns,user_global_ns,
58 cin, cout, cerr,
58 cin, cout, cerr,
59 exit_handler,time_loop)
59 ask_exit_handler, do_exit_handler, time_loop)
60
60
61 # This creates a new Event class and a EVT binder function
61 # This creates a new Event class and a EVT binder function
62 (self.IPythonAskExitEvent, EVT_IP_ASK_EXIT) = wx.lib.newevent.NewEvent()
62 (self.IPythonAskExitEvent, EVT_IP_ASK_EXIT) = wx.lib.newevent.NewEvent()
63 (self.IPythonDoExitEvent, EVT_IP_DO_EXIT) = wx.lib.newevent.NewEvent()
63 (self.IPythonAddButtonEvent, EVT_IP_ADD_BUTTON_EXIT) = wx.lib.newevent.NewEvent()
64 (self.IPythonAddButtonEvent, EVT_IP_ADD_BUTTON_EXIT) = wx.lib.newevent.NewEvent()
64 (self.IPythonExecuteDoneEvent, EVT_IP_EXECUTE_DONE) = wx.lib.newevent.NewEvent()
65 (self.IPythonExecuteDoneEvent, EVT_IP_EXECUTE_DONE) = wx.lib.newevent.NewEvent()
65
66
66 wx_instance.Bind(EVT_IP_ASK_EXIT, wx_instance.exit_handler)
67 wx_instance.Bind(EVT_IP_ASK_EXIT, wx_instance.ask_exit_handler)
68 wx_instance.Bind(EVT_IP_DO_EXIT, wx_instance.do_exit_handler)
67 wx_instance.Bind(EVT_IP_ADD_BUTTON_EXIT, wx_instance.add_button_handler)
69 wx_instance.Bind(EVT_IP_ADD_BUTTON_EXIT, wx_instance.add_button_handler)
68 wx_instance.Bind(EVT_IP_EXECUTE_DONE, wx_instance.evtStateExecuteDone)
70 wx_instance.Bind(EVT_IP_EXECUTE_DONE, wx_instance.evtStateExecuteDone)
69
71
70 self.wx_instance = wx_instance
72 self.wx_instance = wx_instance
71 self._IP.exit = self._AskExit
73 self._IP.ask_exit = self._AskExit
74 self._IP.do_exit = self._DoExit
72
75
73 def addGUIShortcut(self,text,func):
76 def addGUIShortcut(self,text,func):
74 evt = self.IPythonAddButtonEvent(button_info={'text':text,'func':self.wx_instance.doExecuteLine(func)})
77 evt = self.IPythonAddButtonEvent(button_info={'text':text,'func':self.wx_instance.doExecuteLine(func)})
@@ -78,6 +81,10 b' class WxIterableIPShell(IterableIPShell):'
78 evt = self.IPythonAskExitEvent()
81 evt = self.IPythonAskExitEvent()
79 wx.PostEvent(self.wx_instance, evt)
82 wx.PostEvent(self.wx_instance, evt)
80
83
84 def _DoExit(self):
85 evt = self.IPythonDoExitEvent()
86 wx.PostEvent(self.wx_instance, evt)
87
81 def _afterExecute(self):
88 def _afterExecute(self):
82 evt = self.IPythonExecuteDoneEvent()
89 evt = self.IPythonExecuteDoneEvent()
83 wx.PostEvent(self.wx_instance, evt)
90 wx.PostEvent(self.wx_instance, evt)
@@ -464,7 +471,7 b' class WxIPythonViewPanel(wx.Panel):'
464 I've choosed to derivate from a wx.Panel because it seems to be ore usefull
471 I've choosed to derivate from a wx.Panel because it seems to be ore usefull
465 Any idea to make it more 'genric' welcomed.
472 Any idea to make it more 'genric' welcomed.
466 '''
473 '''
467 def __init__(self,parent,exit_handler=None,intro=None,
474 def __init__(self,parent,ask_exit_handler=None,do_exit_handler=None,intro=None,
468 background_color="BLACK",add_button_handler=None):
475 background_color="BLACK",add_button_handler=None):
469 '''
476 '''
470 Initialize.
477 Initialize.
@@ -478,14 +485,14 b' class WxIPythonViewPanel(wx.Panel):'
478 self.cout = StringIO()
485 self.cout = StringIO()
479
486
480 self.add_button_handler = add_button_handler
487 self.add_button_handler = add_button_handler
481 self.exit_handler = exit_handler
488 self.ask_exit_handler = ask_exit_handler
489 self.do_exit_handler = do_exit_handler
482
490
483 self.IP = WxIterableIPShell(self,
491 self.IP = WxIterableIPShell(self,
484 cout=self.cout,cerr=self.cout,
492 cout=self.cout,cerr=self.cout,
485 exit_handler = exit_handler,
493 ask_exit_handler = ask_exit_handler,
494 do_exit_handler = do_exit_handler,
486 time_loop = 0.1)
495 time_loop = 0.1)
487 self.IP.start()
488
489 ### IPython wx console view instanciation ###
496 ### IPython wx console view instanciation ###
490 #If user didn't defined an intro text, we create one for him
497 #If user didn't defined an intro text, we create one for him
491 #If you really wnat an empty intrp just call wxIPythonViewPanel with intro=''
498 #If you really wnat an empty intrp just call wxIPythonViewPanel with intro=''
@@ -537,8 +544,6 b' class WxIPythonViewPanel(wx.Panel):'
537 #self.Bind(wx.EVT_IDLE, self.runStateMachine)
544 #self.Bind(wx.EVT_IDLE, self.runStateMachine)
538
545
539 def __del__(self):
546 def __del__(self):
540 self.IP.shutdown()
541 self.IP.join()
542 WxConsoleView.__del__()
547 WxConsoleView.__del__()
543
548
544 #---------------------------- IPython Thread Management ---------------------------------------
549 #---------------------------- IPython Thread Management ---------------------------------------
@@ -701,7 +706,7 b' class WxIPythonViewPanel(wx.Panel):'
701 if event.Modifiers == wx.MOD_CONTROL:
706 if event.Modifiers == wx.MOD_CONTROL:
702 if self.cur_state == 'WAIT_END_OF_EXECUTION':
707 if self.cur_state == 'WAIT_END_OF_EXECUTION':
703 #we raise an exception inside the IPython thread container
708 #we raise an exception inside the IPython thread container
704 self.IP.raise_exc(KeyboardInterrupt)
709 self.IP.ce.raise_exc(KeyboardInterrupt)
705 return
710 return
706
711
707 if event.KeyCode == wx.WXK_RETURN:
712 if event.KeyCode == wx.WXK_RETURN:
General Comments 0
You need to be logged in to leave comments. Login now