Show More
@@ -50,30 +50,34 b' class WxNonBlockingIPShell(NonBlockingIPShell):' | |||
|
50 | 50 | def __init__(self,wx_instance, |
|
51 | 51 | argv=[],user_ns={},user_global_ns=None, |
|
52 | 52 | cin=None, cout=None, cerr=None, |
|
53 |
exit_handler=None |
|
|
53 | ask_exit_handler=None): | |
|
54 | 54 | |
|
55 | user_ns['addGUIShortcut'] = self.addGUIShortcut | |
|
55 | #user_ns['addGUIShortcut'] = self.addGUIShortcut | |
|
56 | 56 | NonBlockingIPShell.__init__(self,argv,user_ns,user_global_ns, |
|
57 | 57 | cin, cout, cerr, |
|
58 |
exit_handler |
|
|
58 | ask_exit_handler) | |
|
59 | 59 | |
|
60 | 60 | # This creates a new Event class and a EVT binder function |
|
61 | 61 | (self.IPythonAskExitEvent, EVT_IP_ASK_EXIT) = wx.lib.newevent.NewEvent() |
|
62 |
(self.IPythonAddButtonEvent, EVT_IP_ADD_BUTTON_EXIT) = |
|
|
63 | (self.IPythonExecuteDoneEvent, EVT_IP_EXECUTE_DONE) = wx.lib.newevent.NewEvent() | |
|
62 | (self.IPythonAddButtonEvent, EVT_IP_ADD_BUTTON_EXIT) = \ | |
|
63 | wx.lib.newevent.NewEvent() | |
|
64 | (self.IPythonExecuteDoneEvent, EVT_IP_EXECUTE_DONE) = \ | |
|
65 | wx.lib.newevent.NewEvent() | |
|
64 | 66 | |
|
65 | wx_instance.Bind(EVT_IP_ASK_EXIT, wx_instance.exit_handler) | |
|
67 | wx_instance.Bind(EVT_IP_ASK_EXIT, wx_instance.ask_exit_handler) | |
|
66 | 68 | wx_instance.Bind(EVT_IP_ADD_BUTTON_EXIT, wx_instance.add_button_handler) |
|
67 | 69 | wx_instance.Bind(EVT_IP_EXECUTE_DONE, wx_instance.evtStateExecuteDone) |
|
68 | 70 | |
|
69 | 71 | self.wx_instance = wx_instance |
|
70 |
self._IP.exit = self._ |
|
|
72 | self._IP.ask_exit = self._askExit | |
|
71 | 73 | |
|
72 | 74 | def addGUIShortcut(self,text,func): |
|
73 | evt = self.IPythonAddButtonEvent(button_info={'text':text,'func':self.wx_instance.doExecuteLine(func)}) | |
|
75 | evt = self.IPythonAddButtonEvent( | |
|
76 | button_info={ 'text':text, | |
|
77 | 'func':self.wx_instance.doExecuteLine(func)}) | |
|
74 | 78 | wx.PostEvent(self.wx_instance, evt) |
|
75 | 79 | |
|
76 |
def _ |
|
|
80 | def _askExit(self): | |
|
77 | 81 | evt = self.IPythonAskExitEvent() |
|
78 | 82 | wx.PostEvent(self.wx_instance, evt) |
|
79 | 83 | |
@@ -463,7 +467,8 b' class WxIPythonViewPanel(wx.Panel):' | |||
|
463 | 467 | I've choosed to derivate from a wx.Panel because it seems to be ore usefull |
|
464 | 468 | Any idea to make it more 'genric' welcomed. |
|
465 | 469 | ''' |
|
466 | def __init__(self, parent, exit_handler=None, intro=None, | |
|
470 | ||
|
471 | def __init__(self, parent, ask_exit_handler=None, intro=None, | |
|
467 | 472 | background_color="BLACK", add_button_handler=None, |
|
468 | 473 | wx_ip_shell=None, |
|
469 | 474 | ): |
@@ -479,17 +484,14 b' class WxIPythonViewPanel(wx.Panel):' | |||
|
479 | 484 | self.cout = StringIO() |
|
480 | 485 | |
|
481 | 486 | self.add_button_handler = add_button_handler |
|
482 | self.exit_handler = exit_handler | |
|
487 | self.ask_exit_handler = ask_exit_handler | |
|
483 | 488 | |
|
484 | 489 | if wx_ip_shell is not None: |
|
485 | 490 | self.IP = wx_ip_shell |
|
486 | 491 | else: |
|
487 | 492 | self.IP = WxNonBlockingIPShell(self, |
|
488 | 493 | cout=self.cout,cerr=self.cout, |
|
489 |
exit_handler = exit_handler |
|
|
490 | time_loop = 0.1) | |
|
491 | self.IP.start() | |
|
492 | ||
|
494 | ask_exit_handler = ask_exit_handler) | |
|
493 | 495 | ### IPython wx console view instanciation ### |
|
494 | 496 | #If user didn't defined an intro text, we create one for him |
|
495 | 497 | #If you really wnat an empty intrp just call wxIPythonViewPanel with intro='' |
@@ -541,8 +543,6 b' class WxIPythonViewPanel(wx.Panel):' | |||
|
541 | 543 | #self.Bind(wx.EVT_IDLE, self.runStateMachine) |
|
542 | 544 | |
|
543 | 545 | def __del__(self): |
|
544 | self.IP.shutdown() | |
|
545 | self.IP.join() | |
|
546 | 546 | WxConsoleView.__del__() |
|
547 | 547 | |
|
548 | 548 | #---------------------------- IPython Thread Management --------------------------------------- |
@@ -705,7 +705,7 b' class WxIPythonViewPanel(wx.Panel):' | |||
|
705 | 705 | if event.Modifiers == wx.MOD_CONTROL: |
|
706 | 706 | if self.cur_state == 'WAIT_END_OF_EXECUTION': |
|
707 | 707 | #we raise an exception inside the IPython thread container |
|
708 | self.IP.raise_exc(KeyboardInterrupt) | |
|
708 | self.IP.ce.raise_exc(KeyboardInterrupt) | |
|
709 | 709 | return |
|
710 | 710 | |
|
711 | 711 | if event.KeyCode == wx.WXK_RETURN: |
@@ -31,16 +31,19 b' try:' | |||
|
31 | 31 | except Exception,e: |
|
32 | 32 | raise "Error importing IPython (%s)" % str(e) |
|
33 | 33 | |
|
34 | ############################################################################## | |
|
34 | 35 | class _Helper(object): |
|
35 | 36 | """Redefine the built-in 'help'. |
|
36 | 37 | This is a wrapper around pydoc.help (with a twist). |
|
37 | 38 | """ |
|
39 | ||
|
38 | 40 | def __init__(self,pager): |
|
39 | 41 | self._pager = pager |
|
40 | 42 | |
|
41 | 43 | def __repr__(self): |
|
42 | 44 | return "Type help() for interactive help, " \ |
|
43 | 45 | "or help(object) for help about object." |
|
46 | ||
|
44 | 47 | def __call__(self, *args, **kwds): |
|
45 | 48 | class DummyWriter(object): |
|
46 | 49 | def __init__(self,pager): |
@@ -57,20 +60,41 b' class _Helper(object):' | |||
|
57 | 60 | return pydoc.help(*args, **kwds) |
|
58 | 61 | |
|
59 | 62 | |
|
60 | class NonBlockingIPShell(ThreadEx): | |
|
63 | ############################################################################## | |
|
64 | class _CodeExecutor(ThreadEx): | |
|
65 | ||
|
66 | def __init__(self, instance, after): | |
|
67 | ThreadEx.__init__(self) | |
|
68 | self.instance = instance | |
|
69 | self._afterExecute=after | |
|
70 | ||
|
71 | def run(self): | |
|
72 | try: | |
|
73 | self.instance._doc_text = None | |
|
74 | self.instance._help_text = None | |
|
75 | self.instance._execute() | |
|
76 | # used for uper class to generate event after execution | |
|
77 | self._afterExecute() | |
|
78 | ||
|
79 | except KeyboardInterrupt: | |
|
80 | pass | |
|
81 | ||
|
82 | ||
|
83 | ############################################################################## | |
|
84 | class NonBlockingIPShell(object): | |
|
61 | 85 | ''' |
|
62 |
Create an IPython instance |
|
|
63 | Does not start a blocking event loop, instead allow single iterations. | |
|
86 | Create an IPython instance, running the commands in a separate, | |
|
87 | non-blocking thread. | |
|
64 | 88 | This allows embedding in any GUI without blockage. |
|
65 | The thread is a slave one, in that it doesn't interact directly with the GUI. | |
|
66 | Note ThreadEx class supports asynchroneous function call | |
|
89 | ||
|
90 | Note: The ThreadEx class supports asynchroneous function call | |
|
67 | 91 | via raise_exc() |
|
68 | 92 | ''' |
|
69 | 93 | |
|
70 | 94 | def __init__(self,argv |
|
71 | 95 | =[],user_ns={},user_global_ns=None, |
|
72 | 96 | cin=None, cout=None, cerr=None, |
|
73 |
exit_handler=None |
|
|
97 | ask_exit_handler=None): | |
|
74 | 98 | ''' |
|
75 | 99 | @param argv: Command line options for IPython |
|
76 | 100 | @type argv: list |
@@ -89,8 +113,6 b' class NonBlockingIPShell(ThreadEx):' | |||
|
89 | 113 | @param time_loop: Define the sleep time between two thread's loop |
|
90 | 114 | @type int |
|
91 | 115 | ''' |
|
92 | ThreadEx.__init__(self) | |
|
93 | ||
|
94 | 116 | #first we redefine in/out/error functions of IPython |
|
95 | 117 | if cin: |
|
96 | 118 | IPython.Shell.Term.cin = cin |
@@ -127,6 +149,10 b' class NonBlockingIPShell(ThreadEx):' | |||
|
127 | 149 | IPython.iplib.raw_input_original = self._raw_input |
|
128 | 150 | #we replace the ipython default exit command by our method |
|
129 | 151 | self._IP.exit = self._setAskExit |
|
152 | #we modify Exit and Quit Magic | |
|
153 | ip = IPython.ipapi.get() | |
|
154 | ip.expose_magic('Exit', self._setDoExit) | |
|
155 | ip.expose_magic('Quit', self._setDoExit) | |
|
130 | 156 | |
|
131 | 157 | sys.excepthook = excepthook |
|
132 | 158 | |
@@ -136,9 +162,6 b' class NonBlockingIPShell(ThreadEx):' | |||
|
136 | 162 | self._prompt = str(self._IP.outputcache.prompt1).strip() |
|
137 | 163 | |
|
138 | 164 | #thread working vars |
|
139 | self._terminate = False | |
|
140 | self._time_loop = time_loop | |
|
141 | self._do_execute = False | |
|
142 | 165 | self._line_to_execute = '' |
|
143 | 166 | |
|
144 | 167 | #vars that will be checked by GUI loop to handle thread states... |
@@ -152,45 +175,15 b' class NonBlockingIPShell(ThreadEx):' | |||
|
152 | 175 | self._IP.user_ns['help'] = _Helper(self._pager_help) |
|
153 | 176 | |
|
154 | 177 | #----------------------- 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 | 178 | def doExecute(self,line): |
|
183 | 179 | """ |
|
184 | 180 | Tell the thread to process the 'line' command |
|
185 | 181 | """ |
|
186 | self._do_execute = True | |
|
182 | ||
|
187 | 183 | self._line_to_execute = line |
|
188 | 184 |
|
|
189 | def isExecuteDone(self): | |
|
190 | """ | |
|
191 | Returns the processing state | |
|
192 | """ | |
|
193 | return not self._do_execute | |
|
185 | self.ce = _CodeExecutor(self,self._afterExecute) | |
|
186 | self.ce.start() | |
|
194 | 187 | |
|
195 | 188 | #----------------------- IPython management section ---------------------- |
|
196 | 189 | def getAskExit(self): |
@@ -351,7 +344,7 b' class NonBlockingIPShell(ThreadEx):' | |||
|
351 | 344 | ''' |
|
352 | 345 | self._history_level = self._getHistoryMaxIndex()+1 |
|
353 | 346 | |
|
354 |
#----------------------- IPython PRIVATE management section -------------- |
|
|
347 | #----------------------- IPython PRIVATE management section -------------- | |
|
355 | 348 | def _afterExecute(self): |
|
356 | 349 | ''' |
|
357 | 350 | Can be redefined to generate post event after excution is done |
@@ -360,11 +353,18 b' class NonBlockingIPShell(ThreadEx):' | |||
|
360 | 353 | |
|
361 | 354 | def _setAskExit(self): |
|
362 | 355 | ''' |
|
363 |
set the _ask_exit variable that can be c |
|
|
356 | set the _ask_exit variable that can be checked by GUI to see if | |
|
364 | 357 | IPython request an exit handling |
|
365 | 358 | ''' |
|
366 | 359 | self._ask_exit = True |
|
367 | 360 | |
|
361 | def _setDoExit(self, toto, arg): | |
|
362 | ''' | |
|
363 | set the _do_exit variable that can be checked by GUI to see if | |
|
364 | IPython do a direct exit of the app | |
|
365 | ''' | |
|
366 | self._do_exit = True | |
|
367 | ||
|
368 | 368 | def _getHistoryMaxIndex(self): |
|
369 | 369 | ''' |
|
370 | 370 | returns the max length of the history buffer |
@@ -378,7 +378,7 b' class NonBlockingIPShell(ThreadEx):' | |||
|
378 | 378 | ''' |
|
379 | 379 | Get's the command string of the current history level. |
|
380 | 380 | |
|
381 |
@return: Historic command stri |
|
|
381 | @return: Historic command stri | |
|
382 | 382 | @rtype: string |
|
383 | 383 | ''' |
|
384 | 384 | rv = self._IP.input_hist_raw[self._history_level].strip('\n') |
General Comments 0
You need to be logged in to leave comments.
Login now