##// END OF EJS Templates
move hijack_qt into its own function, to be consistent with the rest of ...
darren.dale -
Show More
@@ -1,1138 +1,1152 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 2760 2007-09-11 17:30:32Z darren.dale $"""
7 $Id: Shell.py 2761 2007-09-11 17:40: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. We need to use a norma lock, not an RLock
361 # Locking control variable. We need to use a norma lock, not an RLock
362 # here. I'm not exactly sure why, it seems to me like it should be
362 # here. I'm not exactly sure why, it seems to me like it should be
363 # the opposite, but we deadlock with an RLock. Puzzled...
363 # the opposite, but we deadlock with an RLock. Puzzled...
364 self.thread_ready = threading.Condition(threading.Lock())
364 self.thread_ready = threading.Condition(threading.Lock())
365
365
366 # A queue to hold the code to be executed. A scalar variable is NOT
366 # A queue to hold the code to be executed. A scalar variable is NOT
367 # enough, because uses like macros cause reentrancy.
367 # enough, because uses like macros cause reentrancy.
368 self.code_queue = Queue.Queue()
368 self.code_queue = Queue.Queue()
369
369
370 # Stuff to do at closing time
370 # Stuff to do at closing time
371 self._kill = False
371 self._kill = False
372 on_kill = kw.get('on_kill')
372 on_kill = kw.get('on_kill')
373 if on_kill is None:
373 if on_kill is None:
374 on_kill = []
374 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
380
381 def runsource(self, source, filename="<input>", symbol="single"):
381 def runsource(self, source, filename="<input>", symbol="single"):
382 """Compile and run some source in the interpreter.
382 """Compile and run some source in the interpreter.
383
383
384 Modified version of code.py's runsource(), to handle threading issues.
384 Modified version of code.py's runsource(), to handle threading issues.
385 See the original for full docstring details."""
385 See the original for full docstring details."""
386
386
387 global KBINT
387 global KBINT
388
388
389 # If Ctrl-C was typed, we reset the flag and return right away
389 # If Ctrl-C was typed, we reset the flag and return right away
390 if KBINT:
390 if KBINT:
391 KBINT = False
391 KBINT = False
392 return False
392 return False
393
393
394 try:
394 try:
395 code = self.compile(source, filename, symbol)
395 code = self.compile(source, filename, symbol)
396 except (OverflowError, SyntaxError, ValueError):
396 except (OverflowError, SyntaxError, ValueError):
397 # Case 1
397 # Case 1
398 self.showsyntaxerror(filename)
398 self.showsyntaxerror(filename)
399 return False
399 return False
400
400
401 if code is None:
401 if code is None:
402 # Case 2
402 # Case 2
403 return True
403 return True
404
404
405 # Case 3
405 # Case 3
406 # Store code in queue, so the execution thread can handle it.
406 # Store code in queue, so the execution thread can handle it.
407
407
408 # Note that with macros and other applications, we MAY re-enter this
408 # Note that with macros and other applications, we MAY re-enter this
409 # section, so we have to acquire the lock with non-blocking semantics,
409 # section, so we have to acquire the lock with non-blocking semantics,
410 # else we deadlock.
410 # else we deadlock.
411 got_lock = self.thread_ready.acquire(False)
411 got_lock = self.thread_ready.acquire(False)
412 self.code_queue.put(code)
412 self.code_queue.put(code)
413 if got_lock:
413 if got_lock:
414 self.thread_ready.wait() # Wait until processed in timeout interval
414 self.thread_ready.wait() # Wait until processed in timeout interval
415 self.thread_ready.release()
415 self.thread_ready.release()
416
416
417 return False
417 return False
418
418
419 def runcode(self):
419 def runcode(self):
420 """Execute a code object.
420 """Execute a code object.
421
421
422 Multithreaded wrapper around IPython's runcode()."""
422 Multithreaded wrapper around IPython's runcode()."""
423
423
424 global CODE_RUN
424 global CODE_RUN
425
425
426 # Exceptions need to be raised differently depending on which thread is
426 # Exceptions need to be raised differently depending on which thread is
427 # active
427 # active
428 CODE_RUN = True
428 CODE_RUN = True
429
429
430 # lock thread-protected stuff
430 # lock thread-protected stuff
431 got_lock = self.thread_ready.acquire(False)
431 got_lock = self.thread_ready.acquire(False)
432
432
433 if self._kill:
433 if self._kill:
434 print >>Term.cout, 'Closing threads...',
434 print >>Term.cout, 'Closing threads...',
435 Term.cout.flush()
435 Term.cout.flush()
436 for tokill in self.on_kill:
436 for tokill in self.on_kill:
437 tokill()
437 tokill()
438 print >>Term.cout, 'Done.'
438 print >>Term.cout, 'Done.'
439
439
440 # Install sigint handler. We do it every time to ensure that if user
440 # Install sigint handler. We do it every time to ensure that if user
441 # code modifies it, we restore our own handling.
441 # code modifies it, we restore our own handling.
442 try:
442 try:
443 signal(SIGINT,sigint_handler)
443 signal(SIGINT,sigint_handler)
444 except SystemError:
444 except SystemError:
445 # This happens under Windows, which seems to have all sorts
445 # This happens under Windows, which seems to have all sorts
446 # of problems with signal handling. Oh well...
446 # of problems with signal handling. Oh well...
447 pass
447 pass
448
448
449 # Flush queue of pending code by calling the run methood of the parent
449 # Flush queue of pending code by calling the run methood of the parent
450 # class with all items which may be in the queue.
450 # class with all items which may be in the queue.
451 while 1:
451 while 1:
452 try:
452 try:
453 code_to_run = self.code_queue.get_nowait()
453 code_to_run = self.code_queue.get_nowait()
454 except Queue.Empty:
454 except Queue.Empty:
455 break
455 break
456 if got_lock:
456 if got_lock:
457 self.thread_ready.notify()
457 self.thread_ready.notify()
458 InteractiveShell.runcode(self,code_to_run)
458 InteractiveShell.runcode(self,code_to_run)
459 else:
459 else:
460 break
460 break
461
461
462 # We're done with thread-protected variables
462 # We're done with thread-protected variables
463 if got_lock:
463 if got_lock:
464 self.thread_ready.release()
464 self.thread_ready.release()
465
465
466 # We're done...
466 # We're done...
467 CODE_RUN = False
467 CODE_RUN = False
468 # This MUST return true for gtk threading to work
468 # This MUST return true for gtk threading to work
469 return True
469 return True
470
470
471 def kill(self):
471 def kill(self):
472 """Kill the thread, returning when it has been shut down."""
472 """Kill the thread, returning when it has been shut down."""
473 got_lock = self.thread_ready.acquire(False)
473 got_lock = self.thread_ready.acquire(False)
474 self._kill = True
474 self._kill = True
475 if got_lock:
475 if got_lock:
476 self.thread_ready.release()
476 self.thread_ready.release()
477
477
478 class MatplotlibShellBase:
478 class MatplotlibShellBase:
479 """Mixin class to provide the necessary modifications to regular IPython
479 """Mixin class to provide the necessary modifications to regular IPython
480 shell classes for matplotlib support.
480 shell classes for matplotlib support.
481
481
482 Given Python's MRO, this should be used as the FIRST class in the
482 Given Python's MRO, this should be used as the FIRST class in the
483 inheritance hierarchy, so that it overrides the relevant methods."""
483 inheritance hierarchy, so that it overrides the relevant methods."""
484
484
485 def _matplotlib_config(self,name,user_ns):
485 def _matplotlib_config(self,name,user_ns):
486 """Return items needed to setup the user's shell with matplotlib"""
486 """Return items needed to setup the user's shell with matplotlib"""
487
487
488 # Initialize matplotlib to interactive mode always
488 # Initialize matplotlib to interactive mode always
489 import matplotlib
489 import matplotlib
490 from matplotlib import backends
490 from matplotlib import backends
491 matplotlib.interactive(True)
491 matplotlib.interactive(True)
492
492
493 def use(arg):
493 def use(arg):
494 """IPython wrapper for matplotlib's backend switcher.
494 """IPython wrapper for matplotlib's backend switcher.
495
495
496 In interactive use, we can not allow switching to a different
496 In interactive use, we can not allow switching to a different
497 interactive backend, since thread conflicts will most likely crash
497 interactive backend, since thread conflicts will most likely crash
498 the python interpreter. This routine does a safety check first,
498 the python interpreter. This routine does a safety check first,
499 and refuses to perform a dangerous switch. It still allows
499 and refuses to perform a dangerous switch. It still allows
500 switching to non-interactive backends."""
500 switching to non-interactive backends."""
501
501
502 if arg in backends.interactive_bk and arg != self.mpl_backend:
502 if arg in backends.interactive_bk and arg != self.mpl_backend:
503 m=('invalid matplotlib backend switch.\n'
503 m=('invalid matplotlib backend switch.\n'
504 'This script attempted to switch to the interactive '
504 'This script attempted to switch to the interactive '
505 'backend: `%s`\n'
505 'backend: `%s`\n'
506 'Your current choice of interactive backend is: `%s`\n\n'
506 'Your current choice of interactive backend is: `%s`\n\n'
507 'Switching interactive matplotlib backends at runtime\n'
507 'Switching interactive matplotlib backends at runtime\n'
508 'would crash the python interpreter, '
508 'would crash the python interpreter, '
509 'and IPython has blocked it.\n\n'
509 'and IPython has blocked it.\n\n'
510 'You need to either change your choice of matplotlib backend\n'
510 'You need to either change your choice of matplotlib backend\n'
511 'by editing your .matplotlibrc file, or run this script as a \n'
511 'by editing your .matplotlibrc file, or run this script as a \n'
512 'standalone file from the command line, not using IPython.\n' %
512 'standalone file from the command line, not using IPython.\n' %
513 (arg,self.mpl_backend) )
513 (arg,self.mpl_backend) )
514 raise RuntimeError, m
514 raise RuntimeError, m
515 else:
515 else:
516 self.mpl_use(arg)
516 self.mpl_use(arg)
517 self.mpl_use._called = True
517 self.mpl_use._called = True
518
518
519 self.matplotlib = matplotlib
519 self.matplotlib = matplotlib
520 self.mpl_backend = matplotlib.rcParams['backend']
520 self.mpl_backend = matplotlib.rcParams['backend']
521
521
522 # we also need to block switching of interactive backends by use()
522 # we also need to block switching of interactive backends by use()
523 self.mpl_use = matplotlib.use
523 self.mpl_use = matplotlib.use
524 self.mpl_use._called = False
524 self.mpl_use._called = False
525 # overwrite the original matplotlib.use with our wrapper
525 # overwrite the original matplotlib.use with our wrapper
526 matplotlib.use = use
526 matplotlib.use = use
527
527
528 # This must be imported last in the matplotlib series, after
528 # This must be imported last in the matplotlib series, after
529 # backend/interactivity choices have been made
529 # backend/interactivity choices have been made
530 import matplotlib.pylab as pylab
530 import matplotlib.pylab as pylab
531 self.pylab = pylab
531 self.pylab = pylab
532
532
533 self.pylab.show._needmain = False
533 self.pylab.show._needmain = False
534 # We need to detect at runtime whether show() is called by the user.
534 # We need to detect at runtime whether show() is called by the user.
535 # For this, we wrap it into a decorator which adds a 'called' flag.
535 # For this, we wrap it into a decorator which adds a 'called' flag.
536 self.pylab.draw_if_interactive = flag_calls(self.pylab.draw_if_interactive)
536 self.pylab.draw_if_interactive = flag_calls(self.pylab.draw_if_interactive)
537
537
538 # Build a user namespace initialized with matplotlib/matlab features.
538 # Build a user namespace initialized with matplotlib/matlab features.
539 user_ns = IPython.ipapi.make_user_ns(user_ns)
539 user_ns = IPython.ipapi.make_user_ns(user_ns)
540
540
541 exec ("import matplotlib\n"
541 exec ("import matplotlib\n"
542 "import matplotlib.pylab as pylab\n") in user_ns
542 "import matplotlib.pylab as pylab\n") in user_ns
543
543
544 # Build matplotlib info banner
544 # Build matplotlib info banner
545 b="""
545 b="""
546 Welcome to pylab, a matplotlib-based Python environment.
546 Welcome to pylab, a matplotlib-based Python environment.
547 For more information, type 'help(pylab)'.
547 For more information, type 'help(pylab)'.
548 """
548 """
549 return user_ns,b
549 return user_ns,b
550
550
551 def mplot_exec(self,fname,*where,**kw):
551 def mplot_exec(self,fname,*where,**kw):
552 """Execute a matplotlib script.
552 """Execute a matplotlib script.
553
553
554 This is a call to execfile(), but wrapped in safeties to properly
554 This is a call to execfile(), but wrapped in safeties to properly
555 handle interactive rendering and backend switching."""
555 handle interactive rendering and backend switching."""
556
556
557 #print '*** Matplotlib runner ***' # dbg
557 #print '*** Matplotlib runner ***' # dbg
558 # turn off rendering until end of script
558 # turn off rendering until end of script
559 isInteractive = self.matplotlib.rcParams['interactive']
559 isInteractive = self.matplotlib.rcParams['interactive']
560 self.matplotlib.interactive(False)
560 self.matplotlib.interactive(False)
561 self.safe_execfile(fname,*where,**kw)
561 self.safe_execfile(fname,*where,**kw)
562 self.matplotlib.interactive(isInteractive)
562 self.matplotlib.interactive(isInteractive)
563 # make rendering call now, if the user tried to do it
563 # make rendering call now, if the user tried to do it
564 if self.pylab.draw_if_interactive.called:
564 if self.pylab.draw_if_interactive.called:
565 self.pylab.draw()
565 self.pylab.draw()
566 self.pylab.draw_if_interactive.called = False
566 self.pylab.draw_if_interactive.called = False
567
567
568 # if a backend switch was performed, reverse it now
568 # if a backend switch was performed, reverse it now
569 if self.mpl_use._called:
569 if self.mpl_use._called:
570 self.matplotlib.rcParams['backend'] = self.mpl_backend
570 self.matplotlib.rcParams['backend'] = self.mpl_backend
571
571
572 def magic_run(self,parameter_s=''):
572 def magic_run(self,parameter_s=''):
573 Magic.magic_run(self,parameter_s,runner=self.mplot_exec)
573 Magic.magic_run(self,parameter_s,runner=self.mplot_exec)
574
574
575 # Fix the docstring so users see the original as well
575 # Fix the docstring so users see the original as well
576 magic_run.__doc__ = "%s\n%s" % (Magic.magic_run.__doc__,
576 magic_run.__doc__ = "%s\n%s" % (Magic.magic_run.__doc__,
577 "\n *** Modified %run for Matplotlib,"
577 "\n *** Modified %run for Matplotlib,"
578 " with proper interactive handling ***")
578 " with proper interactive handling ***")
579
579
580 # Now we provide 2 versions of a matplotlib-aware IPython base shells, single
580 # Now we provide 2 versions of a matplotlib-aware IPython base shells, single
581 # and multithreaded. Note that these are meant for internal use, the IPShell*
581 # and multithreaded. Note that these are meant for internal use, the IPShell*
582 # classes below are the ones meant for public consumption.
582 # classes below are the ones meant for public consumption.
583
583
584 class MatplotlibShell(MatplotlibShellBase,InteractiveShell):
584 class MatplotlibShell(MatplotlibShellBase,InteractiveShell):
585 """Single-threaded shell with matplotlib support."""
585 """Single-threaded shell with matplotlib support."""
586
586
587 def __init__(self,name,usage=None,rc=Struct(opts=None,args=None),
587 def __init__(self,name,usage=None,rc=Struct(opts=None,args=None),
588 user_ns=None,user_global_ns=None,**kw):
588 user_ns=None,user_global_ns=None,**kw):
589 user_ns,b2 = self._matplotlib_config(name,user_ns)
589 user_ns,b2 = self._matplotlib_config(name,user_ns)
590 InteractiveShell.__init__(self,name,usage,rc,user_ns,user_global_ns,
590 InteractiveShell.__init__(self,name,usage,rc,user_ns,user_global_ns,
591 banner2=b2,**kw)
591 banner2=b2,**kw)
592
592
593 class MatplotlibMTShell(MatplotlibShellBase,MTInteractiveShell):
593 class MatplotlibMTShell(MatplotlibShellBase,MTInteractiveShell):
594 """Multi-threaded shell with matplotlib support."""
594 """Multi-threaded shell with matplotlib support."""
595
595
596 def __init__(self,name,usage=None,rc=Struct(opts=None,args=None),
596 def __init__(self,name,usage=None,rc=Struct(opts=None,args=None),
597 user_ns=None,user_global_ns=None, **kw):
597 user_ns=None,user_global_ns=None, **kw):
598 user_ns,b2 = self._matplotlib_config(name,user_ns)
598 user_ns,b2 = self._matplotlib_config(name,user_ns)
599 MTInteractiveShell.__init__(self,name,usage,rc,user_ns,user_global_ns,
599 MTInteractiveShell.__init__(self,name,usage,rc,user_ns,user_global_ns,
600 banner2=b2,**kw)
600 banner2=b2,**kw)
601
601
602 #-----------------------------------------------------------------------------
602 #-----------------------------------------------------------------------------
603 # Utility functions for the different GUI enabled IPShell* classes.
603 # Utility functions for the different GUI enabled IPShell* classes.
604
604
605 def get_tk():
605 def get_tk():
606 """Tries to import Tkinter and returns a withdrawn Tkinter root
606 """Tries to import Tkinter and returns a withdrawn Tkinter root
607 window. If Tkinter is already imported or not available, this
607 window. If Tkinter is already imported or not available, this
608 returns None. This function calls `hijack_tk` underneath.
608 returns None. This function calls `hijack_tk` underneath.
609 """
609 """
610 if not USE_TK or sys.modules.has_key('Tkinter'):
610 if not USE_TK or sys.modules.has_key('Tkinter'):
611 return None
611 return None
612 else:
612 else:
613 try:
613 try:
614 import Tkinter
614 import Tkinter
615 except ImportError:
615 except ImportError:
616 return None
616 return None
617 else:
617 else:
618 hijack_tk()
618 hijack_tk()
619 r = Tkinter.Tk()
619 r = Tkinter.Tk()
620 r.withdraw()
620 r.withdraw()
621 return r
621 return r
622
622
623 def hijack_tk():
623 def hijack_tk():
624 """Modifies Tkinter's mainloop with a dummy so when a module calls
624 """Modifies Tkinter's mainloop with a dummy so when a module calls
625 mainloop, it does not block.
625 mainloop, it does not block.
626
626
627 """
627 """
628 def misc_mainloop(self, n=0):
628 def misc_mainloop(self, n=0):
629 pass
629 pass
630 def tkinter_mainloop(n=0):
630 def tkinter_mainloop(n=0):
631 pass
631 pass
632
632
633 import Tkinter
633 import Tkinter
634 Tkinter.Misc.mainloop = misc_mainloop
634 Tkinter.Misc.mainloop = misc_mainloop
635 Tkinter.mainloop = tkinter_mainloop
635 Tkinter.mainloop = tkinter_mainloop
636
636
637 def update_tk(tk):
637 def update_tk(tk):
638 """Updates the Tkinter event loop. This is typically called from
638 """Updates the Tkinter event loop. This is typically called from
639 the respective WX or GTK mainloops.
639 the respective WX or GTK mainloops.
640 """
640 """
641 if tk:
641 if tk:
642 tk.update()
642 tk.update()
643
643
644 def hijack_wx():
644 def hijack_wx():
645 """Modifies wxPython's MainLoop with a dummy so user code does not
645 """Modifies wxPython's MainLoop with a dummy so user code does not
646 block IPython. The hijacked mainloop function is returned.
646 block IPython. The hijacked mainloop function is returned.
647 """
647 """
648 def dummy_mainloop(*args, **kw):
648 def dummy_mainloop(*args, **kw):
649 pass
649 pass
650
650
651 try:
651 try:
652 import wx
652 import wx
653 except ImportError:
653 except ImportError:
654 # For very old versions of WX
654 # For very old versions of WX
655 import wxPython as wx
655 import wxPython as wx
656
656
657 ver = wx.__version__
657 ver = wx.__version__
658 orig_mainloop = None
658 orig_mainloop = None
659 if ver[:3] >= '2.5':
659 if ver[:3] >= '2.5':
660 import wx
660 import wx
661 if hasattr(wx, '_core_'): core = getattr(wx, '_core_')
661 if hasattr(wx, '_core_'): core = getattr(wx, '_core_')
662 elif hasattr(wx, '_core'): core = getattr(wx, '_core')
662 elif hasattr(wx, '_core'): core = getattr(wx, '_core')
663 else: raise AttributeError('Could not find wx core module')
663 else: raise AttributeError('Could not find wx core module')
664 orig_mainloop = core.PyApp_MainLoop
664 orig_mainloop = core.PyApp_MainLoop
665 core.PyApp_MainLoop = dummy_mainloop
665 core.PyApp_MainLoop = dummy_mainloop
666 elif ver[:3] == '2.4':
666 elif ver[:3] == '2.4':
667 orig_mainloop = wx.wxc.wxPyApp_MainLoop
667 orig_mainloop = wx.wxc.wxPyApp_MainLoop
668 wx.wxc.wxPyApp_MainLoop = dummy_mainloop
668 wx.wxc.wxPyApp_MainLoop = dummy_mainloop
669 else:
669 else:
670 warn("Unable to find either wxPython version 2.4 or >= 2.5.")
670 warn("Unable to find either wxPython version 2.4 or >= 2.5.")
671 return orig_mainloop
671 return orig_mainloop
672
672
673 def hijack_gtk():
673 def hijack_gtk():
674 """Modifies pyGTK's mainloop with a dummy so user code does not
674 """Modifies pyGTK's mainloop with a dummy so user code does not
675 block IPython. This function returns the original `gtk.mainloop`
675 block IPython. This function returns the original `gtk.mainloop`
676 function that has been hijacked.
676 function that has been hijacked.
677 """
677 """
678 def dummy_mainloop(*args, **kw):
678 def dummy_mainloop(*args, **kw):
679 pass
679 pass
680 import gtk
680 import gtk
681 if gtk.pygtk_version >= (2,4,0): orig_mainloop = gtk.main
681 if gtk.pygtk_version >= (2,4,0): orig_mainloop = gtk.main
682 else: orig_mainloop = gtk.mainloop
682 else: orig_mainloop = gtk.mainloop
683 gtk.mainloop = dummy_mainloop
683 gtk.mainloop = dummy_mainloop
684 gtk.main = dummy_mainloop
684 gtk.main = dummy_mainloop
685 return orig_mainloop
685 return orig_mainloop
686
686
687 def hijack_qt():
688 """Modifies PyQt's mainloop with a dummy so user code does not
689 block IPython. This function returns the original
690 `qt.qApp.exec_loop` function that has been hijacked.
691 """
692 def dummy_mainloop(*args, **kw):
693 pass
694 import qt
695 orig_mainloop = qt.qApp.exec_loop
696 qt.qApp.exec_loop = dummy_mainloop
697 qt.QApplication.exec_loop = dummy_mainloop
698 return orig_mainloop
699
700 def hijack_qt4():
701 """Modifies PyQt4's mainloop with a dummy so user code does not
702 block IPython. This function returns the original
703 `QtGui.qApp.exec_` function that has been hijacked.
704 """
705 def dummy_mainloop(*args, **kw):
706 pass
707 from PyQt4 import QtGui, QtCore
708 orig_mainloop = QtGui.qApp.exec_
709 QtGui.qApp.exec_ = dummy_mainloop
710 QtGui.QApplication.exec_ = dummy_mainloop
711 QtCore.QCoreApplication.exec_ = dummy_mainloop
712 return orig_mainloop
713
687 #-----------------------------------------------------------------------------
714 #-----------------------------------------------------------------------------
688 # The IPShell* classes below are the ones meant to be run by external code as
715 # The IPShell* classes below are the ones meant to be run by external code as
689 # IPython instances. Note that unless a specific threading strategy is
716 # IPython instances. Note that unless a specific threading strategy is
690 # desired, the factory function start() below should be used instead (it
717 # desired, the factory function start() below should be used instead (it
691 # selects the proper threaded class).
718 # selects the proper threaded class).
692
719
693 class IPThread(threading.Thread):
720 class IPThread(threading.Thread):
694 def run(self):
721 def run(self):
695 self.IP.mainloop(self._banner)
722 self.IP.mainloop(self._banner)
696 self.IP.kill()
723 self.IP.kill()
697
724
698 class IPShellGTK(IPThread):
725 class IPShellGTK(IPThread):
699 """Run a gtk mainloop() in a separate thread.
726 """Run a gtk mainloop() in a separate thread.
700
727
701 Python commands can be passed to the thread where they will be executed.
728 Python commands can be passed to the thread where they will be executed.
702 This is implemented by periodically checking for passed code using a
729 This is implemented by periodically checking for passed code using a
703 GTK timeout callback."""
730 GTK timeout callback."""
704
731
705 TIMEOUT = 100 # Millisecond interval between timeouts.
732 TIMEOUT = 100 # Millisecond interval between timeouts.
706
733
707 def __init__(self,argv=None,user_ns=None,user_global_ns=None,
734 def __init__(self,argv=None,user_ns=None,user_global_ns=None,
708 debug=1,shell_class=MTInteractiveShell):
735 debug=1,shell_class=MTInteractiveShell):
709
736
710 import gtk
737 import gtk
711
738
712 self.gtk = gtk
739 self.gtk = gtk
713 self.gtk_mainloop = hijack_gtk()
740 self.gtk_mainloop = hijack_gtk()
714
741
715 # Allows us to use both Tk and GTK.
742 # Allows us to use both Tk and GTK.
716 self.tk = get_tk()
743 self.tk = get_tk()
717
744
718 if gtk.pygtk_version >= (2,4,0): mainquit = self.gtk.main_quit
745 if gtk.pygtk_version >= (2,4,0): mainquit = self.gtk.main_quit
719 else: mainquit = self.gtk.mainquit
746 else: mainquit = self.gtk.mainquit
720
747
721 self.IP = make_IPython(argv,user_ns=user_ns,
748 self.IP = make_IPython(argv,user_ns=user_ns,
722 user_global_ns=user_global_ns,
749 user_global_ns=user_global_ns,
723 debug=debug,
750 debug=debug,
724 shell_class=shell_class,
751 shell_class=shell_class,
725 on_kill=[mainquit])
752 on_kill=[mainquit])
726
753
727 # HACK: slot for banner in self; it will be passed to the mainloop
754 # HACK: slot for banner in self; it will be passed to the mainloop
728 # method only and .run() needs it. The actual value will be set by
755 # method only and .run() needs it. The actual value will be set by
729 # .mainloop().
756 # .mainloop().
730 self._banner = None
757 self._banner = None
731
758
732 threading.Thread.__init__(self)
759 threading.Thread.__init__(self)
733
760
734 def mainloop(self,sys_exit=0,banner=None):
761 def mainloop(self,sys_exit=0,banner=None):
735
762
736 self._banner = banner
763 self._banner = banner
737
764
738 if self.gtk.pygtk_version >= (2,4,0):
765 if self.gtk.pygtk_version >= (2,4,0):
739 import gobject
766 import gobject
740 gobject.idle_add(self.on_timer)
767 gobject.idle_add(self.on_timer)
741 else:
768 else:
742 self.gtk.idle_add(self.on_timer)
769 self.gtk.idle_add(self.on_timer)
743
770
744 if sys.platform != 'win32':
771 if sys.platform != 'win32':
745 try:
772 try:
746 if self.gtk.gtk_version[0] >= 2:
773 if self.gtk.gtk_version[0] >= 2:
747 self.gtk.gdk.threads_init()
774 self.gtk.gdk.threads_init()
748 except AttributeError:
775 except AttributeError:
749 pass
776 pass
750 except RuntimeError:
777 except RuntimeError:
751 error('Your pyGTK likely has not been compiled with '
778 error('Your pyGTK likely has not been compiled with '
752 'threading support.\n'
779 'threading support.\n'
753 'The exception printout is below.\n'
780 'The exception printout is below.\n'
754 'You can either rebuild pyGTK with threads, or '
781 'You can either rebuild pyGTK with threads, or '
755 'try using \n'
782 'try using \n'
756 'matplotlib with a different backend (like Tk or WX).\n'
783 'matplotlib with a different backend (like Tk or WX).\n'
757 'Note that matplotlib will most likely not work in its '
784 'Note that matplotlib will most likely not work in its '
758 'current state!')
785 'current state!')
759 self.IP.InteractiveTB()
786 self.IP.InteractiveTB()
760
787
761 self.start()
788 self.start()
762 self.gtk.gdk.threads_enter()
789 self.gtk.gdk.threads_enter()
763 self.gtk_mainloop()
790 self.gtk_mainloop()
764 self.gtk.gdk.threads_leave()
791 self.gtk.gdk.threads_leave()
765 self.join()
792 self.join()
766
793
767 def on_timer(self):
794 def on_timer(self):
768 """Called when GTK is idle.
795 """Called when GTK is idle.
769
796
770 Must return True always, otherwise GTK stops calling it"""
797 Must return True always, otherwise GTK stops calling it"""
771
798
772 update_tk(self.tk)
799 update_tk(self.tk)
773 self.IP.runcode()
800 self.IP.runcode()
774 time.sleep(0.01)
801 time.sleep(0.01)
775 return True
802 return True
776
803
777
804
778 class IPShellWX(IPThread):
805 class IPShellWX(IPThread):
779 """Run a wx mainloop() in a separate thread.
806 """Run a wx mainloop() in a separate thread.
780
807
781 Python commands can be passed to the thread where they will be executed.
808 Python commands can be passed to the thread where they will be executed.
782 This is implemented by periodically checking for passed code using a
809 This is implemented by periodically checking for passed code using a
783 GTK timeout callback."""
810 GTK timeout callback."""
784
811
785 TIMEOUT = 100 # Millisecond interval between timeouts.
812 TIMEOUT = 100 # Millisecond interval between timeouts.
786
813
787 def __init__(self,argv=None,user_ns=None,user_global_ns=None,
814 def __init__(self,argv=None,user_ns=None,user_global_ns=None,
788 debug=1,shell_class=MTInteractiveShell):
815 debug=1,shell_class=MTInteractiveShell):
789
816
790 self.IP = make_IPython(argv,user_ns=user_ns,
817 self.IP = make_IPython(argv,user_ns=user_ns,
791 user_global_ns=user_global_ns,
818 user_global_ns=user_global_ns,
792 debug=debug,
819 debug=debug,
793 shell_class=shell_class,
820 shell_class=shell_class,
794 on_kill=[self.wxexit])
821 on_kill=[self.wxexit])
795
822
796 wantedwxversion=self.IP.rc.wxversion
823 wantedwxversion=self.IP.rc.wxversion
797 if wantedwxversion!="0":
824 if wantedwxversion!="0":
798 try:
825 try:
799 import wxversion
826 import wxversion
800 except ImportError:
827 except ImportError:
801 error('The wxversion module is needed for WX version selection')
828 error('The wxversion module is needed for WX version selection')
802 else:
829 else:
803 try:
830 try:
804 wxversion.select(wantedwxversion)
831 wxversion.select(wantedwxversion)
805 except:
832 except:
806 self.IP.InteractiveTB()
833 self.IP.InteractiveTB()
807 error('Requested wxPython version %s could not be loaded' %
834 error('Requested wxPython version %s could not be loaded' %
808 wantedwxversion)
835 wantedwxversion)
809
836
810 import wx
837 import wx
811
838
812 threading.Thread.__init__(self)
839 threading.Thread.__init__(self)
813 self.wx = wx
840 self.wx = wx
814 self.wx_mainloop = hijack_wx()
841 self.wx_mainloop = hijack_wx()
815
842
816 # Allows us to use both Tk and GTK.
843 # Allows us to use both Tk and GTK.
817 self.tk = get_tk()
844 self.tk = get_tk()
818
845
819 # HACK: slot for banner in self; it will be passed to the mainloop
846 # HACK: slot for banner in self; it will be passed to the mainloop
820 # method only and .run() needs it. The actual value will be set by
847 # method only and .run() needs it. The actual value will be set by
821 # .mainloop().
848 # .mainloop().
822 self._banner = None
849 self._banner = None
823
850
824 self.app = None
851 self.app = None
825
852
826 def wxexit(self, *args):
853 def wxexit(self, *args):
827 if self.app is not None:
854 if self.app is not None:
828 self.app.agent.timer.Stop()
855 self.app.agent.timer.Stop()
829 self.app.ExitMainLoop()
856 self.app.ExitMainLoop()
830
857
831 def mainloop(self,sys_exit=0,banner=None):
858 def mainloop(self,sys_exit=0,banner=None):
832
859
833 self._banner = banner
860 self._banner = banner
834
861
835 self.start()
862 self.start()
836
863
837 class TimerAgent(self.wx.MiniFrame):
864 class TimerAgent(self.wx.MiniFrame):
838 wx = self.wx
865 wx = self.wx
839 IP = self.IP
866 IP = self.IP
840 tk = self.tk
867 tk = self.tk
841 def __init__(self, parent, interval):
868 def __init__(self, parent, interval):
842 style = self.wx.DEFAULT_FRAME_STYLE | self.wx.TINY_CAPTION_HORIZ
869 style = self.wx.DEFAULT_FRAME_STYLE | self.wx.TINY_CAPTION_HORIZ
843 self.wx.MiniFrame.__init__(self, parent, -1, ' ', pos=(200, 200),
870 self.wx.MiniFrame.__init__(self, parent, -1, ' ', pos=(200, 200),
844 size=(100, 100),style=style)
871 size=(100, 100),style=style)
845 self.Show(False)
872 self.Show(False)
846 self.interval = interval
873 self.interval = interval
847 self.timerId = self.wx.NewId()
874 self.timerId = self.wx.NewId()
848
875
849 def StartWork(self):
876 def StartWork(self):
850 self.timer = self.wx.Timer(self, self.timerId)
877 self.timer = self.wx.Timer(self, self.timerId)
851 self.wx.EVT_TIMER(self, self.timerId, self.OnTimer)
878 self.wx.EVT_TIMER(self, self.timerId, self.OnTimer)
852 self.timer.Start(self.interval)
879 self.timer.Start(self.interval)
853
880
854 def OnTimer(self, event):
881 def OnTimer(self, event):
855 update_tk(self.tk)
882 update_tk(self.tk)
856 self.IP.runcode()
883 self.IP.runcode()
857
884
858 class App(self.wx.App):
885 class App(self.wx.App):
859 wx = self.wx
886 wx = self.wx
860 TIMEOUT = self.TIMEOUT
887 TIMEOUT = self.TIMEOUT
861 def OnInit(self):
888 def OnInit(self):
862 'Create the main window and insert the custom frame'
889 'Create the main window and insert the custom frame'
863 self.agent = TimerAgent(None, self.TIMEOUT)
890 self.agent = TimerAgent(None, self.TIMEOUT)
864 self.agent.Show(False)
891 self.agent.Show(False)
865 self.agent.StartWork()
892 self.agent.StartWork()
866 return True
893 return True
867
894
868 self.app = App(redirect=False)
895 self.app = App(redirect=False)
869 self.wx_mainloop(self.app)
896 self.wx_mainloop(self.app)
870 self.join()
897 self.join()
871
898
872
899
873 class IPShellQt(IPThread):
900 class IPShellQt(IPThread):
874 """Run a Qt event loop in a separate thread.
901 """Run a Qt event loop in a separate thread.
875
902
876 Python commands can be passed to the thread where they will be executed.
903 Python commands can be passed to the thread where they will be executed.
877 This is implemented by periodically checking for passed code using a
904 This is implemented by periodically checking for passed code using a
878 Qt timer / slot."""
905 Qt timer / slot."""
879
906
880 TIMEOUT = 100 # Millisecond interval between timeouts.
907 TIMEOUT = 100 # Millisecond interval between timeouts.
881
908
882 def __init__(self, argv=None, user_ns=None, user_global_ns=None,
909 def __init__(self, argv=None, user_ns=None, user_global_ns=None,
883 debug=0, shell_class=MTInteractiveShell):
910 debug=0, shell_class=MTInteractiveShell):
884
911
885 import qt
912 import qt
886
913
887 def dummy_mainloop(*args, **kwargs):
914 self.exec_loop = hijack_qt()
888 pass
889
890 self.exec_loop = qt.qApp.exec_loop
891
892 qt.qApp.exec_loop = dummy_mainloop
893 qt.QApplication.exec_loop = dummy_mainloop
894
915
895 # Allows us to use both Tk and QT.
916 # Allows us to use both Tk and QT.
896 self.tk = get_tk()
917 self.tk = get_tk()
897
918
898 self.IP = make_IPython(argv,
919 self.IP = make_IPython(argv,
899 user_ns=user_ns,
920 user_ns=user_ns,
900 user_global_ns=user_global_ns,
921 user_global_ns=user_global_ns,
901 debug=debug,
922 debug=debug,
902 shell_class=shell_class,
923 shell_class=shell_class,
903 on_kill=[qt.qApp.exit])
924 on_kill=[qt.qApp.exit])
904
925
905 # HACK: slot for banner in self; it will be passed to the mainloop
926 # HACK: slot for banner in self; it will be passed to the mainloop
906 # method only and .run() needs it. The actual value will be set by
927 # method only and .run() needs it. The actual value will be set by
907 # .mainloop().
928 # .mainloop().
908 self._banner = None
929 self._banner = None
909
930
910 threading.Thread.__init__(self)
931 threading.Thread.__init__(self)
911
932
912 def mainloop(self, sys_exit=0, banner=None):
933 def mainloop(self, sys_exit=0, banner=None):
913
934
914 import qt
935 import qt
915
936
916 self._banner = banner
937 self._banner = banner
917
938
918 if qt.QApplication.startingUp():
939 if qt.QApplication.startingUp():
919 a = qt.QApplication(sys.argv)
940 a = qt.QApplication(sys.argv)
920
941
921 self.timer = qt.QTimer()
942 self.timer = qt.QTimer()
922 qt.QObject.connect(self.timer,
943 qt.QObject.connect(self.timer,
923 qt.SIGNAL('timeout()'),
944 qt.SIGNAL('timeout()'),
924 self.on_timer)
945 self.on_timer)
925
946
926 self.start()
947 self.start()
927 self.timer.start(self.TIMEOUT, True)
948 self.timer.start(self.TIMEOUT, True)
928 while True:
949 while True:
929 if self.IP._kill: break
950 if self.IP._kill: break
930 self.exec_loop()
951 self.exec_loop()
931 self.join()
952 self.join()
932
953
933 def on_timer(self):
954 def on_timer(self):
934 update_tk(self.tk)
955 update_tk(self.tk)
935 result = self.IP.runcode()
956 result = self.IP.runcode()
936 self.timer.start(self.TIMEOUT, True)
957 self.timer.start(self.TIMEOUT, True)
937 return result
958 return result
938
959
939
960
940 class IPShellQt4(IPThread):
961 class IPShellQt4(IPThread):
941 """Run a Qt event loop in a separate thread.
962 """Run a Qt event loop in a separate thread.
942
963
943 Python commands can be passed to the thread where they will be executed.
964 Python commands can be passed to the thread where they will be executed.
944 This is implemented by periodically checking for passed code using a
965 This is implemented by periodically checking for passed code using a
945 Qt timer / slot."""
966 Qt timer / slot."""
946
967
947 TIMEOUT = 100 # Millisecond interval between timeouts.
968 TIMEOUT = 100 # Millisecond interval between timeouts.
948
969
949 def __init__(self, argv=None, user_ns=None, user_global_ns=None,
970 def __init__(self, argv=None, user_ns=None, user_global_ns=None,
950 debug=0, shell_class=MTInteractiveShell):
971 debug=0, shell_class=MTInteractiveShell):
951
972
952 from PyQt4 import QtCore, QtGui
973 from PyQt4 import QtCore, QtGui
953
954 def dummy_mainloop(*args, **kwargs):
955 pass
956
974
957 self.exec_ = QtGui.qApp.exec_
975 self.exec_ = hijack_qt4()
958
959 QtGui.qApp.exec_ = dummy_mainloop
960 QtGui.QApplication.exec_ = dummy_mainloop
961 QtCore.QCoreApplication.exec_ = dummy_mainloop
962
976
963 # Allows us to use both Tk and QT.
977 # Allows us to use both Tk and QT.
964 self.tk = get_tk()
978 self.tk = get_tk()
965
979
966 self.IP = make_IPython(argv,
980 self.IP = make_IPython(argv,
967 user_ns=user_ns,
981 user_ns=user_ns,
968 user_global_ns=user_global_ns,
982 user_global_ns=user_global_ns,
969 debug=debug,
983 debug=debug,
970 shell_class=shell_class,
984 shell_class=shell_class,
971 on_kill=[QtGui.qApp.exit])
985 on_kill=[QtGui.qApp.exit])
972
986
973 # HACK: slot for banner in self; it will be passed to the mainloop
987 # HACK: slot for banner in self; it will be passed to the mainloop
974 # method only and .run() needs it. The actual value will be set by
988 # method only and .run() needs it. The actual value will be set by
975 # .mainloop().
989 # .mainloop().
976 self._banner = None
990 self._banner = None
977
991
978 threading.Thread.__init__(self)
992 threading.Thread.__init__(self)
979
993
980 def mainloop(self, sys_exit=0, banner=None):
994 def mainloop(self, sys_exit=0, banner=None):
981
995
982 from PyQt4 import QtCore, QtGui
996 from PyQt4 import QtCore, QtGui
983
997
984 self._banner = banner
998 self._banner = banner
985
999
986 if QtGui.QApplication.startingUp():
1000 if QtGui.QApplication.startingUp():
987 a = QtGui.QApplication(sys.argv)
1001 a = QtGui.QApplication(sys.argv)
988
1002
989 self.timer = QtCore.QTimer()
1003 self.timer = QtCore.QTimer()
990 QtCore.QObject.connect(self.timer,
1004 QtCore.QObject.connect(self.timer,
991 QtCore.SIGNAL('timeout()'),
1005 QtCore.SIGNAL('timeout()'),
992 self.on_timer)
1006 self.on_timer)
993
1007
994 self.start()
1008 self.start()
995 self.timer.start(self.TIMEOUT)
1009 self.timer.start(self.TIMEOUT)
996 while True:
1010 while True:
997 if self.IP._kill: break
1011 if self.IP._kill: break
998 self.exec_()
1012 self.exec_()
999 self.join()
1013 self.join()
1000
1014
1001 def on_timer(self):
1015 def on_timer(self):
1002 update_tk(self.tk)
1016 update_tk(self.tk)
1003 result = self.IP.runcode()
1017 result = self.IP.runcode()
1004 self.timer.start(self.TIMEOUT)
1018 self.timer.start(self.TIMEOUT)
1005 return result
1019 return result
1006
1020
1007
1021
1008 # A set of matplotlib public IPython shell classes, for single-threaded (Tk*
1022 # A set of matplotlib public IPython shell classes, for single-threaded (Tk*
1009 # and FLTK*) and multithreaded (GTK*, WX* and Qt*) backends to use.
1023 # and FLTK*) and multithreaded (GTK*, WX* and Qt*) backends to use.
1010 def _load_pylab(user_ns):
1024 def _load_pylab(user_ns):
1011 """Allow users to disable pulling all of pylab into the top-level
1025 """Allow users to disable pulling all of pylab into the top-level
1012 namespace.
1026 namespace.
1013
1027
1014 This little utility must be called AFTER the actual ipython instance is
1028 This little utility must be called AFTER the actual ipython instance is
1015 running, since only then will the options file have been fully parsed."""
1029 running, since only then will the options file have been fully parsed."""
1016
1030
1017 ip = IPython.ipapi.get()
1031 ip = IPython.ipapi.get()
1018 if ip.options.pylab_import_all:
1032 if ip.options.pylab_import_all:
1019 exec "from matplotlib.pylab import *" in user_ns
1033 exec "from matplotlib.pylab import *" in user_ns
1020
1034
1021 class IPShellMatplotlib(IPShell):
1035 class IPShellMatplotlib(IPShell):
1022 """Subclass IPShell with MatplotlibShell as the internal shell.
1036 """Subclass IPShell with MatplotlibShell as the internal shell.
1023
1037
1024 Single-threaded class, meant for the Tk* and FLTK* backends.
1038 Single-threaded class, meant for the Tk* and FLTK* backends.
1025
1039
1026 Having this on a separate class simplifies the external driver code."""
1040 Having this on a separate class simplifies the external driver code."""
1027
1041
1028 def __init__(self,argv=None,user_ns=None,user_global_ns=None,debug=1):
1042 def __init__(self,argv=None,user_ns=None,user_global_ns=None,debug=1):
1029 IPShell.__init__(self,argv,user_ns,user_global_ns,debug,
1043 IPShell.__init__(self,argv,user_ns,user_global_ns,debug,
1030 shell_class=MatplotlibShell)
1044 shell_class=MatplotlibShell)
1031 _load_pylab(self.IP.user_ns)
1045 _load_pylab(self.IP.user_ns)
1032
1046
1033 class IPShellMatplotlibGTK(IPShellGTK):
1047 class IPShellMatplotlibGTK(IPShellGTK):
1034 """Subclass IPShellGTK with MatplotlibMTShell as the internal shell.
1048 """Subclass IPShellGTK with MatplotlibMTShell as the internal shell.
1035
1049
1036 Multi-threaded class, meant for the GTK* backends."""
1050 Multi-threaded class, meant for the GTK* backends."""
1037
1051
1038 def __init__(self,argv=None,user_ns=None,user_global_ns=None,debug=1):
1052 def __init__(self,argv=None,user_ns=None,user_global_ns=None,debug=1):
1039 IPShellGTK.__init__(self,argv,user_ns,user_global_ns,debug,
1053 IPShellGTK.__init__(self,argv,user_ns,user_global_ns,debug,
1040 shell_class=MatplotlibMTShell)
1054 shell_class=MatplotlibMTShell)
1041 _load_pylab(self.IP.user_ns)
1055 _load_pylab(self.IP.user_ns)
1042
1056
1043 class IPShellMatplotlibWX(IPShellWX):
1057 class IPShellMatplotlibWX(IPShellWX):
1044 """Subclass IPShellWX with MatplotlibMTShell as the internal shell.
1058 """Subclass IPShellWX with MatplotlibMTShell as the internal shell.
1045
1059
1046 Multi-threaded class, meant for the WX* backends."""
1060 Multi-threaded class, meant for the WX* backends."""
1047
1061
1048 def __init__(self,argv=None,user_ns=None,user_global_ns=None,debug=1):
1062 def __init__(self,argv=None,user_ns=None,user_global_ns=None,debug=1):
1049 IPShellWX.__init__(self,argv,user_ns,user_global_ns,debug,
1063 IPShellWX.__init__(self,argv,user_ns,user_global_ns,debug,
1050 shell_class=MatplotlibMTShell)
1064 shell_class=MatplotlibMTShell)
1051 _load_pylab(self.IP.user_ns)
1065 _load_pylab(self.IP.user_ns)
1052
1066
1053 class IPShellMatplotlibQt(IPShellQt):
1067 class IPShellMatplotlibQt(IPShellQt):
1054 """Subclass IPShellQt with MatplotlibMTShell as the internal shell.
1068 """Subclass IPShellQt with MatplotlibMTShell as the internal shell.
1055
1069
1056 Multi-threaded class, meant for the Qt* backends."""
1070 Multi-threaded class, meant for the Qt* backends."""
1057
1071
1058 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):
1059 IPShellQt.__init__(self,argv,user_ns,user_global_ns,debug,
1073 IPShellQt.__init__(self,argv,user_ns,user_global_ns,debug,
1060 shell_class=MatplotlibMTShell)
1074 shell_class=MatplotlibMTShell)
1061 _load_pylab(self.IP.user_ns)
1075 _load_pylab(self.IP.user_ns)
1062
1076
1063 class IPShellMatplotlibQt4(IPShellQt4):
1077 class IPShellMatplotlibQt4(IPShellQt4):
1064 """Subclass IPShellQt4 with MatplotlibMTShell as the internal shell.
1078 """Subclass IPShellQt4 with MatplotlibMTShell as the internal shell.
1065
1079
1066 Multi-threaded class, meant for the Qt4* backends."""
1080 Multi-threaded class, meant for the Qt4* backends."""
1067
1081
1068 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):
1069 IPShellQt4.__init__(self,argv,user_ns,user_global_ns,debug,
1083 IPShellQt4.__init__(self,argv,user_ns,user_global_ns,debug,
1070 shell_class=MatplotlibMTShell)
1084 shell_class=MatplotlibMTShell)
1071 _load_pylab(self.IP.user_ns)
1085 _load_pylab(self.IP.user_ns)
1072
1086
1073 #-----------------------------------------------------------------------------
1087 #-----------------------------------------------------------------------------
1074 # Factory functions to actually start the proper thread-aware shell
1088 # Factory functions to actually start the proper thread-aware shell
1075
1089
1076 def _matplotlib_shell_class():
1090 def _matplotlib_shell_class():
1077 """Factory function to handle shell class selection for matplotlib.
1091 """Factory function to handle shell class selection for matplotlib.
1078
1092
1079 The proper shell class to use depends on the matplotlib backend, since
1093 The proper shell class to use depends on the matplotlib backend, since
1080 each backend requires a different threading strategy."""
1094 each backend requires a different threading strategy."""
1081
1095
1082 try:
1096 try:
1083 import matplotlib
1097 import matplotlib
1084 except ImportError:
1098 except ImportError:
1085 error('matplotlib could NOT be imported! Starting normal IPython.')
1099 error('matplotlib could NOT be imported! Starting normal IPython.')
1086 sh_class = IPShell
1100 sh_class = IPShell
1087 else:
1101 else:
1088 backend = matplotlib.rcParams['backend']
1102 backend = matplotlib.rcParams['backend']
1089 if backend.startswith('GTK'):
1103 if backend.startswith('GTK'):
1090 sh_class = IPShellMatplotlibGTK
1104 sh_class = IPShellMatplotlibGTK
1091 elif backend.startswith('WX'):
1105 elif backend.startswith('WX'):
1092 sh_class = IPShellMatplotlibWX
1106 sh_class = IPShellMatplotlibWX
1093 elif backend.startswith('Qt4'):
1107 elif backend.startswith('Qt4'):
1094 sh_class = IPShellMatplotlibQt4
1108 sh_class = IPShellMatplotlibQt4
1095 elif backend.startswith('Qt'):
1109 elif backend.startswith('Qt'):
1096 sh_class = IPShellMatplotlibQt
1110 sh_class = IPShellMatplotlibQt
1097 else:
1111 else:
1098 sh_class = IPShellMatplotlib
1112 sh_class = IPShellMatplotlib
1099 #print 'Using %s with the %s backend.' % (sh_class,backend) # dbg
1113 #print 'Using %s with the %s backend.' % (sh_class,backend) # dbg
1100 return sh_class
1114 return sh_class
1101
1115
1102 # This is the one which should be called by external code.
1116 # This is the one which should be called by external code.
1103 def start(user_ns = None):
1117 def start(user_ns = None):
1104 """Return a running shell instance, dealing with threading options.
1118 """Return a running shell instance, dealing with threading options.
1105
1119
1106 This is a factory function which will instantiate the proper IPython shell
1120 This is a factory function which will instantiate the proper IPython shell
1107 based on the user's threading choice. Such a selector is needed because
1121 based on the user's threading choice. Such a selector is needed because
1108 different GUI toolkits require different thread handling details."""
1122 different GUI toolkits require different thread handling details."""
1109
1123
1110 global USE_TK
1124 global USE_TK
1111 # Crude sys.argv hack to extract the threading options.
1125 # Crude sys.argv hack to extract the threading options.
1112 argv = sys.argv
1126 argv = sys.argv
1113 if len(argv) > 1:
1127 if len(argv) > 1:
1114 if len(argv) > 2:
1128 if len(argv) > 2:
1115 arg2 = argv[2]
1129 arg2 = argv[2]
1116 if arg2.endswith('-tk'):
1130 if arg2.endswith('-tk'):
1117 USE_TK = True
1131 USE_TK = True
1118 arg1 = argv[1]
1132 arg1 = argv[1]
1119 if arg1.endswith('-gthread'):
1133 if arg1.endswith('-gthread'):
1120 shell = IPShellGTK
1134 shell = IPShellGTK
1121 elif arg1.endswith( '-qthread' ):
1135 elif arg1.endswith( '-qthread' ):
1122 shell = IPShellQt
1136 shell = IPShellQt
1123 elif arg1.endswith( '-q4thread' ):
1137 elif arg1.endswith( '-q4thread' ):
1124 shell = IPShellQt4
1138 shell = IPShellQt4
1125 elif arg1.endswith('-wthread'):
1139 elif arg1.endswith('-wthread'):
1126 shell = IPShellWX
1140 shell = IPShellWX
1127 elif arg1.endswith('-pylab'):
1141 elif arg1.endswith('-pylab'):
1128 shell = _matplotlib_shell_class()
1142 shell = _matplotlib_shell_class()
1129 else:
1143 else:
1130 shell = IPShell
1144 shell = IPShell
1131 else:
1145 else:
1132 shell = IPShell
1146 shell = IPShell
1133 return shell(user_ns = user_ns)
1147 return shell(user_ns = user_ns)
1134
1148
1135 # Some aliases for backwards compatibility
1149 # Some aliases for backwards compatibility
1136 IPythonShell = IPShell
1150 IPythonShell = IPShell
1137 IPythonShellEmbed = IPShellEmbed
1151 IPythonShellEmbed = IPShellEmbed
1138 #************************ End of file <Shell.py> ***************************
1152 #************************ End of file <Shell.py> ***************************
General Comments 0
You need to be logged in to leave comments. Login now