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