##// END OF EJS Templates
Make the prefilterfrontend take an optional ipython0 instance as the...
Gael Varoquaux -
r1504:1d3334e3 merge
parent child Browse files
Show More
@@ -1,1236 +1,1236 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2 """IPython Shell classes.
2 """IPython Shell classes.
3
3
4 All the matplotlib support code was co-developed with John Hunter,
4 All the matplotlib support code was co-developed with John Hunter,
5 matplotlib's author.
5 matplotlib's author.
6
6
7 $Id: Shell.py 3024 2008-02-07 15:34:42Z darren.dale $"""
7 $Id: Shell.py 3024 2008-02-07 15:34:42Z darren.dale $"""
8
8
9 #*****************************************************************************
9 #*****************************************************************************
10 # Copyright (C) 2001-2006 Fernando Perez <fperez@colorado.edu>
10 # Copyright (C) 2001-2006 Fernando Perez <fperez@colorado.edu>
11 #
11 #
12 # Distributed under the terms of the BSD License. The full license is in
12 # Distributed under the terms of the BSD License. The full license is in
13 # the file COPYING, distributed as part of this software.
13 # the file COPYING, distributed as part of this software.
14 #*****************************************************************************
14 #*****************************************************************************
15
15
16 from IPython import Release
16 from IPython import Release
17 __author__ = '%s <%s>' % Release.authors['Fernando']
17 __author__ = '%s <%s>' % Release.authors['Fernando']
18 __license__ = Release.license
18 __license__ = Release.license
19
19
20 # Code begins
20 # Code begins
21 # Stdlib imports
21 # Stdlib imports
22 import __builtin__
22 import __builtin__
23 import __main__
23 import __main__
24 import Queue
24 import Queue
25 import inspect
25 import inspect
26 import os
26 import os
27 import sys
27 import sys
28 import thread
28 import thread
29 import threading
29 import threading
30 import time
30 import time
31
31
32 from signal import signal, SIGINT
32 from signal import signal, SIGINT
33
33
34 try:
34 try:
35 import ctypes
35 import ctypes
36 HAS_CTYPES = True
36 HAS_CTYPES = True
37 except ImportError:
37 except ImportError:
38 HAS_CTYPES = False
38 HAS_CTYPES = False
39
39
40 # IPython imports
40 # IPython imports
41 import IPython
41 import IPython
42 from IPython import ultraTB, ipapi
42 from IPython import ultraTB, ipapi
43 from IPython.genutils import Term,warn,error,flag_calls, ask_yes_no
43 from IPython.genutils import Term,warn,error,flag_calls, ask_yes_no
44 from IPython.iplib import InteractiveShell
44 from IPython.iplib import InteractiveShell
45 from IPython.ipmaker import make_IPython
45 from IPython.ipmaker import make_IPython
46 from IPython.Magic import Magic
46 from IPython.Magic import Magic
47 from IPython.ipstruct import Struct
47 from IPython.ipstruct import Struct
48
48
49 # Globals
49 # Globals
50 # global flag to pass around information about Ctrl-C without exceptions
50 # global flag to pass around information about Ctrl-C without exceptions
51 KBINT = False
51 KBINT = False
52
52
53 # global flag to turn on/off Tk support.
53 # global flag to turn on/off Tk support.
54 USE_TK = False
54 USE_TK = False
55
55
56 # ID for the main thread, used for cross-thread exceptions
56 # ID for the main thread, used for cross-thread exceptions
57 MAIN_THREAD_ID = thread.get_ident()
57 MAIN_THREAD_ID = thread.get_ident()
58
58
59 # Tag when runcode() is active, for exception handling
59 # Tag when runcode() is active, for exception handling
60 CODE_RUN = None
60 CODE_RUN = None
61
61
62 # Default timeout for waiting for multithreaded shells (in seconds)
62 # Default timeout for waiting for multithreaded shells (in seconds)
63 GUI_TIMEOUT = 10
63 GUI_TIMEOUT = 10
64
64
65 #-----------------------------------------------------------------------------
65 #-----------------------------------------------------------------------------
66 # This class is trivial now, but I want to have it in to publish a clean
66 # This class is trivial now, but I want to have it in to publish a clean
67 # interface. Later when the internals are reorganized, code that uses this
67 # interface. Later when the internals are reorganized, code that uses this
68 # shouldn't have to change.
68 # shouldn't have to change.
69
69
70 class IPShell:
70 class IPShell:
71 """Create an IPython instance."""
71 """Create an IPython instance."""
72
72
73 def __init__(self,argv=None,user_ns=None,user_global_ns=None,
73 def __init__(self,argv=None,user_ns=None,user_global_ns=None,
74 debug=1,shell_class=InteractiveShell):
74 debug=1,shell_class=InteractiveShell):
75 self.IP = make_IPython(argv,user_ns=user_ns,
75 self.IP = make_IPython(argv,user_ns=user_ns,
76 user_global_ns=user_global_ns,
76 user_global_ns=user_global_ns,
77 debug=debug,shell_class=shell_class)
77 debug=debug,shell_class=shell_class)
78
78
79 def mainloop(self,sys_exit=0,banner=None):
79 def mainloop(self,sys_exit=0,banner=None):
80 self.IP.mainloop(banner)
80 self.IP.mainloop(banner)
81 if sys_exit:
81 if sys_exit:
82 sys.exit()
82 sys.exit()
83
83
84 #-----------------------------------------------------------------------------
84 #-----------------------------------------------------------------------------
85 def kill_embedded(self,parameter_s=''):
85 def kill_embedded(self,parameter_s=''):
86 """%kill_embedded : deactivate for good the current embedded IPython.
86 """%kill_embedded : deactivate for good the current embedded IPython.
87
87
88 This function (after asking for confirmation) sets an internal flag so that
88 This function (after asking for confirmation) sets an internal flag so that
89 an embedded IPython will never activate again. This is useful to
89 an embedded IPython will never activate again. This is useful to
90 permanently disable a shell that is being called inside a loop: once you've
90 permanently disable a shell that is being called inside a loop: once you've
91 figured out what you needed from it, you may then kill it and the program
91 figured out what you needed from it, you may then kill it and the program
92 will then continue to run without the interactive shell interfering again.
92 will then continue to run without the interactive shell interfering again.
93 """
93 """
94
94
95 kill = ask_yes_no("Are you sure you want to kill this embedded instance "
95 kill = ask_yes_no("Are you sure you want to kill this embedded instance "
96 "(y/n)? [y/N] ",'n')
96 "(y/n)? [y/N] ",'n')
97 if kill:
97 if kill:
98 self.shell.embedded_active = False
98 self.shell.embedded_active = False
99 print "This embedded IPython will not reactivate anymore once you exit."
99 print "This embedded IPython will not reactivate anymore once you exit."
100
100
101 class IPShellEmbed:
101 class IPShellEmbed:
102 """Allow embedding an IPython shell into a running program.
102 """Allow embedding an IPython shell into a running program.
103
103
104 Instances of this class are callable, with the __call__ method being an
104 Instances of this class are callable, with the __call__ method being an
105 alias to the embed() method of an InteractiveShell instance.
105 alias to the embed() method of an InteractiveShell instance.
106
106
107 Usage (see also the example-embed.py file for a running example):
107 Usage (see also the example-embed.py file for a running example):
108
108
109 ipshell = IPShellEmbed([argv,banner,exit_msg,rc_override])
109 ipshell = IPShellEmbed([argv,banner,exit_msg,rc_override])
110
110
111 - argv: list containing valid command-line options for IPython, as they
111 - argv: list containing valid command-line options for IPython, as they
112 would appear in sys.argv[1:].
112 would appear in sys.argv[1:].
113
113
114 For example, the following command-line options:
114 For example, the following command-line options:
115
115
116 $ ipython -prompt_in1 'Input <\\#>' -colors LightBG
116 $ ipython -prompt_in1 'Input <\\#>' -colors LightBG
117
117
118 would be passed in the argv list as:
118 would be passed in the argv list as:
119
119
120 ['-prompt_in1','Input <\\#>','-colors','LightBG']
120 ['-prompt_in1','Input <\\#>','-colors','LightBG']
121
121
122 - banner: string which gets printed every time the interpreter starts.
122 - banner: string which gets printed every time the interpreter starts.
123
123
124 - exit_msg: string which gets printed every time the interpreter exits.
124 - exit_msg: string which gets printed every time the interpreter exits.
125
125
126 - rc_override: a dict or Struct of configuration options such as those
126 - rc_override: a dict or Struct of configuration options such as those
127 used by IPython. These options are read from your ~/.ipython/ipythonrc
127 used by IPython. These options are read from your ~/.ipython/ipythonrc
128 file when the Shell object is created. Passing an explicit rc_override
128 file when the Shell object is created. Passing an explicit rc_override
129 dict with any options you want allows you to override those values at
129 dict with any options you want allows you to override those values at
130 creation time without having to modify the file. This way you can create
130 creation time without having to modify the file. This way you can create
131 embeddable instances configured in any way you want without editing any
131 embeddable instances configured in any way you want without editing any
132 global files (thus keeping your interactive IPython configuration
132 global files (thus keeping your interactive IPython configuration
133 unchanged).
133 unchanged).
134
134
135 Then the ipshell instance can be called anywhere inside your code:
135 Then the ipshell instance can be called anywhere inside your code:
136
136
137 ipshell(header='') -> Opens up an IPython shell.
137 ipshell(header='') -> Opens up an IPython shell.
138
138
139 - header: string printed by the IPython shell upon startup. This can let
139 - header: string printed by the IPython shell upon startup. This can let
140 you know where in your code you are when dropping into the shell. Note
140 you know where in your code you are when dropping into the shell. Note
141 that 'banner' gets prepended to all calls, so header is used for
141 that 'banner' gets prepended to all calls, so header is used for
142 location-specific information.
142 location-specific information.
143
143
144 For more details, see the __call__ method below.
144 For more details, see the __call__ method below.
145
145
146 When the IPython shell is exited with Ctrl-D, normal program execution
146 When the IPython shell is exited with Ctrl-D, normal program execution
147 resumes.
147 resumes.
148
148
149 This functionality was inspired by a posting on comp.lang.python by cmkl
149 This functionality was inspired by a posting on comp.lang.python by cmkl
150 <cmkleffner@gmx.de> on Dec. 06/01 concerning similar uses of pyrepl, and
150 <cmkleffner@gmx.de> on Dec. 06/01 concerning similar uses of pyrepl, and
151 by the IDL stop/continue commands."""
151 by the IDL stop/continue commands."""
152
152
153 def __init__(self,argv=None,banner='',exit_msg=None,rc_override=None,
153 def __init__(self,argv=None,banner='',exit_msg=None,rc_override=None,
154 user_ns=None):
154 user_ns=None):
155 """Note that argv here is a string, NOT a list."""
155 """Note that argv here is a string, NOT a list."""
156 self.set_banner(banner)
156 self.set_banner(banner)
157 self.set_exit_msg(exit_msg)
157 self.set_exit_msg(exit_msg)
158 self.set_dummy_mode(0)
158 self.set_dummy_mode(0)
159
159
160 # sys.displayhook is a global, we need to save the user's original
160 # sys.displayhook is a global, we need to save the user's original
161 # Don't rely on __displayhook__, as the user may have changed that.
161 # Don't rely on __displayhook__, as the user may have changed that.
162 self.sys_displayhook_ori = sys.displayhook
162 self.sys_displayhook_ori = sys.displayhook
163
163
164 # save readline completer status
164 # save readline completer status
165 try:
165 try:
166 #print 'Save completer',sys.ipcompleter # dbg
166 #print 'Save completer',sys.ipcompleter # dbg
167 self.sys_ipcompleter_ori = sys.ipcompleter
167 self.sys_ipcompleter_ori = sys.ipcompleter
168 except:
168 except:
169 pass # not nested with IPython
169 pass # not nested with IPython
170
170
171 self.IP = make_IPython(argv,rc_override=rc_override,
171 self.IP = make_IPython(argv,rc_override=rc_override,
172 embedded=True,
172 embedded=True,
173 user_ns=user_ns)
173 user_ns=user_ns)
174
174
175 ip = ipapi.IPApi(self.IP)
175 ip = ipapi.IPApi(self.IP)
176 ip.expose_magic("kill_embedded",kill_embedded)
176 ip.expose_magic("kill_embedded",kill_embedded)
177
177
178 # copy our own displayhook also
178 # copy our own displayhook also
179 self.sys_displayhook_embed = sys.displayhook
179 self.sys_displayhook_embed = sys.displayhook
180 # and leave the system's display hook clean
180 # and leave the system's display hook clean
181 sys.displayhook = self.sys_displayhook_ori
181 sys.displayhook = self.sys_displayhook_ori
182 # don't use the ipython crash handler so that user exceptions aren't
182 # don't use the ipython crash handler so that user exceptions aren't
183 # trapped
183 # trapped
184 sys.excepthook = ultraTB.FormattedTB(color_scheme = self.IP.rc.colors,
184 sys.excepthook = ultraTB.FormattedTB(color_scheme = self.IP.rc.colors,
185 mode = self.IP.rc.xmode,
185 mode = self.IP.rc.xmode,
186 call_pdb = self.IP.rc.pdb)
186 call_pdb = self.IP.rc.pdb)
187 self.restore_system_completer()
187 self.restore_system_completer()
188
188
189 def restore_system_completer(self):
189 def restore_system_completer(self):
190 """Restores the readline completer which was in place.
190 """Restores the readline completer which was in place.
191
191
192 This allows embedded IPython within IPython not to disrupt the
192 This allows embedded IPython within IPython not to disrupt the
193 parent's completion.
193 parent's completion.
194 """
194 """
195
195
196 try:
196 try:
197 self.IP.readline.set_completer(self.sys_ipcompleter_ori)
197 self.IP.readline.set_completer(self.sys_ipcompleter_ori)
198 sys.ipcompleter = self.sys_ipcompleter_ori
198 sys.ipcompleter = self.sys_ipcompleter_ori
199 except:
199 except:
200 pass
200 pass
201
201
202 def __call__(self,header='',local_ns=None,global_ns=None,dummy=None):
202 def __call__(self,header='',local_ns=None,global_ns=None,dummy=None):
203 """Activate the interactive interpreter.
203 """Activate the interactive interpreter.
204
204
205 __call__(self,header='',local_ns=None,global_ns,dummy=None) -> Start
205 __call__(self,header='',local_ns=None,global_ns,dummy=None) -> Start
206 the interpreter shell with the given local and global namespaces, and
206 the interpreter shell with the given local and global namespaces, and
207 optionally print a header string at startup.
207 optionally print a header string at startup.
208
208
209 The shell can be globally activated/deactivated using the
209 The shell can be globally activated/deactivated using the
210 set/get_dummy_mode methods. This allows you to turn off a shell used
210 set/get_dummy_mode methods. This allows you to turn off a shell used
211 for debugging globally.
211 for debugging globally.
212
212
213 However, *each* time you call the shell you can override the current
213 However, *each* time you call the shell you can override the current
214 state of dummy_mode with the optional keyword parameter 'dummy'. For
214 state of dummy_mode with the optional keyword parameter 'dummy'. For
215 example, if you set dummy mode on with IPShell.set_dummy_mode(1), you
215 example, if you set dummy mode on with IPShell.set_dummy_mode(1), you
216 can still have a specific call work by making it as IPShell(dummy=0).
216 can still have a specific call work by making it as IPShell(dummy=0).
217
217
218 The optional keyword parameter dummy controls whether the call
218 The optional keyword parameter dummy controls whether the call
219 actually does anything. """
219 actually does anything. """
220
220
221 # If the user has turned it off, go away
221 # If the user has turned it off, go away
222 if not self.IP.embedded_active:
222 if not self.IP.embedded_active:
223 return
223 return
224
224
225 # Normal exits from interactive mode set this flag, so the shell can't
225 # Normal exits from interactive mode set this flag, so the shell can't
226 # re-enter (it checks this variable at the start of interactive mode).
226 # re-enter (it checks this variable at the start of interactive mode).
227 self.IP.exit_now = False
227 self.IP.exit_now = False
228
228
229 # Allow the dummy parameter to override the global __dummy_mode
229 # Allow the dummy parameter to override the global __dummy_mode
230 if dummy or (dummy != 0 and self.__dummy_mode):
230 if dummy or (dummy != 0 and self.__dummy_mode):
231 return
231 return
232
232
233 # Set global subsystems (display,completions) to our values
233 # Set global subsystems (display,completions) to our values
234 sys.displayhook = self.sys_displayhook_embed
234 sys.displayhook = self.sys_displayhook_embed
235 if self.IP.has_readline:
235 if self.IP.has_readline:
236 self.IP.set_completer()
236 self.IP.set_completer()
237
237
238 if self.banner and header:
238 if self.banner and header:
239 format = '%s\n%s\n'
239 format = '%s\n%s\n'
240 else:
240 else:
241 format = '%s%s\n'
241 format = '%s%s\n'
242 banner = format % (self.banner,header)
242 banner = format % (self.banner,header)
243
243
244 # Call the embedding code with a stack depth of 1 so it can skip over
244 # Call the embedding code with a stack depth of 1 so it can skip over
245 # our call and get the original caller's namespaces.
245 # our call and get the original caller's namespaces.
246 self.IP.embed_mainloop(banner,local_ns,global_ns,stack_depth=1)
246 self.IP.embed_mainloop(banner,local_ns,global_ns,stack_depth=1)
247
247
248 if self.exit_msg:
248 if self.exit_msg:
249 print self.exit_msg
249 print self.exit_msg
250
250
251 # Restore global systems (display, completion)
251 # Restore global systems (display, completion)
252 sys.displayhook = self.sys_displayhook_ori
252 sys.displayhook = self.sys_displayhook_ori
253 self.restore_system_completer()
253 self.restore_system_completer()
254
254
255 def set_dummy_mode(self,dummy):
255 def set_dummy_mode(self,dummy):
256 """Sets the embeddable shell's dummy mode parameter.
256 """Sets the embeddable shell's dummy mode parameter.
257
257
258 set_dummy_mode(dummy): dummy = 0 or 1.
258 set_dummy_mode(dummy): dummy = 0 or 1.
259
259
260 This parameter is persistent and makes calls to the embeddable shell
260 This parameter is persistent and makes calls to the embeddable shell
261 silently return without performing any action. This allows you to
261 silently return without performing any action. This allows you to
262 globally activate or deactivate a shell you're using with a single call.
262 globally activate or deactivate a shell you're using with a single call.
263
263
264 If you need to manually"""
264 If you need to manually"""
265
265
266 if dummy not in [0,1,False,True]:
266 if dummy not in [0,1,False,True]:
267 raise ValueError,'dummy parameter must be boolean'
267 raise ValueError,'dummy parameter must be boolean'
268 self.__dummy_mode = dummy
268 self.__dummy_mode = dummy
269
269
270 def get_dummy_mode(self):
270 def get_dummy_mode(self):
271 """Return the current value of the dummy mode parameter.
271 """Return the current value of the dummy mode parameter.
272 """
272 """
273 return self.__dummy_mode
273 return self.__dummy_mode
274
274
275 def set_banner(self,banner):
275 def set_banner(self,banner):
276 """Sets the global banner.
276 """Sets the global banner.
277
277
278 This banner gets prepended to every header printed when the shell
278 This banner gets prepended to every header printed when the shell
279 instance is called."""
279 instance is called."""
280
280
281 self.banner = banner
281 self.banner = banner
282
282
283 def set_exit_msg(self,exit_msg):
283 def set_exit_msg(self,exit_msg):
284 """Sets the global exit_msg.
284 """Sets the global exit_msg.
285
285
286 This exit message gets printed upon exiting every time the embedded
286 This exit message gets printed upon exiting every time the embedded
287 shell is called. It is None by default. """
287 shell is called. It is None by default. """
288
288
289 self.exit_msg = exit_msg
289 self.exit_msg = exit_msg
290
290
291 #-----------------------------------------------------------------------------
291 #-----------------------------------------------------------------------------
292 if HAS_CTYPES:
292 if HAS_CTYPES:
293 # Add async exception support. Trick taken from:
293 # Add async exception support. Trick taken from:
294 # http://sebulba.wikispaces.com/recipe+thread2
294 # http://sebulba.wikispaces.com/recipe+thread2
295 def _async_raise(tid, exctype):
295 def _async_raise(tid, exctype):
296 """raises the exception, performs cleanup if needed"""
296 """raises the exception, performs cleanup if needed"""
297 if not inspect.isclass(exctype):
297 if not inspect.isclass(exctype):
298 raise TypeError("Only types can be raised (not instances)")
298 raise TypeError("Only types can be raised (not instances)")
299 res = ctypes.pythonapi.PyThreadState_SetAsyncExc(tid,
299 res = ctypes.pythonapi.PyThreadState_SetAsyncExc(tid,
300 ctypes.py_object(exctype))
300 ctypes.py_object(exctype))
301 if res == 0:
301 if res == 0:
302 raise ValueError("invalid thread id")
302 raise ValueError("invalid thread id")
303 elif res != 1:
303 elif res != 1:
304 # """if it returns a number greater than one, you're in trouble,
304 # """if it returns a number greater than one, you're in trouble,
305 # and you should call it again with exc=NULL to revert the effect"""
305 # and you should call it again with exc=NULL to revert the effect"""
306 ctypes.pythonapi.PyThreadState_SetAsyncExc(tid, 0)
306 ctypes.pythonapi.PyThreadState_SetAsyncExc(tid, 0)
307 raise SystemError("PyThreadState_SetAsyncExc failed")
307 raise SystemError("PyThreadState_SetAsyncExc failed")
308
308
309 def sigint_handler (signum,stack_frame):
309 def sigint_handler (signum,stack_frame):
310 """Sigint handler for threaded apps.
310 """Sigint handler for threaded apps.
311
311
312 This is a horrible hack to pass information about SIGINT _without_
312 This is a horrible hack to pass information about SIGINT _without_
313 using exceptions, since I haven't been able to properly manage
313 using exceptions, since I haven't been able to properly manage
314 cross-thread exceptions in GTK/WX. In fact, I don't think it can be
314 cross-thread exceptions in GTK/WX. In fact, I don't think it can be
315 done (or at least that's my understanding from a c.l.py thread where
315 done (or at least that's my understanding from a c.l.py thread where
316 this was discussed)."""
316 this was discussed)."""
317
317
318 global KBINT
318 global KBINT
319
319
320 if CODE_RUN:
320 if CODE_RUN:
321 _async_raise(MAIN_THREAD_ID,KeyboardInterrupt)
321 _async_raise(MAIN_THREAD_ID,KeyboardInterrupt)
322 else:
322 else:
323 KBINT = True
323 KBINT = True
324 print '\nKeyboardInterrupt - Press <Enter> to continue.',
324 print '\nKeyboardInterrupt - Press <Enter> to continue.',
325 Term.cout.flush()
325 Term.cout.flush()
326
326
327 else:
327 else:
328 def sigint_handler (signum,stack_frame):
328 def sigint_handler (signum,stack_frame):
329 """Sigint handler for threaded apps.
329 """Sigint handler for threaded apps.
330
330
331 This is a horrible hack to pass information about SIGINT _without_
331 This is a horrible hack to pass information about SIGINT _without_
332 using exceptions, since I haven't been able to properly manage
332 using exceptions, since I haven't been able to properly manage
333 cross-thread exceptions in GTK/WX. In fact, I don't think it can be
333 cross-thread exceptions in GTK/WX. In fact, I don't think it can be
334 done (or at least that's my understanding from a c.l.py thread where
334 done (or at least that's my understanding from a c.l.py thread where
335 this was discussed)."""
335 this was discussed)."""
336
336
337 global KBINT
337 global KBINT
338
338
339 print '\nKeyboardInterrupt - Press <Enter> to continue.',
339 print '\nKeyboardInterrupt - Press <Enter> to continue.',
340 Term.cout.flush()
340 Term.cout.flush()
341 # Set global flag so that runsource can know that Ctrl-C was hit
341 # Set global flag so that runsource can know that Ctrl-C was hit
342 KBINT = True
342 KBINT = True
343
343
344
344
345 class MTInteractiveShell(InteractiveShell):
345 class MTInteractiveShell(InteractiveShell):
346 """Simple multi-threaded shell."""
346 """Simple multi-threaded shell."""
347
347
348 # Threading strategy taken from:
348 # Threading strategy taken from:
349 # http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/65109, by Brian
349 # http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/65109, by Brian
350 # McErlean and John Finlay. Modified with corrections by Antoon Pardon,
350 # McErlean and John Finlay. Modified with corrections by Antoon Pardon,
351 # from the pygtk mailing list, to avoid lockups with system calls.
351 # from the pygtk mailing list, to avoid lockups with system calls.
352
352
353 # class attribute to indicate whether the class supports threads or not.
353 # class attribute to indicate whether the class supports threads or not.
354 # Subclasses with thread support should override this as needed.
354 # Subclasses with thread support should override this as needed.
355 isthreaded = True
355 isthreaded = True
356
356
357 def __init__(self,name,usage=None,rc=Struct(opts=None,args=None),
357 def __init__(self,name,usage=None,rc=Struct(opts=None,args=None),
358 user_ns=None,user_global_ns=None,banner2='',
358 user_ns=None,user_global_ns=None,banner2='',
359 gui_timeout=GUI_TIMEOUT,**kw):
359 gui_timeout=GUI_TIMEOUT,**kw):
360 """Similar to the normal InteractiveShell, but with threading control"""
360 """Similar to the normal InteractiveShell, but with threading control"""
361
361
362 InteractiveShell.__init__(self,name,usage,rc,user_ns,
362 InteractiveShell.__init__(self,name,usage,rc,user_ns,
363 user_global_ns,banner2)
363 user_global_ns,banner2)
364
364
365 # Timeout we wait for GUI thread
365 # Timeout we wait for GUI thread
366 self.gui_timeout = gui_timeout
366 self.gui_timeout = gui_timeout
367
367
368 # A queue to hold the code to be executed.
368 # A queue to hold the code to be executed.
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 = None
372 self._kill = None
373 on_kill = kw.get('on_kill', [])
373 on_kill = kw.get('on_kill', [])
374 # Check that all things to kill are callable:
374 # Check that all things to kill are callable:
375 for t in on_kill:
375 for t in on_kill:
376 if not callable(t):
376 if not callable(t):
377 raise TypeError,'on_kill must be a list of callables'
377 raise TypeError,'on_kill must be a list of callables'
378 self.on_kill = on_kill
378 self.on_kill = on_kill
379 # thread identity of the "worker thread" (that may execute code directly)
379 # thread identity of the "worker thread" (that may execute code directly)
380 self.worker_ident = None
380 self.worker_ident = None
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 if self._kill:
395 if self._kill:
396 # can't queue new code if we are being killed
396 # can't queue new code if we are being killed
397 return True
397 return True
398
398
399 try:
399 try:
400 code = self.compile(source, filename, symbol)
400 code = self.compile(source, filename, symbol)
401 except (OverflowError, SyntaxError, ValueError):
401 except (OverflowError, SyntaxError, ValueError):
402 # Case 1
402 # Case 1
403 self.showsyntaxerror(filename)
403 self.showsyntaxerror(filename)
404 return False
404 return False
405
405
406 if code is None:
406 if code is None:
407 # Case 2
407 # Case 2
408 return True
408 return True
409
409
410 # shortcut - if we are in worker thread, or the worker thread is not
410 # shortcut - if we are in worker thread, or the worker thread is not
411 # running, execute directly (to allow recursion and prevent deadlock if
411 # running, execute directly (to allow recursion and prevent deadlock if
412 # code is run early in IPython construction)
412 # code is run early in IPython construction)
413
413
414 if (self.worker_ident is None
414 if (self.worker_ident is None
415 or self.worker_ident == thread.get_ident() ):
415 or self.worker_ident == thread.get_ident() ):
416 InteractiveShell.runcode(self,code)
416 InteractiveShell.runcode(self,code)
417 return
417 return
418
418
419 # Case 3
419 # Case 3
420 # Store code in queue, so the execution thread can handle it.
420 # Store code in queue, so the execution thread can handle it.
421
421
422 completed_ev, received_ev = threading.Event(), threading.Event()
422 completed_ev, received_ev = threading.Event(), threading.Event()
423
423
424 self.code_queue.put((code,completed_ev, received_ev))
424 self.code_queue.put((code,completed_ev, received_ev))
425 # first make sure the message was received, with timeout
425 # first make sure the message was received, with timeout
426 received_ev.wait(self.gui_timeout)
426 received_ev.wait(self.gui_timeout)
427 if not received_ev.isSet():
427 if not received_ev.isSet():
428 # the mainloop is dead, start executing code directly
428 # the mainloop is dead, start executing code directly
429 print "Warning: Timeout for mainloop thread exceeded"
429 print "Warning: Timeout for mainloop thread exceeded"
430 print "switching to nonthreaded mode (until mainloop wakes up again)"
430 print "switching to nonthreaded mode (until mainloop wakes up again)"
431 self.worker_ident = None
431 self.worker_ident = None
432 else:
432 else:
433 completed_ev.wait()
433 completed_ev.wait()
434 return False
434 return False
435
435
436 def runcode(self):
436 def runcode(self):
437 """Execute a code object.
437 """Execute a code object.
438
438
439 Multithreaded wrapper around IPython's runcode()."""
439 Multithreaded wrapper around IPython's runcode()."""
440
440
441 global CODE_RUN
441 global CODE_RUN
442
442
443 # we are in worker thread, stash out the id for runsource()
443 # we are in worker thread, stash out the id for runsource()
444 self.worker_ident = thread.get_ident()
444 self.worker_ident = thread.get_ident()
445
445
446 if self._kill:
446 if self._kill:
447 print >>Term.cout, 'Closing threads...',
447 print >>Term.cout, 'Closing threads...',
448 Term.cout.flush()
448 Term.cout.flush()
449 for tokill in self.on_kill:
449 for tokill in self.on_kill:
450 tokill()
450 tokill()
451 print >>Term.cout, 'Done.'
451 print >>Term.cout, 'Done.'
452 # allow kill() to return
452 # allow kill() to return
453 self._kill.set()
453 self._kill.set()
454 return True
454 return True
455
455
456 # Install sigint handler. We do it every time to ensure that if user
456 # Install sigint handler. We do it every time to ensure that if user
457 # code modifies it, we restore our own handling.
457 # code modifies it, we restore our own handling.
458 try:
458 try:
459 signal(SIGINT,sigint_handler)
459 signal(SIGINT,sigint_handler)
460 except SystemError:
460 except SystemError:
461 # This happens under Windows, which seems to have all sorts
461 # This happens under Windows, which seems to have all sorts
462 # of problems with signal handling. Oh well...
462 # of problems with signal handling. Oh well...
463 pass
463 pass
464
464
465 # Flush queue of pending code by calling the run methood of the parent
465 # Flush queue of pending code by calling the run methood of the parent
466 # class with all items which may be in the queue.
466 # class with all items which may be in the queue.
467 code_to_run = None
467 code_to_run = None
468 while 1:
468 while 1:
469 try:
469 try:
470 code_to_run, completed_ev, received_ev = self.code_queue.get_nowait()
470 code_to_run, completed_ev, received_ev = self.code_queue.get_nowait()
471 except Queue.Empty:
471 except Queue.Empty:
472 break
472 break
473 received_ev.set()
473 received_ev.set()
474
474
475 # Exceptions need to be raised differently depending on which
475 # Exceptions need to be raised differently depending on which
476 # thread is active. This convoluted try/except is only there to
476 # thread is active. This convoluted try/except is only there to
477 # protect against asynchronous exceptions, to ensure that a KBINT
477 # protect against asynchronous exceptions, to ensure that a KBINT
478 # at the wrong time doesn't deadlock everything. The global
478 # at the wrong time doesn't deadlock everything. The global
479 # CODE_TO_RUN is set to true/false as close as possible to the
479 # CODE_TO_RUN is set to true/false as close as possible to the
480 # runcode() call, so that the KBINT handler is correctly informed.
480 # runcode() call, so that the KBINT handler is correctly informed.
481 try:
481 try:
482 try:
482 try:
483 CODE_RUN = True
483 CODE_RUN = True
484 InteractiveShell.runcode(self,code_to_run)
484 InteractiveShell.runcode(self,code_to_run)
485 except KeyboardInterrupt:
485 except KeyboardInterrupt:
486 print "Keyboard interrupted in mainloop"
486 print "Keyboard interrupted in mainloop"
487 while not self.code_queue.empty():
487 while not self.code_queue.empty():
488 code, ev1,ev2 = self.code_queue.get_nowait()
488 code, ev1,ev2 = self.code_queue.get_nowait()
489 ev1.set()
489 ev1.set()
490 ev2.set()
490 ev2.set()
491 break
491 break
492 finally:
492 finally:
493 CODE_RUN = False
493 CODE_RUN = False
494 # allow runsource() return from wait
494 # allow runsource() return from wait
495 completed_ev.set()
495 completed_ev.set()
496
496
497
497
498 # This MUST return true for gtk threading to work
498 # This MUST return true for gtk threading to work
499 return True
499 return True
500
500
501 def kill(self):
501 def kill(self):
502 """Kill the thread, returning when it has been shut down."""
502 """Kill the thread, returning when it has been shut down."""
503 self._kill = threading.Event()
503 self._kill = threading.Event()
504 self._kill.wait()
504 self._kill.wait()
505
505
506 class MatplotlibShellBase:
506 class MatplotlibShellBase:
507 """Mixin class to provide the necessary modifications to regular IPython
507 """Mixin class to provide the necessary modifications to regular IPython
508 shell classes for matplotlib support.
508 shell classes for matplotlib support.
509
509
510 Given Python's MRO, this should be used as the FIRST class in the
510 Given Python's MRO, this should be used as the FIRST class in the
511 inheritance hierarchy, so that it overrides the relevant methods."""
511 inheritance hierarchy, so that it overrides the relevant methods."""
512
512
513 def _matplotlib_config(self,name,user_ns,user_global_ns=None):
513 def _matplotlib_config(self,name,user_ns,user_global_ns=None):
514 """Return items needed to setup the user's shell with matplotlib"""
514 """Return items needed to setup the user's shell with matplotlib"""
515
515
516 # Initialize matplotlib to interactive mode always
516 # Initialize matplotlib to interactive mode always
517 import matplotlib
517 import matplotlib
518 from matplotlib import backends
518 from matplotlib import backends
519 matplotlib.interactive(True)
519 matplotlib.interactive(True)
520
520
521 def use(arg):
521 def use(arg):
522 """IPython wrapper for matplotlib's backend switcher.
522 """IPython wrapper for matplotlib's backend switcher.
523
523
524 In interactive use, we can not allow switching to a different
524 In interactive use, we can not allow switching to a different
525 interactive backend, since thread conflicts will most likely crash
525 interactive backend, since thread conflicts will most likely crash
526 the python interpreter. This routine does a safety check first,
526 the python interpreter. This routine does a safety check first,
527 and refuses to perform a dangerous switch. It still allows
527 and refuses to perform a dangerous switch. It still allows
528 switching to non-interactive backends."""
528 switching to non-interactive backends."""
529
529
530 if arg in backends.interactive_bk and arg != self.mpl_backend:
530 if arg in backends.interactive_bk and arg != self.mpl_backend:
531 m=('invalid matplotlib backend switch.\n'
531 m=('invalid matplotlib backend switch.\n'
532 'This script attempted to switch to the interactive '
532 'This script attempted to switch to the interactive '
533 'backend: `%s`\n'
533 'backend: `%s`\n'
534 'Your current choice of interactive backend is: `%s`\n\n'
534 'Your current choice of interactive backend is: `%s`\n\n'
535 'Switching interactive matplotlib backends at runtime\n'
535 'Switching interactive matplotlib backends at runtime\n'
536 'would crash the python interpreter, '
536 'would crash the python interpreter, '
537 'and IPython has blocked it.\n\n'
537 'and IPython has blocked it.\n\n'
538 'You need to either change your choice of matplotlib backend\n'
538 'You need to either change your choice of matplotlib backend\n'
539 'by editing your .matplotlibrc file, or run this script as a \n'
539 'by editing your .matplotlibrc file, or run this script as a \n'
540 'standalone file from the command line, not using IPython.\n' %
540 'standalone file from the command line, not using IPython.\n' %
541 (arg,self.mpl_backend) )
541 (arg,self.mpl_backend) )
542 raise RuntimeError, m
542 raise RuntimeError, m
543 else:
543 else:
544 self.mpl_use(arg)
544 self.mpl_use(arg)
545 self.mpl_use._called = True
545 self.mpl_use._called = True
546
546
547 self.matplotlib = matplotlib
547 self.matplotlib = matplotlib
548 self.mpl_backend = matplotlib.rcParams['backend']
548 self.mpl_backend = matplotlib.rcParams['backend']
549
549
550 # we also need to block switching of interactive backends by use()
550 # we also need to block switching of interactive backends by use()
551 self.mpl_use = matplotlib.use
551 self.mpl_use = matplotlib.use
552 self.mpl_use._called = False
552 self.mpl_use._called = False
553 # overwrite the original matplotlib.use with our wrapper
553 # overwrite the original matplotlib.use with our wrapper
554 matplotlib.use = use
554 matplotlib.use = use
555
555
556 # This must be imported last in the matplotlib series, after
556 # This must be imported last in the matplotlib series, after
557 # backend/interactivity choices have been made
557 # backend/interactivity choices have been made
558 import matplotlib.pylab as pylab
558 import matplotlib.pylab as pylab
559 self.pylab = pylab
559 self.pylab = pylab
560
560
561 self.pylab.show._needmain = False
561 self.pylab.show._needmain = False
562 # We need to detect at runtime whether show() is called by the user.
562 # We need to detect at runtime whether show() is called by the user.
563 # For this, we wrap it into a decorator which adds a 'called' flag.
563 # For this, we wrap it into a decorator which adds a 'called' flag.
564 self.pylab.draw_if_interactive = flag_calls(self.pylab.draw_if_interactive)
564 self.pylab.draw_if_interactive = flag_calls(self.pylab.draw_if_interactive)
565
565
566 # Build a user namespace initialized with matplotlib/matlab features.
566 # Build a user namespace initialized with matplotlib/matlab features.
567 user_ns, user_global_ns = IPython.ipapi.make_user_namespaces(user_ns,
567 user_ns, user_global_ns = IPython.ipapi.make_user_namespaces(user_ns,
568 user_global_ns)
568 user_global_ns)
569
569
570 # Import numpy as np/pyplot as plt are conventions we're trying to
570 # Import numpy as np/pyplot as plt are conventions we're trying to
571 # somewhat standardize on. Making them available to users by default
571 # somewhat standardize on. Making them available to users by default
572 # will greatly help this.
572 # will greatly help this.
573 exec ("import numpy\n"
573 exec ("import numpy\n"
574 "import numpy as np\n"
574 "import numpy as np\n"
575 "import matplotlib\n"
575 "import matplotlib\n"
576 "import matplotlib.pylab as pylab\n"
576 "import matplotlib.pylab as pylab\n"
577 "try:\n"
577 "try:\n"
578 " import matplotlib.pyplot as plt\n"
578 " import matplotlib.pyplot as plt\n"
579 "except ImportError:\n"
579 "except ImportError:\n"
580 " pass\n"
580 " pass\n"
581 ) in user_ns
581 ) in user_ns
582
582
583 # Build matplotlib info banner
583 # Build matplotlib info banner
584 b="""
584 b="""
585 Welcome to pylab, a matplotlib-based Python environment.
585 Welcome to pylab, a matplotlib-based Python environment.
586 For more information, type 'help(pylab)'.
586 For more information, type 'help(pylab)'.
587 """
587 """
588 return user_ns,user_global_ns,b
588 return user_ns,user_global_ns,b
589
589
590 def mplot_exec(self,fname,*where,**kw):
590 def mplot_exec(self,fname,*where,**kw):
591 """Execute a matplotlib script.
591 """Execute a matplotlib script.
592
592
593 This is a call to execfile(), but wrapped in safeties to properly
593 This is a call to execfile(), but wrapped in safeties to properly
594 handle interactive rendering and backend switching."""
594 handle interactive rendering and backend switching."""
595
595
596 #print '*** Matplotlib runner ***' # dbg
596 #print '*** Matplotlib runner ***' # dbg
597 # turn off rendering until end of script
597 # turn off rendering until end of script
598 isInteractive = self.matplotlib.rcParams['interactive']
598 isInteractive = self.matplotlib.rcParams['interactive']
599 self.matplotlib.interactive(False)
599 self.matplotlib.interactive(False)
600 self.safe_execfile(fname,*where,**kw)
600 self.safe_execfile(fname,*where,**kw)
601 self.matplotlib.interactive(isInteractive)
601 self.matplotlib.interactive(isInteractive)
602 # make rendering call now, if the user tried to do it
602 # make rendering call now, if the user tried to do it
603 if self.pylab.draw_if_interactive.called:
603 if self.pylab.draw_if_interactive.called:
604 self.pylab.draw()
604 self.pylab.draw()
605 self.pylab.draw_if_interactive.called = False
605 self.pylab.draw_if_interactive.called = False
606
606
607 # if a backend switch was performed, reverse it now
607 # if a backend switch was performed, reverse it now
608 if self.mpl_use._called:
608 if self.mpl_use._called:
609 self.matplotlib.rcParams['backend'] = self.mpl_backend
609 self.matplotlib.rcParams['backend'] = self.mpl_backend
610
610
611 def magic_run(self,parameter_s=''):
611 def magic_run(self,parameter_s=''):
612 Magic.magic_run(self,parameter_s,runner=self.mplot_exec)
612 Magic.magic_run(self,parameter_s,runner=self.mplot_exec)
613
613
614 # Fix the docstring so users see the original as well
614 # Fix the docstring so users see the original as well
615 magic_run.__doc__ = "%s\n%s" % (Magic.magic_run.__doc__,
615 magic_run.__doc__ = "%s\n%s" % (Magic.magic_run.__doc__,
616 "\n *** Modified %run for Matplotlib,"
616 "\n *** Modified %run for Matplotlib,"
617 " with proper interactive handling ***")
617 " with proper interactive handling ***")
618
618
619 # Now we provide 2 versions of a matplotlib-aware IPython base shells, single
619 # Now we provide 2 versions of a matplotlib-aware IPython base shells, single
620 # and multithreaded. Note that these are meant for internal use, the IPShell*
620 # and multithreaded. Note that these are meant for internal use, the IPShell*
621 # classes below are the ones meant for public consumption.
621 # classes below are the ones meant for public consumption.
622
622
623 class MatplotlibShell(MatplotlibShellBase,InteractiveShell):
623 class MatplotlibShell(MatplotlibShellBase,InteractiveShell):
624 """Single-threaded shell with matplotlib support."""
624 """Single-threaded shell with matplotlib support."""
625
625
626 def __init__(self,name,usage=None,rc=Struct(opts=None,args=None),
626 def __init__(self,name,usage=None,rc=Struct(opts=None,args=None),
627 user_ns=None,user_global_ns=None,**kw):
627 user_ns=None,user_global_ns=None,**kw):
628 user_ns,user_global_ns,b2 = self._matplotlib_config(name,user_ns,user_global_ns)
628 user_ns,user_global_ns,b2 = self._matplotlib_config(name,user_ns,user_global_ns)
629 InteractiveShell.__init__(self,name,usage,rc,user_ns,user_global_ns,
629 InteractiveShell.__init__(self,name,usage,rc,user_ns,user_global_ns,
630 banner2=b2,**kw)
630 banner2=b2,**kw)
631
631
632 class MatplotlibMTShell(MatplotlibShellBase,MTInteractiveShell):
632 class MatplotlibMTShell(MatplotlibShellBase,MTInteractiveShell):
633 """Multi-threaded shell with matplotlib support."""
633 """Multi-threaded shell with matplotlib support."""
634
634
635 def __init__(self,name,usage=None,rc=Struct(opts=None,args=None),
635 def __init__(self,name,usage=None,rc=Struct(opts=None,args=None),
636 user_ns=None,user_global_ns=None, **kw):
636 user_ns=None,user_global_ns=None, **kw):
637 user_ns,b2 = self._matplotlib_config(name,user_ns)
637 user_ns,user_global_ns,b2 = self._matplotlib_config(name,user_ns,user_global_ns)
638 MTInteractiveShell.__init__(self,name,usage,rc,user_ns,user_global_ns,
638 MTInteractiveShell.__init__(self,name,usage,rc,user_ns,user_global_ns,
639 banner2=b2,**kw)
639 banner2=b2,**kw)
640
640
641 #-----------------------------------------------------------------------------
641 #-----------------------------------------------------------------------------
642 # Utility functions for the different GUI enabled IPShell* classes.
642 # Utility functions for the different GUI enabled IPShell* classes.
643
643
644 def get_tk():
644 def get_tk():
645 """Tries to import Tkinter and returns a withdrawn Tkinter root
645 """Tries to import Tkinter and returns a withdrawn Tkinter root
646 window. If Tkinter is already imported or not available, this
646 window. If Tkinter is already imported or not available, this
647 returns None. This function calls `hijack_tk` underneath.
647 returns None. This function calls `hijack_tk` underneath.
648 """
648 """
649 if not USE_TK or sys.modules.has_key('Tkinter'):
649 if not USE_TK or sys.modules.has_key('Tkinter'):
650 return None
650 return None
651 else:
651 else:
652 try:
652 try:
653 import Tkinter
653 import Tkinter
654 except ImportError:
654 except ImportError:
655 return None
655 return None
656 else:
656 else:
657 hijack_tk()
657 hijack_tk()
658 r = Tkinter.Tk()
658 r = Tkinter.Tk()
659 r.withdraw()
659 r.withdraw()
660 return r
660 return r
661
661
662 def hijack_tk():
662 def hijack_tk():
663 """Modifies Tkinter's mainloop with a dummy so when a module calls
663 """Modifies Tkinter's mainloop with a dummy so when a module calls
664 mainloop, it does not block.
664 mainloop, it does not block.
665
665
666 """
666 """
667 def misc_mainloop(self, n=0):
667 def misc_mainloop(self, n=0):
668 pass
668 pass
669 def tkinter_mainloop(n=0):
669 def tkinter_mainloop(n=0):
670 pass
670 pass
671
671
672 import Tkinter
672 import Tkinter
673 Tkinter.Misc.mainloop = misc_mainloop
673 Tkinter.Misc.mainloop = misc_mainloop
674 Tkinter.mainloop = tkinter_mainloop
674 Tkinter.mainloop = tkinter_mainloop
675
675
676 def update_tk(tk):
676 def update_tk(tk):
677 """Updates the Tkinter event loop. This is typically called from
677 """Updates the Tkinter event loop. This is typically called from
678 the respective WX or GTK mainloops.
678 the respective WX or GTK mainloops.
679 """
679 """
680 if tk:
680 if tk:
681 tk.update()
681 tk.update()
682
682
683 def hijack_wx():
683 def hijack_wx():
684 """Modifies wxPython's MainLoop with a dummy so user code does not
684 """Modifies wxPython's MainLoop with a dummy so user code does not
685 block IPython. The hijacked mainloop function is returned.
685 block IPython. The hijacked mainloop function is returned.
686 """
686 """
687 def dummy_mainloop(*args, **kw):
687 def dummy_mainloop(*args, **kw):
688 pass
688 pass
689
689
690 try:
690 try:
691 import wx
691 import wx
692 except ImportError:
692 except ImportError:
693 # For very old versions of WX
693 # For very old versions of WX
694 import wxPython as wx
694 import wxPython as wx
695
695
696 ver = wx.__version__
696 ver = wx.__version__
697 orig_mainloop = None
697 orig_mainloop = None
698 if ver[:3] >= '2.5':
698 if ver[:3] >= '2.5':
699 import wx
699 import wx
700 if hasattr(wx, '_core_'): core = getattr(wx, '_core_')
700 if hasattr(wx, '_core_'): core = getattr(wx, '_core_')
701 elif hasattr(wx, '_core'): core = getattr(wx, '_core')
701 elif hasattr(wx, '_core'): core = getattr(wx, '_core')
702 else: raise AttributeError('Could not find wx core module')
702 else: raise AttributeError('Could not find wx core module')
703 orig_mainloop = core.PyApp_MainLoop
703 orig_mainloop = core.PyApp_MainLoop
704 core.PyApp_MainLoop = dummy_mainloop
704 core.PyApp_MainLoop = dummy_mainloop
705 elif ver[:3] == '2.4':
705 elif ver[:3] == '2.4':
706 orig_mainloop = wx.wxc.wxPyApp_MainLoop
706 orig_mainloop = wx.wxc.wxPyApp_MainLoop
707 wx.wxc.wxPyApp_MainLoop = dummy_mainloop
707 wx.wxc.wxPyApp_MainLoop = dummy_mainloop
708 else:
708 else:
709 warn("Unable to find either wxPython version 2.4 or >= 2.5.")
709 warn("Unable to find either wxPython version 2.4 or >= 2.5.")
710 return orig_mainloop
710 return orig_mainloop
711
711
712 def hijack_gtk():
712 def hijack_gtk():
713 """Modifies pyGTK's mainloop with a dummy so user code does not
713 """Modifies pyGTK's mainloop with a dummy so user code does not
714 block IPython. This function returns the original `gtk.mainloop`
714 block IPython. This function returns the original `gtk.mainloop`
715 function that has been hijacked.
715 function that has been hijacked.
716 """
716 """
717 def dummy_mainloop(*args, **kw):
717 def dummy_mainloop(*args, **kw):
718 pass
718 pass
719 import gtk
719 import gtk
720 if gtk.pygtk_version >= (2,4,0): orig_mainloop = gtk.main
720 if gtk.pygtk_version >= (2,4,0): orig_mainloop = gtk.main
721 else: orig_mainloop = gtk.mainloop
721 else: orig_mainloop = gtk.mainloop
722 gtk.mainloop = dummy_mainloop
722 gtk.mainloop = dummy_mainloop
723 gtk.main = dummy_mainloop
723 gtk.main = dummy_mainloop
724 return orig_mainloop
724 return orig_mainloop
725
725
726 def hijack_qt():
726 def hijack_qt():
727 """Modifies PyQt's mainloop with a dummy so user code does not
727 """Modifies PyQt's mainloop with a dummy so user code does not
728 block IPython. This function returns the original
728 block IPython. This function returns the original
729 `qt.qApp.exec_loop` function that has been hijacked.
729 `qt.qApp.exec_loop` function that has been hijacked.
730 """
730 """
731 def dummy_mainloop(*args, **kw):
731 def dummy_mainloop(*args, **kw):
732 pass
732 pass
733 import qt
733 import qt
734 orig_mainloop = qt.qApp.exec_loop
734 orig_mainloop = qt.qApp.exec_loop
735 qt.qApp.exec_loop = dummy_mainloop
735 qt.qApp.exec_loop = dummy_mainloop
736 qt.QApplication.exec_loop = dummy_mainloop
736 qt.QApplication.exec_loop = dummy_mainloop
737 return orig_mainloop
737 return orig_mainloop
738
738
739 def hijack_qt4():
739 def hijack_qt4():
740 """Modifies PyQt4's mainloop with a dummy so user code does not
740 """Modifies PyQt4's mainloop with a dummy so user code does not
741 block IPython. This function returns the original
741 block IPython. This function returns the original
742 `QtGui.qApp.exec_` function that has been hijacked.
742 `QtGui.qApp.exec_` function that has been hijacked.
743 """
743 """
744 def dummy_mainloop(*args, **kw):
744 def dummy_mainloop(*args, **kw):
745 pass
745 pass
746 from PyQt4 import QtGui, QtCore
746 from PyQt4 import QtGui, QtCore
747 orig_mainloop = QtGui.qApp.exec_
747 orig_mainloop = QtGui.qApp.exec_
748 QtGui.qApp.exec_ = dummy_mainloop
748 QtGui.qApp.exec_ = dummy_mainloop
749 QtGui.QApplication.exec_ = dummy_mainloop
749 QtGui.QApplication.exec_ = dummy_mainloop
750 QtCore.QCoreApplication.exec_ = dummy_mainloop
750 QtCore.QCoreApplication.exec_ = dummy_mainloop
751 return orig_mainloop
751 return orig_mainloop
752
752
753 #-----------------------------------------------------------------------------
753 #-----------------------------------------------------------------------------
754 # The IPShell* classes below are the ones meant to be run by external code as
754 # The IPShell* classes below are the ones meant to be run by external code as
755 # IPython instances. Note that unless a specific threading strategy is
755 # IPython instances. Note that unless a specific threading strategy is
756 # desired, the factory function start() below should be used instead (it
756 # desired, the factory function start() below should be used instead (it
757 # selects the proper threaded class).
757 # selects the proper threaded class).
758
758
759 class IPThread(threading.Thread):
759 class IPThread(threading.Thread):
760 def run(self):
760 def run(self):
761 self.IP.mainloop(self._banner)
761 self.IP.mainloop(self._banner)
762 self.IP.kill()
762 self.IP.kill()
763
763
764 class IPShellGTK(IPThread):
764 class IPShellGTK(IPThread):
765 """Run a gtk mainloop() in a separate thread.
765 """Run a gtk mainloop() in a separate thread.
766
766
767 Python commands can be passed to the thread where they will be executed.
767 Python commands can be passed to the thread where they will be executed.
768 This is implemented by periodically checking for passed code using a
768 This is implemented by periodically checking for passed code using a
769 GTK timeout callback."""
769 GTK timeout callback."""
770
770
771 TIMEOUT = 100 # Millisecond interval between timeouts.
771 TIMEOUT = 100 # Millisecond interval between timeouts.
772
772
773 def __init__(self,argv=None,user_ns=None,user_global_ns=None,
773 def __init__(self,argv=None,user_ns=None,user_global_ns=None,
774 debug=1,shell_class=MTInteractiveShell):
774 debug=1,shell_class=MTInteractiveShell):
775
775
776 import gtk
776 import gtk
777
777
778 self.gtk = gtk
778 self.gtk = gtk
779 self.gtk_mainloop = hijack_gtk()
779 self.gtk_mainloop = hijack_gtk()
780
780
781 # Allows us to use both Tk and GTK.
781 # Allows us to use both Tk and GTK.
782 self.tk = get_tk()
782 self.tk = get_tk()
783
783
784 if gtk.pygtk_version >= (2,4,0): mainquit = self.gtk.main_quit
784 if gtk.pygtk_version >= (2,4,0): mainquit = self.gtk.main_quit
785 else: mainquit = self.gtk.mainquit
785 else: mainquit = self.gtk.mainquit
786
786
787 self.IP = make_IPython(argv,user_ns=user_ns,
787 self.IP = make_IPython(argv,user_ns=user_ns,
788 user_global_ns=user_global_ns,
788 user_global_ns=user_global_ns,
789 debug=debug,
789 debug=debug,
790 shell_class=shell_class,
790 shell_class=shell_class,
791 on_kill=[mainquit])
791 on_kill=[mainquit])
792
792
793 # HACK: slot for banner in self; it will be passed to the mainloop
793 # HACK: slot for banner in self; it will be passed to the mainloop
794 # method only and .run() needs it. The actual value will be set by
794 # method only and .run() needs it. The actual value will be set by
795 # .mainloop().
795 # .mainloop().
796 self._banner = None
796 self._banner = None
797
797
798 threading.Thread.__init__(self)
798 threading.Thread.__init__(self)
799
799
800 def mainloop(self,sys_exit=0,banner=None):
800 def mainloop(self,sys_exit=0,banner=None):
801
801
802 self._banner = banner
802 self._banner = banner
803
803
804 if self.gtk.pygtk_version >= (2,4,0):
804 if self.gtk.pygtk_version >= (2,4,0):
805 import gobject
805 import gobject
806 gobject.idle_add(self.on_timer)
806 gobject.idle_add(self.on_timer)
807 else:
807 else:
808 self.gtk.idle_add(self.on_timer)
808 self.gtk.idle_add(self.on_timer)
809
809
810 if sys.platform != 'win32':
810 if sys.platform != 'win32':
811 try:
811 try:
812 if self.gtk.gtk_version[0] >= 2:
812 if self.gtk.gtk_version[0] >= 2:
813 self.gtk.gdk.threads_init()
813 self.gtk.gdk.threads_init()
814 except AttributeError:
814 except AttributeError:
815 pass
815 pass
816 except RuntimeError:
816 except RuntimeError:
817 error('Your pyGTK likely has not been compiled with '
817 error('Your pyGTK likely has not been compiled with '
818 'threading support.\n'
818 'threading support.\n'
819 'The exception printout is below.\n'
819 'The exception printout is below.\n'
820 'You can either rebuild pyGTK with threads, or '
820 'You can either rebuild pyGTK with threads, or '
821 'try using \n'
821 'try using \n'
822 'matplotlib with a different backend (like Tk or WX).\n'
822 'matplotlib with a different backend (like Tk or WX).\n'
823 'Note that matplotlib will most likely not work in its '
823 'Note that matplotlib will most likely not work in its '
824 'current state!')
824 'current state!')
825 self.IP.InteractiveTB()
825 self.IP.InteractiveTB()
826
826
827 self.start()
827 self.start()
828 self.gtk.gdk.threads_enter()
828 self.gtk.gdk.threads_enter()
829 self.gtk_mainloop()
829 self.gtk_mainloop()
830 self.gtk.gdk.threads_leave()
830 self.gtk.gdk.threads_leave()
831 self.join()
831 self.join()
832
832
833 def on_timer(self):
833 def on_timer(self):
834 """Called when GTK is idle.
834 """Called when GTK is idle.
835
835
836 Must return True always, otherwise GTK stops calling it"""
836 Must return True always, otherwise GTK stops calling it"""
837
837
838 update_tk(self.tk)
838 update_tk(self.tk)
839 self.IP.runcode()
839 self.IP.runcode()
840 time.sleep(0.01)
840 time.sleep(0.01)
841 return True
841 return True
842
842
843
843
844 class IPShellWX(IPThread):
844 class IPShellWX(IPThread):
845 """Run a wx mainloop() in a separate thread.
845 """Run a wx mainloop() in a separate thread.
846
846
847 Python commands can be passed to the thread where they will be executed.
847 Python commands can be passed to the thread where they will be executed.
848 This is implemented by periodically checking for passed code using a
848 This is implemented by periodically checking for passed code using a
849 GTK timeout callback."""
849 GTK timeout callback."""
850
850
851 TIMEOUT = 100 # Millisecond interval between timeouts.
851 TIMEOUT = 100 # Millisecond interval between timeouts.
852
852
853 def __init__(self,argv=None,user_ns=None,user_global_ns=None,
853 def __init__(self,argv=None,user_ns=None,user_global_ns=None,
854 debug=1,shell_class=MTInteractiveShell):
854 debug=1,shell_class=MTInteractiveShell):
855
855
856 self.IP = make_IPython(argv,user_ns=user_ns,
856 self.IP = make_IPython(argv,user_ns=user_ns,
857 user_global_ns=user_global_ns,
857 user_global_ns=user_global_ns,
858 debug=debug,
858 debug=debug,
859 shell_class=shell_class,
859 shell_class=shell_class,
860 on_kill=[self.wxexit])
860 on_kill=[self.wxexit])
861
861
862 wantedwxversion=self.IP.rc.wxversion
862 wantedwxversion=self.IP.rc.wxversion
863 if wantedwxversion!="0":
863 if wantedwxversion!="0":
864 try:
864 try:
865 import wxversion
865 import wxversion
866 except ImportError:
866 except ImportError:
867 error('The wxversion module is needed for WX version selection')
867 error('The wxversion module is needed for WX version selection')
868 else:
868 else:
869 try:
869 try:
870 wxversion.select(wantedwxversion)
870 wxversion.select(wantedwxversion)
871 except:
871 except:
872 self.IP.InteractiveTB()
872 self.IP.InteractiveTB()
873 error('Requested wxPython version %s could not be loaded' %
873 error('Requested wxPython version %s could not be loaded' %
874 wantedwxversion)
874 wantedwxversion)
875
875
876 import wx
876 import wx
877
877
878 threading.Thread.__init__(self)
878 threading.Thread.__init__(self)
879 self.wx = wx
879 self.wx = wx
880 self.wx_mainloop = hijack_wx()
880 self.wx_mainloop = hijack_wx()
881
881
882 # Allows us to use both Tk and GTK.
882 # Allows us to use both Tk and GTK.
883 self.tk = get_tk()
883 self.tk = get_tk()
884
884
885 # HACK: slot for banner in self; it will be passed to the mainloop
885 # HACK: slot for banner in self; it will be passed to the mainloop
886 # method only and .run() needs it. The actual value will be set by
886 # method only and .run() needs it. The actual value will be set by
887 # .mainloop().
887 # .mainloop().
888 self._banner = None
888 self._banner = None
889
889
890 self.app = None
890 self.app = None
891
891
892 def wxexit(self, *args):
892 def wxexit(self, *args):
893 if self.app is not None:
893 if self.app is not None:
894 self.app.agent.timer.Stop()
894 self.app.agent.timer.Stop()
895 self.app.ExitMainLoop()
895 self.app.ExitMainLoop()
896
896
897 def mainloop(self,sys_exit=0,banner=None):
897 def mainloop(self,sys_exit=0,banner=None):
898
898
899 self._banner = banner
899 self._banner = banner
900
900
901 self.start()
901 self.start()
902
902
903 class TimerAgent(self.wx.MiniFrame):
903 class TimerAgent(self.wx.MiniFrame):
904 wx = self.wx
904 wx = self.wx
905 IP = self.IP
905 IP = self.IP
906 tk = self.tk
906 tk = self.tk
907 def __init__(self, parent, interval):
907 def __init__(self, parent, interval):
908 style = self.wx.DEFAULT_FRAME_STYLE | self.wx.TINY_CAPTION_HORIZ
908 style = self.wx.DEFAULT_FRAME_STYLE | self.wx.TINY_CAPTION_HORIZ
909 self.wx.MiniFrame.__init__(self, parent, -1, ' ', pos=(200, 200),
909 self.wx.MiniFrame.__init__(self, parent, -1, ' ', pos=(200, 200),
910 size=(100, 100),style=style)
910 size=(100, 100),style=style)
911 self.Show(False)
911 self.Show(False)
912 self.interval = interval
912 self.interval = interval
913 self.timerId = self.wx.NewId()
913 self.timerId = self.wx.NewId()
914
914
915 def StartWork(self):
915 def StartWork(self):
916 self.timer = self.wx.Timer(self, self.timerId)
916 self.timer = self.wx.Timer(self, self.timerId)
917 self.wx.EVT_TIMER(self, self.timerId, self.OnTimer)
917 self.wx.EVT_TIMER(self, self.timerId, self.OnTimer)
918 self.timer.Start(self.interval)
918 self.timer.Start(self.interval)
919
919
920 def OnTimer(self, event):
920 def OnTimer(self, event):
921 update_tk(self.tk)
921 update_tk(self.tk)
922 self.IP.runcode()
922 self.IP.runcode()
923
923
924 class App(self.wx.App):
924 class App(self.wx.App):
925 wx = self.wx
925 wx = self.wx
926 TIMEOUT = self.TIMEOUT
926 TIMEOUT = self.TIMEOUT
927 def OnInit(self):
927 def OnInit(self):
928 'Create the main window and insert the custom frame'
928 'Create the main window and insert the custom frame'
929 self.agent = TimerAgent(None, self.TIMEOUT)
929 self.agent = TimerAgent(None, self.TIMEOUT)
930 self.agent.Show(False)
930 self.agent.Show(False)
931 self.agent.StartWork()
931 self.agent.StartWork()
932 return True
932 return True
933
933
934 self.app = App(redirect=False)
934 self.app = App(redirect=False)
935 self.wx_mainloop(self.app)
935 self.wx_mainloop(self.app)
936 self.join()
936 self.join()
937
937
938
938
939 class IPShellQt(IPThread):
939 class IPShellQt(IPThread):
940 """Run a Qt event loop in a separate thread.
940 """Run a Qt event loop in a separate thread.
941
941
942 Python commands can be passed to the thread where they will be executed.
942 Python commands can be passed to the thread where they will be executed.
943 This is implemented by periodically checking for passed code using a
943 This is implemented by periodically checking for passed code using a
944 Qt timer / slot."""
944 Qt timer / slot."""
945
945
946 TIMEOUT = 100 # Millisecond interval between timeouts.
946 TIMEOUT = 100 # Millisecond interval between timeouts.
947
947
948 def __init__(self, argv=None, user_ns=None, user_global_ns=None,
948 def __init__(self, argv=None, user_ns=None, user_global_ns=None,
949 debug=0, shell_class=MTInteractiveShell):
949 debug=0, shell_class=MTInteractiveShell):
950
950
951 import qt
951 import qt
952
952
953 self.exec_loop = hijack_qt()
953 self.exec_loop = hijack_qt()
954
954
955 # Allows us to use both Tk and QT.
955 # Allows us to use both Tk and QT.
956 self.tk = get_tk()
956 self.tk = get_tk()
957
957
958 self.IP = make_IPython(argv,
958 self.IP = make_IPython(argv,
959 user_ns=user_ns,
959 user_ns=user_ns,
960 user_global_ns=user_global_ns,
960 user_global_ns=user_global_ns,
961 debug=debug,
961 debug=debug,
962 shell_class=shell_class,
962 shell_class=shell_class,
963 on_kill=[qt.qApp.exit])
963 on_kill=[qt.qApp.exit])
964
964
965 # HACK: slot for banner in self; it will be passed to the mainloop
965 # HACK: slot for banner in self; it will be passed to the mainloop
966 # method only and .run() needs it. The actual value will be set by
966 # method only and .run() needs it. The actual value will be set by
967 # .mainloop().
967 # .mainloop().
968 self._banner = None
968 self._banner = None
969
969
970 threading.Thread.__init__(self)
970 threading.Thread.__init__(self)
971
971
972 def mainloop(self, sys_exit=0, banner=None):
972 def mainloop(self, sys_exit=0, banner=None):
973
973
974 import qt
974 import qt
975
975
976 self._banner = banner
976 self._banner = banner
977
977
978 if qt.QApplication.startingUp():
978 if qt.QApplication.startingUp():
979 a = qt.QApplication(sys.argv)
979 a = qt.QApplication(sys.argv)
980
980
981 self.timer = qt.QTimer()
981 self.timer = qt.QTimer()
982 qt.QObject.connect(self.timer,
982 qt.QObject.connect(self.timer,
983 qt.SIGNAL('timeout()'),
983 qt.SIGNAL('timeout()'),
984 self.on_timer)
984 self.on_timer)
985
985
986 self.start()
986 self.start()
987 self.timer.start(self.TIMEOUT, True)
987 self.timer.start(self.TIMEOUT, True)
988 while True:
988 while True:
989 if self.IP._kill: break
989 if self.IP._kill: break
990 self.exec_loop()
990 self.exec_loop()
991 self.join()
991 self.join()
992
992
993 def on_timer(self):
993 def on_timer(self):
994 update_tk(self.tk)
994 update_tk(self.tk)
995 result = self.IP.runcode()
995 result = self.IP.runcode()
996 self.timer.start(self.TIMEOUT, True)
996 self.timer.start(self.TIMEOUT, True)
997 return result
997 return result
998
998
999
999
1000 class IPShellQt4(IPThread):
1000 class IPShellQt4(IPThread):
1001 """Run a Qt event loop in a separate thread.
1001 """Run a Qt event loop in a separate thread.
1002
1002
1003 Python commands can be passed to the thread where they will be executed.
1003 Python commands can be passed to the thread where they will be executed.
1004 This is implemented by periodically checking for passed code using a
1004 This is implemented by periodically checking for passed code using a
1005 Qt timer / slot."""
1005 Qt timer / slot."""
1006
1006
1007 TIMEOUT = 100 # Millisecond interval between timeouts.
1007 TIMEOUT = 100 # Millisecond interval between timeouts.
1008
1008
1009 def __init__(self, argv=None, user_ns=None, user_global_ns=None,
1009 def __init__(self, argv=None, user_ns=None, user_global_ns=None,
1010 debug=0, shell_class=MTInteractiveShell):
1010 debug=0, shell_class=MTInteractiveShell):
1011
1011
1012 from PyQt4 import QtCore, QtGui
1012 from PyQt4 import QtCore, QtGui
1013
1013
1014 try:
1014 try:
1015 # present in PyQt4-4.2.1 or later
1015 # present in PyQt4-4.2.1 or later
1016 QtCore.pyqtRemoveInputHook()
1016 QtCore.pyqtRemoveInputHook()
1017 except AttributeError:
1017 except AttributeError:
1018 pass
1018 pass
1019
1019
1020 if QtCore.PYQT_VERSION_STR == '4.3':
1020 if QtCore.PYQT_VERSION_STR == '4.3':
1021 warn('''PyQt4 version 4.3 detected.
1021 warn('''PyQt4 version 4.3 detected.
1022 If you experience repeated threading warnings, please update PyQt4.
1022 If you experience repeated threading warnings, please update PyQt4.
1023 ''')
1023 ''')
1024
1024
1025 self.exec_ = hijack_qt4()
1025 self.exec_ = hijack_qt4()
1026
1026
1027 # Allows us to use both Tk and QT.
1027 # Allows us to use both Tk and QT.
1028 self.tk = get_tk()
1028 self.tk = get_tk()
1029
1029
1030 self.IP = make_IPython(argv,
1030 self.IP = make_IPython(argv,
1031 user_ns=user_ns,
1031 user_ns=user_ns,
1032 user_global_ns=user_global_ns,
1032 user_global_ns=user_global_ns,
1033 debug=debug,
1033 debug=debug,
1034 shell_class=shell_class,
1034 shell_class=shell_class,
1035 on_kill=[QtGui.qApp.exit])
1035 on_kill=[QtGui.qApp.exit])
1036
1036
1037 # HACK: slot for banner in self; it will be passed to the mainloop
1037 # HACK: slot for banner in self; it will be passed to the mainloop
1038 # method only and .run() needs it. The actual value will be set by
1038 # method only and .run() needs it. The actual value will be set by
1039 # .mainloop().
1039 # .mainloop().
1040 self._banner = None
1040 self._banner = None
1041
1041
1042 threading.Thread.__init__(self)
1042 threading.Thread.__init__(self)
1043
1043
1044 def mainloop(self, sys_exit=0, banner=None):
1044 def mainloop(self, sys_exit=0, banner=None):
1045
1045
1046 from PyQt4 import QtCore, QtGui
1046 from PyQt4 import QtCore, QtGui
1047
1047
1048 self._banner = banner
1048 self._banner = banner
1049
1049
1050 if QtGui.QApplication.startingUp():
1050 if QtGui.QApplication.startingUp():
1051 a = QtGui.QApplication(sys.argv)
1051 a = QtGui.QApplication(sys.argv)
1052
1052
1053 self.timer = QtCore.QTimer()
1053 self.timer = QtCore.QTimer()
1054 QtCore.QObject.connect(self.timer,
1054 QtCore.QObject.connect(self.timer,
1055 QtCore.SIGNAL('timeout()'),
1055 QtCore.SIGNAL('timeout()'),
1056 self.on_timer)
1056 self.on_timer)
1057
1057
1058 self.start()
1058 self.start()
1059 self.timer.start(self.TIMEOUT)
1059 self.timer.start(self.TIMEOUT)
1060 while True:
1060 while True:
1061 if self.IP._kill: break
1061 if self.IP._kill: break
1062 self.exec_()
1062 self.exec_()
1063 self.join()
1063 self.join()
1064
1064
1065 def on_timer(self):
1065 def on_timer(self):
1066 update_tk(self.tk)
1066 update_tk(self.tk)
1067 result = self.IP.runcode()
1067 result = self.IP.runcode()
1068 self.timer.start(self.TIMEOUT)
1068 self.timer.start(self.TIMEOUT)
1069 return result
1069 return result
1070
1070
1071
1071
1072 # A set of matplotlib public IPython shell classes, for single-threaded (Tk*
1072 # A set of matplotlib public IPython shell classes, for single-threaded (Tk*
1073 # and FLTK*) and multithreaded (GTK*, WX* and Qt*) backends to use.
1073 # and FLTK*) and multithreaded (GTK*, WX* and Qt*) backends to use.
1074 def _load_pylab(user_ns):
1074 def _load_pylab(user_ns):
1075 """Allow users to disable pulling all of pylab into the top-level
1075 """Allow users to disable pulling all of pylab into the top-level
1076 namespace.
1076 namespace.
1077
1077
1078 This little utility must be called AFTER the actual ipython instance is
1078 This little utility must be called AFTER the actual ipython instance is
1079 running, since only then will the options file have been fully parsed."""
1079 running, since only then will the options file have been fully parsed."""
1080
1080
1081 ip = IPython.ipapi.get()
1081 ip = IPython.ipapi.get()
1082 if ip.options.pylab_import_all:
1082 if ip.options.pylab_import_all:
1083 ip.ex("from matplotlib.pylab import *")
1083 ip.ex("from matplotlib.pylab import *")
1084 ip.IP.user_config_ns.update(ip.user_ns)
1084 ip.IP.user_config_ns.update(ip.user_ns)
1085
1085
1086
1086
1087 class IPShellMatplotlib(IPShell):
1087 class IPShellMatplotlib(IPShell):
1088 """Subclass IPShell with MatplotlibShell as the internal shell.
1088 """Subclass IPShell with MatplotlibShell as the internal shell.
1089
1089
1090 Single-threaded class, meant for the Tk* and FLTK* backends.
1090 Single-threaded class, meant for the Tk* and FLTK* backends.
1091
1091
1092 Having this on a separate class simplifies the external driver code."""
1092 Having this on a separate class simplifies the external driver code."""
1093
1093
1094 def __init__(self,argv=None,user_ns=None,user_global_ns=None,debug=1):
1094 def __init__(self,argv=None,user_ns=None,user_global_ns=None,debug=1):
1095 IPShell.__init__(self,argv,user_ns,user_global_ns,debug,
1095 IPShell.__init__(self,argv,user_ns,user_global_ns,debug,
1096 shell_class=MatplotlibShell)
1096 shell_class=MatplotlibShell)
1097 _load_pylab(self.IP.user_ns)
1097 _load_pylab(self.IP.user_ns)
1098
1098
1099 class IPShellMatplotlibGTK(IPShellGTK):
1099 class IPShellMatplotlibGTK(IPShellGTK):
1100 """Subclass IPShellGTK with MatplotlibMTShell as the internal shell.
1100 """Subclass IPShellGTK with MatplotlibMTShell as the internal shell.
1101
1101
1102 Multi-threaded class, meant for the GTK* backends."""
1102 Multi-threaded class, meant for the GTK* backends."""
1103
1103
1104 def __init__(self,argv=None,user_ns=None,user_global_ns=None,debug=1):
1104 def __init__(self,argv=None,user_ns=None,user_global_ns=None,debug=1):
1105 IPShellGTK.__init__(self,argv,user_ns,user_global_ns,debug,
1105 IPShellGTK.__init__(self,argv,user_ns,user_global_ns,debug,
1106 shell_class=MatplotlibMTShell)
1106 shell_class=MatplotlibMTShell)
1107 _load_pylab(self.IP.user_ns)
1107 _load_pylab(self.IP.user_ns)
1108
1108
1109 class IPShellMatplotlibWX(IPShellWX):
1109 class IPShellMatplotlibWX(IPShellWX):
1110 """Subclass IPShellWX with MatplotlibMTShell as the internal shell.
1110 """Subclass IPShellWX with MatplotlibMTShell as the internal shell.
1111
1111
1112 Multi-threaded class, meant for the WX* backends."""
1112 Multi-threaded class, meant for the WX* backends."""
1113
1113
1114 def __init__(self,argv=None,user_ns=None,user_global_ns=None,debug=1):
1114 def __init__(self,argv=None,user_ns=None,user_global_ns=None,debug=1):
1115 IPShellWX.__init__(self,argv,user_ns,user_global_ns,debug,
1115 IPShellWX.__init__(self,argv,user_ns,user_global_ns,debug,
1116 shell_class=MatplotlibMTShell)
1116 shell_class=MatplotlibMTShell)
1117 _load_pylab(self.IP.user_ns)
1117 _load_pylab(self.IP.user_ns)
1118
1118
1119 class IPShellMatplotlibQt(IPShellQt):
1119 class IPShellMatplotlibQt(IPShellQt):
1120 """Subclass IPShellQt with MatplotlibMTShell as the internal shell.
1120 """Subclass IPShellQt with MatplotlibMTShell as the internal shell.
1121
1121
1122 Multi-threaded class, meant for the Qt* backends."""
1122 Multi-threaded class, meant for the Qt* backends."""
1123
1123
1124 def __init__(self,argv=None,user_ns=None,user_global_ns=None,debug=1):
1124 def __init__(self,argv=None,user_ns=None,user_global_ns=None,debug=1):
1125 IPShellQt.__init__(self,argv,user_ns,user_global_ns,debug,
1125 IPShellQt.__init__(self,argv,user_ns,user_global_ns,debug,
1126 shell_class=MatplotlibMTShell)
1126 shell_class=MatplotlibMTShell)
1127 _load_pylab(self.IP.user_ns)
1127 _load_pylab(self.IP.user_ns)
1128
1128
1129 class IPShellMatplotlibQt4(IPShellQt4):
1129 class IPShellMatplotlibQt4(IPShellQt4):
1130 """Subclass IPShellQt4 with MatplotlibMTShell as the internal shell.
1130 """Subclass IPShellQt4 with MatplotlibMTShell as the internal shell.
1131
1131
1132 Multi-threaded class, meant for the Qt4* backends."""
1132 Multi-threaded class, meant for the Qt4* backends."""
1133
1133
1134 def __init__(self,argv=None,user_ns=None,user_global_ns=None,debug=1):
1134 def __init__(self,argv=None,user_ns=None,user_global_ns=None,debug=1):
1135 IPShellQt4.__init__(self,argv,user_ns,user_global_ns,debug,
1135 IPShellQt4.__init__(self,argv,user_ns,user_global_ns,debug,
1136 shell_class=MatplotlibMTShell)
1136 shell_class=MatplotlibMTShell)
1137 _load_pylab(self.IP.user_ns)
1137 _load_pylab(self.IP.user_ns)
1138
1138
1139 #-----------------------------------------------------------------------------
1139 #-----------------------------------------------------------------------------
1140 # Factory functions to actually start the proper thread-aware shell
1140 # Factory functions to actually start the proper thread-aware shell
1141
1141
1142 def _select_shell(argv):
1142 def _select_shell(argv):
1143 """Select a shell from the given argv vector.
1143 """Select a shell from the given argv vector.
1144
1144
1145 This function implements the threading selection policy, allowing runtime
1145 This function implements the threading selection policy, allowing runtime
1146 control of the threading mode, both for general users and for matplotlib.
1146 control of the threading mode, both for general users and for matplotlib.
1147
1147
1148 Return:
1148 Return:
1149 Shell class to be instantiated for runtime operation.
1149 Shell class to be instantiated for runtime operation.
1150 """
1150 """
1151
1151
1152 global USE_TK
1152 global USE_TK
1153
1153
1154 mpl_shell = {'gthread' : IPShellMatplotlibGTK,
1154 mpl_shell = {'gthread' : IPShellMatplotlibGTK,
1155 'wthread' : IPShellMatplotlibWX,
1155 'wthread' : IPShellMatplotlibWX,
1156 'qthread' : IPShellMatplotlibQt,
1156 'qthread' : IPShellMatplotlibQt,
1157 'q4thread' : IPShellMatplotlibQt4,
1157 'q4thread' : IPShellMatplotlibQt4,
1158 'tkthread' : IPShellMatplotlib, # Tk is built-in
1158 'tkthread' : IPShellMatplotlib, # Tk is built-in
1159 }
1159 }
1160
1160
1161 th_shell = {'gthread' : IPShellGTK,
1161 th_shell = {'gthread' : IPShellGTK,
1162 'wthread' : IPShellWX,
1162 'wthread' : IPShellWX,
1163 'qthread' : IPShellQt,
1163 'qthread' : IPShellQt,
1164 'q4thread' : IPShellQt4,
1164 'q4thread' : IPShellQt4,
1165 'tkthread' : IPShell, # Tk is built-in
1165 'tkthread' : IPShell, # Tk is built-in
1166 }
1166 }
1167
1167
1168 backends = {'gthread' : 'GTKAgg',
1168 backends = {'gthread' : 'GTKAgg',
1169 'wthread' : 'WXAgg',
1169 'wthread' : 'WXAgg',
1170 'qthread' : 'QtAgg',
1170 'qthread' : 'QtAgg',
1171 'q4thread' :'Qt4Agg',
1171 'q4thread' :'Qt4Agg',
1172 'tkthread' :'TkAgg',
1172 'tkthread' :'TkAgg',
1173 }
1173 }
1174
1174
1175 all_opts = set(['tk','pylab','gthread','qthread','q4thread','wthread',
1175 all_opts = set(['tk','pylab','gthread','qthread','q4thread','wthread',
1176 'tkthread'])
1176 'tkthread'])
1177 user_opts = set([s.replace('-','') for s in argv[:3]])
1177 user_opts = set([s.replace('-','') for s in argv[:3]])
1178 special_opts = user_opts & all_opts
1178 special_opts = user_opts & all_opts
1179
1179
1180 if 'tk' in special_opts:
1180 if 'tk' in special_opts:
1181 USE_TK = True
1181 USE_TK = True
1182 special_opts.remove('tk')
1182 special_opts.remove('tk')
1183
1183
1184 if 'pylab' in special_opts:
1184 if 'pylab' in special_opts:
1185
1185
1186 try:
1186 try:
1187 import matplotlib
1187 import matplotlib
1188 except ImportError:
1188 except ImportError:
1189 error('matplotlib could NOT be imported! Starting normal IPython.')
1189 error('matplotlib could NOT be imported! Starting normal IPython.')
1190 return IPShell
1190 return IPShell
1191
1191
1192 special_opts.remove('pylab')
1192 special_opts.remove('pylab')
1193 # If there's any option left, it means the user wants to force the
1193 # If there's any option left, it means the user wants to force the
1194 # threading backend, else it's auto-selected from the rc file
1194 # threading backend, else it's auto-selected from the rc file
1195 if special_opts:
1195 if special_opts:
1196 th_mode = special_opts.pop()
1196 th_mode = special_opts.pop()
1197 matplotlib.rcParams['backend'] = backends[th_mode]
1197 matplotlib.rcParams['backend'] = backends[th_mode]
1198 else:
1198 else:
1199 backend = matplotlib.rcParams['backend']
1199 backend = matplotlib.rcParams['backend']
1200 if backend.startswith('GTK'):
1200 if backend.startswith('GTK'):
1201 th_mode = 'gthread'
1201 th_mode = 'gthread'
1202 elif backend.startswith('WX'):
1202 elif backend.startswith('WX'):
1203 th_mode = 'wthread'
1203 th_mode = 'wthread'
1204 elif backend.startswith('Qt4'):
1204 elif backend.startswith('Qt4'):
1205 th_mode = 'q4thread'
1205 th_mode = 'q4thread'
1206 elif backend.startswith('Qt'):
1206 elif backend.startswith('Qt'):
1207 th_mode = 'qthread'
1207 th_mode = 'qthread'
1208 else:
1208 else:
1209 # Any other backend, use plain Tk
1209 # Any other backend, use plain Tk
1210 th_mode = 'tkthread'
1210 th_mode = 'tkthread'
1211
1211
1212 return mpl_shell[th_mode]
1212 return mpl_shell[th_mode]
1213 else:
1213 else:
1214 # No pylab requested, just plain threads
1214 # No pylab requested, just plain threads
1215 try:
1215 try:
1216 th_mode = special_opts.pop()
1216 th_mode = special_opts.pop()
1217 except KeyError:
1217 except KeyError:
1218 th_mode = 'tkthread'
1218 th_mode = 'tkthread'
1219 return th_shell[th_mode]
1219 return th_shell[th_mode]
1220
1220
1221
1221
1222 # This is the one which should be called by external code.
1222 # This is the one which should be called by external code.
1223 def start(user_ns = None):
1223 def start(user_ns = None):
1224 """Return a running shell instance, dealing with threading options.
1224 """Return a running shell instance, dealing with threading options.
1225
1225
1226 This is a factory function which will instantiate the proper IPython shell
1226 This is a factory function which will instantiate the proper IPython shell
1227 based on the user's threading choice. Such a selector is needed because
1227 based on the user's threading choice. Such a selector is needed because
1228 different GUI toolkits require different thread handling details."""
1228 different GUI toolkits require different thread handling details."""
1229
1229
1230 shell = _select_shell(sys.argv)
1230 shell = _select_shell(sys.argv)
1231 return shell(user_ns = user_ns)
1231 return shell(user_ns = user_ns)
1232
1232
1233 # Some aliases for backwards compatibility
1233 # Some aliases for backwards compatibility
1234 IPythonShell = IPShell
1234 IPythonShell = IPShell
1235 IPythonShellEmbed = IPShellEmbed
1235 IPythonShellEmbed = IPShellEmbed
1236 #************************ End of file <Shell.py> ***************************
1236 #************************ End of file <Shell.py> ***************************
@@ -1,212 +1,220 b''
1 """
1 """
2 Frontend class that uses IPython0 to prefilter the inputs.
2 Frontend class that uses IPython0 to prefilter the inputs.
3
3
4 Using the IPython0 mechanism gives us access to the magics.
4 Using the IPython0 mechanism gives us access to the magics.
5
5
6 This is a transitory class, used here to do the transition between
6 This is a transitory class, used here to do the transition between
7 ipython0 and ipython1. This class is meant to be short-lived as more
7 ipython0 and ipython1. This class is meant to be short-lived as more
8 functionnality is abstracted out of ipython0 in reusable functions and
8 functionnality is abstracted out of ipython0 in reusable functions and
9 is added on the interpreter. This class can be a used to guide this
9 is added on the interpreter. This class can be a used to guide this
10 refactoring.
10 refactoring.
11 """
11 """
12 __docformat__ = "restructuredtext en"
12 __docformat__ = "restructuredtext en"
13
13
14 #-------------------------------------------------------------------------------
14 #-------------------------------------------------------------------------------
15 # Copyright (C) 2008 The IPython Development Team
15 # Copyright (C) 2008 The IPython Development Team
16 #
16 #
17 # Distributed under the terms of the BSD License. The full license is in
17 # Distributed under the terms of the BSD License. The full license is in
18 # the file COPYING, distributed as part of this software.
18 # the file COPYING, distributed as part of this software.
19 #-------------------------------------------------------------------------------
19 #-------------------------------------------------------------------------------
20
20
21 #-------------------------------------------------------------------------------
21 #-------------------------------------------------------------------------------
22 # Imports
22 # Imports
23 #-------------------------------------------------------------------------------
23 #-------------------------------------------------------------------------------
24 import sys
24 import sys
25
25
26 from linefrontendbase import LineFrontEndBase, common_prefix
26 from linefrontendbase import LineFrontEndBase, common_prefix
27
27
28 from IPython.ipmaker import make_IPython
28 from IPython.ipmaker import make_IPython
29 from IPython.ipapi import IPApi
29 from IPython.ipapi import IPApi
30 from IPython.kernel.core.redirector_output_trap import RedirectorOutputTrap
30 from IPython.kernel.core.redirector_output_trap import RedirectorOutputTrap
31
31
32 from IPython.kernel.core.sync_traceback_trap import SyncTracebackTrap
32 from IPython.kernel.core.sync_traceback_trap import SyncTracebackTrap
33
33
34 from IPython.genutils import Term
34 from IPython.genutils import Term
35 import pydoc
35 import pydoc
36 import os
36 import os
37
37
38
38
39 def mk_system_call(system_call_function, command):
39 def mk_system_call(system_call_function, command):
40 """ given a os.system replacement, and a leading string command,
40 """ given a os.system replacement, and a leading string command,
41 returns a function that will execute the command with the given
41 returns a function that will execute the command with the given
42 argument string.
42 argument string.
43 """
43 """
44 def my_system_call(args):
44 def my_system_call(args):
45 system_call_function("%s %s" % (command, args))
45 system_call_function("%s %s" % (command, args))
46 return my_system_call
46 return my_system_call
47
47
48 #-------------------------------------------------------------------------------
48 #-------------------------------------------------------------------------------
49 # Frontend class using ipython0 to do the prefiltering.
49 # Frontend class using ipython0 to do the prefiltering.
50 #-------------------------------------------------------------------------------
50 #-------------------------------------------------------------------------------
51 class PrefilterFrontEnd(LineFrontEndBase):
51 class PrefilterFrontEnd(LineFrontEndBase):
52 """ Class that uses ipython0 to do prefilter the input, do the
52 """ Class that uses ipython0 to do prefilter the input, do the
53 completion and the magics.
53 completion and the magics.
54
54
55 The core trick is to use an ipython0 instance to prefilter the
55 The core trick is to use an ipython0 instance to prefilter the
56 input, and share the namespace between the interpreter instance used
56 input, and share the namespace between the interpreter instance used
57 to execute the statements and the ipython0 used for code
57 to execute the statements and the ipython0 used for code
58 completion...
58 completion...
59 """
59 """
60
60
61 def __init__(self, *args, **kwargs):
61 def __init__(self, ipython0=None, *args, **kwargs):
62 """ Parameters:
63 -----------
64
65 ipython0: an optional ipython0 instance to use for command
66 prefiltering and completion.
67 """
62 self.save_output_hooks()
68 self.save_output_hooks()
63 # Instanciate an IPython0 interpreter to be able to use the
69 if ipython0 is None:
64 # prefiltering.
70 # Instanciate an IPython0 interpreter to be able to use the
65 self.ipython0 = make_IPython()
71 # prefiltering.
72 ipython0 = make_IPython()
73 self.ipython0 = ipython0
66 # Set the pager:
74 # Set the pager:
67 self.ipython0.set_hook('show_in_pager',
75 self.ipython0.set_hook('show_in_pager',
68 lambda s, string: self.write("\n"+string))
76 lambda s, string: self.write("\n" + string))
69 self.ipython0.write = self.write
77 self.ipython0.write = self.write
70 self._ip = _ip = IPApi(self.ipython0)
78 self._ip = _ip = IPApi(self.ipython0)
71 # Make sure the raw system call doesn't get called, as we don't
79 # Make sure the raw system call doesn't get called, as we don't
72 # have a stdin accessible.
80 # have a stdin accessible.
73 self._ip.system = self.system_call
81 self._ip.system = self.system_call
74 # XXX: Muck around with magics so that they work better
82 # XXX: Muck around with magics so that they work better
75 # in our environment
83 # in our environment
76 self.ipython0.magic_ls = mk_system_call(self.system_call,
84 self.ipython0.magic_ls = mk_system_call(self.system_call,
77 'ls -CF')
85 'ls -CF')
78 # And now clean up the mess created by ipython0
86 # And now clean up the mess created by ipython0
79 self.release_output()
87 self.release_output()
80 if not 'banner' in kwargs:
88 if not 'banner' in kwargs:
81 kwargs['banner'] = self.ipython0.BANNER + """
89 kwargs['banner'] = self.ipython0.BANNER + """
82 This is the wx frontend, by Gael Varoquaux. This is EXPERIMENTAL code."""
90 This is the wx frontend, by Gael Varoquaux. This is EXPERIMENTAL code."""
83
91
84 LineFrontEndBase.__init__(self, *args, **kwargs)
92 LineFrontEndBase.__init__(self, *args, **kwargs)
85 # XXX: Hack: mix the two namespaces
93 # XXX: Hack: mix the two namespaces
86 self.shell.user_ns = self.ipython0.user_ns
94 self.shell.user_ns = self.ipython0.user_ns
87 self.shell.user_global_ns = self.ipython0.user_global_ns
95 self.shell.user_global_ns = self.ipython0.user_global_ns
88
96
89 self.shell.output_trap = RedirectorOutputTrap(
97 self.shell.output_trap = RedirectorOutputTrap(
90 out_callback=self.write,
98 out_callback=self.write,
91 err_callback=self.write,
99 err_callback=self.write,
92 )
100 )
93 self.shell.traceback_trap = SyncTracebackTrap(
101 self.shell.traceback_trap = SyncTracebackTrap(
94 formatters=self.shell.traceback_trap.formatters,
102 formatters=self.shell.traceback_trap.formatters,
95 )
103 )
96
104
97 #--------------------------------------------------------------------------
105 #--------------------------------------------------------------------------
98 # FrontEndBase interface
106 # FrontEndBase interface
99 #--------------------------------------------------------------------------
107 #--------------------------------------------------------------------------
100
108
101 def show_traceback(self):
109 def show_traceback(self):
102 """ Use ipython0 to capture the last traceback and display it.
110 """ Use ipython0 to capture the last traceback and display it.
103 """
111 """
104 self.capture_output()
112 self.capture_output()
105 self.ipython0.showtraceback()
113 self.ipython0.showtraceback()
106 self.release_output()
114 self.release_output()
107
115
108
116
109 def execute(self, python_string, raw_string=None):
117 def execute(self, python_string, raw_string=None):
110 if self.debug:
118 if self.debug:
111 print 'Executing Python code:', repr(python_string)
119 print 'Executing Python code:', repr(python_string)
112 self.capture_output()
120 self.capture_output()
113 LineFrontEndBase.execute(self, python_string,
121 LineFrontEndBase.execute(self, python_string,
114 raw_string=raw_string)
122 raw_string=raw_string)
115 self.release_output()
123 self.release_output()
116
124
117
125
118 def save_output_hooks(self):
126 def save_output_hooks(self):
119 """ Store all the output hooks we can think of, to be able to
127 """ Store all the output hooks we can think of, to be able to
120 restore them.
128 restore them.
121
129
122 We need to do this early, as starting the ipython0 instance will
130 We need to do this early, as starting the ipython0 instance will
123 screw ouput hooks.
131 screw ouput hooks.
124 """
132 """
125 self.__old_cout_write = Term.cout.write
133 self.__old_cout_write = Term.cout.write
126 self.__old_cerr_write = Term.cerr.write
134 self.__old_cerr_write = Term.cerr.write
127 self.__old_stdout = sys.stdout
135 self.__old_stdout = sys.stdout
128 self.__old_stderr= sys.stderr
136 self.__old_stderr= sys.stderr
129 self.__old_help_output = pydoc.help.output
137 self.__old_help_output = pydoc.help.output
130 self.__old_display_hook = sys.displayhook
138 self.__old_display_hook = sys.displayhook
131
139
132
140
133 def capture_output(self):
141 def capture_output(self):
134 """ Capture all the output mechanisms we can think of.
142 """ Capture all the output mechanisms we can think of.
135 """
143 """
136 self.save_output_hooks()
144 self.save_output_hooks()
137 Term.cout.write = self.write
145 Term.cout.write = self.write
138 Term.cerr.write = self.write
146 Term.cerr.write = self.write
139 sys.stdout = Term.cout
147 sys.stdout = Term.cout
140 sys.stderr = Term.cerr
148 sys.stderr = Term.cerr
141 pydoc.help.output = self.shell.output_trap.out
149 pydoc.help.output = self.shell.output_trap.out
142
150
143
151
144 def release_output(self):
152 def release_output(self):
145 """ Release all the different captures we have made.
153 """ Release all the different captures we have made.
146 """
154 """
147 Term.cout.write = self.__old_cout_write
155 Term.cout.write = self.__old_cout_write
148 Term.cerr.write = self.__old_cerr_write
156 Term.cerr.write = self.__old_cerr_write
149 sys.stdout = self.__old_stdout
157 sys.stdout = self.__old_stdout
150 sys.stderr = self.__old_stderr
158 sys.stderr = self.__old_stderr
151 pydoc.help.output = self.__old_help_output
159 pydoc.help.output = self.__old_help_output
152 sys.displayhook = self.__old_display_hook
160 sys.displayhook = self.__old_display_hook
153
161
154
162
155 def complete(self, line):
163 def complete(self, line):
156 word = line.split('\n')[-1].split(' ')[-1]
164 word = line.split('\n')[-1].split(' ')[-1]
157 completions = self.ipython0.complete(word)
165 completions = self.ipython0.complete(word)
158 # FIXME: The proper sort should be done in the complete method.
166 # FIXME: The proper sort should be done in the complete method.
159 key = lambda x: x.replace('_', '')
167 key = lambda x: x.replace('_', '')
160 completions.sort(key=key)
168 completions.sort(key=key)
161 if completions:
169 if completions:
162 prefix = common_prefix(completions)
170 prefix = common_prefix(completions)
163 line = line[:-len(word)] + prefix
171 line = line[:-len(word)] + prefix
164 return line, completions
172 return line, completions
165
173
166
174
167 #--------------------------------------------------------------------------
175 #--------------------------------------------------------------------------
168 # LineFrontEndBase interface
176 # LineFrontEndBase interface
169 #--------------------------------------------------------------------------
177 #--------------------------------------------------------------------------
170
178
171 def prefilter_input(self, input_string):
179 def prefilter_input(self, input_string):
172 """ Using IPython0 to prefilter the commands to turn them
180 """ Using IPython0 to prefilter the commands to turn them
173 in executable statements that are valid Python strings.
181 in executable statements that are valid Python strings.
174 """
182 """
175 input_string = LineFrontEndBase.prefilter_input(self, input_string)
183 input_string = LineFrontEndBase.prefilter_input(self, input_string)
176 filtered_lines = []
184 filtered_lines = []
177 # The IPython0 prefilters sometime produce output. We need to
185 # The IPython0 prefilters sometime produce output. We need to
178 # capture it.
186 # capture it.
179 self.capture_output()
187 self.capture_output()
180 self.last_result = dict(number=self.prompt_number)
188 self.last_result = dict(number=self.prompt_number)
181 try:
189 try:
182 for line in input_string.split('\n'):
190 for line in input_string.split('\n'):
183 filtered_lines.append(
191 filtered_lines.append(
184 self.ipython0.prefilter(line, False).rstrip())
192 self.ipython0.prefilter(line, False).rstrip())
185 except:
193 except:
186 # XXX: probably not the right thing to do.
194 # XXX: probably not the right thing to do.
187 self.ipython0.showsyntaxerror()
195 self.ipython0.showsyntaxerror()
188 self.after_execute()
196 self.after_execute()
189 finally:
197 finally:
190 self.release_output()
198 self.release_output()
191
199
192 # Clean up the trailing whitespace, to avoid indentation errors
200 # Clean up the trailing whitespace, to avoid indentation errors
193 filtered_string = '\n'.join(filtered_lines)
201 filtered_string = '\n'.join(filtered_lines)
194 return filtered_string
202 return filtered_string
195
203
196
204
197 #--------------------------------------------------------------------------
205 #--------------------------------------------------------------------------
198 # PrefilterFrontEnd interface
206 # PrefilterFrontEnd interface
199 #--------------------------------------------------------------------------
207 #--------------------------------------------------------------------------
200
208
201 def system_call(self, command_string):
209 def system_call(self, command_string):
202 """ Allows for frontend to define their own system call, to be
210 """ Allows for frontend to define their own system call, to be
203 able capture output and redirect input.
211 able capture output and redirect input.
204 """
212 """
205 return os.system(command_string)
213 return os.system(command_string)
206
214
207
215
208 def do_exit(self):
216 def do_exit(self):
209 """ Exit the shell, cleanup and save the history.
217 """ Exit the shell, cleanup and save the history.
210 """
218 """
211 self.ipython0.atexit_operations()
219 self.ipython0.atexit_operations()
212
220
@@ -1,130 +1,132 b''
1 # encoding: utf-8
1 # encoding: utf-8
2 """
2 """
3 Test process execution and IO redirection.
3 Test process execution and IO redirection.
4 """
4 """
5
5
6 __docformat__ = "restructuredtext en"
6 __docformat__ = "restructuredtext en"
7
7
8 #-------------------------------------------------------------------------------
8 #-------------------------------------------------------------------------------
9 # Copyright (C) 2008 The IPython Development Team
9 # Copyright (C) 2008 The IPython Development Team
10 #
10 #
11 # Distributed under the terms of the BSD License. The full license is
11 # Distributed under the terms of the BSD License. The full license is
12 # in the file COPYING, distributed as part of this software.
12 # in the file COPYING, distributed as part of this software.
13 #-------------------------------------------------------------------------------
13 #-------------------------------------------------------------------------------
14
14
15 from IPython.frontend.prefilterfrontend import PrefilterFrontEnd
15 from IPython.frontend.prefilterfrontend import PrefilterFrontEnd
16 from cStringIO import StringIO
16 from cStringIO import StringIO
17 import string
17 import string
18 import sys
18 import sys
19 from IPython.ipapi import get as get_ipython0
19
20
20 class TestPrefilterFrontEnd(PrefilterFrontEnd):
21 class TestPrefilterFrontEnd(PrefilterFrontEnd):
21
22
22 input_prompt_template = string.Template('')
23 input_prompt_template = string.Template('')
23 output_prompt_template = string.Template('')
24 output_prompt_template = string.Template('')
24
25
25 def __init__(self):
26 def __init__(self):
27 ipython0 = get_ipython0()
26 self.out = StringIO()
28 self.out = StringIO()
27 PrefilterFrontEnd.__init__(self)
29 PrefilterFrontEnd.__init__(self, ipython0=ipython0)
28
30
29 def write(self, string):
31 def write(self, string):
30 self.out.write(string)
32 self.out.write(string)
31
33
32 def _on_enter(self):
34 def _on_enter(self):
33 self.input_buffer += '\n'
35 self.input_buffer += '\n'
34 PrefilterFrontEnd._on_enter(self)
36 PrefilterFrontEnd._on_enter(self)
35
37
36
38
37 def test_execution():
39 def test_execution():
38 """ Test execution of a command.
40 """ Test execution of a command.
39 """
41 """
40 f = TestPrefilterFrontEnd()
42 f = TestPrefilterFrontEnd()
41 f.input_buffer = 'print 1\n'
43 f.input_buffer = 'print 1\n'
42 f._on_enter()
44 f._on_enter()
43 assert f.out.getvalue() == '1\n'
45 assert f.out.getvalue() == '1\n'
44
46
45
47
46 def test_multiline():
48 def test_multiline():
47 """ Test execution of a multiline command.
49 """ Test execution of a multiline command.
48 """
50 """
49 f = TestPrefilterFrontEnd()
51 f = TestPrefilterFrontEnd()
50 f.input_buffer = 'if True:'
52 f.input_buffer = 'if True:'
51 f._on_enter()
53 f._on_enter()
52 f.input_buffer += 'print 1'
54 f.input_buffer += 'print 1'
53 f._on_enter()
55 f._on_enter()
54 assert f.out.getvalue() == ''
56 assert f.out.getvalue() == ''
55 f._on_enter()
57 f._on_enter()
56 assert f.out.getvalue() == '1\n'
58 assert f.out.getvalue() == '1\n'
57 f = TestPrefilterFrontEnd()
59 f = TestPrefilterFrontEnd()
58 f.input_buffer='(1 +'
60 f.input_buffer='(1 +'
59 f._on_enter()
61 f._on_enter()
60 f.input_buffer += '0)'
62 f.input_buffer += '0)'
61 f._on_enter()
63 f._on_enter()
62 assert f.out.getvalue() == ''
64 assert f.out.getvalue() == ''
63 f._on_enter()
65 f._on_enter()
64 assert f.out.getvalue() == '1\n'
66 assert f.out.getvalue() == '1\n'
65
67
66
68
67 def test_capture():
69 def test_capture():
68 """ Test the capture of output in different channels.
70 """ Test the capture of output in different channels.
69 """
71 """
70 # Test on the OS-level stdout, stderr.
72 # Test on the OS-level stdout, stderr.
71 f = TestPrefilterFrontEnd()
73 f = TestPrefilterFrontEnd()
72 f.input_buffer = \
74 f.input_buffer = \
73 'import os; out=os.fdopen(1, "w"); out.write("1") ; out.flush()'
75 'import os; out=os.fdopen(1, "w"); out.write("1") ; out.flush()'
74 f._on_enter()
76 f._on_enter()
75 assert f.out.getvalue() == '1'
77 assert f.out.getvalue() == '1'
76 f = TestPrefilterFrontEnd()
78 f = TestPrefilterFrontEnd()
77 f.input_buffer = \
79 f.input_buffer = \
78 'import os; out=os.fdopen(2, "w"); out.write("1") ; out.flush()'
80 'import os; out=os.fdopen(2, "w"); out.write("1") ; out.flush()'
79 f._on_enter()
81 f._on_enter()
80 assert f.out.getvalue() == '1'
82 assert f.out.getvalue() == '1'
81
83
82
84
83 def test_magic():
85 def test_magic():
84 """ Test the magic expansion and history.
86 """ Test the magic expansion and history.
85
87
86 This test is fairly fragile and will break when magics change.
88 This test is fairly fragile and will break when magics change.
87 """
89 """
88 f = TestPrefilterFrontEnd()
90 f = TestPrefilterFrontEnd()
89 f.input_buffer += '%who\n'
91 f.input_buffer += '%who\n'
90 f._on_enter()
92 f._on_enter()
91 assert f.out.getvalue() == 'Interactive namespace is empty.\n'
93 assert f.out.getvalue() == 'Interactive namespace is empty.\n'
92
94
93
95
94 def test_help():
96 def test_help():
95 """ Test object inspection.
97 """ Test object inspection.
96 """
98 """
97 f = TestPrefilterFrontEnd()
99 f = TestPrefilterFrontEnd()
98 f.input_buffer += "def f():"
100 f.input_buffer += "def f():"
99 f._on_enter()
101 f._on_enter()
100 f.input_buffer += "'foobar'"
102 f.input_buffer += "'foobar'"
101 f._on_enter()
103 f._on_enter()
102 f.input_buffer += "pass"
104 f.input_buffer += "pass"
103 f._on_enter()
105 f._on_enter()
104 f._on_enter()
106 f._on_enter()
105 f.input_buffer += "f?"
107 f.input_buffer += "f?"
106 f._on_enter()
108 f._on_enter()
107 assert f.out.getvalue().split()[-1] == 'foobar'
109 assert f.out.getvalue().split()[-1] == 'foobar'
108
110
109
111
110 def test_completion():
112 def test_completion():
111 """ Test command-line completion.
113 """ Test command-line completion.
112 """
114 """
113 f = TestPrefilterFrontEnd()
115 f = TestPrefilterFrontEnd()
114 f.input_buffer = 'zzza = 1'
116 f.input_buffer = 'zzza = 1'
115 f._on_enter()
117 f._on_enter()
116 f.input_buffer = 'zzzb = 2'
118 f.input_buffer = 'zzzb = 2'
117 f._on_enter()
119 f._on_enter()
118 f.input_buffer = 'zz'
120 f.input_buffer = 'zz'
119 f.complete_current_input()
121 f.complete_current_input()
120 assert f.out.getvalue() == '\nzzza zzzb '
122 assert f.out.getvalue() == '\nzzza zzzb '
121 assert f.input_buffer == 'zzz'
123 assert f.input_buffer == 'zzz'
122
124
123
125
124 if __name__ == '__main__':
126 if __name__ == '__main__':
125 test_magic()
127 test_magic()
126 test_help()
128 test_help()
127 test_execution()
129 test_execution()
128 test_multiline()
130 test_multiline()
129 test_capture()
131 test_capture()
130 test_completion()
132 test_completion()
@@ -1,647 +1,687 b''
1 """IPython customization API
1 """IPython customization API
2
2
3 Your one-stop module for configuring & extending ipython
3 Your one-stop module for configuring & extending ipython
4
4
5 The API will probably break when ipython 1.0 is released, but so
5 The API will probably break when ipython 1.0 is released, but so
6 will the other configuration method (rc files).
6 will the other configuration method (rc files).
7
7
8 All names prefixed by underscores are for internal use, not part
8 All names prefixed by underscores are for internal use, not part
9 of the public api.
9 of the public api.
10
10
11 Below is an example that you can just put to a module and import from ipython.
11 Below is an example that you can just put to a module and import from ipython.
12
12
13 A good practice is to install the config script below as e.g.
13 A good practice is to install the config script below as e.g.
14
14
15 ~/.ipython/my_private_conf.py
15 ~/.ipython/my_private_conf.py
16
16
17 And do
17 And do
18
18
19 import_mod my_private_conf
19 import_mod my_private_conf
20
20
21 in ~/.ipython/ipythonrc
21 in ~/.ipython/ipythonrc
22
22
23 That way the module is imported at startup and you can have all your
23 That way the module is imported at startup and you can have all your
24 personal configuration (as opposed to boilerplate ipythonrc-PROFILENAME
24 personal configuration (as opposed to boilerplate ipythonrc-PROFILENAME
25 stuff) in there.
25 stuff) in there.
26
26
27 -----------------------------------------------
27 -----------------------------------------------
28 import IPython.ipapi
28 import IPython.ipapi
29 ip = IPython.ipapi.get()
29 ip = IPython.ipapi.get()
30
30
31 def ankka_f(self, arg):
31 def ankka_f(self, arg):
32 print 'Ankka',self,'says uppercase:',arg.upper()
32 print 'Ankka',self,'says uppercase:',arg.upper()
33
33
34 ip.expose_magic('ankka',ankka_f)
34 ip.expose_magic('ankka',ankka_f)
35
35
36 ip.magic('alias sayhi echo "Testing, hi ok"')
36 ip.magic('alias sayhi echo "Testing, hi ok"')
37 ip.magic('alias helloworld echo "Hello world"')
37 ip.magic('alias helloworld echo "Hello world"')
38 ip.system('pwd')
38 ip.system('pwd')
39
39
40 ip.ex('import re')
40 ip.ex('import re')
41 ip.ex('''
41 ip.ex('''
42 def funcci(a,b):
42 def funcci(a,b):
43 print a+b
43 print a+b
44 print funcci(3,4)
44 print funcci(3,4)
45 ''')
45 ''')
46 ip.ex('funcci(348,9)')
46 ip.ex('funcci(348,9)')
47
47
48 def jed_editor(self,filename, linenum=None):
48 def jed_editor(self,filename, linenum=None):
49 print 'Calling my own editor, jed ... via hook!'
49 print 'Calling my own editor, jed ... via hook!'
50 import os
50 import os
51 if linenum is None: linenum = 0
51 if linenum is None: linenum = 0
52 os.system('jed +%d %s' % (linenum, filename))
52 os.system('jed +%d %s' % (linenum, filename))
53 print 'exiting jed'
53 print 'exiting jed'
54
54
55 ip.set_hook('editor',jed_editor)
55 ip.set_hook('editor',jed_editor)
56
56
57 o = ip.options
57 o = ip.options
58 o.autocall = 2 # FULL autocall mode
58 o.autocall = 2 # FULL autocall mode
59
59
60 print 'done!'
60 print 'done!'
61 """
61 """
62
62
63 #-----------------------------------------------------------------------------
63 #-----------------------------------------------------------------------------
64 # Modules and globals
64 # Modules and globals
65
65
66 # stdlib imports
66 # stdlib imports
67 import __builtin__
67 import __builtin__
68 import sys
68 import sys
69
69
70 # contains the most recently instantiated IPApi
70 # contains the most recently instantiated IPApi
71 _RECENT_IP = None
71 _RECENT_IP = None
72
72
73 #-----------------------------------------------------------------------------
73 #-----------------------------------------------------------------------------
74 # Code begins
74 # Code begins
75
75
76 class TryNext(Exception):
76 class TryNext(Exception):
77 """Try next hook exception.
77 """Try next hook exception.
78
78
79 Raise this in your hook function to indicate that the next hook handler
79 Raise this in your hook function to indicate that the next hook handler
80 should be used to handle the operation. If you pass arguments to the
80 should be used to handle the operation. If you pass arguments to the
81 constructor those arguments will be used by the next hook instead of the
81 constructor those arguments will be used by the next hook instead of the
82 original ones.
82 original ones.
83 """
83 """
84
84
85 def __init__(self, *args, **kwargs):
85 def __init__(self, *args, **kwargs):
86 self.args = args
86 self.args = args
87 self.kwargs = kwargs
87 self.kwargs = kwargs
88
88
89
89
90 class UsageError(Exception):
90 class UsageError(Exception):
91 """ Error in magic function arguments, etc.
91 """ Error in magic function arguments, etc.
92
92
93 Something that probably won't warrant a full traceback, but should
93 Something that probably won't warrant a full traceback, but should
94 nevertheless interrupt a macro / batch file.
94 nevertheless interrupt a macro / batch file.
95 """
95 """
96
96
97
97
98 class IPyAutocall:
98 class IPyAutocall:
99 """ Instances of this class are always autocalled
99 """ Instances of this class are always autocalled
100
100
101 This happens regardless of 'autocall' variable state. Use this to
101 This happens regardless of 'autocall' variable state. Use this to
102 develop macro-like mechanisms.
102 develop macro-like mechanisms.
103 """
103 """
104
104
105 def set_ip(self,ip):
105 def set_ip(self,ip):
106 """ Will be used to set _ip point to current ipython instance b/f call
106 """ Will be used to set _ip point to current ipython instance b/f call
107
107
108 Override this method if you don't want this to happen.
108 Override this method if you don't want this to happen.
109
109
110 """
110 """
111 self._ip = ip
111 self._ip = ip
112
112
113
113
114 class IPythonNotRunning:
114 class IPythonNotRunning:
115 """Dummy do-nothing class.
115 """Dummy do-nothing class.
116
116
117 Instances of this class return a dummy attribute on all accesses, which
117 Instances of this class return a dummy attribute on all accesses, which
118 can be called and warns. This makes it easier to write scripts which use
118 can be called and warns. This makes it easier to write scripts which use
119 the ipapi.get() object for informational purposes to operate both with and
119 the ipapi.get() object for informational purposes to operate both with and
120 without ipython. Obviously code which uses the ipython object for
120 without ipython. Obviously code which uses the ipython object for
121 computations will not work, but this allows a wider range of code to
121 computations will not work, but this allows a wider range of code to
122 transparently work whether ipython is being used or not."""
122 transparently work whether ipython is being used or not."""
123
123
124 def __init__(self,warn=True):
124 def __init__(self,warn=True):
125 if warn:
125 if warn:
126 self.dummy = self._dummy_warn
126 self.dummy = self._dummy_warn
127 else:
127 else:
128 self.dummy = self._dummy_silent
128 self.dummy = self._dummy_silent
129
129
130 def __str__(self):
130 def __str__(self):
131 return "<IPythonNotRunning>"
131 return "<IPythonNotRunning>"
132
132
133 __repr__ = __str__
133 __repr__ = __str__
134
134
135 def __getattr__(self,name):
135 def __getattr__(self,name):
136 return self.dummy
136 return self.dummy
137
137
138 def _dummy_warn(self,*args,**kw):
138 def _dummy_warn(self,*args,**kw):
139 """Dummy function, which doesn't do anything but warn."""
139 """Dummy function, which doesn't do anything but warn."""
140
140
141 print ("IPython is not running, this is a dummy no-op function")
141 print ("IPython is not running, this is a dummy no-op function")
142
142
143 def _dummy_silent(self,*args,**kw):
143 def _dummy_silent(self,*args,**kw):
144 """Dummy function, which doesn't do anything and emits no warnings."""
144 """Dummy function, which doesn't do anything and emits no warnings."""
145 pass
145 pass
146
146
147
147
148 def get(allow_dummy=False,dummy_warn=True):
148 def get(allow_dummy=False,dummy_warn=True):
149 """Get an IPApi object.
149 """Get an IPApi object.
150
150
151 If allow_dummy is true, returns an instance of IPythonNotRunning
151 If allow_dummy is true, returns an instance of IPythonNotRunning
152 instead of None if not running under IPython.
152 instead of None if not running under IPython.
153
153
154 If dummy_warn is false, the dummy instance will be completely silent.
154 If dummy_warn is false, the dummy instance will be completely silent.
155
155
156 Running this should be the first thing you do when writing extensions that
156 Running this should be the first thing you do when writing extensions that
157 can be imported as normal modules. You can then direct all the
157 can be imported as normal modules. You can then direct all the
158 configuration operations against the returned object.
158 configuration operations against the returned object.
159 """
159 """
160 global _RECENT_IP
160 global _RECENT_IP
161 if allow_dummy and not _RECENT_IP:
161 if allow_dummy and not _RECENT_IP:
162 _RECENT_IP = IPythonNotRunning(dummy_warn)
162 _RECENT_IP = IPythonNotRunning(dummy_warn)
163 return _RECENT_IP
163 return _RECENT_IP
164
164
165
165
166 class IPApi(object):
166 class IPApi(object):
167 """ The actual API class for configuring IPython
167 """ The actual API class for configuring IPython
168
168
169 You should do all of the IPython configuration by getting an IPApi object
169 You should do all of the IPython configuration by getting an IPApi object
170 with IPython.ipapi.get() and using the attributes and methods of the
170 with IPython.ipapi.get() and using the attributes and methods of the
171 returned object."""
171 returned object."""
172
172
173 def __init__(self,ip):
173 def __init__(self,ip):
174
174
175 global _RECENT_IP
175 global _RECENT_IP
176
176
177 # All attributes exposed here are considered to be the public API of
177 # All attributes exposed here are considered to be the public API of
178 # IPython. As needs dictate, some of these may be wrapped as
178 # IPython. As needs dictate, some of these may be wrapped as
179 # properties.
179 # properties.
180
180
181 self.magic = ip.ipmagic
181 self.magic = ip.ipmagic
182
182
183 self.system = ip.system
183 self.system = ip.system
184
184
185 self.set_hook = ip.set_hook
185 self.set_hook = ip.set_hook
186
186
187 self.set_custom_exc = ip.set_custom_exc
187 self.set_custom_exc = ip.set_custom_exc
188
188
189 self.user_ns = ip.user_ns
189 self.user_ns = ip.user_ns
190 self.user_ns['_ip'] = self
190 self.user_ns['_ip'] = self
191
191
192 self.set_crash_handler = ip.set_crash_handler
192 self.set_crash_handler = ip.set_crash_handler
193
193
194 # Session-specific data store, which can be used to store
194 # Session-specific data store, which can be used to store
195 # data that should persist through the ipython session.
195 # data that should persist through the ipython session.
196 self.meta = ip.meta
196 self.meta = ip.meta
197
197
198 # The ipython instance provided
198 # The ipython instance provided
199 self.IP = ip
199 self.IP = ip
200
200
201 self.extensions = {}
201 self.extensions = {}
202
202
203 self.dbg = DebugTools(self)
203 self.dbg = DebugTools(self)
204
204
205 _RECENT_IP = self
205 _RECENT_IP = self
206
206
207 # Use a property for some things which are added to the instance very
207 # Use a property for some things which are added to the instance very
208 # late. I don't have time right now to disentangle the initialization
208 # late. I don't have time right now to disentangle the initialization
209 # order issues, so a property lets us delay item extraction while
209 # order issues, so a property lets us delay item extraction while
210 # providing a normal attribute API.
210 # providing a normal attribute API.
211 def get_db(self):
211 def get_db(self):
212 """A handle to persistent dict-like database (a PickleShareDB object)"""
212 """A handle to persistent dict-like database (a PickleShareDB object)"""
213 return self.IP.db
213 return self.IP.db
214
214
215 db = property(get_db,None,None,get_db.__doc__)
215 db = property(get_db,None,None,get_db.__doc__)
216
216
217 def get_options(self):
217 def get_options(self):
218 """All configurable variables."""
218 """All configurable variables."""
219
219
220 # catch typos by disabling new attribute creation. If new attr creation
220 # catch typos by disabling new attribute creation. If new attr creation
221 # is in fact wanted (e.g. when exposing new options), do
221 # is in fact wanted (e.g. when exposing new options), do
222 # allow_new_attr(True) for the received rc struct.
222 # allow_new_attr(True) for the received rc struct.
223
223
224 self.IP.rc.allow_new_attr(False)
224 self.IP.rc.allow_new_attr(False)
225 return self.IP.rc
225 return self.IP.rc
226
226
227 options = property(get_options,None,None,get_options.__doc__)
227 options = property(get_options,None,None,get_options.__doc__)
228
228
229 def expose_magic(self,magicname, func):
229 def expose_magic(self,magicname, func):
230 """Expose own function as magic function for ipython
230 """Expose own function as magic function for ipython
231
231
232 def foo_impl(self,parameter_s=''):
232 def foo_impl(self,parameter_s=''):
233 'My very own magic!. (Use docstrings, IPython reads them).'
233 'My very own magic!. (Use docstrings, IPython reads them).'
234 print 'Magic function. Passed parameter is between < >:'
234 print 'Magic function. Passed parameter is between < >:'
235 print '<%s>' % parameter_s
235 print '<%s>' % parameter_s
236 print 'The self object is:',self
236 print 'The self object is:',self
237
237
238 ipapi.expose_magic('foo',foo_impl)
238 ipapi.expose_magic('foo',foo_impl)
239 """
239 """
240
240
241 import new
241 import new
242 im = new.instancemethod(func,self.IP, self.IP.__class__)
242 im = new.instancemethod(func,self.IP, self.IP.__class__)
243 old = getattr(self.IP, "magic_" + magicname, None)
243 old = getattr(self.IP, "magic_" + magicname, None)
244 if old:
244 if old:
245 self.dbg.debug_stack("Magic redefinition '%s', old %s" %
245 self.dbg.debug_stack("Magic redefinition '%s', old %s" %
246 (magicname,old) )
246 (magicname,old) )
247
247
248 setattr(self.IP, "magic_" + magicname, im)
248 setattr(self.IP, "magic_" + magicname, im)
249
249
250 def ex(self,cmd):
250 def ex(self,cmd):
251 """ Execute a normal python statement in user namespace """
251 """ Execute a normal python statement in user namespace """
252 exec cmd in self.user_ns
252 exec cmd in self.user_ns
253
253
254 def ev(self,expr):
254 def ev(self,expr):
255 """ Evaluate python expression expr in user namespace
255 """ Evaluate python expression expr in user namespace
256
256
257 Returns the result of evaluation"""
257 Returns the result of evaluation"""
258 return eval(expr,self.user_ns)
258 return eval(expr,self.user_ns)
259
259
260 def runlines(self,lines):
260 def runlines(self,lines):
261 """ Run the specified lines in interpreter, honoring ipython directives.
261 """ Run the specified lines in interpreter, honoring ipython directives.
262
262
263 This allows %magic and !shell escape notations.
263 This allows %magic and !shell escape notations.
264
264
265 Takes either all lines in one string or list of lines.
265 Takes either all lines in one string or list of lines.
266 """
266 """
267
267
268 def cleanup_ipy_script(script):
268 def cleanup_ipy_script(script):
269 """ Make a script safe for _ip.runlines()
269 """ Make a script safe for _ip.runlines()
270
270
271 - Removes empty lines Suffixes all indented blocks that end with
271 - Removes empty lines Suffixes all indented blocks that end with
272 - unindented lines with empty lines
272 - unindented lines with empty lines
273 """
273 """
274
274
275 res = []
275 res = []
276 lines = script.splitlines()
276 lines = script.splitlines()
277
277
278 level = 0
278 level = 0
279 for l in lines:
279 for l in lines:
280 lstripped = l.lstrip()
280 lstripped = l.lstrip()
281 stripped = l.strip()
281 stripped = l.strip()
282 if not stripped:
282 if not stripped:
283 continue
283 continue
284 newlevel = len(l) - len(lstripped)
284 newlevel = len(l) - len(lstripped)
285 def is_secondary_block_start(s):
285 def is_secondary_block_start(s):
286 if not s.endswith(':'):
286 if not s.endswith(':'):
287 return False
287 return False
288 if (s.startswith('elif') or
288 if (s.startswith('elif') or
289 s.startswith('else') or
289 s.startswith('else') or
290 s.startswith('except') or
290 s.startswith('except') or
291 s.startswith('finally')):
291 s.startswith('finally')):
292 return True
292 return True
293
293
294 if level > 0 and newlevel == 0 and \
294 if level > 0 and newlevel == 0 and \
295 not is_secondary_block_start(stripped):
295 not is_secondary_block_start(stripped):
296 # add empty line
296 # add empty line
297 res.append('')
297 res.append('')
298
298
299 res.append(l)
299 res.append(l)
300 level = newlevel
300 level = newlevel
301 return '\n'.join(res) + '\n'
301 return '\n'.join(res) + '\n'
302
302
303 if isinstance(lines,basestring):
303 if isinstance(lines,basestring):
304 script = lines
304 script = lines
305 else:
305 else:
306 script = '\n'.join(lines)
306 script = '\n'.join(lines)
307 clean=cleanup_ipy_script(script)
307 clean=cleanup_ipy_script(script)
308 # print "_ip.runlines() script:\n",clean # dbg
308 # print "_ip.runlines() script:\n",clean # dbg
309 self.IP.runlines(clean)
309 self.IP.runlines(clean)
310
310
311 def to_user_ns(self,vars, interactive = True):
311 def to_user_ns(self,vars, interactive = True):
312 """Inject a group of variables into the IPython user namespace.
312 """Inject a group of variables into the IPython user namespace.
313
313
314 Inputs:
314 Inputs:
315
315
316 - vars: string with variable names separated by whitespace, or a
316 - vars: string with variable names separated by whitespace, or a
317 dict with name/value pairs.
317 dict with name/value pairs.
318
318
319 - interactive: if True (default), the var will be listed with
319 - interactive: if True (default), the var will be listed with
320 %whos et. al.
320 %whos et. al.
321
321
322 This utility routine is meant to ease interactive debugging work,
322 This utility routine is meant to ease interactive debugging work,
323 where you want to easily propagate some internal variable in your code
323 where you want to easily propagate some internal variable in your code
324 up to the interactive namespace for further exploration.
324 up to the interactive namespace for further exploration.
325
325
326 When you run code via %run, globals in your script become visible at
326 When you run code via %run, globals in your script become visible at
327 the interactive prompt, but this doesn't happen for locals inside your
327 the interactive prompt, but this doesn't happen for locals inside your
328 own functions and methods. Yet when debugging, it is common to want
328 own functions and methods. Yet when debugging, it is common to want
329 to explore some internal variables further at the interactive propmt.
329 to explore some internal variables further at the interactive propmt.
330
330
331 Examples:
331 Examples:
332
332
333 To use this, you first must obtain a handle on the ipython object as
333 To use this, you first must obtain a handle on the ipython object as
334 indicated above, via:
334 indicated above, via:
335
335
336 import IPython.ipapi
336 import IPython.ipapi
337 ip = IPython.ipapi.get()
337 ip = IPython.ipapi.get()
338
338
339 Once this is done, inside a routine foo() where you want to expose
339 Once this is done, inside a routine foo() where you want to expose
340 variables x and y, you do the following:
340 variables x and y, you do the following:
341
341
342 def foo():
342 def foo():
343 ...
343 ...
344 x = your_computation()
344 x = your_computation()
345 y = something_else()
345 y = something_else()
346
346
347 # This pushes x and y to the interactive prompt immediately, even
347 # This pushes x and y to the interactive prompt immediately, even
348 # if this routine crashes on the next line after:
348 # if this routine crashes on the next line after:
349 ip.to_user_ns('x y')
349 ip.to_user_ns('x y')
350 ...
350 ...
351
351
352 # To expose *ALL* the local variables from the function, use:
352 # To expose *ALL* the local variables from the function, use:
353 ip.to_user_ns(locals())
353 ip.to_user_ns(locals())
354
354
355 ...
355 ...
356 # return
356 # return
357
357
358
358
359 If you need to rename variables, the dict input makes it easy. For
359 If you need to rename variables, the dict input makes it easy. For
360 example, this call exposes variables 'foo' as 'x' and 'bar' as 'y'
360 example, this call exposes variables 'foo' as 'x' and 'bar' as 'y'
361 in IPython user namespace:
361 in IPython user namespace:
362
362
363 ip.to_user_ns(dict(x=foo,y=bar))
363 ip.to_user_ns(dict(x=foo,y=bar))
364 """
364 """
365
365
366 # print 'vars given:',vars # dbg
366 # print 'vars given:',vars # dbg
367
367
368 # We need a dict of name/value pairs to do namespace updates.
368 # We need a dict of name/value pairs to do namespace updates.
369 if isinstance(vars,dict):
369 if isinstance(vars,dict):
370 # If a dict was given, no need to change anything.
370 # If a dict was given, no need to change anything.
371 vdict = vars
371 vdict = vars
372 elif isinstance(vars,basestring):
372 elif isinstance(vars,basestring):
373 # If a string with names was given, get the caller's frame to
373 # If a string with names was given, get the caller's frame to
374 # evaluate the given names in
374 # evaluate the given names in
375 cf = sys._getframe(1)
375 cf = sys._getframe(1)
376 vdict = {}
376 vdict = {}
377 for name in vars.split():
377 for name in vars.split():
378 try:
378 try:
379 vdict[name] = eval(name,cf.f_globals,cf.f_locals)
379 vdict[name] = eval(name,cf.f_globals,cf.f_locals)
380 except:
380 except:
381 print ('could not get var. %s from %s' %
381 print ('could not get var. %s from %s' %
382 (name,cf.f_code.co_name))
382 (name,cf.f_code.co_name))
383 else:
383 else:
384 raise ValueError('vars must be a string or a dict')
384 raise ValueError('vars must be a string or a dict')
385
385
386 # Propagate variables to user namespace
386 # Propagate variables to user namespace
387 self.user_ns.update(vdict)
387 self.user_ns.update(vdict)
388
388
389 # And configure interactive visibility
389 # And configure interactive visibility
390 config_ns = self.IP.user_config_ns
390 config_ns = self.IP.user_config_ns
391 if interactive:
391 if interactive:
392 for name,val in vdict.iteritems():
392 for name,val in vdict.iteritems():
393 config_ns.pop(name,None)
393 config_ns.pop(name,None)
394 else:
394 else:
395 for name,val in vdict.iteritems():
395 for name,val in vdict.iteritems():
396 config_ns[name] = val
396 config_ns[name] = val
397
397
398 def expand_alias(self,line):
398 def expand_alias(self,line):
399 """ Expand an alias in the command line
399 """ Expand an alias in the command line
400
400
401 Returns the provided command line, possibly with the first word
401 Returns the provided command line, possibly with the first word
402 (command) translated according to alias expansion rules.
402 (command) translated according to alias expansion rules.
403
403
404 [ipython]|16> _ip.expand_aliases("np myfile.txt")
404 [ipython]|16> _ip.expand_aliases("np myfile.txt")
405 <16> 'q:/opt/np/notepad++.exe myfile.txt'
405 <16> 'q:/opt/np/notepad++.exe myfile.txt'
406 """
406 """
407
407
408 pre,fn,rest = self.IP.split_user_input(line)
408 pre,fn,rest = self.IP.split_user_input(line)
409 res = pre + self.IP.expand_aliases(fn,rest)
409 res = pre + self.IP.expand_aliases(fn,rest)
410 return res
410 return res
411
411
412 def itpl(self, s, depth = 1):
412 def itpl(self, s, depth = 1):
413 """ Expand Itpl format string s.
413 """ Expand Itpl format string s.
414
414
415 Only callable from command line (i.e. prefilter results);
415 Only callable from command line (i.e. prefilter results);
416 If you use in your scripts, you need to use a bigger depth!
416 If you use in your scripts, you need to use a bigger depth!
417 """
417 """
418 return self.IP.var_expand(s, depth)
418 return self.IP.var_expand(s, depth)
419
419
420 def defalias(self, name, cmd):
420 def defalias(self, name, cmd):
421 """ Define a new alias
421 """ Define a new alias
422
422
423 _ip.defalias('bb','bldmake bldfiles')
423 _ip.defalias('bb','bldmake bldfiles')
424
424
425 Creates a new alias named 'bb' in ipython user namespace
425 Creates a new alias named 'bb' in ipython user namespace
426 """
426 """
427
427
428 self.dbg.check_hotname(name)
428 self.dbg.check_hotname(name)
429
429
430 if name in self.IP.alias_table:
430 if name in self.IP.alias_table:
431 self.dbg.debug_stack("Alias redefinition: '%s' => '%s' (old '%s')"
431 self.dbg.debug_stack("Alias redefinition: '%s' => '%s' (old '%s')"
432 % (name, cmd, self.IP.alias_table[name]))
432 % (name, cmd, self.IP.alias_table[name]))
433
433
434 if callable(cmd):
434 if callable(cmd):
435 self.IP.alias_table[name] = cmd
435 self.IP.alias_table[name] = cmd
436 import IPython.shadowns
436 import IPython.shadowns
437 setattr(IPython.shadowns, name,cmd)
437 setattr(IPython.shadowns, name,cmd)
438 return
438 return
439
439
440 if isinstance(cmd,basestring):
440 if isinstance(cmd,basestring):
441 nargs = cmd.count('%s')
441 nargs = cmd.count('%s')
442 if nargs>0 and cmd.find('%l')>=0:
442 if nargs>0 and cmd.find('%l')>=0:
443 raise Exception('The %s and %l specifiers are mutually '
443 raise Exception('The %s and %l specifiers are mutually '
444 'exclusive in alias definitions.')
444 'exclusive in alias definitions.')
445
445
446 self.IP.alias_table[name] = (nargs,cmd)
446 self.IP.alias_table[name] = (nargs,cmd)
447 return
447 return
448
448
449 # just put it in - it's probably (0,'foo')
449 # just put it in - it's probably (0,'foo')
450 self.IP.alias_table[name] = cmd
450 self.IP.alias_table[name] = cmd
451
451
452 def defmacro(self, *args):
452 def defmacro(self, *args):
453 """ Define a new macro
453 """ Define a new macro
454
454
455 2 forms of calling:
455 2 forms of calling:
456
456
457 mac = _ip.defmacro('print "hello"\nprint "world"')
457 mac = _ip.defmacro('print "hello"\nprint "world"')
458
458
459 (doesn't put the created macro on user namespace)
459 (doesn't put the created macro on user namespace)
460
460
461 _ip.defmacro('build', 'bldmake bldfiles\nabld build winscw udeb')
461 _ip.defmacro('build', 'bldmake bldfiles\nabld build winscw udeb')
462
462
463 (creates a macro named 'build' in user namespace)
463 (creates a macro named 'build' in user namespace)
464 """
464 """
465
465
466 import IPython.macro
466 import IPython.macro
467
467
468 if len(args) == 1:
468 if len(args) == 1:
469 return IPython.macro.Macro(args[0])
469 return IPython.macro.Macro(args[0])
470 elif len(args) == 2:
470 elif len(args) == 2:
471 self.user_ns[args[0]] = IPython.macro.Macro(args[1])
471 self.user_ns[args[0]] = IPython.macro.Macro(args[1])
472 else:
472 else:
473 return Exception("_ip.defmacro must be called with 1 or 2 arguments")
473 return Exception("_ip.defmacro must be called with 1 or 2 arguments")
474
474
475 def set_next_input(self, s):
475 def set_next_input(self, s):
476 """ Sets the 'default' input string for the next command line.
476 """ Sets the 'default' input string for the next command line.
477
477
478 Requires readline.
478 Requires readline.
479
479
480 Example:
480 Example:
481
481
482 [D:\ipython]|1> _ip.set_next_input("Hello Word")
482 [D:\ipython]|1> _ip.set_next_input("Hello Word")
483 [D:\ipython]|2> Hello Word_ # cursor is here
483 [D:\ipython]|2> Hello Word_ # cursor is here
484 """
484 """
485
485
486 self.IP.rl_next_input = s
486 self.IP.rl_next_input = s
487
487
488 def load(self, mod):
488 def load(self, mod):
489 """ Load an extension.
489 """ Load an extension.
490
490
491 Some modules should (or must) be 'load()':ed, rather than just imported.
491 Some modules should (or must) be 'load()':ed, rather than just imported.
492
492
493 Loading will do:
493 Loading will do:
494
494
495 - run init_ipython(ip)
495 - run init_ipython(ip)
496 - run ipython_firstrun(ip)
496 - run ipython_firstrun(ip)
497 """
497 """
498
498
499 if mod in self.extensions:
499 if mod in self.extensions:
500 # just to make sure we don't init it twice
500 # just to make sure we don't init it twice
501 # note that if you 'load' a module that has already been
501 # note that if you 'load' a module that has already been
502 # imported, init_ipython gets run anyway
502 # imported, init_ipython gets run anyway
503
503
504 return self.extensions[mod]
504 return self.extensions[mod]
505 __import__(mod)
505 __import__(mod)
506 m = sys.modules[mod]
506 m = sys.modules[mod]
507 if hasattr(m,'init_ipython'):
507 if hasattr(m,'init_ipython'):
508 m.init_ipython(self)
508 m.init_ipython(self)
509
509
510 if hasattr(m,'ipython_firstrun'):
510 if hasattr(m,'ipython_firstrun'):
511 already_loaded = self.db.get('firstrun_done', set())
511 already_loaded = self.db.get('firstrun_done', set())
512 if mod not in already_loaded:
512 if mod not in already_loaded:
513 m.ipython_firstrun(self)
513 m.ipython_firstrun(self)
514 already_loaded.add(mod)
514 already_loaded.add(mod)
515 self.db['firstrun_done'] = already_loaded
515 self.db['firstrun_done'] = already_loaded
516
516
517 self.extensions[mod] = m
517 self.extensions[mod] = m
518 return m
518 return m
519
519
520
520
521 class DebugTools:
521 class DebugTools:
522 """ Used for debugging mishaps in api usage
522 """ Used for debugging mishaps in api usage
523
523
524 So far, tracing redefinitions is supported.
524 So far, tracing redefinitions is supported.
525 """
525 """
526
526
527 def __init__(self, ip):
527 def __init__(self, ip):
528 self.ip = ip
528 self.ip = ip
529 self.debugmode = False
529 self.debugmode = False
530 self.hotnames = set()
530 self.hotnames = set()
531
531
532 def hotname(self, name_to_catch):
532 def hotname(self, name_to_catch):
533 self.hotnames.add(name_to_catch)
533 self.hotnames.add(name_to_catch)
534
534
535 def debug_stack(self, msg = None):
535 def debug_stack(self, msg = None):
536 if not self.debugmode:
536 if not self.debugmode:
537 return
537 return
538
538
539 import traceback
539 import traceback
540 if msg is not None:
540 if msg is not None:
541 print '====== %s ========' % msg
541 print '====== %s ========' % msg
542 traceback.print_stack()
542 traceback.print_stack()
543
543
544 def check_hotname(self,name):
544 def check_hotname(self,name):
545 if name in self.hotnames:
545 if name in self.hotnames:
546 self.debug_stack( "HotName '%s' caught" % name)
546 self.debug_stack( "HotName '%s' caught" % name)
547
547
548
548
549 def launch_new_instance(user_ns = None,shellclass = None):
549 def launch_new_instance(user_ns = None,shellclass = None):
550 """ Make and start a new ipython instance.
550 """ Make and start a new ipython instance.
551
551
552 This can be called even without having an already initialized
552 This can be called even without having an already initialized
553 ipython session running.
553 ipython session running.
554
554
555 This is also used as the egg entry point for the 'ipython' script.
555 This is also used as the egg entry point for the 'ipython' script.
556
556
557 """
557 """
558 ses = make_session(user_ns,shellclass)
558 ses = make_session(user_ns,shellclass)
559 ses.mainloop()
559 ses.mainloop()
560
560
561
561
562 def make_user_ns(user_ns = None):
562 def make_user_ns(user_ns = None):
563 """Return a valid user interactive namespace.
563 """Return a valid user interactive namespace.
564
564
565 This builds a dict with the minimal information needed to operate as a
565 This builds a dict with the minimal information needed to operate as a
566 valid IPython user namespace, which you can pass to the various embedding
566 valid IPython user namespace, which you can pass to the various embedding
567 classes in ipython.
567 classes in ipython.
568
569 This API is currently deprecated. Use ipapi.make_user_namespaces() instead
570 to make both the local and global namespace objects simultaneously.
571
572 :Parameters:
573 user_ns : dict-like, optional
574 The current user namespace. The items in this namespace should be
575 included in the output. If None, an appropriate blank namespace
576 should be created.
577
578 :Returns:
579 A dictionary-like object to be used as the local namespace of the
580 interpreter.
568 """
581 """
569
582
570 raise NotImplementedError
583 raise NotImplementedError
571
584
572
585
573 def make_user_global_ns(ns = None):
586 def make_user_global_ns(ns = None):
574 """Return a valid user global namespace.
587 """Return a valid user global namespace.
575
588
576 Similar to make_user_ns(), but global namespaces are really only needed in
589 Similar to make_user_ns(), but global namespaces are really only needed in
577 embedded applications, where there is a distinction between the user's
590 embedded applications, where there is a distinction between the user's
578 interactive namespace and the global one where ipython is running."""
591 interactive namespace and the global one where ipython is running.
592
593 This API is currently deprecated. Use ipapi.make_user_namespaces() instead
594 to make both the local and global namespace objects simultaneously.
595
596 :Parameters:
597 ns : dict, optional
598 The current user global namespace. The items in this namespace
599 should be included in the output. If None, an appropriate blank
600 namespace should be created.
601
602 :Returns:
603 A true dict to be used as the global namespace of the interpreter.
604 """
579
605
580 raise NotImplementedError
606 raise NotImplementedError
581
607
582 # Record the true objects in order to be able to test if the user has overridden
608 # Record the true objects in order to be able to test if the user has overridden
583 # these API functions.
609 # these API functions.
584 _make_user_ns = make_user_ns
610 _make_user_ns = make_user_ns
585 _make_user_global_ns = make_user_global_ns
611 _make_user_global_ns = make_user_global_ns
586
612
587
613
588 def make_user_namespaces(user_ns = None,user_global_ns = None):
614 def make_user_namespaces(user_ns = None,user_global_ns = None):
589 """Return a valid local and global user interactive namespaces.
615 """Return a valid local and global user interactive namespaces.
590
616
591 This builds a dict with the minimal information needed to operate as a
617 This builds a dict with the minimal information needed to operate as a
592 valid IPython user namespace, which you can pass to the various embedding
618 valid IPython user namespace, which you can pass to the various embedding
593 classes in ipython. The default implementation returns the same dict for
619 classes in ipython. The default implementation returns the same dict for
594 both the locals and the globals to allow functions to refer to variables in
620 both the locals and the globals to allow functions to refer to variables in
595 the namespace. Customized implementations can return different dicts. The
621 the namespace. Customized implementations can return different dicts. The
596 locals dictionary can actually be anything following the basic mapping
622 locals dictionary can actually be anything following the basic mapping
597 protocol of a dict, but the globals dict must be a true dict, not even
623 protocol of a dict, but the globals dict must be a true dict, not even
598 a subclass. It is recommended that any custom object for the locals
624 a subclass. It is recommended that any custom object for the locals
599 namespace synchronize with the globals dict somehow.
625 namespace synchronize with the globals dict somehow.
600
626
601 Raises TypeError if the provided globals namespace is not a true dict.
627 Raises TypeError if the provided globals namespace is not a true dict.
628
629 :Parameters:
630 user_ns : dict-like, optional
631 The current user namespace. The items in this namespace should be
632 included in the output. If None, an appropriate blank namespace
633 should be created.
634 user_global_ns : dict, optional
635 The current user global namespace. The items in this namespace
636 should be included in the output. If None, an appropriate blank
637 namespace should be created.
638
639 :Returns:
640 A tuple pair of dictionary-like object to be used as the local namespace
641 of the interpreter and a dict to be used as the global namespace.
602 """
642 """
603
643
604 if user_ns is None:
644 if user_ns is None:
605 if make_user_ns is not _make_user_ns:
645 if make_user_ns is not _make_user_ns:
606 # Old API overridden.
646 # Old API overridden.
607 # FIXME: Issue DeprecationWarning, or just let the old API live on?
647 # FIXME: Issue DeprecationWarning, or just let the old API live on?
608 user_ns = make_user_ns(user_ns)
648 user_ns = make_user_ns(user_ns)
609 else:
649 else:
610 # Set __name__ to __main__ to better match the behavior of the
650 # Set __name__ to __main__ to better match the behavior of the
611 # normal interpreter.
651 # normal interpreter.
612 user_ns = {'__name__' :'__main__',
652 user_ns = {'__name__' :'__main__',
613 '__builtins__' : __builtin__,
653 '__builtins__' : __builtin__,
614 }
654 }
615 else:
655 else:
616 user_ns.setdefault('__name__','__main__')
656 user_ns.setdefault('__name__','__main__')
617 user_ns.setdefault('__builtins__',__builtin__)
657 user_ns.setdefault('__builtins__',__builtin__)
618
658
619 if user_global_ns is None:
659 if user_global_ns is None:
620 if make_user_global_ns is not _make_user_global_ns:
660 if make_user_global_ns is not _make_user_global_ns:
621 # Old API overridden.
661 # Old API overridden.
622 user_global_ns = make_user_global_ns(user_global_ns)
662 user_global_ns = make_user_global_ns(user_global_ns)
623 else:
663 else:
624 user_global_ns = user_ns
664 user_global_ns = user_ns
625 if type(user_global_ns) is not dict:
665 if type(user_global_ns) is not dict:
626 raise TypeError("user_global_ns must be a true dict; got %r"
666 raise TypeError("user_global_ns must be a true dict; got %r"
627 % type(user_global_ns))
667 % type(user_global_ns))
628
668
629 return user_ns, user_global_ns
669 return user_ns, user_global_ns
630
670
631
671
632 def make_session(user_ns = None, shellclass = None):
672 def make_session(user_ns = None, shellclass = None):
633 """Makes, but does not launch an IPython session.
673 """Makes, but does not launch an IPython session.
634
674
635 Later on you can call obj.mainloop() on the returned object.
675 Later on you can call obj.mainloop() on the returned object.
636
676
637 Inputs:
677 Inputs:
638
678
639 - user_ns(None): a dict to be used as the user's namespace with initial
679 - user_ns(None): a dict to be used as the user's namespace with initial
640 data.
680 data.
641
681
642 WARNING: This should *not* be run when a session exists already."""
682 WARNING: This should *not* be run when a session exists already."""
643
683
644 import IPython.Shell
684 import IPython.Shell
645 if shellclass is None:
685 if shellclass is None:
646 return IPython.Shell.start(user_ns)
686 return IPython.Shell.start(user_ns)
647 return shellclass(user_ns = user_ns)
687 return shellclass(user_ns = user_ns)
General Comments 0
You need to be logged in to leave comments. Login now