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