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