##// END OF EJS Templates
Revert Shell.py changes, they don't work.
fperez -
r21:90110a9c
parent child
Show More
@@ -1,861 +1,881
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 874 2005-09-20 20:13:04Z fperez $"""
7 $Id: Shell.py 882 2005-09-20 23:17:41Z fperez $"""
8
8
9 #*****************************************************************************
9 #*****************************************************************************
10 # Copyright (C) 2001-2004 Fernando Perez <fperez@colorado.edu>
10 # Copyright (C) 2001-2004 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 import __main__
21 import __main__
22 import __builtin__
22 import __builtin__
23 import sys
23 import sys
24 import os
24 import os
25 import code
25 import code
26 import threading
26 import threading
27 import signal
27 import signal
28
28
29 import IPython
29 import IPython
30 from IPython.iplib import InteractiveShell
30 from IPython.iplib import InteractiveShell
31 from IPython.ipmaker import make_IPython
31 from IPython.ipmaker import make_IPython
32 from IPython.genutils import Term,warn,error,flag_calls
32 from IPython.genutils import Term,warn,error,flag_calls
33 from IPython.Struct import Struct
33 from IPython.Struct import Struct
34 from IPython.Magic import Magic
34 from IPython.Magic import Magic
35 from IPython import ultraTB
35 from IPython import ultraTB
36
36
37 # global flag to pass around information about Ctrl-C without exceptions
38 KBINT = False
39
37 # global flag to turn on/off Tk support.
40 # global flag to turn on/off Tk support.
38 USE_TK = False
41 USE_TK = False
39
42
40 #-----------------------------------------------------------------------------
43 #-----------------------------------------------------------------------------
41 # This class is trivial now, but I want to have it in to publish a clean
44 # This class is trivial now, but I want to have it in to publish a clean
42 # interface. Later when the internals are reorganized, code that uses this
45 # interface. Later when the internals are reorganized, code that uses this
43 # shouldn't have to change.
46 # shouldn't have to change.
44
47
45 class IPShell:
48 class IPShell:
46 """Create an IPython instance."""
49 """Create an IPython instance."""
47
50
48 def __init__(self,argv=None,user_ns=None,debug=1,
51 def __init__(self,argv=None,user_ns=None,debug=1,
49 shell_class=InteractiveShell):
52 shell_class=InteractiveShell):
50 self.IP = make_IPython(argv,user_ns=user_ns,debug=debug,
53 self.IP = make_IPython(argv,user_ns=user_ns,debug=debug,
51 shell_class=shell_class)
54 shell_class=shell_class)
52
55
53 def mainloop(self,sys_exit=0,banner=None):
56 def mainloop(self,sys_exit=0,banner=None):
54 self.IP.mainloop(banner)
57 self.IP.mainloop(banner)
55 if sys_exit:
58 if sys_exit:
56 sys.exit()
59 sys.exit()
57
60
58 #-----------------------------------------------------------------------------
61 #-----------------------------------------------------------------------------
59 class IPShellEmbed:
62 class IPShellEmbed:
60 """Allow embedding an IPython shell into a running program.
63 """Allow embedding an IPython shell into a running program.
61
64
62 Instances of this class are callable, with the __call__ method being an
65 Instances of this class are callable, with the __call__ method being an
63 alias to the embed() method of an InteractiveShell instance.
66 alias to the embed() method of an InteractiveShell instance.
64
67
65 Usage (see also the example-embed.py file for a running example):
68 Usage (see also the example-embed.py file for a running example):
66
69
67 ipshell = IPShellEmbed([argv,banner,exit_msg,rc_override])
70 ipshell = IPShellEmbed([argv,banner,exit_msg,rc_override])
68
71
69 - argv: list containing valid command-line options for IPython, as they
72 - argv: list containing valid command-line options for IPython, as they
70 would appear in sys.argv[1:].
73 would appear in sys.argv[1:].
71
74
72 For example, the following command-line options:
75 For example, the following command-line options:
73
76
74 $ ipython -prompt_in1 'Input <\\#>' -colors LightBG
77 $ ipython -prompt_in1 'Input <\\#>' -colors LightBG
75
78
76 would be passed in the argv list as:
79 would be passed in the argv list as:
77
80
78 ['-prompt_in1','Input <\\#>','-colors','LightBG']
81 ['-prompt_in1','Input <\\#>','-colors','LightBG']
79
82
80 - banner: string which gets printed every time the interpreter starts.
83 - banner: string which gets printed every time the interpreter starts.
81
84
82 - exit_msg: string which gets printed every time the interpreter exits.
85 - exit_msg: string which gets printed every time the interpreter exits.
83
86
84 - rc_override: a dict or Struct of configuration options such as those
87 - rc_override: a dict or Struct of configuration options such as those
85 used by IPython. These options are read from your ~/.ipython/ipythonrc
88 used by IPython. These options are read from your ~/.ipython/ipythonrc
86 file when the Shell object is created. Passing an explicit rc_override
89 file when the Shell object is created. Passing an explicit rc_override
87 dict with any options you want allows you to override those values at
90 dict with any options you want allows you to override those values at
88 creation time without having to modify the file. This way you can create
91 creation time without having to modify the file. This way you can create
89 embeddable instances configured in any way you want without editing any
92 embeddable instances configured in any way you want without editing any
90 global files (thus keeping your interactive IPython configuration
93 global files (thus keeping your interactive IPython configuration
91 unchanged).
94 unchanged).
92
95
93 Then the ipshell instance can be called anywhere inside your code:
96 Then the ipshell instance can be called anywhere inside your code:
94
97
95 ipshell(header='') -> Opens up an IPython shell.
98 ipshell(header='') -> Opens up an IPython shell.
96
99
97 - header: string printed by the IPython shell upon startup. This can let
100 - header: string printed by the IPython shell upon startup. This can let
98 you know where in your code you are when dropping into the shell. Note
101 you know where in your code you are when dropping into the shell. Note
99 that 'banner' gets prepended to all calls, so header is used for
102 that 'banner' gets prepended to all calls, so header is used for
100 location-specific information.
103 location-specific information.
101
104
102 For more details, see the __call__ method below.
105 For more details, see the __call__ method below.
103
106
104 When the IPython shell is exited with Ctrl-D, normal program execution
107 When the IPython shell is exited with Ctrl-D, normal program execution
105 resumes.
108 resumes.
106
109
107 This functionality was inspired by a posting on comp.lang.python by cmkl
110 This functionality was inspired by a posting on comp.lang.python by cmkl
108 <cmkleffner@gmx.de> on Dec. 06/01 concerning similar uses of pyrepl, and
111 <cmkleffner@gmx.de> on Dec. 06/01 concerning similar uses of pyrepl, and
109 by the IDL stop/continue commands."""
112 by the IDL stop/continue commands."""
110
113
111 def __init__(self,argv=None,banner='',exit_msg=None,rc_override=None):
114 def __init__(self,argv=None,banner='',exit_msg=None,rc_override=None):
112 """Note that argv here is a string, NOT a list."""
115 """Note that argv here is a string, NOT a list."""
113 self.set_banner(banner)
116 self.set_banner(banner)
114 self.set_exit_msg(exit_msg)
117 self.set_exit_msg(exit_msg)
115 self.set_dummy_mode(0)
118 self.set_dummy_mode(0)
116
119
117 # sys.displayhook is a global, we need to save the user's original
120 # sys.displayhook is a global, we need to save the user's original
118 # Don't rely on __displayhook__, as the user may have changed that.
121 # Don't rely on __displayhook__, as the user may have changed that.
119 self.sys_displayhook_ori = sys.displayhook
122 self.sys_displayhook_ori = sys.displayhook
120
123
121 # save readline completer status
124 # save readline completer status
122 try:
125 try:
123 #print 'Save completer',sys.ipcompleter # dbg
126 #print 'Save completer',sys.ipcompleter # dbg
124 self.sys_ipcompleter_ori = sys.ipcompleter
127 self.sys_ipcompleter_ori = sys.ipcompleter
125 except:
128 except:
126 pass # not nested with IPython
129 pass # not nested with IPython
127
130
128 # FIXME. Passing user_ns breaks namespace handling.
131 # FIXME. Passing user_ns breaks namespace handling.
129 #self.IP = make_IPython(argv,user_ns=__main__.__dict__)
132 #self.IP = make_IPython(argv,user_ns=__main__.__dict__)
130 self.IP = make_IPython(argv,rc_override=rc_override,embedded=True)
133 self.IP = make_IPython(argv,rc_override=rc_override,embedded=True)
131
134
132 self.IP.name_space_init()
135 self.IP.name_space_init()
133 # mark this as an embedded instance so we know if we get a crash
136 # mark this as an embedded instance so we know if we get a crash
134 # post-mortem
137 # post-mortem
135 self.IP.rc.embedded = 1
138 self.IP.rc.embedded = 1
136 # copy our own displayhook also
139 # copy our own displayhook also
137 self.sys_displayhook_embed = sys.displayhook
140 self.sys_displayhook_embed = sys.displayhook
138 # and leave the system's display hook clean
141 # and leave the system's display hook clean
139 sys.displayhook = self.sys_displayhook_ori
142 sys.displayhook = self.sys_displayhook_ori
140 # don't use the ipython crash handler so that user exceptions aren't
143 # don't use the ipython crash handler so that user exceptions aren't
141 # trapped
144 # trapped
142 sys.excepthook = ultraTB.FormattedTB(color_scheme = self.IP.rc.colors,
145 sys.excepthook = ultraTB.FormattedTB(color_scheme = self.IP.rc.colors,
143 mode = self.IP.rc.xmode,
146 mode = self.IP.rc.xmode,
144 call_pdb = self.IP.rc.pdb)
147 call_pdb = self.IP.rc.pdb)
145 self.restore_system_completer()
148 self.restore_system_completer()
146
149
147 def restore_system_completer(self):
150 def restore_system_completer(self):
148 """Restores the readline completer which was in place.
151 """Restores the readline completer which was in place.
149
152
150 This allows embedded IPython within IPython not to disrupt the
153 This allows embedded IPython within IPython not to disrupt the
151 parent's completion.
154 parent's completion.
152 """
155 """
153
156
154 try:
157 try:
155 self.IP.readline.set_completer(self.sys_ipcompleter_ori)
158 self.IP.readline.set_completer(self.sys_ipcompleter_ori)
156 sys.ipcompleter = self.sys_ipcompleter_ori
159 sys.ipcompleter = self.sys_ipcompleter_ori
157 except:
160 except:
158 pass
161 pass
159
162
160 def __call__(self,header='',local_ns=None,global_ns=None,dummy=None):
163 def __call__(self,header='',local_ns=None,global_ns=None,dummy=None):
161 """Activate the interactive interpreter.
164 """Activate the interactive interpreter.
162
165
163 __call__(self,header='',local_ns=None,global_ns,dummy=None) -> Start
166 __call__(self,header='',local_ns=None,global_ns,dummy=None) -> Start
164 the interpreter shell with the given local and global namespaces, and
167 the interpreter shell with the given local and global namespaces, and
165 optionally print a header string at startup.
168 optionally print a header string at startup.
166
169
167 The shell can be globally activated/deactivated using the
170 The shell can be globally activated/deactivated using the
168 set/get_dummy_mode methods. This allows you to turn off a shell used
171 set/get_dummy_mode methods. This allows you to turn off a shell used
169 for debugging globally.
172 for debugging globally.
170
173
171 However, *each* time you call the shell you can override the current
174 However, *each* time you call the shell you can override the current
172 state of dummy_mode with the optional keyword parameter 'dummy'. For
175 state of dummy_mode with the optional keyword parameter 'dummy'. For
173 example, if you set dummy mode on with IPShell.set_dummy_mode(1), you
176 example, if you set dummy mode on with IPShell.set_dummy_mode(1), you
174 can still have a specific call work by making it as IPShell(dummy=0).
177 can still have a specific call work by making it as IPShell(dummy=0).
175
178
176 The optional keyword parameter dummy controls whether the call
179 The optional keyword parameter dummy controls whether the call
177 actually does anything. """
180 actually does anything. """
178
181
179 # Allow the dummy parameter to override the global __dummy_mode
182 # Allow the dummy parameter to override the global __dummy_mode
180 if dummy or (dummy != 0 and self.__dummy_mode):
183 if dummy or (dummy != 0 and self.__dummy_mode):
181 return
184 return
182
185
183 # Set global subsystems (display,completions) to our values
186 # Set global subsystems (display,completions) to our values
184 sys.displayhook = self.sys_displayhook_embed
187 sys.displayhook = self.sys_displayhook_embed
185 if self.IP.has_readline:
188 if self.IP.has_readline:
186 self.IP.readline.set_completer(self.IP.Completer.complete)
189 self.IP.readline.set_completer(self.IP.Completer.complete)
187
190
188 if self.banner and header:
191 if self.banner and header:
189 format = '%s\n%s\n'
192 format = '%s\n%s\n'
190 else:
193 else:
191 format = '%s%s\n'
194 format = '%s%s\n'
192 banner = format % (self.banner,header)
195 banner = format % (self.banner,header)
193
196
194 # Call the embedding code with a stack depth of 1 so it can skip over
197 # Call the embedding code with a stack depth of 1 so it can skip over
195 # our call and get the original caller's namespaces.
198 # our call and get the original caller's namespaces.
196 self.IP.embed_mainloop(banner,local_ns,global_ns,stack_depth=1)
199 self.IP.embed_mainloop(banner,local_ns,global_ns,stack_depth=1)
197
200
198 if self.exit_msg:
201 if self.exit_msg:
199 print self.exit_msg
202 print self.exit_msg
200
203
201 # Restore global systems (display, completion)
204 # Restore global systems (display, completion)
202 sys.displayhook = self.sys_displayhook_ori
205 sys.displayhook = self.sys_displayhook_ori
203 self.restore_system_completer()
206 self.restore_system_completer()
204
207
205 def set_dummy_mode(self,dummy):
208 def set_dummy_mode(self,dummy):
206 """Sets the embeddable shell's dummy mode parameter.
209 """Sets the embeddable shell's dummy mode parameter.
207
210
208 set_dummy_mode(dummy): dummy = 0 or 1.
211 set_dummy_mode(dummy): dummy = 0 or 1.
209
212
210 This parameter is persistent and makes calls to the embeddable shell
213 This parameter is persistent and makes calls to the embeddable shell
211 silently return without performing any action. This allows you to
214 silently return without performing any action. This allows you to
212 globally activate or deactivate a shell you're using with a single call.
215 globally activate or deactivate a shell you're using with a single call.
213
216
214 If you need to manually"""
217 If you need to manually"""
215
218
216 if dummy not in [0,1]:
219 if dummy not in [0,1]:
217 raise ValueError,'dummy parameter must be 0 or 1'
220 raise ValueError,'dummy parameter must be 0 or 1'
218 self.__dummy_mode = dummy
221 self.__dummy_mode = dummy
219
222
220 def get_dummy_mode(self):
223 def get_dummy_mode(self):
221 """Return the current value of the dummy mode parameter.
224 """Return the current value of the dummy mode parameter.
222 """
225 """
223 return self.__dummy_mode
226 return self.__dummy_mode
224
227
225 def set_banner(self,banner):
228 def set_banner(self,banner):
226 """Sets the global banner.
229 """Sets the global banner.
227
230
228 This banner gets prepended to every header printed when the shell
231 This banner gets prepended to every header printed when the shell
229 instance is called."""
232 instance is called."""
230
233
231 self.banner = banner
234 self.banner = banner
232
235
233 def set_exit_msg(self,exit_msg):
236 def set_exit_msg(self,exit_msg):
234 """Sets the global exit_msg.
237 """Sets the global exit_msg.
235
238
236 This exit message gets printed upon exiting every time the embedded
239 This exit message gets printed upon exiting every time the embedded
237 shell is called. It is None by default. """
240 shell is called. It is None by default. """
238
241
239 self.exit_msg = exit_msg
242 self.exit_msg = exit_msg
240
243
241 #-----------------------------------------------------------------------------
244 #-----------------------------------------------------------------------------
242 def sigint_handler (signum,stack_frame):
245 def sigint_handler (signum,stack_frame):
243 """Sigint handler for threaded apps.
246 """Sigint handler for threaded apps.
244 """
247
245 raise KeyboardInterrupt
248 This is a horrible hack to pass information about SIGINT _without_ using
249 exceptions, since I haven't been able to properly manage cross-thread
250 exceptions in GTK/WX. In fact, I don't think it can be done (or at least
251 that's my understanding from a c.l.py thread where this was discussed)."""
252
253 global KBINT
254
255 print '\nKeyboardInterrupt - Press <Enter> to continue.',
256 Term.cout.flush()
257 # Set global flag so that runsource can know that Ctrl-C was hit
258 KBINT = True
246
259
247 class MTInteractiveShell(InteractiveShell):
260 class MTInteractiveShell(InteractiveShell):
248 """Simple multi-threaded shell."""
261 """Simple multi-threaded shell."""
249
262
250 # Threading strategy taken from:
263 # Threading strategy taken from:
251 # http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/65109, by Brian
264 # http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/65109, by Brian
252 # McErlean and John Finlay. Modified with corrections by Antoon Pardon,
265 # McErlean and John Finlay. Modified with corrections by Antoon Pardon,
253 # from the pygtk mailing list, to avoid lockups with system calls.
266 # from the pygtk mailing list, to avoid lockups with system calls.
254
267
255 def __init__(self,name,usage=None,rc=Struct(opts=None,args=None),
268 def __init__(self,name,usage=None,rc=Struct(opts=None,args=None),
256 user_ns = None, banner2='',**kw):
269 user_ns = None, banner2='',**kw):
257 """Similar to the normal InteractiveShell, but with threading control"""
270 """Similar to the normal InteractiveShell, but with threading control"""
258
271
259 IPython.iplib.InteractiveShell.__init__(self,name,usage,rc,user_ns,banner2)
272 IPython.iplib.InteractiveShell.__init__(self,name,usage,rc,user_ns,banner2)
260
273
261 # Locking control variable
274 # Locking control variable
262 self.thread_ready = threading.Condition()
275 self.thread_ready = threading.Condition()
263
276
264 # Stuff to do at closing time
277 # Stuff to do at closing time
265 self._kill = False
278 self._kill = False
266 on_kill = kw.get('on_kill')
279 on_kill = kw.get('on_kill')
267 if on_kill is None:
280 if on_kill is None:
268 on_kill = []
281 on_kill = []
269 # Check that all things to kill are callable:
282 # Check that all things to kill are callable:
270 for t in on_kill:
283 for t in on_kill:
271 if not callable(t):
284 if not callable(t):
272 raise TypeError,'on_kill must be a list of callables'
285 raise TypeError,'on_kill must be a list of callables'
273 self.on_kill = on_kill
286 self.on_kill = on_kill
274
287
275 def runsource(self, source, filename="<input>", symbol="single"):
288 def runsource(self, source, filename="<input>", symbol="single"):
276 """Compile and run some source in the interpreter.
289 """Compile and run some source in the interpreter.
277
290
278 Modified version of code.py's runsource(), to handle threading issues.
291 Modified version of code.py's runsource(), to handle threading issues.
279 See the original for full docstring details."""
292 See the original for full docstring details."""
293
294 global KBINT
295
296 # If Ctrl-C was typed, we reset the flag and return right away
297 if KBINT:
298 KBINT = False
299 return False
280
300
281 try:
301 try:
282 code = self.compile(source, filename, symbol)
302 code = self.compile(source, filename, symbol)
283 except (OverflowError, SyntaxError, ValueError):
303 except (OverflowError, SyntaxError, ValueError):
284 # Case 1
304 # Case 1
285 self.showsyntaxerror(filename)
305 self.showsyntaxerror(filename)
286 return False
306 return False
287
307
288 if code is None:
308 if code is None:
289 # Case 2
309 # Case 2
290 return True
310 return True
291
311
292 # Case 3
312 # Case 3
293 # Store code in self, so the execution thread can handle it
313 # Store code in self, so the execution thread can handle it
294 self.thread_ready.acquire()
314 self.thread_ready.acquire()
295 self.code_to_run = code
315 self.code_to_run = code
296 self.thread_ready.wait() # Wait until processed in timeout interval
316 self.thread_ready.wait() # Wait until processed in timeout interval
297 self.thread_ready.release()
317 self.thread_ready.release()
298
318
299 return False
319 return False
300
320
301 def runcode(self):
321 def runcode(self):
302 """Execute a code object.
322 """Execute a code object.
303
323
304 Multithreaded wrapper around IPython's runcode()."""
324 Multithreaded wrapper around IPython's runcode()."""
305
325
306 # lock thread-protected stuff
326 # lock thread-protected stuff
307 self.thread_ready.acquire()
327 self.thread_ready.acquire()
308
328
309 # Install sigint handler
329 # Install sigint handler
310 try:
330 try:
311 signal.signal(signal.SIGINT, sigint_handler)
331 signal.signal(signal.SIGINT, sigint_handler)
312 except SystemError:
332 except SystemError:
313 # This happens under Windows, which seems to have all sorts
333 # This happens under Windows, which seems to have all sorts
314 # of problems with signal handling. Oh well...
334 # of problems with signal handling. Oh well...
315 pass
335 pass
316
336
317 if self._kill:
337 if self._kill:
318 print >>Term.cout, 'Closing threads...',
338 print >>Term.cout, 'Closing threads...',
319 Term.cout.flush()
339 Term.cout.flush()
320 for tokill in self.on_kill:
340 for tokill in self.on_kill:
321 tokill()
341 tokill()
322 print >>Term.cout, 'Done.'
342 print >>Term.cout, 'Done.'
323
343
324 # Run pending code by calling parent class
344 # Run pending code by calling parent class
325 if self.code_to_run is not None:
345 if self.code_to_run is not None:
326 self.thread_ready.notify()
346 self.thread_ready.notify()
327 InteractiveShell.runcode(self,self.code_to_run)
347 InteractiveShell.runcode(self,self.code_to_run)
328
348
329 # We're done with thread-protected variables
349 # We're done with thread-protected variables
330 self.thread_ready.release()
350 self.thread_ready.release()
331 # This MUST return true for gtk threading to work
351 # This MUST return true for gtk threading to work
332 return True
352 return True
333
353
334 def kill (self):
354 def kill (self):
335 """Kill the thread, returning when it has been shut down."""
355 """Kill the thread, returning when it has been shut down."""
336 self.thread_ready.acquire()
356 self.thread_ready.acquire()
337 self._kill = True
357 self._kill = True
338 self.thread_ready.release()
358 self.thread_ready.release()
339
359
340 class MatplotlibShellBase:
360 class MatplotlibShellBase:
341 """Mixin class to provide the necessary modifications to regular IPython
361 """Mixin class to provide the necessary modifications to regular IPython
342 shell classes for matplotlib support.
362 shell classes for matplotlib support.
343
363
344 Given Python's MRO, this should be used as the FIRST class in the
364 Given Python's MRO, this should be used as the FIRST class in the
345 inheritance hierarchy, so that it overrides the relevant methods."""
365 inheritance hierarchy, so that it overrides the relevant methods."""
346
366
347 def _matplotlib_config(self,name):
367 def _matplotlib_config(self,name):
348 """Return various items needed to setup the user's shell with matplotlib"""
368 """Return various items needed to setup the user's shell with matplotlib"""
349
369
350 # Initialize matplotlib to interactive mode always
370 # Initialize matplotlib to interactive mode always
351 import matplotlib
371 import matplotlib
352 from matplotlib import backends
372 from matplotlib import backends
353 matplotlib.interactive(True)
373 matplotlib.interactive(True)
354
374
355 def use(arg):
375 def use(arg):
356 """IPython wrapper for matplotlib's backend switcher.
376 """IPython wrapper for matplotlib's backend switcher.
357
377
358 In interactive use, we can not allow switching to a different
378 In interactive use, we can not allow switching to a different
359 interactive backend, since thread conflicts will most likely crash
379 interactive backend, since thread conflicts will most likely crash
360 the python interpreter. This routine does a safety check first,
380 the python interpreter. This routine does a safety check first,
361 and refuses to perform a dangerous switch. It still allows
381 and refuses to perform a dangerous switch. It still allows
362 switching to non-interactive backends."""
382 switching to non-interactive backends."""
363
383
364 if arg in backends.interactive_bk and arg != self.mpl_backend:
384 if arg in backends.interactive_bk and arg != self.mpl_backend:
365 m=('invalid matplotlib backend switch.\n'
385 m=('invalid matplotlib backend switch.\n'
366 'This script attempted to switch to the interactive '
386 'This script attempted to switch to the interactive '
367 'backend: `%s`\n'
387 'backend: `%s`\n'
368 'Your current choice of interactive backend is: `%s`\n\n'
388 'Your current choice of interactive backend is: `%s`\n\n'
369 'Switching interactive matplotlib backends at runtime\n'
389 'Switching interactive matplotlib backends at runtime\n'
370 'would crash the python interpreter, '
390 'would crash the python interpreter, '
371 'and IPython has blocked it.\n\n'
391 'and IPython has blocked it.\n\n'
372 'You need to either change your choice of matplotlib backend\n'
392 'You need to either change your choice of matplotlib backend\n'
373 'by editing your .matplotlibrc file, or run this script as a \n'
393 'by editing your .matplotlibrc file, or run this script as a \n'
374 'standalone file from the command line, not using IPython.\n' %
394 'standalone file from the command line, not using IPython.\n' %
375 (arg,self.mpl_backend) )
395 (arg,self.mpl_backend) )
376 raise RuntimeError, m
396 raise RuntimeError, m
377 else:
397 else:
378 self.mpl_use(arg)
398 self.mpl_use(arg)
379 self.mpl_use._called = True
399 self.mpl_use._called = True
380
400
381 self.matplotlib = matplotlib
401 self.matplotlib = matplotlib
382 self.mpl_backend = matplotlib.rcParams['backend']
402 self.mpl_backend = matplotlib.rcParams['backend']
383
403
384 # we also need to block switching of interactive backends by use()
404 # we also need to block switching of interactive backends by use()
385 self.mpl_use = matplotlib.use
405 self.mpl_use = matplotlib.use
386 self.mpl_use._called = False
406 self.mpl_use._called = False
387 # overwrite the original matplotlib.use with our wrapper
407 # overwrite the original matplotlib.use with our wrapper
388 matplotlib.use = use
408 matplotlib.use = use
389
409
390
410
391 # This must be imported last in the matplotlib series, after
411 # This must be imported last in the matplotlib series, after
392 # backend/interactivity choices have been made
412 # backend/interactivity choices have been made
393 try:
413 try:
394 import matplotlib.pylab as pylab
414 import matplotlib.pylab as pylab
395 self.pylab = pylab
415 self.pylab = pylab
396 self.pylab_name = 'pylab'
416 self.pylab_name = 'pylab'
397 except ImportError:
417 except ImportError:
398 import matplotlib.matlab as matlab
418 import matplotlib.matlab as matlab
399 self.pylab = matlab
419 self.pylab = matlab
400 self.pylab_name = 'matlab'
420 self.pylab_name = 'matlab'
401
421
402 self.pylab.show._needmain = False
422 self.pylab.show._needmain = False
403 # We need to detect at runtime whether show() is called by the user.
423 # We need to detect at runtime whether show() is called by the user.
404 # For this, we wrap it into a decorator which adds a 'called' flag.
424 # For this, we wrap it into a decorator which adds a 'called' flag.
405 self.pylab.draw_if_interactive = flag_calls(self.pylab.draw_if_interactive)
425 self.pylab.draw_if_interactive = flag_calls(self.pylab.draw_if_interactive)
406
426
407 # Build a user namespace initialized with matplotlib/matlab features.
427 # Build a user namespace initialized with matplotlib/matlab features.
408 user_ns = {'__name__':'__main__',
428 user_ns = {'__name__':'__main__',
409 '__builtins__' : __builtin__ }
429 '__builtins__' : __builtin__ }
410
430
411 # Be careful not to remove the final \n in the code string below, or
431 # Be careful not to remove the final \n in the code string below, or
412 # things will break badly with py22 (I think it's a python bug, 2.3 is
432 # things will break badly with py22 (I think it's a python bug, 2.3 is
413 # OK).
433 # OK).
414 pname = self.pylab_name # Python can't interpolate dotted var names
434 pname = self.pylab_name # Python can't interpolate dotted var names
415 exec ("import matplotlib\n"
435 exec ("import matplotlib\n"
416 "import matplotlib.%(pname)s as %(pname)s\n"
436 "import matplotlib.%(pname)s as %(pname)s\n"
417 "from matplotlib.%(pname)s import *\n" % locals()) in user_ns
437 "from matplotlib.%(pname)s import *\n" % locals()) in user_ns
418
438
419 # Build matplotlib info banner
439 # Build matplotlib info banner
420 b="""
440 b="""
421 Welcome to pylab, a matplotlib-based Python environment.
441 Welcome to pylab, a matplotlib-based Python environment.
422 For more information, type 'help(pylab)'.
442 For more information, type 'help(pylab)'.
423 """
443 """
424 return user_ns,b
444 return user_ns,b
425
445
426 def mplot_exec(self,fname,*where,**kw):
446 def mplot_exec(self,fname,*where,**kw):
427 """Execute a matplotlib script.
447 """Execute a matplotlib script.
428
448
429 This is a call to execfile(), but wrapped in safeties to properly
449 This is a call to execfile(), but wrapped in safeties to properly
430 handle interactive rendering and backend switching."""
450 handle interactive rendering and backend switching."""
431
451
432 #print '*** Matplotlib runner ***' # dbg
452 #print '*** Matplotlib runner ***' # dbg
433 # turn off rendering until end of script
453 # turn off rendering until end of script
434 isInteractive = self.matplotlib.rcParams['interactive']
454 isInteractive = self.matplotlib.rcParams['interactive']
435 self.matplotlib.interactive(False)
455 self.matplotlib.interactive(False)
436 self.safe_execfile(fname,*where,**kw)
456 self.safe_execfile(fname,*where,**kw)
437 self.matplotlib.interactive(isInteractive)
457 self.matplotlib.interactive(isInteractive)
438 # make rendering call now, if the user tried to do it
458 # make rendering call now, if the user tried to do it
439 if self.pylab.draw_if_interactive.called:
459 if self.pylab.draw_if_interactive.called:
440 self.pylab.draw()
460 self.pylab.draw()
441 self.pylab.draw_if_interactive.called = False
461 self.pylab.draw_if_interactive.called = False
442
462
443 # if a backend switch was performed, reverse it now
463 # if a backend switch was performed, reverse it now
444 if self.mpl_use._called:
464 if self.mpl_use._called:
445 self.matplotlib.rcParams['backend'] = self.mpl_backend
465 self.matplotlib.rcParams['backend'] = self.mpl_backend
446
466
447 def magic_run(self,parameter_s=''):
467 def magic_run(self,parameter_s=''):
448 Magic.magic_run(self,parameter_s,runner=self.mplot_exec)
468 Magic.magic_run(self,parameter_s,runner=self.mplot_exec)
449
469
450 # Fix the docstring so users see the original as well
470 # Fix the docstring so users see the original as well
451 magic_run.__doc__ = "%s\n%s" % (Magic.magic_run.__doc__,
471 magic_run.__doc__ = "%s\n%s" % (Magic.magic_run.__doc__,
452 "\n *** Modified %run for Matplotlib,"
472 "\n *** Modified %run for Matplotlib,"
453 " with proper interactive handling ***")
473 " with proper interactive handling ***")
454
474
455 # Now we provide 2 versions of a matplotlib-aware IPython base shells, single
475 # Now we provide 2 versions of a matplotlib-aware IPython base shells, single
456 # and multithreaded. Note that these are meant for internal use, the IPShell*
476 # and multithreaded. Note that these are meant for internal use, the IPShell*
457 # classes below are the ones meant for public consumption.
477 # classes below are the ones meant for public consumption.
458
478
459 class MatplotlibShell(MatplotlibShellBase,InteractiveShell):
479 class MatplotlibShell(MatplotlibShellBase,InteractiveShell):
460 """Single-threaded shell with matplotlib support."""
480 """Single-threaded shell with matplotlib support."""
461
481
462 def __init__(self,name,usage=None,rc=Struct(opts=None,args=None),
482 def __init__(self,name,usage=None,rc=Struct(opts=None,args=None),
463 user_ns = None, **kw):
483 user_ns = None, **kw):
464 user_ns,b2 = self._matplotlib_config(name)
484 user_ns,b2 = self._matplotlib_config(name)
465 InteractiveShell.__init__(self,name,usage,rc,user_ns,banner2=b2,**kw)
485 InteractiveShell.__init__(self,name,usage,rc,user_ns,banner2=b2,**kw)
466
486
467 class MatplotlibMTShell(MatplotlibShellBase,MTInteractiveShell):
487 class MatplotlibMTShell(MatplotlibShellBase,MTInteractiveShell):
468 """Multi-threaded shell with matplotlib support."""
488 """Multi-threaded shell with matplotlib support."""
469
489
470 def __init__(self,name,usage=None,rc=Struct(opts=None,args=None),
490 def __init__(self,name,usage=None,rc=Struct(opts=None,args=None),
471 user_ns = None, **kw):
491 user_ns = None, **kw):
472 user_ns,b2 = self._matplotlib_config(name)
492 user_ns,b2 = self._matplotlib_config(name)
473 MTInteractiveShell.__init__(self,name,usage,rc,user_ns,banner2=b2,**kw)
493 MTInteractiveShell.__init__(self,name,usage,rc,user_ns,banner2=b2,**kw)
474
494
475 #-----------------------------------------------------------------------------
495 #-----------------------------------------------------------------------------
476 # Utility functions for the different GUI enabled IPShell* classes.
496 # Utility functions for the different GUI enabled IPShell* classes.
477
497
478 def get_tk():
498 def get_tk():
479 """Tries to import Tkinter and returns a withdrawn Tkinter root
499 """Tries to import Tkinter and returns a withdrawn Tkinter root
480 window. If Tkinter is already imported or not available, this
500 window. If Tkinter is already imported or not available, this
481 returns None. This function calls `hijack_tk` underneath.
501 returns None. This function calls `hijack_tk` underneath.
482 """
502 """
483 if not USE_TK or sys.modules.has_key('Tkinter'):
503 if not USE_TK or sys.modules.has_key('Tkinter'):
484 return None
504 return None
485 else:
505 else:
486 try:
506 try:
487 import Tkinter
507 import Tkinter
488 except ImportError:
508 except ImportError:
489 return None
509 return None
490 else:
510 else:
491 hijack_tk()
511 hijack_tk()
492 r = Tkinter.Tk()
512 r = Tkinter.Tk()
493 r.withdraw()
513 r.withdraw()
494 return r
514 return r
495
515
496 def hijack_tk():
516 def hijack_tk():
497 """Modifies Tkinter's mainloop with a dummy so when a module calls
517 """Modifies Tkinter's mainloop with a dummy so when a module calls
498 mainloop, it does not block.
518 mainloop, it does not block.
499
519
500 """
520 """
501 def misc_mainloop(self, n=0):
521 def misc_mainloop(self, n=0):
502 pass
522 pass
503 def tkinter_mainloop(n=0):
523 def tkinter_mainloop(n=0):
504 pass
524 pass
505
525
506 import Tkinter
526 import Tkinter
507 Tkinter.Misc.mainloop = misc_mainloop
527 Tkinter.Misc.mainloop = misc_mainloop
508 Tkinter.mainloop = tkinter_mainloop
528 Tkinter.mainloop = tkinter_mainloop
509
529
510 def update_tk(tk):
530 def update_tk(tk):
511 """Updates the Tkinter event loop. This is typically called from
531 """Updates the Tkinter event loop. This is typically called from
512 the respective WX or GTK mainloops.
532 the respective WX or GTK mainloops.
513 """
533 """
514 if tk:
534 if tk:
515 tk.update()
535 tk.update()
516
536
517 def hijack_wx():
537 def hijack_wx():
518 """Modifies wxPython's MainLoop with a dummy so user code does not
538 """Modifies wxPython's MainLoop with a dummy so user code does not
519 block IPython. The hijacked mainloop function is returned.
539 block IPython. The hijacked mainloop function is returned.
520 """
540 """
521 def dummy_mainloop(*args, **kw):
541 def dummy_mainloop(*args, **kw):
522 pass
542 pass
523 import wxPython
543 import wxPython
524 ver = wxPython.__version__
544 ver = wxPython.__version__
525 orig_mainloop = None
545 orig_mainloop = None
526 if ver[:3] >= '2.5':
546 if ver[:3] >= '2.5':
527 import wx
547 import wx
528 if hasattr(wx, '_core_'): core = getattr(wx, '_core_')
548 if hasattr(wx, '_core_'): core = getattr(wx, '_core_')
529 elif hasattr(wx, '_core'): core = getattr(wx, '_core')
549 elif hasattr(wx, '_core'): core = getattr(wx, '_core')
530 else: raise AttributeError('Could not find wx core module')
550 else: raise AttributeError('Could not find wx core module')
531 orig_mainloop = core.PyApp_MainLoop
551 orig_mainloop = core.PyApp_MainLoop
532 core.PyApp_MainLoop = dummy_mainloop
552 core.PyApp_MainLoop = dummy_mainloop
533 elif ver[:3] == '2.4':
553 elif ver[:3] == '2.4':
534 orig_mainloop = wxPython.wxc.wxPyApp_MainLoop
554 orig_mainloop = wxPython.wxc.wxPyApp_MainLoop
535 wxPython.wxc.wxPyApp_MainLoop = dummy_mainloop
555 wxPython.wxc.wxPyApp_MainLoop = dummy_mainloop
536 else:
556 else:
537 warn("Unable to find either wxPython version 2.4 or >= 2.5.")
557 warn("Unable to find either wxPython version 2.4 or >= 2.5.")
538 return orig_mainloop
558 return orig_mainloop
539
559
540 def hijack_gtk():
560 def hijack_gtk():
541 """Modifies pyGTK's mainloop with a dummy so user code does not
561 """Modifies pyGTK's mainloop with a dummy so user code does not
542 block IPython. This function returns the original `gtk.mainloop`
562 block IPython. This function returns the original `gtk.mainloop`
543 function that has been hijacked.
563 function that has been hijacked.
544 """
564 """
545 def dummy_mainloop(*args, **kw):
565 def dummy_mainloop(*args, **kw):
546 pass
566 pass
547 import gtk
567 import gtk
548 if gtk.pygtk_version >= (2,4,0): orig_mainloop = gtk.main
568 if gtk.pygtk_version >= (2,4,0): orig_mainloop = gtk.main
549 else: orig_mainloop = gtk.mainloop
569 else: orig_mainloop = gtk.mainloop
550 gtk.mainloop = dummy_mainloop
570 gtk.mainloop = dummy_mainloop
551 gtk.main = dummy_mainloop
571 gtk.main = dummy_mainloop
552 return orig_mainloop
572 return orig_mainloop
553
573
554 #-----------------------------------------------------------------------------
574 #-----------------------------------------------------------------------------
555 # The IPShell* classes below are the ones meant to be run by external code as
575 # The IPShell* classes below are the ones meant to be run by external code as
556 # IPython instances. Note that unless a specific threading strategy is
576 # IPython instances. Note that unless a specific threading strategy is
557 # desired, the factory function start() below should be used instead (it
577 # desired, the factory function start() below should be used instead (it
558 # selects the proper threaded class).
578 # selects the proper threaded class).
559
579
560 class IPShellGTK(threading.Thread):
580 class IPShellGTK(threading.Thread):
561 """Run a gtk mainloop() in a separate thread.
581 """Run a gtk mainloop() in a separate thread.
562
582
563 Python commands can be passed to the thread where they will be executed.
583 Python commands can be passed to the thread where they will be executed.
564 This is implemented by periodically checking for passed code using a
584 This is implemented by periodically checking for passed code using a
565 GTK timeout callback."""
585 GTK timeout callback."""
566
586
567 TIMEOUT = 100 # Millisecond interval between timeouts.
587 TIMEOUT = 100 # Millisecond interval between timeouts.
568
588
569 def __init__(self,argv=None,user_ns=None,debug=1,
589 def __init__(self,argv=None,user_ns=None,debug=1,
570 shell_class=MTInteractiveShell):
590 shell_class=MTInteractiveShell):
571
591
572 import gtk
592 import gtk
573
593
574 self.gtk = gtk
594 self.gtk = gtk
575 self.gtk_mainloop = hijack_gtk()
595 self.gtk_mainloop = hijack_gtk()
576
596
577 # Allows us to use both Tk and GTK.
597 # Allows us to use both Tk and GTK.
578 self.tk = get_tk()
598 self.tk = get_tk()
579
599
580 if gtk.pygtk_version >= (2,4,0): mainquit = self.gtk.main_quit
600 if gtk.pygtk_version >= (2,4,0): mainquit = self.gtk.main_quit
581 else: mainquit = self.gtk.mainquit
601 else: mainquit = self.gtk.mainquit
582
602
583 self.IP = make_IPython(argv,user_ns=user_ns,debug=debug,
603 self.IP = make_IPython(argv,user_ns=user_ns,debug=debug,
584 shell_class=shell_class,
604 shell_class=shell_class,
585 on_kill=[mainquit])
605 on_kill=[mainquit])
586 threading.Thread.__init__(self)
606 threading.Thread.__init__(self)
587
607
588 def run(self):
608 def run(self):
589 self.IP.mainloop()
609 self.IP.mainloop()
590 self.IP.kill()
610 self.IP.kill()
591
611
592 def mainloop(self):
612 def mainloop(self):
593
613
594 if self.gtk.pygtk_version >= (2,4,0):
614 if self.gtk.pygtk_version >= (2,4,0):
595 import gobject
615 import gobject
596 gobject.timeout_add(self.TIMEOUT, self.on_timer)
616 gobject.timeout_add(self.TIMEOUT, self.on_timer)
597 else:
617 else:
598 self.gtk.timeout_add(self.TIMEOUT, self.on_timer)
618 self.gtk.timeout_add(self.TIMEOUT, self.on_timer)
599
619
600 if sys.platform != 'win32':
620 if sys.platform != 'win32':
601 try:
621 try:
602 if self.gtk.gtk_version[0] >= 2:
622 if self.gtk.gtk_version[0] >= 2:
603 self.gtk.threads_init()
623 self.gtk.threads_init()