##// END OF EJS Templates
Allow recursive execution of IPython code in MTInteractiveShell.runsource by checking if we are already in worker thread, and execute code directly if we are.
Ville M. Vainio -
Show More
@@ -1,1207 +1,1214 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2 """IPython Shell classes.
2 """IPython Shell classes.
3
3
4 All the matplotlib support code was co-developed with John Hunter,
4 All the matplotlib support code was co-developed with John Hunter,
5 matplotlib's author.
5 matplotlib's author.
6
6
7 $Id: Shell.py 3024 2008-02-07 15:34:42Z darren.dale $"""
7 $Id: Shell.py 3024 2008-02-07 15:34:42Z darren.dale $"""
8
8
9 #*****************************************************************************
9 #*****************************************************************************
10 # Copyright (C) 2001-2006 Fernando Perez <fperez@colorado.edu>
10 # Copyright (C) 2001-2006 Fernando Perez <fperez@colorado.edu>
11 #
11 #
12 # Distributed under the terms of the BSD License. The full license is in
12 # Distributed under the terms of the BSD License. The full license is in
13 # the file COPYING, distributed as part of this software.
13 # the file COPYING, distributed as part of this software.
14 #*****************************************************************************
14 #*****************************************************************************
15
15
16 from IPython import Release
16 from IPython import Release
17 __author__ = '%s <%s>' % Release.authors['Fernando']
17 __author__ = '%s <%s>' % Release.authors['Fernando']
18 __license__ = Release.license
18 __license__ = Release.license
19
19
20 # Code begins
20 # Code begins
21 # Stdlib imports
21 # Stdlib imports
22 import __builtin__
22 import __builtin__
23 import __main__
23 import __main__
24 import Queue
24 import Queue
25 import inspect
25 import inspect
26 import os
26 import os
27 import sys
27 import sys
28 import thread
28 import thread
29 import threading
29 import threading
30 import time
30 import time
31
31
32 from signal import signal, SIGINT
32 from signal import signal, SIGINT
33
33
34 try:
34 try:
35 import ctypes
35 import ctypes
36 HAS_CTYPES = True
36 HAS_CTYPES = True
37 except ImportError:
37 except ImportError:
38 HAS_CTYPES = False
38 HAS_CTYPES = False
39
39
40 # IPython imports
40 # IPython imports
41 import IPython
41 import IPython
42 from IPython import ultraTB, ipapi
42 from IPython import ultraTB, ipapi
43 from IPython.genutils import Term,warn,error,flag_calls, ask_yes_no
43 from IPython.genutils import Term,warn,error,flag_calls, ask_yes_no
44 from IPython.iplib import InteractiveShell
44 from IPython.iplib import InteractiveShell
45 from IPython.ipmaker import make_IPython
45 from IPython.ipmaker import make_IPython
46 from IPython.Magic import Magic
46 from IPython.Magic import Magic
47 from IPython.ipstruct import Struct
47 from IPython.ipstruct import Struct
48
48
49 # Globals
49 # Globals
50 # global flag to pass around information about Ctrl-C without exceptions
50 # global flag to pass around information about Ctrl-C without exceptions
51 KBINT = False
51 KBINT = False
52
52
53 # global flag to turn on/off Tk support.
53 # global flag to turn on/off Tk support.
54 USE_TK = False
54 USE_TK = False
55
55
56 # ID for the main thread, used for cross-thread exceptions
56 # ID for the main thread, used for cross-thread exceptions
57 MAIN_THREAD_ID = thread.get_ident()
57 MAIN_THREAD_ID = thread.get_ident()
58
58
59 # Tag when runcode() is active, for exception handling
59 # Tag when runcode() is active, for exception handling
60 CODE_RUN = None
60 CODE_RUN = None
61
61
62 #-----------------------------------------------------------------------------
62 #-----------------------------------------------------------------------------
63 # This class is trivial now, but I want to have it in to publish a clean
63 # This class is trivial now, but I want to have it in to publish a clean
64 # interface. Later when the internals are reorganized, code that uses this
64 # interface. Later when the internals are reorganized, code that uses this
65 # shouldn't have to change.
65 # shouldn't have to change.
66
66
67 class IPShell:
67 class IPShell:
68 """Create an IPython instance."""
68 """Create an IPython instance."""
69
69
70 def __init__(self,argv=None,user_ns=None,user_global_ns=None,
70 def __init__(self,argv=None,user_ns=None,user_global_ns=None,
71 debug=1,shell_class=InteractiveShell):
71 debug=1,shell_class=InteractiveShell):
72 self.IP = make_IPython(argv,user_ns=user_ns,
72 self.IP = make_IPython(argv,user_ns=user_ns,
73 user_global_ns=user_global_ns,
73 user_global_ns=user_global_ns,
74 debug=debug,shell_class=shell_class)
74 debug=debug,shell_class=shell_class)
75
75
76 def mainloop(self,sys_exit=0,banner=None):
76 def mainloop(self,sys_exit=0,banner=None):
77 self.IP.mainloop(banner)
77 self.IP.mainloop(banner)
78 if sys_exit:
78 if sys_exit:
79 sys.exit()
79 sys.exit()
80
80
81 #-----------------------------------------------------------------------------
81 #-----------------------------------------------------------------------------
82 def kill_embedded(self,parameter_s=''):
82 def kill_embedded(self,parameter_s=''):
83 """%kill_embedded : deactivate for good the current embedded IPython.
83 """%kill_embedded : deactivate for good the current embedded IPython.
84
84
85 This function (after asking for confirmation) sets an internal flag so that
85 This function (after asking for confirmation) sets an internal flag so that
86 an embedded IPython will never activate again. This is useful to
86 an embedded IPython will never activate again. This is useful to
87 permanently disable a shell that is being called inside a loop: once you've
87 permanently disable a shell that is being called inside a loop: once you've
88 figured out what you needed from it, you may then kill it and the program
88 figured out what you needed from it, you may then kill it and the program
89 will then continue to run without the interactive shell interfering again.
89 will then continue to run without the interactive shell interfering again.
90 """
90 """
91
91
92 kill = ask_yes_no("Are you sure you want to kill this embedded instance "
92 kill = ask_yes_no("Are you sure you want to kill this embedded instance "
93 "(y/n)? [y/N] ",'n')
93 "(y/n)? [y/N] ",'n')
94 if kill:
94 if kill:
95 self.shell.embedded_active = False
95 self.shell.embedded_active = False
96 print "This embedded IPython will not reactivate anymore once you exit."
96 print "This embedded IPython will not reactivate anymore once you exit."
97
97
98 class IPShellEmbed:
98 class IPShellEmbed:
99 """Allow embedding an IPython shell into a running program.
99 """Allow embedding an IPython shell into a running program.
100
100
101 Instances of this class are callable, with the __call__ method being an
101 Instances of this class are callable, with the __call__ method being an
102 alias to the embed() method of an InteractiveShell instance.
102 alias to the embed() method of an InteractiveShell instance.
103
103
104 Usage (see also the example-embed.py file for a running example):
104 Usage (see also the example-embed.py file for a running example):
105
105
106 ipshell = IPShellEmbed([argv,banner,exit_msg,rc_override])
106 ipshell = IPShellEmbed([argv,banner,exit_msg,rc_override])
107
107
108 - argv: list containing valid command-line options for IPython, as they
108 - argv: list containing valid command-line options for IPython, as they
109 would appear in sys.argv[1:].
109 would appear in sys.argv[1:].
110
110
111 For example, the following command-line options:
111 For example, the following command-line options:
112
112
113 $ ipython -prompt_in1 'Input <\\#>' -colors LightBG
113 $ ipython -prompt_in1 'Input <\\#>' -colors LightBG
114
114
115 would be passed in the argv list as:
115 would be passed in the argv list as:
116
116
117 ['-prompt_in1','Input <\\#>','-colors','LightBG']
117 ['-prompt_in1','Input <\\#>','-colors','LightBG']
118
118
119 - banner: string which gets printed every time the interpreter starts.
119 - banner: string which gets printed every time the interpreter starts.
120
120
121 - exit_msg: string which gets printed every time the interpreter exits.
121 - exit_msg: string which gets printed every time the interpreter exits.
122
122
123 - rc_override: a dict or Struct of configuration options such as those
123 - rc_override: a dict or Struct of configuration options such as those
124 used by IPython. These options are read from your ~/.ipython/ipythonrc
124 used by IPython. These options are read from your ~/.ipython/ipythonrc
125 file when the Shell object is created. Passing an explicit rc_override
125 file when the Shell object is created. Passing an explicit rc_override
126 dict with any options you want allows you to override those values at
126 dict with any options you want allows you to override those values at
127 creation time without having to modify the file. This way you can create
127 creation time without having to modify the file. This way you can create
128 embeddable instances configured in any way you want without editing any
128 embeddable instances configured in any way you want without editing any
129 global files (thus keeping your interactive IPython configuration
129 global files (thus keeping your interactive IPython configuration
130 unchanged).
130 unchanged).
131
131
132 Then the ipshell instance can be called anywhere inside your code:
132 Then the ipshell instance can be called anywhere inside your code:
133
133
134 ipshell(header='') -> Opens up an IPython shell.
134 ipshell(header='') -> Opens up an IPython shell.
135
135
136 - header: string printed by the IPython shell upon startup. This can let
136 - header: string printed by the IPython shell upon startup. This can let
137 you know where in your code you are when dropping into the shell. Note
137 you know where in your code you are when dropping into the shell. Note
138 that 'banner' gets prepended to all calls, so header is used for
138 that 'banner' gets prepended to all calls, so header is used for
139 location-specific information.
139 location-specific information.
140
140
141 For more details, see the __call__ method below.
141 For more details, see the __call__ method below.
142
142
143 When the IPython shell is exited with Ctrl-D, normal program execution
143 When the IPython shell is exited with Ctrl-D, normal program execution
144 resumes.
144 resumes.
145
145
146 This functionality was inspired by a posting on comp.lang.python by cmkl
146 This functionality was inspired by a posting on comp.lang.python by cmkl
147 <cmkleffner@gmx.de> on Dec. 06/01 concerning similar uses of pyrepl, and
147 <cmkleffner@gmx.de> on Dec. 06/01 concerning similar uses of pyrepl, and
148 by the IDL stop/continue commands."""
148 by the IDL stop/continue commands."""
149
149
150 def __init__(self,argv=None,banner='',exit_msg=None,rc_override=None,
150 def __init__(self,argv=None,banner='',exit_msg=None,rc_override=None,
151 user_ns=None):
151 user_ns=None):
152 """Note that argv here is a string, NOT a list."""
152 """Note that argv here is a string, NOT a list."""
153 self.set_banner(banner)
153 self.set_banner(banner)
154 self.set_exit_msg(exit_msg)
154 self.set_exit_msg(exit_msg)
155 self.set_dummy_mode(0)
155 self.set_dummy_mode(0)
156
156
157 # sys.displayhook is a global, we need to save the user's original
157 # sys.displayhook is a global, we need to save the user's original
158 # Don't rely on __displayhook__, as the user may have changed that.
158 # Don't rely on __displayhook__, as the user may have changed that.
159 self.sys_displayhook_ori = sys.displayhook
159 self.sys_displayhook_ori = sys.displayhook
160
160
161 # save readline completer status
161 # save readline completer status
162 try:
162 try:
163 #print 'Save completer',sys.ipcompleter # dbg
163 #print 'Save completer',sys.ipcompleter # dbg
164 self.sys_ipcompleter_ori = sys.ipcompleter
164 self.sys_ipcompleter_ori = sys.ipcompleter
165 except:
165 except:
166 pass # not nested with IPython
166 pass # not nested with IPython
167
167
168 self.IP = make_IPython(argv,rc_override=rc_override,
168 self.IP = make_IPython(argv,rc_override=rc_override,
169 embedded=True,
169 embedded=True,
170 user_ns=user_ns)
170 user_ns=user_ns)
171
171
172 ip = ipapi.IPApi(self.IP)
172 ip = ipapi.IPApi(self.IP)
173 ip.expose_magic("kill_embedded",kill_embedded)
173 ip.expose_magic("kill_embedded",kill_embedded)
174
174
175 # copy our own displayhook also
175 # copy our own displayhook also
176 self.sys_displayhook_embed = sys.displayhook
176 self.sys_displayhook_embed = sys.displayhook
177 # and leave the system's display hook clean
177 # and leave the system's display hook clean
178 sys.displayhook = self.sys_displayhook_ori
178 sys.displayhook = self.sys_displayhook_ori
179 # don't use the ipython crash handler so that user exceptions aren't
179 # don't use the ipython crash handler so that user exceptions aren't
180 # trapped
180 # trapped
181 sys.excepthook = ultraTB.FormattedTB(color_scheme = self.IP.rc.colors,
181 sys.excepthook = ultraTB.FormattedTB(color_scheme = self.IP.rc.colors,
182 mode = self.IP.rc.xmode,
182 mode = self.IP.rc.xmode,
183 call_pdb = self.IP.rc.pdb)
183 call_pdb = self.IP.rc.pdb)
184 self.restore_system_completer()
184 self.restore_system_completer()
185
185
186 def restore_system_completer(self):
186 def restore_system_completer(self):
187 """Restores the readline completer which was in place.
187 """Restores the readline completer which was in place.
188
188
189 This allows embedded IPython within IPython not to disrupt the
189 This allows embedded IPython within IPython not to disrupt the
190 parent's completion.
190 parent's completion.
191 """
191 """
192
192
193 try:
193 try:
194 self.IP.readline.set_completer(self.sys_ipcompleter_ori)
194 self.IP.readline.set_completer(self.sys_ipcompleter_ori)
195 sys.ipcompleter = self.sys_ipcompleter_ori
195 sys.ipcompleter = self.sys_ipcompleter_ori
196 except:
196 except:
197 pass
197 pass
198
198
199 def __call__(self,header='',local_ns=None,global_ns=None,dummy=None):
199 def __call__(self,header='',local_ns=None,global_ns=None,dummy=None):
200 """Activate the interactive interpreter.
200 """Activate the interactive interpreter.
201
201
202 __call__(self,header='',local_ns=None,global_ns,dummy=None) -> Start
202 __call__(self,header='',local_ns=None,global_ns,dummy=None) -> Start
203 the interpreter shell with the given local and global namespaces, and
203 the interpreter shell with the given local and global namespaces, and
204 optionally print a header string at startup.
204 optionally print a header string at startup.
205
205
206 The shell can be globally activated/deactivated using the
206 The shell can be globally activated/deactivated using the
207 set/get_dummy_mode methods. This allows you to turn off a shell used
207 set/get_dummy_mode methods. This allows you to turn off a shell used
208 for debugging globally.
208 for debugging globally.
209
209
210 However, *each* time you call the shell you can override the current
210 However, *each* time you call the shell you can override the current
211 state of dummy_mode with the optional keyword parameter 'dummy'. For
211 state of dummy_mode with the optional keyword parameter 'dummy'. For
212 example, if you set dummy mode on with IPShell.set_dummy_mode(1), you
212 example, if you set dummy mode on with IPShell.set_dummy_mode(1), you
213 can still have a specific call work by making it as IPShell(dummy=0).
213 can still have a specific call work by making it as IPShell(dummy=0).
214
214
215 The optional keyword parameter dummy controls whether the call
215 The optional keyword parameter dummy controls whether the call
216 actually does anything. """
216 actually does anything. """
217
217
218 # If the user has turned it off, go away
218 # If the user has turned it off, go away
219 if not self.IP.embedded_active:
219 if not self.IP.embedded_active:
220 return
220 return
221
221
222 # Normal exits from interactive mode set this flag, so the shell can't
222 # Normal exits from interactive mode set this flag, so the shell can't
223 # re-enter (it checks this variable at the start of interactive mode).
223 # re-enter (it checks this variable at the start of interactive mode).
224 self.IP.exit_now = False
224 self.IP.exit_now = False
225
225
226 # Allow the dummy parameter to override the global __dummy_mode
226 # Allow the dummy parameter to override the global __dummy_mode
227 if dummy or (dummy != 0 and self.__dummy_mode):
227 if dummy or (dummy != 0 and self.__dummy_mode):
228 return
228 return
229
229
230 # Set global subsystems (display,completions) to our values
230 # Set global subsystems (display,completions) to our values
231 sys.displayhook = self.sys_displayhook_embed
231 sys.displayhook = self.sys_displayhook_embed
232 if self.IP.has_readline:
232 if self.IP.has_readline:
233 self.IP.set_completer()
233 self.IP.set_completer()
234
234
235 if self.banner and header:
235 if self.banner and header:
236 format = '%s\n%s\n'
236 format = '%s\n%s\n'
237 else:
237 else:
238 format = '%s%s\n'
238 format = '%s%s\n'
239 banner = format % (self.banner,header)
239 banner = format % (self.banner,header)
240
240
241 # Call the embedding code with a stack depth of 1 so it can skip over
241 # Call the embedding code with a stack depth of 1 so it can skip over
242 # our call and get the original caller's namespaces.
242 # our call and get the original caller's namespaces.
243 self.IP.embed_mainloop(banner,local_ns,global_ns,stack_depth=1)
243 self.IP.embed_mainloop(banner,local_ns,global_ns,stack_depth=1)
244
244
245 if self.exit_msg:
245 if self.exit_msg:
246 print self.exit_msg
246 print self.exit_msg
247
247
248 # Restore global systems (display, completion)
248 # Restore global systems (display, completion)
249 sys.displayhook = self.sys_displayhook_ori
249 sys.displayhook = self.sys_displayhook_ori
250 self.restore_system_completer()
250 self.restore_system_completer()
251
251
252 def set_dummy_mode(self,dummy):
252 def set_dummy_mode(self,dummy):
253 """Sets the embeddable shell's dummy mode parameter.
253 """Sets the embeddable shell's dummy mode parameter.
254
254
255 set_dummy_mode(dummy): dummy = 0 or 1.
255 set_dummy_mode(dummy): dummy = 0 or 1.
256
256
257 This parameter is persistent and makes calls to the embeddable shell
257 This parameter is persistent and makes calls to the embeddable shell
258 silently return without performing any action. This allows you to
258 silently return without performing any action. This allows you to
259 globally activate or deactivate a shell you're using with a single call.
259 globally activate or deactivate a shell you're using with a single call.
260
260
261 If you need to manually"""
261 If you need to manually"""
262
262
263 if dummy not in [0,1,False,True]:
263 if dummy not in [0,1,False,True]:
264 raise ValueError,'dummy parameter must be boolean'
264 raise ValueError,'dummy parameter must be boolean'
265 self.__dummy_mode = dummy
265 self.__dummy_mode = dummy
266
266
267 def get_dummy_mode(self):
267 def get_dummy_mode(self):
268 """Return the current value of the dummy mode parameter.
268 """Return the current value of the dummy mode parameter.
269 """
269 """
270 return self.__dummy_mode
270 return self.__dummy_mode
271
271
272 def set_banner(self,banner):
272 def set_banner(self,banner):
273 """Sets the global banner.
273 """Sets the global banner.
274
274
275 This banner gets prepended to every header printed when the shell
275 This banner gets prepended to every header printed when the shell
276 instance is called."""
276 instance is called."""
277
277
278 self.banner = banner
278 self.banner = banner
279
279
280 def set_exit_msg(self,exit_msg):
280 def set_exit_msg(self,exit_msg):
281 """Sets the global exit_msg.
281 """Sets the global exit_msg.
282
282
283 This exit message gets printed upon exiting every time the embedded
283 This exit message gets printed upon exiting every time the embedded
284 shell is called. It is None by default. """
284 shell is called. It is None by default. """
285
285
286 self.exit_msg = exit_msg
286 self.exit_msg = exit_msg
287
287
288 #-----------------------------------------------------------------------------
288 #-----------------------------------------------------------------------------
289 if HAS_CTYPES:
289 if HAS_CTYPES:
290 # Add async exception support. Trick taken from:
290 # Add async exception support. Trick taken from:
291 # http://sebulba.wikispaces.com/recipe+thread2
291 # http://sebulba.wikispaces.com/recipe+thread2
292 def _async_raise(tid, exctype):
292 def _async_raise(tid, exctype):
293 """raises the exception, performs cleanup if needed"""
293 """raises the exception, performs cleanup if needed"""
294 if not inspect.isclass(exctype):
294 if not inspect.isclass(exctype):
295 raise TypeError("Only types can be raised (not instances)")
295 raise TypeError("Only types can be raised (not instances)")
296 res = ctypes.pythonapi.PyThreadState_SetAsyncExc(tid,
296 res = ctypes.pythonapi.PyThreadState_SetAsyncExc(tid,
297 ctypes.py_object(exctype))
297 ctypes.py_object(exctype))
298 if res == 0:
298 if res == 0:
299 raise ValueError("invalid thread id")
299 raise ValueError("invalid thread id")
300 elif res != 1:
300 elif res != 1:
301 # """if it returns a number greater than one, you're in trouble,
301 # """if it returns a number greater than one, you're in trouble,
302 # and you should call it again with exc=NULL to revert the effect"""
302 # and you should call it again with exc=NULL to revert the effect"""
303 ctypes.pythonapi.PyThreadState_SetAsyncExc(tid, 0)
303 ctypes.pythonapi.PyThreadState_SetAsyncExc(tid, 0)
304 raise SystemError("PyThreadState_SetAsyncExc failed")
304 raise SystemError("PyThreadState_SetAsyncExc failed")
305
305
306 def sigint_handler (signum,stack_frame):
306 def sigint_handler (signum,stack_frame):
307 """Sigint handler for threaded apps.
307 """Sigint handler for threaded apps.
308
308
309 This is a horrible hack to pass information about SIGINT _without_
309 This is a horrible hack to pass information about SIGINT _without_
310 using exceptions, since I haven't been able to properly manage
310 using exceptions, since I haven't been able to properly manage
311 cross-thread exceptions in GTK/WX. In fact, I don't think it can be
311 cross-thread exceptions in GTK/WX. In fact, I don't think it can be
312 done (or at least that's my understanding from a c.l.py thread where
312 done (or at least that's my understanding from a c.l.py thread where
313 this was discussed)."""
313 this was discussed)."""
314
314
315 global KBINT
315 global KBINT
316
316
317 if CODE_RUN:
317 if CODE_RUN:
318 _async_raise(MAIN_THREAD_ID,KeyboardInterrupt)
318 _async_raise(MAIN_THREAD_ID,KeyboardInterrupt)
319 else:
319 else:
320 KBINT = True
320 KBINT = True
321 print '\nKeyboardInterrupt - Press <Enter> to continue.',
321 print '\nKeyboardInterrupt - Press <Enter> to continue.',
322 Term.cout.flush()
322 Term.cout.flush()
323
323
324 else:
324 else:
325 def sigint_handler (signum,stack_frame):
325 def sigint_handler (signum,stack_frame):
326 """Sigint handler for threaded apps.
326 """Sigint handler for threaded apps.
327
327
328 This is a horrible hack to pass information about SIGINT _without_
328 This is a horrible hack to pass information about SIGINT _without_
329 using exceptions, since I haven't been able to properly manage
329 using exceptions, since I haven't been able to properly manage
330 cross-thread exceptions in GTK/WX. In fact, I don't think it can be
330 cross-thread exceptions in GTK/WX. In fact, I don't think it can be
331 done (or at least that's my understanding from a c.l.py thread where
331 done (or at least that's my understanding from a c.l.py thread where
332 this was discussed)."""
332 this was discussed)."""
333
333
334 global KBINT
334 global KBINT
335
335
336 print '\nKeyboardInterrupt - Press <Enter> to continue.',
336 print '\nKeyboardInterrupt - Press <Enter> to continue.',
337 Term.cout.flush()
337 Term.cout.flush()
338 # Set global flag so that runsource can know that Ctrl-C was hit
338 # Set global flag so that runsource can know that Ctrl-C was hit
339 KBINT = True
339 KBINT = True
340
340
341
341
342 class MTInteractiveShell(InteractiveShell):
342 class MTInteractiveShell(InteractiveShell):
343 """Simple multi-threaded shell."""
343 """Simple multi-threaded shell."""
344
344
345 # Threading strategy taken from:
345 # Threading strategy taken from:
346 # http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/65109, by Brian
346 # http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/65109, by Brian
347 # McErlean and John Finlay. Modified with corrections by Antoon Pardon,
347 # McErlean and John Finlay. Modified with corrections by Antoon Pardon,
348 # from the pygtk mailing list, to avoid lockups with system calls.
348 # from the pygtk mailing list, to avoid lockups with system calls.
349
349
350 # class attribute to indicate whether the class supports threads or not.
350 # class attribute to indicate whether the class supports threads or not.
351 # Subclasses with thread support should override this as needed.
351 # Subclasses with thread support should override this as needed.
352 isthreaded = True
352 isthreaded = True
353
353
354 def __init__(self,name,usage=None,rc=Struct(opts=None,args=None),
354 def __init__(self,name,usage=None,rc=Struct(opts=None,args=None),
355 user_ns=None,user_global_ns=None,banner2='',**kw):
355 user_ns=None,user_global_ns=None,banner2='',**kw):
356 """Similar to the normal InteractiveShell, but with threading control"""
356 """Similar to the normal InteractiveShell, but with threading control"""
357
357
358 InteractiveShell.__init__(self,name,usage,rc,user_ns,
358 InteractiveShell.__init__(self,name,usage,rc,user_ns,
359 user_global_ns,banner2)
359 user_global_ns,banner2)
360
360
361 # Locking control variable.
361 # Locking control variable.
362 self.thread_ready = threading.Condition(threading.RLock())
362 self.thread_ready = threading.Condition(threading.RLock())
363
363
364 # A queue to hold the code to be executed. A scalar variable is NOT
364 # A queue to hold the code to be executed. A scalar variable is NOT
365 # enough, because uses like macros cause reentrancy.
365 # enough, because uses like macros cause reentrancy.
366 self.code_queue = Queue.Queue()
366 self.code_queue = Queue.Queue()
367
367
368 # Stuff to do at closing time
368 # Stuff to do at closing time
369 self._kill = False
369 self._kill = False
370 on_kill = kw.get('on_kill')
370 on_kill = kw.get('on_kill')
371 if on_kill is None:
371 if on_kill is None:
372 on_kill = []
372 on_kill = []
373 # Check that all things to kill are callable:
373 # Check that all things to kill are callable:
374 for t in on_kill:
374 for t in on_kill:
375 if not callable(t):
375 if not callable(t):
376 raise TypeError,'on_kill must be a list of callables'
376 raise TypeError,'on_kill must be a list of callables'
377 self.on_kill = on_kill
377 self.on_kill = on_kill
378
378 # thread identity of the "worker thread" (that may execute code directly)
379 self.worker_ident = None
379 def runsource(self, source, filename="<input>", symbol="single"):
380 def runsource(self, source, filename="<input>", symbol="single"):
380 """Compile and run some source in the interpreter.
381 """Compile and run some source in the interpreter.
381
382
382 Modified version of code.py's runsource(), to handle threading issues.
383 Modified version of code.py's runsource(), to handle threading issues.
383 See the original for full docstring details."""
384 See the original for full docstring details."""
384
385
385 global KBINT
386 global KBINT
386
387
387 # If Ctrl-C was typed, we reset the flag and return right away
388 # If Ctrl-C was typed, we reset the flag and return right away
388 if KBINT:
389 if KBINT:
389 KBINT = False
390 KBINT = False
390 return False
391 return False
391
392
392 try:
393 try:
393 code = self.compile(source, filename, symbol)
394 code = self.compile(source, filename, symbol)
394 except (OverflowError, SyntaxError, ValueError):
395 except (OverflowError, SyntaxError, ValueError):
395 # Case 1
396 # Case 1
396 self.showsyntaxerror(filename)
397 self.showsyntaxerror(filename)
397 return False
398 return False
398
399
399 if code is None:
400 if code is None:
400 # Case 2
401 # Case 2
401 return True
402 return True
402
403
403 # Case 3
404 # Case 3
404 # Store code in queue, so the execution thread can handle it.
405 # Store code in queue, so the execution thread can handle it.
405
406
406 # Note that with macros and other applications, we MAY re-enter this
407 # Note that with macros and other applications, we MAY re-enter this
407 # section, so we have to acquire the lock with non-blocking semantics,
408 # section, so we have to acquire the lock with non-blocking semantics,
408 # else we deadlock.
409 # else we deadlock.
409 got_lock = self.thread_ready.acquire()
410
411 # shortcut - if we are in worker thread, execute directly (to allow recursion)
412
413 if self.worker_ident == thread.get_ident():
414 InteractiveShell.runcode(self,code)
415 return
416
417 got_lock = self.thread_ready.acquire(blocking=False)
410 self.code_queue.put(code)
418 self.code_queue.put(code)
411 if got_lock:
419 if got_lock:
412 self.thread_ready.wait() # Wait until processed in timeout interval
420 self.thread_ready.wait() # Wait until processed in timeout interval
413 self.thread_ready.release()
421 self.thread_ready.release()
414
422
415 return False
423 return False
416
424
417 def runcode(self):
425 def runcode(self):
418 """Execute a code object.
426 """Execute a code object.
419
427
420 Multithreaded wrapper around IPython's runcode()."""
428 Multithreaded wrapper around IPython's runcode()."""
421
429
422 global CODE_RUN
430 global CODE_RUN
423
424 # lock thread-protected stuff
431 # lock thread-protected stuff
432 self.worker_ident = thread.get_ident()
425 got_lock = self.thread_ready.acquire()
433 got_lock = self.thread_ready.acquire()
426
434
427 if self._kill:
435 if self._kill:
428 print >>Term.cout, 'Closing threads...',
436 print >>Term.cout, 'Closing threads...',
429 Term.cout.flush()
437 Term.cout.flush()
430 for tokill in self.on_kill:
438 for tokill in self.on_kill:
431 tokill()
439 tokill()
432 print >>Term.cout, 'Done.'
440 print >>Term.cout, 'Done.'
433
441
434 # Install sigint handler. We do it every time to ensure that if user
442 # Install sigint handler. We do it every time to ensure that if user
435 # code modifies it, we restore our own handling.
443 # code modifies it, we restore our own handling.
436 try:
444 try:
437 signal(SIGINT,sigint_handler)
445 signal(SIGINT,sigint_handler)
438 except SystemError:
446 except SystemError:
439 # This happens under Windows, which seems to have all sorts
447 # This happens under Windows, which seems to have all sorts
440 # of problems with signal handling. Oh well...
448 # of problems with signal handling. Oh well...
441 pass
449 pass
442
450
443 # Flush queue of pending code by calling the run methood of the parent
451 # Flush queue of pending code by calling the run methood of the parent
444 # class with all items which may be in the queue.
452 # class with all items which may be in the queue.
445 code_to_run = None
453 code_to_run = None
446 while 1:
454 while 1:
447 try:
455 try:
448 code_to_run = self.code_queue.get_nowait()
456 code_to_run = self.code_queue.get_nowait()
449 except Queue.Empty:
457 except Queue.Empty:
450 break
458 break
451
452 # Exceptions need to be raised differently depending on which
459 # Exceptions need to be raised differently depending on which
453 # thread is active. This convoluted try/except is only there to
460 # thread is active. This convoluted try/except is only there to
454 # protect against asynchronous exceptions, to ensure that a KBINT
461 # protect against asynchronous exceptions, to ensure that a KBINT
455 # at the wrong time doesn't deadlock everything. The global
462 # at the wrong time doesn't deadlock everything. The global
456 # CODE_TO_RUN is set to true/false as close as possible to the
463 # CODE_TO_RUN is set to true/false as close as possible to the
457 # runcode() call, so that the KBINT handler is correctly informed.
464 # runcode() call, so that the KBINT handler is correctly informed.
458 try:
465 try:
459 try:
466 try:
460 CODE_RUN = True
467 CODE_RUN = True
461 InteractiveShell.runcode(self,code_to_run)
468 InteractiveShell.runcode(self,code_to_run)
462 except KeyboardInterrupt:
469 except KeyboardInterrupt:
463 print "Keyboard interrupted in mainloop"
470 print "Keyboard interrupted in mainloop"
464 while not self.code_queue.empty():
471 while not self.code_queue.empty():
465 self.code_queue.get_nowait()
472 self.code_queue.get_nowait()
466 break
473 break
467 finally:
474 finally:
468 if got_lock:
475 if got_lock:
469 CODE_RUN = False
476 CODE_RUN = False
470
477
471 # We're done with thread-protected variables
478 # We're done with thread-protected variables
472 if code_to_run is not None:
479 if code_to_run is not None:
473 self.thread_ready.notify()
480 self.thread_ready.notify()
474 self.thread_ready.release()
481 self.thread_ready.release()
475
482
476 # We're done...
483 # We're done...
477 CODE_RUN = False
484 CODE_RUN = False
478 # This MUST return true for gtk threading to work
485 # This MUST return true for gtk threading to work
479 return True
486 return True
480
487
481 def kill(self):
488 def kill(self):
482 """Kill the thread, returning when it has been shut down."""
489 """Kill the thread, returning when it has been shut down."""
483 got_lock = self.thread_ready.acquire(False)
490 got_lock = self.thread_ready.acquire(False)
484 self._kill = True
491 self._kill = True
485 if got_lock:
492 if got_lock:
486 self.thread_ready.release()
493 self.thread_ready.release()
487
494
488 class MatplotlibShellBase:
495 class MatplotlibShellBase:
489 """Mixin class to provide the necessary modifications to regular IPython
496 """Mixin class to provide the necessary modifications to regular IPython
490 shell classes for matplotlib support.
497 shell classes for matplotlib support.
491
498
492 Given Python's MRO, this should be used as the FIRST class in the
499 Given Python's MRO, this should be used as the FIRST class in the
493 inheritance hierarchy, so that it overrides the relevant methods."""
500 inheritance hierarchy, so that it overrides the relevant methods."""
494
501
495 def _matplotlib_config(self,name,user_ns):
502 def _matplotlib_config(self,name,user_ns):
496 """Return items needed to setup the user's shell with matplotlib"""
503 """Return items needed to setup the user's shell with matplotlib"""
497
504
498 # Initialize matplotlib to interactive mode always
505 # Initialize matplotlib to interactive mode always
499 import matplotlib
506 import matplotlib
500 from matplotlib import backends
507 from matplotlib import backends
501 matplotlib.interactive(True)
508 matplotlib.interactive(True)
502
509
503 def use(arg):
510 def use(arg):
504 """IPython wrapper for matplotlib's backend switcher.
511 """IPython wrapper for matplotlib's backend switcher.
505
512
506 In interactive use, we can not allow switching to a different
513 In interactive use, we can not allow switching to a different
507 interactive backend, since thread conflicts will most likely crash
514 interactive backend, since thread conflicts will most likely crash
508 the python interpreter. This routine does a safety check first,
515 the python interpreter. This routine does a safety check first,
509 and refuses to perform a dangerous switch. It still allows
516 and refuses to perform a dangerous switch. It still allows
510 switching to non-interactive backends."""
517 switching to non-interactive backends."""
511
518
512 if arg in backends.interactive_bk and arg != self.mpl_backend:
519 if arg in backends.interactive_bk and arg != self.mpl_backend:
513 m=('invalid matplotlib backend switch.\n'
520 m=('invalid matplotlib backend switch.\n'
514 'This script attempted to switch to the interactive '
521 'This script attempted to switch to the interactive '
515 'backend: `%s`\n'
522 'backend: `%s`\n'
516 'Your current choice of interactive backend is: `%s`\n\n'
523 'Your current choice of interactive backend is: `%s`\n\n'
517 'Switching interactive matplotlib backends at runtime\n'
524 'Switching interactive matplotlib backends at runtime\n'
518 'would crash the python interpreter, '
525 'would crash the python interpreter, '
519 'and IPython has blocked it.\n\n'
526 'and IPython has blocked it.\n\n'
520 'You need to either change your choice of matplotlib backend\n'
527 'You need to either change your choice of matplotlib backend\n'
521 'by editing your .matplotlibrc file, or run this script as a \n'
528 'by editing your .matplotlibrc file, or run this script as a \n'
522 'standalone file from the command line, not using IPython.\n' %
529 'standalone file from the command line, not using IPython.\n' %
523 (arg,self.mpl_backend) )
530 (arg,self.mpl_backend) )
524 raise RuntimeError, m
531 raise RuntimeError, m
525 else:
532 else:
526 self.mpl_use(arg)
533 self.mpl_use(arg)
527 self.mpl_use._called = True
534 self.mpl_use._called = True
528
535
529 self.matplotlib = matplotlib
536 self.matplotlib = matplotlib
530 self.mpl_backend = matplotlib.rcParams['backend']
537 self.mpl_backend = matplotlib.rcParams['backend']
531
538
532 # we also need to block switching of interactive backends by use()
539 # we also need to block switching of interactive backends by use()
533 self.mpl_use = matplotlib.use
540 self.mpl_use = matplotlib.use
534 self.mpl_use._called = False
541 self.mpl_use._called = False
535 # overwrite the original matplotlib.use with our wrapper
542 # overwrite the original matplotlib.use with our wrapper
536 matplotlib.use = use
543 matplotlib.use = use
537
544
538 # This must be imported last in the matplotlib series, after
545 # This must be imported last in the matplotlib series, after
539 # backend/interactivity choices have been made
546 # backend/interactivity choices have been made
540 import matplotlib.pylab as pylab
547 import matplotlib.pylab as pylab
541 self.pylab = pylab
548 self.pylab = pylab
542
549
543 self.pylab.show._needmain = False
550 self.pylab.show._needmain = False
544 # We need to detect at runtime whether show() is called by the user.
551 # We need to detect at runtime whether show() is called by the user.
545 # For this, we wrap it into a decorator which adds a 'called' flag.
552 # For this, we wrap it into a decorator which adds a 'called' flag.
546 self.pylab.draw_if_interactive = flag_calls(self.pylab.draw_if_interactive)
553 self.pylab.draw_if_interactive = flag_calls(self.pylab.draw_if_interactive)
547
554
548 # Build a user namespace initialized with matplotlib/matlab features.
555 # Build a user namespace initialized with matplotlib/matlab features.
549 user_ns = IPython.ipapi.make_user_ns(user_ns)
556 user_ns = IPython.ipapi.make_user_ns(user_ns)
550
557
551 exec ("import matplotlib\n"
558 exec ("import matplotlib\n"
552 "import matplotlib.pylab as pylab\n") in user_ns
559 "import matplotlib.pylab as pylab\n") in user_ns
553
560
554 # Build matplotlib info banner
561 # Build matplotlib info banner
555 b="""
562 b="""
556 Welcome to pylab, a matplotlib-based Python environment.
563 Welcome to pylab, a matplotlib-based Python environment.
557 For more information, type 'help(pylab)'.
564 For more information, type 'help(pylab)'.
558 """
565 """
559 return user_ns,b
566 return user_ns,b
560
567
561 def mplot_exec(self,fname,*where,**kw):
568 def mplot_exec(self,fname,*where,**kw):
562 """Execute a matplotlib script.
569 """Execute a matplotlib script.
563
570
564 This is a call to execfile(), but wrapped in safeties to properly
571 This is a call to execfile(), but wrapped in safeties to properly
565 handle interactive rendering and backend switching."""
572 handle interactive rendering and backend switching."""
566
573
567 #print '*** Matplotlib runner ***' # dbg
574 #print '*** Matplotlib runner ***' # dbg
568 # turn off rendering until end of script
575 # turn off rendering until end of script
569 isInteractive = self.matplotlib.rcParams['interactive']
576 isInteractive = self.matplotlib.rcParams['interactive']
570 self.matplotlib.interactive(False)
577 self.matplotlib.interactive(False)
571 self.safe_execfile(fname,*where,**kw)
578 self.safe_execfile(fname,*where,**kw)
572 self.matplotlib.interactive(isInteractive)
579 self.matplotlib.interactive(isInteractive)
573 # make rendering call now, if the user tried to do it
580 # make rendering call now, if the user tried to do it
574 if self.pylab.draw_if_interactive.called:
581 if self.pylab.draw_if_interactive.called:
575 self.pylab.draw()
582 self.pylab.draw()
576 self.pylab.draw_if_interactive.called = False
583 self.pylab.draw_if_interactive.called = False
577
584
578 # if a backend switch was performed, reverse it now
585 # if a backend switch was performed, reverse it now
579 if self.mpl_use._called:
586 if self.mpl_use._called:
580 self.matplotlib.rcParams['backend'] = self.mpl_backend
587 self.matplotlib.rcParams['backend'] = self.mpl_backend
581
588
582 def magic_run(self,parameter_s=''):
589 def magic_run(self,parameter_s=''):
583 Magic.magic_run(self,parameter_s,runner=self.mplot_exec)
590 Magic.magic_run(self,parameter_s,runner=self.mplot_exec)
584
591
585 # Fix the docstring so users see the original as well
592 # Fix the docstring so users see the original as well
586 magic_run.__doc__ = "%s\n%s" % (Magic.magic_run.__doc__,
593 magic_run.__doc__ = "%s\n%s" % (Magic.magic_run.__doc__,
587 "\n *** Modified %run for Matplotlib,"
594 "\n *** Modified %run for Matplotlib,"
588 " with proper interactive handling ***")
595 " with proper interactive handling ***")
589
596
590 # Now we provide 2 versions of a matplotlib-aware IPython base shells, single
597 # Now we provide 2 versions of a matplotlib-aware IPython base shells, single
591 # and multithreaded. Note that these are meant for internal use, the IPShell*
598 # and multithreaded. Note that these are meant for internal use, the IPShell*
592 # classes below are the ones meant for public consumption.
599 # classes below are the ones meant for public consumption.
593
600
594 class MatplotlibShell(MatplotlibShellBase,InteractiveShell):
601 class MatplotlibShell(MatplotlibShellBase,InteractiveShell):
595 """Single-threaded shell with matplotlib support."""
602 """Single-threaded shell with matplotlib support."""
596
603
597 def __init__(self,name,usage=None,rc=Struct(opts=None,args=None),
604 def __init__(self,name,usage=None,rc=Struct(opts=None,args=None),
598 user_ns=None,user_global_ns=None,**kw):
605 user_ns=None,user_global_ns=None,**kw):
599 user_ns,b2 = self._matplotlib_config(name,user_ns)
606 user_ns,b2 = self._matplotlib_config(name,user_ns)
600 InteractiveShell.__init__(self,name,usage,rc,user_ns,user_global_ns,
607 InteractiveShell.__init__(self,name,usage,rc,user_ns,user_global_ns,
601 banner2=b2,**kw)
608 banner2=b2,**kw)
602
609
603 class MatplotlibMTShell(MatplotlibShellBase,MTInteractiveShell):
610 class MatplotlibMTShell(MatplotlibShellBase,MTInteractiveShell):
604 """Multi-threaded shell with matplotlib support."""
611 """Multi-threaded shell with matplotlib support."""
605
612
606 def __init__(self,name,usage=None,rc=Struct(opts=None,args=None),
613 def __init__(self,name,usage=None,rc=Struct(opts=None,args=None),
607 user_ns=None,user_global_ns=None, **kw):
614 user_ns=None,user_global_ns=None, **kw):
608 user_ns,b2 = self._matplotlib_config(name,user_ns)
615 user_ns,b2 = self._matplotlib_config(name,user_ns)
609 MTInteractiveShell.__init__(self,name,usage,rc,user_ns,user_global_ns,
616 MTInteractiveShell.__init__(self,name,usage,rc,user_ns,user_global_ns,
610 banner2=b2,**kw)
617 banner2=b2,**kw)
611
618
612 #-----------------------------------------------------------------------------
619 #-----------------------------------------------------------------------------
613 # Utility functions for the different GUI enabled IPShell* classes.
620 # Utility functions for the different GUI enabled IPShell* classes.
614
621
615 def get_tk():
622 def get_tk():
616 """Tries to import Tkinter and returns a withdrawn Tkinter root
623 """Tries to import Tkinter and returns a withdrawn Tkinter root
617 window. If Tkinter is already imported or not available, this
624 window. If Tkinter is already imported or not available, this
618 returns None. This function calls `hijack_tk` underneath.
625 returns None. This function calls `hijack_tk` underneath.
619 """
626 """
620 if not USE_TK or sys.modules.has_key('Tkinter'):
627 if not USE_TK or sys.modules.has_key('Tkinter'):
621 return None
628 return None
622 else:
629 else:
623 try:
630 try:
624 import Tkinter
631 import Tkinter
625 except ImportError:
632 except ImportError:
626 return None
633 return None
627 else:
634 else:
628 hijack_tk()
635 hijack_tk()
629 r = Tkinter.Tk()
636 r = Tkinter.Tk()
630 r.withdraw()
637 r.withdraw()
631 return r
638 return r
632
639
633 def hijack_tk():
640 def hijack_tk():
634 """Modifies Tkinter's mainloop with a dummy so when a module calls
641 """Modifies Tkinter's mainloop with a dummy so when a module calls
635 mainloop, it does not block.
642 mainloop, it does not block.
636
643
637 """
644 """
638 def misc_mainloop(self, n=0):
645 def misc_mainloop(self, n=0):
639 pass
646 pass
640 def tkinter_mainloop(n=0):
647 def tkinter_mainloop(n=0):
641 pass
648 pass
642
649
643 import Tkinter
650 import Tkinter
644 Tkinter.Misc.mainloop = misc_mainloop
651 Tkinter.Misc.mainloop = misc_mainloop
645 Tkinter.mainloop = tkinter_mainloop
652 Tkinter.mainloop = tkinter_mainloop
646
653
647 def update_tk(tk):
654 def update_tk(tk):
648 """Updates the Tkinter event loop. This is typically called from
655 """Updates the Tkinter event loop. This is typically called from
649 the respective WX or GTK mainloops.
656 the respective WX or GTK mainloops.
650 """
657 """
651 if tk:
658 if tk:
652 tk.update()
659 tk.update()
653
660
654 def hijack_wx():
661 def hijack_wx():
655 """Modifies wxPython's MainLoop with a dummy so user code does not
662 """Modifies wxPython's MainLoop with a dummy so user code does not
656 block IPython. The hijacked mainloop function is returned.
663 block IPython. The hijacked mainloop function is returned.
657 """
664 """
658 def dummy_mainloop(*args, **kw):
665 def dummy_mainloop(*args, **kw):
659 pass
666 pass
660
667
661 try:
668 try:
662 import wx
669 import wx
663 except ImportError:
670 except ImportError:
664 # For very old versions of WX
671 # For very old versions of WX
665 import wxPython as wx
672 import wxPython as wx
666
673
667 ver = wx.__version__
674 ver = wx.__version__
668 orig_mainloop = None
675 orig_mainloop = None
669 if ver[:3] >= '2.5':
676 if ver[:3] >= '2.5':
670 import wx
677 import wx
671 if hasattr(wx, '_core_'): core = getattr(wx, '_core_')
678 if hasattr(wx, '_core_'): core = getattr(wx, '_core_')
672 elif hasattr(wx, '_core'): core = getattr(wx, '_core')
679 elif hasattr(wx, '_core'): core = getattr(wx, '_core')
673 else: raise AttributeError('Could not find wx core module')
680 else: raise AttributeError('Could not find wx core module')
674 orig_mainloop = core.PyApp_MainLoop
681 orig_mainloop = core.PyApp_MainLoop
675 core.PyApp_MainLoop = dummy_mainloop
682 core.PyApp_MainLoop = dummy_mainloop
676 elif ver[:3] == '2.4':
683 elif ver[:3] == '2.4':
677 orig_mainloop = wx.wxc.wxPyApp_MainLoop
684 orig_mainloop = wx.wxc.wxPyApp_MainLoop
678 wx.wxc.wxPyApp_MainLoop = dummy_mainloop
685 wx.wxc.wxPyApp_MainLoop = dummy_mainloop
679 else:
686 else:
680 warn("Unable to find either wxPython version 2.4 or >= 2.5.")
687 warn("Unable to find either wxPython version 2.4 or >= 2.5.")
681 return orig_mainloop
688 return orig_mainloop
682
689
683 def hijack_gtk():
690 def hijack_gtk():
684 """Modifies pyGTK's mainloop with a dummy so user code does not
691 """Modifies pyGTK's mainloop with a dummy so user code does not
685 block IPython. This function returns the original `gtk.mainloop`
692 block IPython. This function returns the original `gtk.mainloop`
686 function that has been hijacked.
693 function that has been hijacked.
687 """
694 """
688 def dummy_mainloop(*args, **kw):
695 def dummy_mainloop(*args, **kw):
689 pass
696 pass
690 import gtk
697 import gtk
691 if gtk.pygtk_version >= (2,4,0): orig_mainloop = gtk.main
698 if gtk.pygtk_version >= (2,4,0): orig_mainloop = gtk.main
692 else: orig_mainloop = gtk.mainloop
699 else: orig_mainloop = gtk.mainloop
693 gtk.mainloop = dummy_mainloop
700 gtk.mainloop = dummy_mainloop
694 gtk.main = dummy_mainloop
701 gtk.main = dummy_mainloop
695 return orig_mainloop
702 return orig_mainloop
696
703
697 def hijack_qt():
704 def hijack_qt():
698 """Modifies PyQt's mainloop with a dummy so user code does not
705 """Modifies PyQt's mainloop with a dummy so user code does not
699 block IPython. This function returns the original
706 block IPython. This function returns the original
700 `qt.qApp.exec_loop` function that has been hijacked.
707 `qt.qApp.exec_loop` function that has been hijacked.
701 """
708 """
702 def dummy_mainloop(*args, **kw):
709 def dummy_mainloop(*args, **kw):
703 pass
710 pass
704 import qt
711 import qt
705 orig_mainloop = qt.qApp.exec_loop
712 orig_mainloop = qt.qApp.exec_loop
706 qt.qApp.exec_loop = dummy_mainloop
713 qt.qApp.exec_loop = dummy_mainloop
707 qt.QApplication.exec_loop = dummy_mainloop
714 qt.QApplication.exec_loop = dummy_mainloop
708 return orig_mainloop
715 return orig_mainloop
709
716
710 def hijack_qt4():
717 def hijack_qt4():
711 """Modifies PyQt4's mainloop with a dummy so user code does not
718 """Modifies PyQt4's mainloop with a dummy so user code does not
712 block IPython. This function returns the original
719 block IPython. This function returns the original
713 `QtGui.qApp.exec_` function that has been hijacked.
720 `QtGui.qApp.exec_` function that has been hijacked.
714 """
721 """
715 def dummy_mainloop(*args, **kw):
722 def dummy_mainloop(*args, **kw):
716 pass
723 pass
717 from PyQt4 import QtGui, QtCore
724 from PyQt4 import QtGui, QtCore
718 orig_mainloop = QtGui.qApp.exec_
725 orig_mainloop = QtGui.qApp.exec_
719 QtGui.qApp.exec_ = dummy_mainloop
726 QtGui.qApp.exec_ = dummy_mainloop
720 QtGui.QApplication.exec_ = dummy_mainloop
727 QtGui.QApplication.exec_ = dummy_mainloop
721 QtCore.QCoreApplication.exec_ = dummy_mainloop
728 QtCore.QCoreApplication.exec_ = dummy_mainloop
722 return orig_mainloop
729 return orig_mainloop
723
730
724 #-----------------------------------------------------------------------------
731 #-----------------------------------------------------------------------------
725 # The IPShell* classes below are the ones meant to be run by external code as
732 # The IPShell* classes below are the ones meant to be run by external code as
726 # IPython instances. Note that unless a specific threading strategy is
733 # IPython instances. Note that unless a specific threading strategy is
727 # desired, the factory function start() below should be used instead (it
734 # desired, the factory function start() below should be used instead (it
728 # selects the proper threaded class).
735 # selects the proper threaded class).
729
736
730 class IPThread(threading.Thread):
737 class IPThread(threading.Thread):
731 def run(self):
738 def run(self):
732 self.IP.mainloop(self._banner)
739 self.IP.mainloop(self._banner)
733 self.IP.kill()
740 self.IP.kill()
734
741
735 class IPShellGTK(IPThread):
742 class IPShellGTK(IPThread):
736 """Run a gtk mainloop() in a separate thread.
743 """Run a gtk mainloop() in a separate thread.
737
744
738 Python commands can be passed to the thread where they will be executed.
745 Python commands can be passed to the thread where they will be executed.
739 This is implemented by periodically checking for passed code using a
746 This is implemented by periodically checking for passed code using a
740 GTK timeout callback."""
747 GTK timeout callback."""
741
748
742 TIMEOUT = 100 # Millisecond interval between timeouts.
749 TIMEOUT = 100 # Millisecond interval between timeouts.
743
750
744 def __init__(self,argv=None,user_ns=None,user_global_ns=None,
751 def __init__(self,argv=None,user_ns=None,user_global_ns=None,
745 debug=1,shell_class=MTInteractiveShell):
752 debug=1,shell_class=MTInteractiveShell):
746
753
747 import gtk
754 import gtk
748
755
749 self.gtk = gtk
756 self.gtk = gtk
750 self.gtk_mainloop = hijack_gtk()
757 self.gtk_mainloop = hijack_gtk()
751
758
752 # Allows us to use both Tk and GTK.
759 # Allows us to use both Tk and GTK.
753 self.tk = get_tk()
760 self.tk = get_tk()
754
761
755 if gtk.pygtk_version >= (2,4,0): mainquit = self.gtk.main_quit
762 if gtk.pygtk_version >= (2,4,0): mainquit = self.gtk.main_quit
756 else: mainquit = self.gtk.mainquit
763 else: mainquit = self.gtk.mainquit
757
764
758 self.IP = make_IPython(argv,user_ns=user_ns,
765 self.IP = make_IPython(argv,user_ns=user_ns,
759 user_global_ns=user_global_ns,
766 user_global_ns=user_global_ns,
760 debug=debug,
767 debug=debug,
761 shell_class=shell_class,
768 shell_class=shell_class,
762 on_kill=[mainquit])
769 on_kill=[mainquit])
763
770
764 # HACK: slot for banner in self; it will be passed to the mainloop
771 # HACK: slot for banner in self; it will be passed to the mainloop
765 # method only and .run() needs it. The actual value will be set by
772 # method only and .run() needs it. The actual value will be set by
766 # .mainloop().
773 # .mainloop().
767 self._banner = None
774 self._banner = None
768
775
769 threading.Thread.__init__(self)
776 threading.Thread.__init__(self)
770
777
771 def mainloop(self,sys_exit=0,banner=None):
778 def mainloop(self,sys_exit=0,banner=None):
772
779
773 self._banner = banner
780 self._banner = banner
774
781
775 if self.gtk.pygtk_version >= (2,4,0):
782 if self.gtk.pygtk_version >= (2,4,0):
776 import gobject
783 import gobject
777 gobject.idle_add(self.on_timer)
784 gobject.idle_add(self.on_timer)
778 else:
785 else:
779 self.gtk.idle_add(self.on_timer)
786 self.gtk.idle_add(self.on_timer)
780
787
781 if sys.platform != 'win32':
788 if sys.platform != 'win32':
782 try:
789 try:
783 if self.gtk.gtk_version[0] >= 2:
790 if self.gtk.gtk_version[0] >= 2:
784 self.gtk.gdk.threads_init()
791 self.gtk.gdk.threads_init()
785 except AttributeError:
792 except AttributeError:
786 pass
793 pass
787 except RuntimeError:
794 except RuntimeError:
788 error('Your pyGTK likely has not been compiled with '
795 error('Your pyGTK likely has not been compiled with '
789 'threading support.\n'
796 'threading support.\n'
790 'The exception printout is below.\n'
797 'The exception printout is below.\n'
791 'You can either rebuild pyGTK with threads, or '
798 'You can either rebuild pyGTK with threads, or '
792 'try using \n'
799 'try using \n'
793 'matplotlib with a different backend (like Tk or WX).\n'
800 'matplotlib with a different backend (like Tk or WX).\n'
794 'Note that matplotlib will most likely not work in its '
801 'Note that matplotlib will most likely not work in its '
795 'current state!')
802 'current state!')
796 self.IP.InteractiveTB()
803 self.IP.InteractiveTB()
797
804
798 self.start()
805 self.start()
799 self.gtk.gdk.threads_enter()
806 self.gtk.gdk.threads_enter()
800 self.gtk_mainloop()
807 self.gtk_mainloop()
801 self.gtk.gdk.threads_leave()
808 self.gtk.gdk.threads_leave()
802 self.join()
809 self.join()
803
810
804 def on_timer(self):
811 def on_timer(self):
805 """Called when GTK is idle.
812 """Called when GTK is idle.
806
813
807 Must return True always, otherwise GTK stops calling it"""
814 Must return True always, otherwise GTK stops calling it"""
808
815
809 update_tk(self.tk)
816 update_tk(self.tk)
810 self.IP.runcode()
817 self.IP.runcode()
811 time.sleep(0.01)
818 time.sleep(0.01)
812 return True
819 return True
813
820
814
821
815 class IPShellWX(IPThread):
822 class IPShellWX(IPThread):
816 """Run a wx mainloop() in a separate thread.
823 """Run a wx mainloop() in a separate thread.
817
824
818 Python commands can be passed to the thread where they will be executed.
825 Python commands can be passed to the thread where they will be executed.
819 This is implemented by periodically checking for passed code using a
826 This is implemented by periodically checking for passed code using a
820 GTK timeout callback."""
827 GTK timeout callback."""
821
828
822 TIMEOUT = 100 # Millisecond interval between timeouts.
829 TIMEOUT = 100 # Millisecond interval between timeouts.
823
830
824 def __init__(self,argv=None,user_ns=None,user_global_ns=None,
831 def __init__(self,argv=None,user_ns=None,user_global_ns=None,
825 debug=1,shell_class=MTInteractiveShell):
832 debug=1,shell_class=MTInteractiveShell):
826
833
827 self.IP = make_IPython(argv,user_ns=user_ns,
834 self.IP = make_IPython(argv,user_ns=user_ns,
828 user_global_ns=user_global_ns,
835 user_global_ns=user_global_ns,
829 debug=debug,
836 debug=debug,
830 shell_class=shell_class,
837 shell_class=shell_class,
831 on_kill=[self.wxexit])
838 on_kill=[self.wxexit])
832
839
833 wantedwxversion=self.IP.rc.wxversion
840 wantedwxversion=self.IP.rc.wxversion
834 if wantedwxversion!="0":
841 if wantedwxversion!="0":
835 try:
842 try:
836 import wxversion
843 import wxversion
837 except ImportError:
844 except ImportError:
838 error('The wxversion module is needed for WX version selection')
845 error('The wxversion module is needed for WX version selection')
839 else:
846 else:
840 try:
847 try:
841 wxversion.select(wantedwxversion)
848 wxversion.select(wantedwxversion)
842 except:
849 except:
843 self.IP.InteractiveTB()
850 self.IP.InteractiveTB()
844 error('Requested wxPython version %s could not be loaded' %
851 error('Requested wxPython version %s could not be loaded' %
845 wantedwxversion)
852 wantedwxversion)
846
853
847 import wx
854 import wx
848
855
849 threading.Thread.__init__(self)
856 threading.Thread.__init__(self)
850 self.wx = wx
857 self.wx = wx
851 self.wx_mainloop = hijack_wx()
858 self.wx_mainloop = hijack_wx()
852
859
853 # Allows us to use both Tk and GTK.
860 # Allows us to use both Tk and GTK.
854 self.tk = get_tk()
861 self.tk = get_tk()
855
862
856 # HACK: slot for banner in self; it will be passed to the mainloop
863 # HACK: slot for banner in self; it will be passed to the mainloop
857 # method only and .run() needs it. The actual value will be set by
864 # method only and .run() needs it. The actual value will be set by
858 # .mainloop().
865 # .mainloop().
859 self._banner = None
866 self._banner = None
860
867
861 self.app = None
868 self.app = None
862
869
863 def wxexit(self, *args):
870 def wxexit(self, *args):
864 if self.app is not None:
871 if self.app is not None:
865 self.app.agent.timer.Stop()
872 self.app.agent.timer.Stop()
866 self.app.ExitMainLoop()
873 self.app.ExitMainLoop()
867
874
868 def mainloop(self,sys_exit=0,banner=None):
875 def mainloop(self,sys_exit=0,banner=None):
869
876
870 self._banner = banner
877 self._banner = banner
871
878
872 self.start()
879 self.start()
873
880
874 class TimerAgent(self.wx.MiniFrame):
881 class TimerAgent(self.wx.MiniFrame):
875 wx = self.wx
882 wx = self.wx
876 IP = self.IP
883 IP = self.IP
877 tk = self.tk
884 tk = self.tk
878 def __init__(self, parent, interval):
885 def __init__(self, parent, interval):
879 style = self.wx.DEFAULT_FRAME_STYLE | self.wx.TINY_CAPTION_HORIZ
886 style = self.wx.DEFAULT_FRAME_STYLE | self.wx.TINY_CAPTION_HORIZ
880 self.wx.MiniFrame.__init__(self, parent, -1, ' ', pos=(200, 200),
887 self.wx.MiniFrame.__init__(self, parent, -1, ' ', pos=(200, 200),
881 size=(100, 100),style=style)
888 size=(100, 100),style=style)
882 self.Show(False)
889 self.Show(False)
883 self.interval = interval
890 self.interval = interval
884 self.timerId = self.wx.NewId()
891 self.timerId = self.wx.NewId()
885
892
886 def StartWork(self):
893 def StartWork(self):
887 self.timer = self.wx.Timer(self, self.timerId)
894 self.timer = self.wx.Timer(self, self.timerId)
888 self.wx.EVT_TIMER(self, self.timerId, self.OnTimer)
895 self.wx.EVT_TIMER(self, self.timerId, self.OnTimer)
889 self.timer.Start(self.interval)
896 self.timer.Start(self.interval)
890
897
891 def OnTimer(self, event):
898 def OnTimer(self, event):
892 update_tk(self.tk)
899 update_tk(self.tk)
893 self.IP.runcode()
900 self.IP.runcode()
894
901
895 class App(self.wx.App):
902 class App(self.wx.App):
896 wx = self.wx
903 wx = self.wx
897 TIMEOUT = self.TIMEOUT
904 TIMEOUT = self.TIMEOUT
898 def OnInit(self):
905 def OnInit(self):
899 'Create the main window and insert the custom frame'
906 'Create the main window and insert the custom frame'
900 self.agent = TimerAgent(None, self.TIMEOUT)
907 self.agent = TimerAgent(None, self.TIMEOUT)
901 self.agent.Show(False)
908 self.agent.Show(False)
902 self.agent.StartWork()
909 self.agent.StartWork()
903 return True
910 return True
904
911
905 self.app = App(redirect=False)
912 self.app = App(redirect=False)
906 self.wx_mainloop(self.app)
913 self.wx_mainloop(self.app)
907 self.join()
914 self.join()
908
915
909
916
910 class IPShellQt(IPThread):
917 class IPShellQt(IPThread):
911 """Run a Qt event loop in a separate thread.
918 """Run a Qt event loop in a separate thread.
912
919
913 Python commands can be passed to the thread where they will be executed.
920 Python commands can be passed to the thread where they will be executed.
914 This is implemented by periodically checking for passed code using a
921 This is implemented by periodically checking for passed code using a
915 Qt timer / slot."""
922 Qt timer / slot."""
916
923
917 TIMEOUT = 100 # Millisecond interval between timeouts.
924 TIMEOUT = 100 # Millisecond interval between timeouts.
918
925
919 def __init__(self, argv=None, user_ns=None, user_global_ns=None,
926 def __init__(self, argv=None, user_ns=None, user_global_ns=None,
920 debug=0, shell_class=MTInteractiveShell):
927 debug=0, shell_class=MTInteractiveShell):
921
928
922 import qt
929 import qt
923
930
924 self.exec_loop = hijack_qt()
931 self.exec_loop = hijack_qt()
925
932
926 # Allows us to use both Tk and QT.
933 # Allows us to use both Tk and QT.
927 self.tk = get_tk()
934 self.tk = get_tk()
928
935
929 self.IP = make_IPython(argv,
936 self.IP = make_IPython(argv,
930 user_ns=user_ns,
937 user_ns=user_ns,
931 user_global_ns=user_global_ns,
938 user_global_ns=user_global_ns,
932 debug=debug,
939 debug=debug,
933 shell_class=shell_class,
940 shell_class=shell_class,
934 on_kill=[qt.qApp.exit])
941 on_kill=[qt.qApp.exit])
935
942
936 # HACK: slot for banner in self; it will be passed to the mainloop
943 # HACK: slot for banner in self; it will be passed to the mainloop
937 # method only and .run() needs it. The actual value will be set by
944 # method only and .run() needs it. The actual value will be set by
938 # .mainloop().
945 # .mainloop().
939 self._banner = None
946 self._banner = None
940
947
941 threading.Thread.__init__(self)
948 threading.Thread.__init__(self)
942
949
943 def mainloop(self, sys_exit=0, banner=None):
950 def mainloop(self, sys_exit=0, banner=None):
944
951
945 import qt
952 import qt
946
953
947 self._banner = banner
954 self._banner = banner
948
955
949 if qt.QApplication.startingUp():
956 if qt.QApplication.startingUp():
950 a = qt.QApplication(sys.argv)
957 a = qt.QApplication(sys.argv)
951
958
952 self.timer = qt.QTimer()
959 self.timer = qt.QTimer()
953 qt.QObject.connect(self.timer,
960 qt.QObject.connect(self.timer,
954 qt.SIGNAL('timeout()'),
961 qt.SIGNAL('timeout()'),
955 self.on_timer)
962 self.on_timer)
956
963
957 self.start()
964 self.start()
958 self.timer.start(self.TIMEOUT, True)
965 self.timer.start(self.TIMEOUT, True)
959 while True:
966 while True:
960 if self.IP._kill: break
967 if self.IP._kill: break
961 self.exec_loop()
968 self.exec_loop()
962 self.join()
969 self.join()
963
970
964 def on_timer(self):
971 def on_timer(self):
965 update_tk(self.tk)
972 update_tk(self.tk)
966 result = self.IP.runcode()
973 result = self.IP.runcode()
967 self.timer.start(self.TIMEOUT, True)
974 self.timer.start(self.TIMEOUT, True)
968 return result
975 return result
969
976
970
977
971 class IPShellQt4(IPThread):
978 class IPShellQt4(IPThread):
972 """Run a Qt event loop in a separate thread.
979 """Run a Qt event loop in a separate thread.
973
980
974 Python commands can be passed to the thread where they will be executed.
981 Python commands can be passed to the thread where they will be executed.
975 This is implemented by periodically checking for passed code using a
982 This is implemented by periodically checking for passed code using a
976 Qt timer / slot."""
983 Qt timer / slot."""
977
984
978 TIMEOUT = 100 # Millisecond interval between timeouts.
985 TIMEOUT = 100 # Millisecond interval between timeouts.
979
986
980 def __init__(self, argv=None, user_ns=None, user_global_ns=None,
987 def __init__(self, argv=None, user_ns=None, user_global_ns=None,
981 debug=0, shell_class=MTInteractiveShell):
988 debug=0, shell_class=MTInteractiveShell):
982
989
983 from PyQt4 import QtCore, QtGui
990 from PyQt4 import QtCore, QtGui
984
991
985 try:
992 try:
986 # present in PyQt4-4.2.1 or later
993 # present in PyQt4-4.2.1 or later
987 QtCore.pyqtRemoveInputHook()
994 QtCore.pyqtRemoveInputHook()
988 except AttributeError:
995 except AttributeError:
989 pass
996 pass
990
997
991 if QtCore.PYQT_VERSION_STR == '4.3':
998 if QtCore.PYQT_VERSION_STR == '4.3':
992 warn('''PyQt4 version 4.3 detected.
999 warn('''PyQt4 version 4.3 detected.
993 If you experience repeated threading warnings, please update PyQt4.
1000 If you experience repeated threading warnings, please update PyQt4.
994 ''')
1001 ''')
995
1002
996 self.exec_ = hijack_qt4()
1003 self.exec_ = hijack_qt4()
997
1004
998 # Allows us to use both Tk and QT.
1005 # Allows us to use both Tk and QT.
999 self.tk = get_tk()
1006 self.tk = get_tk()
1000
1007
1001 self.IP = make_IPython(argv,
1008 self.IP = make_IPython(argv,
1002 user_ns=user_ns,
1009 user_ns=user_ns,
1003 user_global_ns=user_global_ns,
1010 user_global_ns=user_global_ns,
1004 debug=debug,
1011 debug=debug,
1005 shell_class=shell_class,
1012 shell_class=shell_class,
1006 on_kill=[QtGui.qApp.exit])
1013 on_kill=[QtGui.qApp.exit])
1007
1014
1008 # HACK: slot for banner in self; it will be passed to the mainloop
1015 # HACK: slot for banner in self; it will be passed to the mainloop
1009 # method only and .run() needs it. The actual value will be set by
1016 # method only and .run() needs it. The actual value will be set by
1010 # .mainloop().
1017 # .mainloop().
1011 self._banner = None
1018 self._banner = None
1012
1019
1013 threading.Thread.__init__(self)
1020 threading.Thread.__init__(self)
1014
1021
1015 def mainloop(self, sys_exit=0, banner=None):
1022 def mainloop(self, sys_exit=0, banner=None):
1016
1023
1017 from PyQt4 import QtCore, QtGui
1024 from PyQt4 import QtCore, QtGui
1018
1025
1019 self._banner = banner
1026 self._banner = banner
1020
1027
1021 if QtGui.QApplication.startingUp():
1028 if QtGui.QApplication.startingUp():
1022 a = QtGui.QApplication(sys.argv)
1029 a = QtGui.QApplication(sys.argv)
1023
1030
1024 self.timer = QtCore.QTimer()
1031 self.timer = QtCore.QTimer()
1025 QtCore.QObject.connect(self.timer,
1032 QtCore.QObject.connect(self.timer,
1026 QtCore.SIGNAL('timeout()'),
1033 QtCore.SIGNAL('timeout()'),
1027 self.on_timer)
1034 self.on_timer)
1028
1035
1029 self.start()
1036 self.start()
1030 self.timer.start(self.TIMEOUT)
1037 self.timer.start(self.TIMEOUT)
1031 while True:
1038 while True:
1032 if self.IP._kill: break
1039 if self.IP._kill: break
1033 self.exec_()
1040 self.exec_()
1034 self.join()
1041 self.join()
1035
1042
1036 def on_timer(self):
1043 def on_timer(self):
1037 update_tk(self.tk)
1044 update_tk(self.tk)
1038 result = self.IP.runcode()
1045 result = self.IP.runcode()
1039 self.timer.start(self.TIMEOUT)
1046 self.timer.start(self.TIMEOUT)
1040 return result
1047 return result
1041
1048
1042
1049
1043 # A set of matplotlib public IPython shell classes, for single-threaded (Tk*
1050 # A set of matplotlib public IPython shell classes, for single-threaded (Tk*
1044 # and FLTK*) and multithreaded (GTK*, WX* and Qt*) backends to use.
1051 # and FLTK*) and multithreaded (GTK*, WX* and Qt*) backends to use.
1045 def _load_pylab(user_ns):
1052 def _load_pylab(user_ns):
1046 """Allow users to disable pulling all of pylab into the top-level
1053 """Allow users to disable pulling all of pylab into the top-level
1047 namespace.
1054 namespace.
1048
1055
1049 This little utility must be called AFTER the actual ipython instance is
1056 This little utility must be called AFTER the actual ipython instance is
1050 running, since only then will the options file have been fully parsed."""
1057 running, since only then will the options file have been fully parsed."""
1051
1058
1052 ip = IPython.ipapi.get()
1059 ip = IPython.ipapi.get()
1053 if ip.options.pylab_import_all:
1060 if ip.options.pylab_import_all:
1054 ip.ex("from matplotlib.pylab import *")
1061 ip.ex("from matplotlib.pylab import *")
1055 ip.IP.user_config_ns.update(ip.user_ns)
1062 ip.IP.user_config_ns.update(ip.user_ns)
1056
1063
1057
1064
1058 class IPShellMatplotlib(IPShell):
1065 class IPShellMatplotlib(IPShell):
1059 """Subclass IPShell with MatplotlibShell as the internal shell.
1066 """Subclass IPShell with MatplotlibShell as the internal shell.
1060
1067
1061 Single-threaded class, meant for the Tk* and FLTK* backends.
1068 Single-threaded class, meant for the Tk* and FLTK* backends.
1062
1069
1063 Having this on a separate class simplifies the external driver code."""
1070 Having this on a separate class simplifies the external driver code."""
1064
1071
1065 def __init__(self,argv=None,user_ns=None,user_global_ns=None,debug=1):
1072 def __init__(self,argv=None,user_ns=None,user_global_ns=None,debug=1):
1066 IPShell.__init__(self,argv,user_ns,user_global_ns,debug,
1073 IPShell.__init__(self,argv,user_ns,user_global_ns,debug,
1067 shell_class=MatplotlibShell)
1074 shell_class=MatplotlibShell)
1068 _load_pylab(self.IP.user_ns)
1075 _load_pylab(self.IP.user_ns)
1069
1076
1070 class IPShellMatplotlibGTK(IPShellGTK):
1077 class IPShellMatplotlibGTK(IPShellGTK):
1071 """Subclass IPShellGTK with MatplotlibMTShell as the internal shell.
1078 """Subclass IPShellGTK with MatplotlibMTShell as the internal shell.
1072
1079
1073 Multi-threaded class, meant for the GTK* backends."""
1080 Multi-threaded class, meant for the GTK* backends."""
1074
1081
1075 def __init__(self,argv=None,user_ns=None,user_global_ns=None,debug=1):
1082 def __init__(self,argv=None,user_ns=None,user_global_ns=None,debug=1):
1076 IPShellGTK.__init__(self,argv,user_ns,user_global_ns,debug,
1083 IPShellGTK.__init__(self,argv,user_ns,user_global_ns,debug,
1077 shell_class=MatplotlibMTShell)
1084 shell_class=MatplotlibMTShell)
1078 _load_pylab(self.IP.user_ns)
1085 _load_pylab(self.IP.user_ns)
1079
1086
1080 class IPShellMatplotlibWX(IPShellWX):
1087 class IPShellMatplotlibWX(IPShellWX):
1081 """Subclass IPShellWX with MatplotlibMTShell as the internal shell.
1088 """Subclass IPShellWX with MatplotlibMTShell as the internal shell.
1082
1089
1083 Multi-threaded class, meant for the WX* backends."""
1090 Multi-threaded class, meant for the WX* backends."""
1084
1091
1085 def __init__(self,argv=None,user_ns=None,user_global_ns=None,debug=1):
1092 def __init__(self,argv=None,user_ns=None,user_global_ns=None,debug=1):
1086 IPShellWX.__init__(self,argv,user_ns,user_global_ns,debug,
1093 IPShellWX.__init__(self,argv,user_ns,user_global_ns,debug,
1087 shell_class=MatplotlibMTShell)
1094 shell_class=MatplotlibMTShell)
1088 _load_pylab(self.IP.user_ns)
1095 _load_pylab(self.IP.user_ns)
1089
1096
1090 class IPShellMatplotlibQt(IPShellQt):
1097 class IPShellMatplotlibQt(IPShellQt):
1091 """Subclass IPShellQt with MatplotlibMTShell as the internal shell.
1098 """Subclass IPShellQt with MatplotlibMTShell as the internal shell.
1092
1099
1093 Multi-threaded class, meant for the Qt* backends."""
1100 Multi-threaded class, meant for the Qt* backends."""
1094
1101
1095 def __init__(self,argv=None,user_ns=None,user_global_ns=None,debug=1):
1102 def __init__(self,argv=None,user_ns=None,user_global_ns=None,debug=1):
1096 IPShellQt.__init__(self,argv,user_ns,user_global_ns,debug,
1103 IPShellQt.__init__(self,argv,user_ns,user_global_ns,debug,
1097 shell_class=MatplotlibMTShell)
1104 shell_class=MatplotlibMTShell)
1098 _load_pylab(self.IP.user_ns)
1105 _load_pylab(self.IP.user_ns)
1099
1106
1100 class IPShellMatplotlibQt4(IPShellQt4):
1107 class IPShellMatplotlibQt4(IPShellQt4):
1101 """Subclass IPShellQt4 with MatplotlibMTShell as the internal shell.
1108 """Subclass IPShellQt4 with MatplotlibMTShell as the internal shell.
1102
1109
1103 Multi-threaded class, meant for the Qt4* backends."""
1110 Multi-threaded class, meant for the Qt4* backends."""
1104
1111
1105 def __init__(self,argv=None,user_ns=None,user_global_ns=None,debug=1):
1112 def __init__(self,argv=None,user_ns=None,user_global_ns=None,debug=1):
1106 IPShellQt4.__init__(self,argv,user_ns,user_global_ns,debug,
1113 IPShellQt4.__init__(self,argv,user_ns,user_global_ns,debug,
1107 shell_class=MatplotlibMTShell)
1114 shell_class=MatplotlibMTShell)
1108 _load_pylab(self.IP.user_ns)
1115 _load_pylab(self.IP.user_ns)
1109
1116
1110 #-----------------------------------------------------------------------------
1117 #-----------------------------------------------------------------------------
1111 # Factory functions to actually start the proper thread-aware shell
1118 # Factory functions to actually start the proper thread-aware shell
1112
1119
1113 def _select_shell(argv):
1120 def _select_shell(argv):
1114 """Select a shell from the given argv vector.
1121 """Select a shell from the given argv vector.
1115
1122
1116 This function implements the threading selection policy, allowing runtime
1123 This function implements the threading selection policy, allowing runtime
1117 control of the threading mode, both for general users and for matplotlib.
1124 control of the threading mode, both for general users and for matplotlib.
1118
1125
1119 Return:
1126 Return:
1120 Shell class to be instantiated for runtime operation.
1127 Shell class to be instantiated for runtime operation.
1121 """
1128 """
1122
1129
1123 global USE_TK
1130 global USE_TK
1124
1131
1125 mpl_shell = {'gthread' : IPShellMatplotlibGTK,
1132 mpl_shell = {'gthread' : IPShellMatplotlibGTK,
1126 'wthread' : IPShellMatplotlibWX,
1133 'wthread' : IPShellMatplotlibWX,
1127 'qthread' : IPShellMatplotlibQt,
1134 'qthread' : IPShellMatplotlibQt,
1128 'q4thread' : IPShellMatplotlibQt4,
1135 'q4thread' : IPShellMatplotlibQt4,
1129 'tkthread' : IPShellMatplotlib, # Tk is built-in
1136 'tkthread' : IPShellMatplotlib, # Tk is built-in
1130 }
1137 }
1131
1138
1132 th_shell = {'gthread' : IPShellGTK,
1139 th_shell = {'gthread' : IPShellGTK,
1133 'wthread' : IPShellWX,
1140 'wthread' : IPShellWX,
1134 'qthread' : IPShellQt,
1141 'qthread' : IPShellQt,
1135 'q4thread' : IPShellQt4,
1142 'q4thread' : IPShellQt4,
1136 'tkthread' : IPShell, # Tk is built-in
1143 'tkthread' : IPShell, # Tk is built-in
1137 }
1144 }
1138
1145
1139 backends = {'gthread' : 'GTKAgg',
1146 backends = {'gthread' : 'GTKAgg',
1140 'wthread' : 'WXAgg',
1147 'wthread' : 'WXAgg',
1141 'qthread' : 'QtAgg',
1148 'qthread' : 'QtAgg',
1142 'q4thread' :'Qt4Agg',
1149 'q4thread' :'Qt4Agg',
1143 'tkthread' :'TkAgg',
1150 'tkthread' :'TkAgg',
1144 }
1151 }
1145
1152
1146 all_opts = set(['tk','pylab','gthread','qthread','q4thread','wthread',
1153 all_opts = set(['tk','pylab','gthread','qthread','q4thread','wthread',
1147 'tkthread'])
1154 'tkthread'])
1148 user_opts = set([s.replace('-','') for s in argv[:3]])
1155 user_opts = set([s.replace('-','') for s in argv[:3]])
1149 special_opts = user_opts & all_opts
1156 special_opts = user_opts & all_opts
1150
1157
1151 if 'tk' in special_opts:
1158 if 'tk' in special_opts:
1152 USE_TK = True
1159 USE_TK = True
1153 special_opts.remove('tk')
1160 special_opts.remove('tk')
1154
1161
1155 if 'pylab' in special_opts:
1162 if 'pylab' in special_opts:
1156
1163
1157 try:
1164 try:
1158 import matplotlib
1165 import matplotlib
1159 except ImportError:
1166 except ImportError:
1160 error('matplotlib could NOT be imported! Starting normal IPython.')
1167 error('matplotlib could NOT be imported! Starting normal IPython.')
1161 return IPShell
1168 return IPShell
1162
1169
1163 special_opts.remove('pylab')
1170 special_opts.remove('pylab')
1164 # If there's any option left, it means the user wants to force the
1171 # If there's any option left, it means the user wants to force the
1165 # threading backend, else it's auto-selected from the rc file
1172 # threading backend, else it's auto-selected from the rc file
1166 if special_opts:
1173 if special_opts:
1167 th_mode = special_opts.pop()
1174 th_mode = special_opts.pop()
1168 matplotlib.rcParams['backend'] = backends[th_mode]
1175 matplotlib.rcParams['backend'] = backends[th_mode]
1169 else:
1176 else:
1170 backend = matplotlib.rcParams['backend']
1177 backend = matplotlib.rcParams['backend']
1171 if backend.startswith('GTK'):
1178 if backend.startswith('GTK'):
1172 th_mode = 'gthread'
1179 th_mode = 'gthread'
1173 elif backend.startswith('WX'):
1180 elif backend.startswith('WX'):
1174 th_mode = 'wthread'
1181 th_mode = 'wthread'
1175 elif backend.startswith('Qt4'):
1182 elif backend.startswith('Qt4'):
1176 th_mode = 'q4thread'
1183 th_mode = 'q4thread'
1177 elif backend.startswith('Qt'):
1184 elif backend.startswith('Qt'):
1178 th_mode = 'qthread'
1185 th_mode = 'qthread'
1179 else:
1186 else:
1180 # Any other backend, use plain Tk
1187 # Any other backend, use plain Tk
1181 th_mode = 'tkthread'
1188 th_mode = 'tkthread'
1182
1189
1183 return mpl_shell[th_mode]
1190 return mpl_shell[th_mode]
1184 else:
1191 else:
1185 # No pylab requested, just plain threads
1192 # No pylab requested, just plain threads
1186 try:
1193 try:
1187 th_mode = special_opts.pop()
1194 th_mode = special_opts.pop()
1188 except KeyError:
1195 except KeyError:
1189 th_mode = 'tkthread'
1196 th_mode = 'tkthread'
1190 return th_shell[th_mode]
1197 return th_shell[th_mode]
1191
1198
1192
1199
1193 # This is the one which should be called by external code.
1200 # This is the one which should be called by external code.
1194 def start(user_ns = None):
1201 def start(user_ns = None):
1195 """Return a running shell instance, dealing with threading options.
1202 """Return a running shell instance, dealing with threading options.
1196
1203
1197 This is a factory function which will instantiate the proper IPython shell
1204 This is a factory function which will instantiate the proper IPython shell
1198 based on the user's threading choice. Such a selector is needed because
1205 based on the user's threading choice. Such a selector is needed because
1199 different GUI toolkits require different thread handling details."""
1206 different GUI toolkits require different thread handling details."""
1200
1207
1201 shell = _select_shell(sys.argv)
1208 shell = _select_shell(sys.argv)
1202 return shell(user_ns = user_ns)
1209 return shell(user_ns = user_ns)
1203
1210
1204 # Some aliases for backwards compatibility
1211 # Some aliases for backwards compatibility
1205 IPythonShell = IPShell
1212 IPythonShell = IPShell
1206 IPythonShellEmbed = IPShellEmbed
1213 IPythonShellEmbed = IPShellEmbed
1207 #************************ End of file <Shell.py> ***************************
1214 #************************ End of file <Shell.py> ***************************
General Comments 0
You need to be logged in to leave comments. Login now