##// END OF EJS Templates
Updated release tag for SVN....
tzanko -
r2:d7d090d0
parent child Browse files
Show More
@@ -1,69 +1,69 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 605 2005-06-09 14:09:03Z fperez $"""
4 $Id: Release.py 634 2005-07-17 01:56:45Z tzanko $"""
5
5
6 #*****************************************************************************
6 #*****************************************************************************
7 # Copyright (C) 2001-2005 Fernando Perez <fperez@colorado.edu>
7 # Copyright (C) 2001-2005 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.7_rc1), use _ but NOT -, since
20 # For versions with substrings (like 0.6.7_rc1), use _ but NOT -, since
21 # bdist_rpm chokes on dashes in the version string.
21 # bdist_rpm chokes on dashes in the version string.
22 version = '0.6.16_cvs'
22 version = '0.6.16_svn'
23
23
24 description = "An enhanced interactive Python shell."
24 description = "An enhanced interactive Python shell."
25
25
26 long_description = \
26 long_description = \
27 """
27 """
28 IPython provides a replacement for the interactive Python interpreter with
28 IPython provides a replacement for the interactive Python interpreter with
29 extra functionality.
29 extra functionality.
30
30
31 Main features:
31 Main features:
32
32
33 * Comprehensive object introspection.
33 * Comprehensive object introspection.
34
34
35 * Input history, persistent across sessions.
35 * Input history, persistent across sessions.
36
36
37 * Caching of output results during a session with automatically generated
37 * Caching of output results during a session with automatically generated
38 references.
38 references.
39
39
40 * Readline based name completion.
40 * Readline based name completion.
41
41
42 * Extensible system of 'magic' commands for controlling the environment and
42 * Extensible system of 'magic' commands for controlling the environment and
43 performing many tasks related either to IPython or the operating system.
43 performing many tasks related either to IPython or the operating system.
44
44
45 * Configuration system with easy switching between different setups (simpler
45 * Configuration system with easy switching between different setups (simpler
46 than changing $PYTHONSTARTUP environment variables every time).
46 than changing $PYTHONSTARTUP environment variables every time).
47
47
48 * Session logging and reloading.
48 * Session logging and reloading.
49
49
50 * Extensible syntax processing for special purpose situations.
50 * Extensible syntax processing for special purpose situations.
51
51
52 * Access to the system shell with user-extensible alias system.
52 * Access to the system shell with user-extensible alias system.
53
53
54 * Easily embeddable in other Python programs.
54 * Easily embeddable in other Python programs.
55
55
56 * Integrated access to the pdb debugger and the Python profiler. """
56 * Integrated access to the pdb debugger and the Python profiler. """
57
57
58 license = 'BSD'
58 license = 'BSD'
59
59
60 authors = {'Fernando' : ('Fernando Perez','fperez@colorado.edu'),
60 authors = {'Fernando' : ('Fernando Perez','fperez@colorado.edu'),
61 'Janko' : ('Janko Hauser','jhauser@zscout.de'),
61 'Janko' : ('Janko Hauser','jhauser@zscout.de'),
62 'Nathan' : ('Nathaniel Gray','n8gray@caltech.edu')
62 'Nathan' : ('Nathaniel Gray','n8gray@caltech.edu')
63 }
63 }
64
64
65 url = 'http://ipython.scipy.org'
65 url = 'http://ipython.scipy.org'
66
66
67 platforms = ['Linux','Mac OSX','Windows XP/2000/NT','Windows 95/98/ME']
67 platforms = ['Linux','Mac OSX','Windows XP/2000/NT','Windows 95/98/ME']
68
68
69 keywords = ['Interactive','Interpreter','Shell']
69 keywords = ['Interactive','Interpreter','Shell']
@@ -1,894 +1,887 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 605 2005-06-09 14:09:03Z fperez $"""
7 $Id: Shell.py 634 2005-07-17 01:56:45Z tzanko $"""
8
8
9 #*****************************************************************************
9 #*****************************************************************************
10 # Copyright (C) 2001-2004 Fernando Perez <fperez@colorado.edu>
10 # Copyright (C) 2001-2004 Fernando Perez <fperez@colorado.edu>
11 #
11 #
12 # Distributed under the terms of the BSD License. The full license is in
12 # Distributed under the terms of the BSD License. The full license is in
13 # the file COPYING, distributed as part of this software.
13 # the file COPYING, distributed as part of this software.
14 #*****************************************************************************
14 #*****************************************************************************
15
15
16 from IPython import Release
16 from IPython import Release
17 __author__ = '%s <%s>' % Release.authors['Fernando']
17 __author__ = '%s <%s>' % Release.authors['Fernando']
18 __license__ = Release.license
18 __license__ = Release.license
19
19
20 # Code begins
20 # Code begins
21 import __main__
21 import __main__
22 import __builtin__
22 import __builtin__
23 import sys
23 import sys
24 import os
24 import os
25 import code
25 import code
26 import threading
26 import threading
27 import signal
27 import signal
28
28
29 import IPython
29 import IPython
30 from IPython.iplib import InteractiveShell
30 from IPython.iplib import InteractiveShell
31 from IPython.ipmaker import make_IPython
31 from IPython.ipmaker import make_IPython
32 from IPython.genutils import Term,warn,error,flag_calls
32 from IPython.genutils import Term,warn,error,flag_calls
33 from IPython.Struct import Struct
33 from IPython.Struct import Struct
34 from IPython.Magic import Magic
34 from IPython.Magic import Magic
35 from IPython import ultraTB
35 from IPython import ultraTB
36
36
37 # global flag to pass around information about Ctrl-C without exceptions
37 # global flag to pass around information about Ctrl-C without exceptions
38 KBINT = False
38 KBINT = False
39
39
40 # global flag to turn on/off Tk support.
40 # global flag to turn on/off Tk support.
41 USE_TK = False
41 USE_TK = False
42
42
43 #-----------------------------------------------------------------------------
43 #-----------------------------------------------------------------------------
44 # This class is trivial now, but I want to have it in to publish a clean
44 # This class is trivial now, but I want to have it in to publish a clean
45 # interface. Later when the internals are reorganized, code that uses this
45 # interface. Later when the internals are reorganized, code that uses this
46 # shouldn't have to change.
46 # shouldn't have to change.
47
47
48 class IPShell:
48 class IPShell:
49 """Create an IPython instance."""
49 """Create an IPython instance."""
50
50
51 def __init__(self,argv=None,user_ns=None,debug=1,
51 def __init__(self,argv=None,user_ns=None,debug=1,
52 shell_class=InteractiveShell):
52 shell_class=InteractiveShell):
53 self.IP = make_IPython(argv,user_ns=user_ns,debug=debug,
53 self.IP = make_IPython(argv,user_ns=user_ns,debug=debug,
54 shell_class=shell_class)
54 shell_class=shell_class)
55
55
56 def mainloop(self,sys_exit=0,banner=None):
56 def mainloop(self,sys_exit=0,banner=None):
57 self.IP.mainloop(banner)
57 self.IP.mainloop(banner)
58 if sys_exit:
58 if sys_exit:
59 sys.exit()
59 sys.exit()
60
60
61 #-----------------------------------------------------------------------------
61 #-----------------------------------------------------------------------------
62 class IPShellEmbed:
62 class IPShellEmbed:
63 """Allow embedding an IPython shell into a running program.
63 """Allow embedding an IPython shell into a running program.
64
64
65 Instances of this class are callable, with the __call__ method being an
65 Instances of this class are callable, with the __call__ method being an
66 alias to the embed() method of an InteractiveShell instance.
66 alias to the embed() method of an InteractiveShell instance.
67
67
68 Usage (see also the example-embed.py file for a running example):
68 Usage (see also the example-embed.py file for a running example):
69
69
70 ipshell = IPShellEmbed([argv,banner,exit_msg,rc_override])
70 ipshell = IPShellEmbed([argv,banner,exit_msg,rc_override])
71
71
72 - argv: list containing valid command-line options for IPython, as they
72 - argv: list containing valid command-line options for IPython, as they
73 would appear in sys.argv[1:].
73 would appear in sys.argv[1:].
74
74
75 For example, the following command-line options:
75 For example, the following command-line options:
76
76
77 $ ipython -prompt_in1 'Input <\\#>' -colors LightBG
77 $ ipython -prompt_in1 'Input <\\#>' -colors LightBG
78
78
79 would be passed in the argv list as:
79 would be passed in the argv list as:
80
80
81 ['-prompt_in1','Input <\\#>','-colors','LightBG']
81 ['-prompt_in1','Input <\\#>','-colors','LightBG']
82
82
83 - banner: string which gets printed every time the interpreter starts.
83 - banner: string which gets printed every time the interpreter starts.
84
84
85 - exit_msg: string which gets printed every time the interpreter exits.
85 - exit_msg: string which gets printed every time the interpreter exits.
86
86
87 - rc_override: a dict or Struct of configuration options such as those
87 - rc_override: a dict or Struct of configuration options such as those
88 used by IPython. These options are read from your ~/.ipython/ipythonrc
88 used by IPython. These options are read from your ~/.ipython/ipythonrc
89 file when the Shell object is created. Passing an explicit rc_override
89 file when the Shell object is created. Passing an explicit rc_override
90 dict with any options you want allows you to override those values at
90 dict with any options you want allows you to override those values at
91 creation time without having to modify the file. This way you can create
91 creation time without having to modify the file. This way you can create
92 embeddable instances configured in any way you want without editing any
92 embeddable instances configured in any way you want without editing any
93 global files (thus keeping your interactive IPython configuration
93 global files (thus keeping your interactive IPython configuration
94 unchanged).
94 unchanged).
95
95
96 Then the ipshell instance can be called anywhere inside your code:
96 Then the ipshell instance can be called anywhere inside your code:
97
97
98 ipshell(header='') -> Opens up an IPython shell.
98 ipshell(header='') -> Opens up an IPython shell.
99
99
100 - header: string printed by the IPython shell upon startup. This can let
100 - header: string printed by the IPython shell upon startup. This can let
101 you know where in your code you are when dropping into the shell. Note
101 you know where in your code you are when dropping into the shell. Note
102 that 'banner' gets prepended to all calls, so header is used for
102 that 'banner' gets prepended to all calls, so header is used for
103 location-specific information.
103 location-specific information.
104
104
105 For more details, see the __call__ method below.
105 For more details, see the __call__ method below.
106
106
107 When the IPython shell is exited with Ctrl-D, normal program execution
107 When the IPython shell is exited with Ctrl-D, normal program execution
108 resumes.
108 resumes.
109
109
110 This functionality was inspired by a posting on comp.lang.python by cmkl
110 This functionality was inspired by a posting on comp.lang.python by cmkl
111 <cmkleffner@gmx.de> on Dec. 06/01 concerning similar uses of pyrepl, and
111 <cmkleffner@gmx.de> on Dec. 06/01 concerning similar uses of pyrepl, and
112 by the IDL stop/continue commands."""
112 by the IDL stop/continue commands."""
113
113
114 def __init__(self,argv=None,banner='',exit_msg=None,rc_override=None):
114 def __init__(self,argv=None,banner='',exit_msg=None,rc_override=None):
115 """Note that argv here is a string, NOT a list."""
115 """Note that argv here is a string, NOT a list."""
116 self.set_banner(banner)
116 self.set_banner(banner)
117 self.set_exit_msg(exit_msg)
117 self.set_exit_msg(exit_msg)
118 self.set_dummy_mode(0)
118 self.set_dummy_mode(0)
119
119
120 # sys.displayhook is a global, we need to save the user's original
120 # sys.displayhook is a global, we need to save the user's original
121 # Don't rely on __displayhook__, as the user may have changed that.
121 # Don't rely on __displayhook__, as the user may have changed that.
122 self.sys_displayhook_ori = sys.displayhook
122 self.sys_displayhook_ori = sys.displayhook
123
123
124 # save readline completer status
124 # save readline completer status
125 try:
125 try:
126 #print 'Save completer',sys.ipcompleter # dbg
126 #print 'Save completer',sys.ipcompleter # dbg
127 self.sys_ipcompleter_ori = sys.ipcompleter
127 self.sys_ipcompleter_ori = sys.ipcompleter
128 except:
128 except:
129 pass # not nested with IPython
129 pass # not nested with IPython
130
130
131 # FIXME. Passing user_ns breaks namespace handling.
131 # FIXME. Passing user_ns breaks namespace handling.
132 #self.IP = make_IPython(argv,user_ns=__main__.__dict__)
132 #self.IP = make_IPython(argv,user_ns=__main__.__dict__)
133 self.IP = make_IPython(argv,rc_override=rc_override,embedded=True)
133 self.IP = make_IPython(argv,rc_override=rc_override,embedded=True)
134
134
135 self.IP.name_space_init()
135 self.IP.name_space_init()
136 # mark this as an embedded instance so we know if we get a crash
136 # mark this as an embedded instance so we know if we get a crash
137 # post-mortem
137 # post-mortem
138 self.IP.rc.embedded = 1
138 self.IP.rc.embedded = 1
139 # copy our own displayhook also
139 # copy our own displayhook also
140 self.sys_displayhook_embed = sys.displayhook
140 self.sys_displayhook_embed = sys.displayhook
141 # and leave the system's display hook clean
141 # and leave the system's display hook clean
142 sys.displayhook = self.sys_displayhook_ori
142 sys.displayhook = self.sys_displayhook_ori
143 # don't use the ipython crash handler so that user exceptions aren't
143 # don't use the ipython crash handler so that user exceptions aren't
144 # trapped
144 # trapped
145 sys.excepthook = ultraTB.FormattedTB(color_scheme = self.IP.rc.colors,
145 sys.excepthook = ultraTB.FormattedTB(color_scheme = self.IP.rc.colors,
146 mode = self.IP.rc.xmode,
146 mode = self.IP.rc.xmode,
147 call_pdb = self.IP.rc.pdb)
147 call_pdb = self.IP.rc.pdb)
148 self.restore_system_completer()
148 self.restore_system_completer()
149
149
150 def restore_system_completer(self):
150 def restore_system_completer(self):
151 """Restores the readline completer which was in place.
151 """Restores the readline completer which was in place.
152
152
153 This allows embedded IPython within IPython not to disrupt the
153 This allows embedded IPython within IPython not to disrupt the
154 parent's completion.
154 parent's completion.
155 """
155 """
156
156
157 try:
157 try:
158 self.IP.readline.set_completer(self.sys_ipcompleter_ori)
158 self.IP.readline.set_completer(self.sys_ipcompleter_ori)
159 sys.ipcompleter = self.sys_ipcompleter_ori
159 sys.ipcompleter = self.sys_ipcompleter_ori
160 except:
160 except:
161 pass
161 pass
162
162
163 def __call__(self,header='',local_ns=None,global_ns=None,dummy=None):
163 def __call__(self,header='',local_ns=None,global_ns=None,dummy=None):
164 """Activate the interactive interpreter.
164 """Activate the interactive interpreter.
165
165
166 __call__(self,header='',local_ns=None,global_ns,dummy=None) -> Start
166 __call__(self,header='',local_ns=None,global_ns,dummy=None) -> Start
167 the interpreter shell with the given local and global namespaces, and
167 the interpreter shell with the given local and global namespaces, and
168 optionally print a header string at startup.
168 optionally print a header string at startup.
169
169
170 The shell can be globally activated/deactivated using the
170 The shell can be globally activated/deactivated using the
171 set/get_dummy_mode methods. This allows you to turn off a shell used
171 set/get_dummy_mode methods. This allows you to turn off a shell used
172 for debugging globally.
172 for debugging globally.
173
173
174 However, *each* time you call the shell you can override the current
174 However, *each* time you call the shell you can override the current
175 state of dummy_mode with the optional keyword parameter 'dummy'. For
175 state of dummy_mode with the optional keyword parameter 'dummy'. For
176 example, if you set dummy mode on with IPShell.set_dummy_mode(1), you
176 example, if you set dummy mode on with IPShell.set_dummy_mode(1), you
177 can still have a specific call work by making it as IPShell(dummy=0).
177 can still have a specific call work by making it as IPShell(dummy=0).
178
178
179 The optional keyword parameter dummy controls whether the call
179 The optional keyword parameter dummy controls whether the call
180 actually does anything. """
180 actually does anything. """
181
181
182 # Allow the dummy parameter to override the global __dummy_mode
182 # Allow the dummy parameter to override the global __dummy_mode
183 if dummy or (dummy != 0 and self.__dummy_mode):
183 if dummy or (dummy != 0 and self.__dummy_mode):
184 return
184 return
185
185
186 # Set global subsystems (display,completions) to our values
186 # Set global subsystems (display,completions) to our values
187 sys.displayhook = self.sys_displayhook_embed
187 sys.displayhook = self.sys_displayhook_embed
188 if self.IP.has_readline:
188 if self.IP.has_readline:
189 self.IP.readline.set_completer(self.IP.Completer.complete)
189 self.IP.readline.set_completer(self.IP.Completer.complete)
190
190
191 if self.banner and header:
191 if self.banner and header:
192 format = '%s\n%s\n'
192 format = '%s\n%s\n'
193 else:
193 else:
194 format = '%s%s\n'
194 format = '%s%s\n'
195 banner = format % (self.banner,header)
195 banner = format % (self.banner,header)
196
196
197 # Call the embedding code with a stack depth of 1 so it can skip over
197 # Call the embedding code with a stack depth of 1 so it can skip over
198 # our call and get the original caller's namespaces.
198 # our call and get the original caller's namespaces.
199 self.IP.embed_mainloop(banner,local_ns,global_ns,stack_depth=1)
199 self.IP.embed_mainloop(banner,local_ns,global_ns,stack_depth=1)
200
200
201 if self.exit_msg:
201 if self.exit_msg:
202 print self.exit_msg
202 print self.exit_msg
203
203
204 # Restore global systems (display, completion)
204 # Restore global systems (display, completion)
205 sys.displayhook = self.sys_displayhook_ori
205 sys.displayhook = self.sys_displayhook_ori
206 self.restore_system_completer()
206 self.restore_system_completer()
207
207
208 def set_dummy_mode(self,dummy):
208 def set_dummy_mode(self,dummy):
209 """Sets the embeddable shell's dummy mode parameter.
209 """Sets the embeddable shell's dummy mode parameter.
210
210
211 set_dummy_mode(dummy): dummy = 0 or 1.
211 set_dummy_mode(dummy): dummy = 0 or 1.
212
212
213 This parameter is persistent and makes calls to the embeddable shell
213 This parameter is persistent and makes calls to the embeddable shell
214 silently return without performing any action. This allows you to
214 silently return without performing any action. This allows you to
215 globally activate or deactivate a shell you're using with a single call.
215 globally activate or deactivate a shell you're using with a single call.
216
216
217 If you need to manually"""
217 If you need to manually"""
218
218
219 if dummy not in [0,1]:
219 if dummy not in [0,1]:
220 raise ValueError,'dummy parameter must be 0 or 1'
220 raise ValueError,'dummy parameter must be 0 or 1'
221 self.__dummy_mode = dummy
221 self.__dummy_mode = dummy
222
222
223 def get_dummy_mode(self):
223 def get_dummy_mode(self):
224 """Return the current value of the dummy mode parameter.
224 """Return the current value of the dummy mode parameter.
225 """
225 """
226 return self.__dummy_mode
226 return self.__dummy_mode
227
227
228 def set_banner(self,banner):
228 def set_banner(self,banner):
229 """Sets the global banner.
229 """Sets the global banner.
230
230
231 This banner gets prepended to every header printed when the shell
231 This banner gets prepended to every header printed when the shell
232 instance is called."""
232 instance is called."""
233
233
234 self.banner = banner
234 self.banner = banner
235
235
236 def set_exit_msg(self,exit_msg):
236 def set_exit_msg(self,exit_msg):
237 """Sets the global exit_msg.
237 """Sets the global exit_msg.
238
238
239 This exit message gets printed upon exiting every time the embedded
239 This exit message gets printed upon exiting every time the embedded
240 shell is called. It is None by default. """
240 shell is called. It is None by default. """
241
241
242 self.exit_msg = exit_msg
242 self.exit_msg = exit_msg
243
243
244 #-----------------------------------------------------------------------------
244 #-----------------------------------------------------------------------------
245 def sigint_handler (signum,stack_frame):
245 def sigint_handler (signum,stack_frame):
246 """Sigint handler for threaded apps.
246 """Sigint handler for threaded apps.
247
247
248 This is a horrible hack to pass information about SIGINT _without_ using
248 This is a horrible hack to pass information about SIGINT _without_ using
249 exceptions, since I haven't been able to properly manage cross-thread
249 exceptions, since I haven't been able to properly manage cross-thread
250 exceptions in GTK/WX. In fact, I don't think it can be done (or at least
250 exceptions in GTK/WX. In fact, I don't think it can be done (or at least
251 that's my understanding from a c.l.py thread where this was discussed)."""
251 that's my understanding from a c.l.py thread where this was discussed)."""
252
252
253 global KBINT
253 global KBINT
254
254
255 print '\nKeyboardInterrupt - Press <Enter> to continue.',
255 print '\nKeyboardInterrupt - Press <Enter> to continue.',
256 Term.cout.flush()
256 Term.cout.flush()
257 # Set global flag so that runsource can know that Ctrl-C was hit
257 # Set global flag so that runsource can know that Ctrl-C was hit
258 KBINT = True
258 KBINT = True
259
259
260 class MTInteractiveShell(InteractiveShell):
260 class MTInteractiveShell(InteractiveShell):
261 """Simple multi-threaded shell."""
261 """Simple multi-threaded shell."""
262
262
263 # Threading strategy taken from:
263 # Threading strategy taken from:
264 # http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/65109, by Brian
264 # http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/65109, by Brian
265 # McErlean and John Finlay. Modified with corrections by Antoon Pardon,
265 # McErlean and John Finlay. Modified with corrections by Antoon Pardon,
266 # from the pygtk mailing list, to avoid lockups with system calls.
266 # from the pygtk mailing list, to avoid lockups with system calls.
267
267
268 def __init__(self,name,usage=None,rc=Struct(opts=None,args=None),
268 def __init__(self,name,usage=None,rc=Struct(opts=None,args=None),
269 user_ns = None, banner2='',**kw):
269 user_ns = None, banner2='',**kw):
270 """Similar to the normal InteractiveShell, but with threading control"""
270 """Similar to the normal InteractiveShell, but with threading control"""
271
271
272 IPython.iplib.InteractiveShell.__init__(self,name,usage,rc,user_ns,banner2)
272 IPython.iplib.InteractiveShell.__init__(self,name,usage,rc,user_ns,banner2)
273
273
274 # Locking control variable
274 # Locking control variable
275 self.thread_ready = threading.Condition()
275 self.thread_ready = threading.Condition()
276
276
277 # Stuff to do at closing time
277 # Stuff to do at closing time
278 self._kill = False
278 self._kill = False
279 on_kill = kw.get('on_kill')
279 on_kill = kw.get('on_kill')
280 if on_kill is None:
280 if on_kill is None:
281 on_kill = []
281 on_kill = []
282 # Check that all things to kill are callable:
282 # Check that all things to kill are callable:
283 for t in on_kill:
283 for t in on_kill:
284 if not callable(t):
284 if not callable(t):
285 raise TypeError,'on_kill must be a list of callables'
285 raise TypeError,'on_kill must be a list of callables'
286 self.on_kill = on_kill
286 self.on_kill = on_kill
287
287
288 def runsource(self, source, filename="<input>", symbol="single"):
288 def runsource(self, source, filename="<input>", symbol="single"):
289 """Compile and run some source in the interpreter.
289 """Compile and run some source in the interpreter.
290
290
291 Modified version of code.py's runsource(), to handle threading issues.
291 Modified version of code.py's runsource(), to handle threading issues.
292 See the original for full docstring details."""
292 See the original for full docstring details."""
293
293
294 global KBINT
294 global KBINT
295
295
296 # If Ctrl-C was typed, we reset the flag and return right away
296 # If Ctrl-C was typed, we reset the flag and return right away
297 if KBINT:
297 if KBINT:
298 KBINT = False
298 KBINT = False
299 return False
299 return False
300
300
301 try:
301 try:
302 code = self.compile(source, filename, symbol)
302 code = self.compile(source, filename, symbol)
303 except (OverflowError, SyntaxError, ValueError):
303 except (OverflowError, SyntaxError, ValueError):
304 # Case 1
304 # Case 1
305 self.showsyntaxerror(filename)
305 self.showsyntaxerror(filename)
306 return False
306 return False
307
307
308 if code is None:
308 if code is None:
309 # Case 2
309 # Case 2
310 return True
310 return True
311
311
312 # Case 3
312 # Case 3
313 # Store code in self, so the execution thread can handle it
313 # Store code in self, so the execution thread can handle it
314 self.thread_ready.acquire()
314 self.thread_ready.acquire()
315 self.code_to_run_src = source
315 self.code_to_run_src = source
316 self.code_to_run = code
316 self.code_to_run = code
317 self.thread_ready.wait() # Wait until processed in timeout interval
317 self.thread_ready.wait() # Wait until processed in timeout interval
318 self.thread_ready.release()
318 self.thread_ready.release()
319
319
320 return False
320 return False
321
321
322 def runcode(self):
322 def runcode(self):
323 """Execute a code object.
323 """Execute a code object.
324
324
325 Multithreaded wrapper around IPython's runcode()."""
325 Multithreaded wrapper around IPython's runcode()."""
326
326
327 # lock thread-protected stuff
327 # lock thread-protected stuff
328 self.thread_ready.acquire()
328 self.thread_ready.acquire()
329
329
330 # Install sigint handler
330 # Install sigint handler
331 try:
331 try:
332 signal.signal(signal.SIGINT, sigint_handler)
332 signal.signal(signal.SIGINT, sigint_handler)
333 except SystemError:
333 except SystemError:
334 # This happens under Windows, which seems to have all sorts
334 # This happens under Windows, which seems to have all sorts
335 # of problems with signal handling. Oh well...
335 # of problems with signal handling. Oh well...
336 pass
336 pass
337
337
338 if self._kill:
338 if self._kill:
339 print >>Term.cout, 'Closing threads...',
339 print >>Term.cout, 'Closing threads...',
340 Term.cout.flush()
340 Term.cout.flush()
341 for tokill in self.on_kill:
341 for tokill in self.on_kill:
342 tokill()
342 tokill()
343 print >>Term.cout, 'Done.'
343 print >>Term.cout, 'Done.'
344
344
345 # Run pending code by calling parent class
345 # Run pending code by calling parent class
346 if self.code_to_run is not None:
346 if self.code_to_run is not None:
347 self.thread_ready.notify()
347 self.thread_ready.notify()
348 InteractiveShell.runcode(self,self.code_to_run)
348 InteractiveShell.runcode(self,self.code_to_run)
349
349
350 # We're done with thread-protected variables
350 # We're done with thread-protected variables
351 self.thread_ready.release()
351 self.thread_ready.release()
352 # This MUST return true for gtk threading to work
352 # This MUST return true for gtk threading to work
353 return True
353 return True
354
354
355 def kill (self):
355 def kill (self):
356 """Kill the thread, returning when it has been shut down."""
356 """Kill the thread, returning when it has been shut down."""
357 self.thread_ready.acquire()
357 self.thread_ready.acquire()
358 self._kill = True
358 self._kill = True
359 self.thread_ready.release()
359 self.thread_ready.release()
360
360
361 class MatplotlibShellBase:
361 class MatplotlibShellBase:
362 """Mixin class to provide the necessary modifications to regular IPython
362 """Mixin class to provide the necessary modifications to regular IPython
363 shell classes for matplotlib support.
363 shell classes for matplotlib support.
364
364
365 Given Python's MRO, this should be used as the FIRST class in the
365 Given Python's MRO, this should be used as the FIRST class in the
366 inheritance hierarchy, so that it overrides the relevant methods."""
366 inheritance hierarchy, so that it overrides the relevant methods."""
367
367
368 def _matplotlib_config(self,name):
368 def _matplotlib_config(self,name):
369 """Return various items needed to setup the user's shell with matplotlib"""
369 """Return various items needed to setup the user's shell with matplotlib"""
370
370
371 # Initialize matplotlib to interactive mode always
371 # Initialize matplotlib to interactive mode always
372 import matplotlib
372 import matplotlib
373 from matplotlib import backends
373 from matplotlib import backends
374 matplotlib.interactive(True)
374 matplotlib.interactive(True)
375
375
376 def use(arg):
376 def use(arg):
377 """IPython wrapper for matplotlib's backend switcher.
377 """IPython wrapper for matplotlib's backend switcher.
378
378
379 In interactive use, we can not allow switching to a different
379 In interactive use, we can not allow switching to a different
380 interactive backend, since thread conflicts will most likely crash
380 interactive backend, since thread conflicts will most likely crash
381 the python interpreter. This routine does a safety check first,
381 the python interpreter. This routine does a safety check first,
382 and refuses to perform a dangerous switch. It still allows
382 and refuses to perform a dangerous switch. It still allows
383 switching to non-interactive backends."""
383 switching to non-interactive backends."""
384
384
385 if arg in backends.interactive_bk and arg != self.mpl_backend:
385 if arg in backends.interactive_bk and arg != self.mpl_backend:
386 m=('invalid matplotlib backend switch.\n'
386 m=('invalid matplotlib backend switch.\n'
387 'This script attempted to switch to the interactive '
387 'This script attempted to switch to the interactive '
388 'backend: `%s`\n'
388 'backend: `%s`\n'
389 'Your current choice of interactive backend is: `%s`\n\n'
389 'Your current choice of interactive backend is: `%s`\n\n'
390 'Switching interactive matplotlib backends at runtime\n'
390 'Switching interactive matplotlib backends at runtime\n'
391 'would crash the python interpreter, '
391 'would crash the python interpreter, '
392 'and IPython has blocked it.\n\n'
392 'and IPython has blocked it.\n\n'
393 'You need to either change your choice of matplotlib backend\n'
393 'You need to either change your choice of matplotlib backend\n'
394 'by editing your .matplotlibrc file, or run this script as a \n'
394 'by editing your .matplotlibrc file, or run this script as a \n'
395 'standalone file from the command line, not using IPython.\n' %
395 'standalone file from the command line, not using IPython.\n' %
396 (arg,self.mpl_backend) )
396 (arg,self.mpl_backend) )
397 raise RuntimeError, m
397 raise RuntimeError, m
398 else:
398 else:
399 self.mpl_use(arg)
399 self.mpl_use(arg)
400 self.mpl_use._called = True
400 self.mpl_use._called = True
401
401
402 self.matplotlib = matplotlib
402 self.matplotlib = matplotlib
403
404 # Take control of matplotlib's error handling, which can normally
405 # lock up the python interpreter when raw_input() is called
406 import matplotlib.backends as backend
407 backend.error_msg = error
408
409 # we'll handle the mainloop, tell show not to
410 import matplotlib.backends
411 matplotlib.backends.show._needmain = False
412 self.mpl_backend = matplotlib.rcParams['backend']
403 self.mpl_backend = matplotlib.rcParams['backend']
413
404
414 # we also need to block switching of interactive backends by use()
405 # we also need to block switching of interactive backends by use()
415 self.mpl_use = matplotlib.use
406 self.mpl_use = matplotlib.use
416 self.mpl_use._called = False
407 self.mpl_use._called = False
417 # overwrite the original matplotlib.use with our wrapper
408 # overwrite the original matplotlib.use with our wrapper
418 matplotlib.use = use
409 matplotlib.use = use
419
410
420 # We need to detect at runtime whether show() is called by the user.
421 # For this, we wrap it into a decorator which adds a 'called' flag.
422 backend.draw_if_interactive = flag_calls(backend.draw_if_interactive)
423
411
424 # This must be imported last in the matplotlib series, after
412 # This must be imported last in the matplotlib series, after
425 # backend/interactivity choices have been made
413 # backend/interactivity choices have been made
426 try:
414 try:
427 import matplotlib.pylab as pylab
415 import matplotlib.pylab as pylab
428 self.pylab = pylab
416 self.pylab = pylab
429 self.pylab_name = 'pylab'
417 self.pylab_name = 'pylab'
430 except ImportError:
418 except ImportError:
431 import matplotlib.matlab as matlab
419 import matplotlib.matlab as matlab
432 self.pylab = matlab
420 self.pylab = matlab
433 self.pylab_name = 'matlab'
421 self.pylab_name = 'matlab'
434
422
423 self.pylab.show._needmain = False
424 # We need to detect at runtime whether show() is called by the user.
425 # For this, we wrap it into a decorator which adds a 'called' flag.
426 self.pylab.draw_if_interactive = flag_calls(self.pylab.draw_if_interactive)
427
435 # Build a user namespace initialized with matplotlib/matlab features.
428 # Build a user namespace initialized with matplotlib/matlab features.
436 user_ns = {'__name__':'__main__',
429 user_ns = {'__name__':'__main__',
437 '__builtins__' : __builtin__ }
430 '__builtins__' : __builtin__ }
438
431
439 # Be careful not to remove the final \n in the code string below, or
432 # Be careful not to remove the final \n in the code string below, or
440 # things will break badly with py22 (I think it's a python bug, 2.3 is
433 # things will break badly with py22 (I think it's a python bug, 2.3 is
441 # OK).
434 # OK).
442 pname = self.pylab_name # Python can't interpolate dotted var names
435 pname = self.pylab_name # Python can't interpolate dotted var names
443 exec ("import matplotlib\n"
436 exec ("import matplotlib\n"
444 "import matplotlib.%(pname)s as %(pname)s\n"
437 "import matplotlib.%(pname)s as %(pname)s\n"
445 "from matplotlib.%(pname)s import *\n" % locals()) in user_ns
438 "from matplotlib.%(pname)s import *\n" % locals()) in user_ns
446
439
447 # Build matplotlib info banner
440 # Build matplotlib info banner
448 b="""
441 b="""
449 Welcome to pylab, a matplotlib-based Python environment.
442 Welcome to pylab, a matplotlib-based Python environment.
450 For more information, type 'help(pylab)'.
443 For more information, type 'help(pylab)'.
451 """
444 """
452 return user_ns,b
445 return user_ns,b
453
446
454 def mplot_exec(self,fname,*where,**kw):
447 def mplot_exec(self,fname,*where,**kw):
455 """Execute a matplotlib script.
448 """Execute a matplotlib script.
456
449
457 This is a call to execfile(), but wrapped in safeties to properly
450 This is a call to execfile(), but wrapped in safeties to properly
458 handle interactive rendering and backend switching."""
451 handle interactive rendering and backend switching."""
459
452
460 #print '*** Matplotlib runner ***' # dbg
453 #print '*** Matplotlib runner ***' # dbg
461 # turn off rendering until end of script
454 # turn off rendering until end of script
462 isInteractive = self.matplotlib.rcParams['interactive']
455 isInteractive = self.matplotlib.rcParams['interactive']
463 self.matplotlib.interactive(False)
456 self.matplotlib.interactive(False)
464 self.safe_execfile(fname,*where,**kw)
457 self.safe_execfile(fname,*where,**kw)
465 self.matplotlib.interactive(isInteractive)
458 self.matplotlib.interactive(isInteractive)
466 # make rendering call now, if the user tried to do it
459 # make rendering call now, if the user tried to do it
467 if self.pylab.draw_if_interactive.called:
460 if self.pylab.draw_if_interactive.called:
468 self.pylab.draw()
461 self.pylab.draw()
469 self.pylab.draw_if_interactive.called = False
462 self.pylab.draw_if_interactive.called = False
470
463
471 # if a backend switch was performed, reverse it now
464 # if a backend switch was performed, reverse it now
472 if self.mpl_use._called:
465 if self.mpl_use._called:
473 self.matplotlib.rcParams['backend'] = self.mpl_backend
466 self.matplotlib.rcParams['backend'] = self.mpl_backend
474
467
475 def magic_run(self,parameter_s=''):
468 def magic_run(self,parameter_s=''):
476 Magic.magic_run(self,parameter_s,runner=self.mplot_exec)
469 Magic.magic_run(self,parameter_s,runner=self.mplot_exec)
477
470
478 # Fix the docstring so users see the original as well
471 # Fix the docstring so users see the original as well
479 magic_run.__doc__ = "%s\n%s" % (Magic.magic_run.__doc__,
472 magic_run.__doc__ = "%s\n%s" % (Magic.magic_run.__doc__,
480 "\n *** Modified %run for Matplotlib,"
473 "\n *** Modified %run for Matplotlib,"
481 " with proper interactive handling ***")
474 " with proper interactive handling ***")
482
475
483 # Now we provide 2 versions of a matplotlib-aware IPython base shells, single
476 # Now we provide 2 versions of a matplotlib-aware IPython base shells, single
484 # and multithreaded. Note that these are meant for internal use, the IPShell*
477 # and multithreaded. Note that these are meant for internal use, the IPShell*
485 # classes below are the ones meant for public consumption.
478 # classes below are the ones meant for public consumption.
486
479
487 class MatplotlibShell(MatplotlibShellBase,InteractiveShell):
480 class MatplotlibShell(MatplotlibShellBase,InteractiveShell):
488 """Single-threaded shell with matplotlib support."""
481 """Single-threaded shell with matplotlib support."""
489
482
490 def __init__(self,name,usage=None,rc=Struct(opts=None,args=None),
483 def __init__(self,name,usage=None,rc=Struct(opts=None,args=None),
491 user_ns = None, **kw):
484 user_ns = None, **kw):
492 user_ns,b2 = self._matplotlib_config(name)
485 user_ns,b2 = self._matplotlib_config(name)
493 InteractiveShell.__init__(self,name,usage,rc,user_ns,banner2=b2,**kw)
486 InteractiveShell.__init__(self,name,usage,rc,user_ns,banner2=b2,**kw)
494
487
495 class MatplotlibMTShell(MatplotlibShellBase,MTInteractiveShell):
488 class MatplotlibMTShell(MatplotlibShellBase,MTInteractiveShell):
496 """Multi-threaded shell with matplotlib support."""
489 """Multi-threaded shell with matplotlib support."""
497
490
498 def __init__(self,name,usage=None,rc=Struct(opts=None,args=None),
491 def __init__(self,name,usage=None,rc=Struct(opts=None,args=None),
499 user_ns = None, **kw):
492 user_ns = None, **kw):
500 user_ns,b2 = self._matplotlib_config(name)
493 user_ns,b2 = self._matplotlib_config(name)
501 MTInteractiveShell.__init__(self,name,usage,rc,user_ns,banner2=b2,**kw)
494 MTInteractiveShell.__init__(self,name,usage,rc,user_ns,banner2=b2,**kw)
502
495
503 #-----------------------------------------------------------------------------
496 #-----------------------------------------------------------------------------
504 # Utility functions for the different GUI enabled IPShell* classes.
497 # Utility functions for the different GUI enabled IPShell* classes.
505
498
506 def get_tk():
499 def get_tk():
507 """Tries to import Tkinter and returns a withdrawn Tkinter root
500 """Tries to import Tkinter and returns a withdrawn Tkinter root
508 window. If Tkinter is already imported or not available, this
501 window. If Tkinter is already imported or not available, this
509 returns None. This function calls `hijack_tk` underneath.
502 returns None. This function calls `hijack_tk` underneath.
510 """
503 """
511 if not USE_TK or sys.modules.has_key('Tkinter'):
504 if not USE_TK or sys.modules.has_key('Tkinter'):
512 return None
505 return None
513 else:
506 else:
514 try:
507 try:
515 import Tkinter
508 import Tkinter
516 except ImportError:
509 except ImportError:
517 return None
510 return None
518 else:
511 else:
519 hijack_tk()
512 hijack_tk()
520 r = Tkinter.Tk()
513 r = Tkinter.Tk()
521 r.withdraw()
514 r.withdraw()
522 return r
515 return r
523
516
524 def hijack_tk():
517 def hijack_tk():
525 """Modifies Tkinter's mainloop with a dummy so when a module calls
518 """Modifies Tkinter's mainloop with a dummy so when a module calls
526 mainloop, it does not block.
519 mainloop, it does not block.
527
520
528 """
521 """
529 def misc_mainloop(self, n=0):
522 def misc_mainloop(self, n=0):
530 pass
523 pass
531 def tkinter_mainloop(n=0):
524 def tkinter_mainloop(n=0):
532 pass
525 pass
533
526
534 import Tkinter
527 import Tkinter
535 Tkinter.Misc.mainloop = misc_mainloop
528 Tkinter.Misc.mainloop = misc_mainloop
536 Tkinter.mainloop = tkinter_mainloop
529 Tkinter.mainloop = tkinter_mainloop
537
530
538 def update_tk(tk):
531 def update_tk(tk):
539 """Updates the Tkinter event loop. This is typically called from
532 """Updates the Tkinter event loop. This is typically called from
540 the respective WX or GTK mainloops.
533 the respective WX or GTK mainloops.
541 """
534 """
542 if tk:
535 if tk:
543 tk.update()
536 tk.update()
544
537
545 def hijack_wx():
538 def hijack_wx():
546 """Modifies wxPython's MainLoop with a dummy so user code does not
539 """Modifies wxPython's MainLoop with a dummy so user code does not
547 block IPython. The hijacked mainloop function is returned.
540 block IPython. The hijacked mainloop function is returned.
548 """
541 """
549 def dummy_mainloop(*args, **kw):
542 def dummy_mainloop(*args, **kw):
550 pass
543 pass
551 import wxPython
544 import wxPython
552 ver = wxPython.__version__
545 ver = wxPython.__version__
553 orig_mainloop = None
546 orig_mainloop = None
554 if ver[:3] >= '2.5':
547 if ver[:3] >= '2.5':
555 import wx
548 import wx
556 if hasattr(wx, '_core_'): core = getattr(wx, '_core_')
549 if hasattr(wx, '_core_'): core = getattr(wx, '_core_')
557 elif hasattr(wx, '_core'): core = getattr(wx, '_core')
550 elif hasattr(wx, '_core'): core = getattr(wx, '_core')
558 else: raise AttributeError('Could not find wx core module')
551 else: raise AttributeError('Could not find wx core module')
559 orig_mainloop = core.PyApp_MainLoop
552 orig_mainloop = core.PyApp_MainLoop
560 core.PyApp_MainLoop = dummy_mainloop
553 core.PyApp_MainLoop = dummy_mainloop
561 elif ver[:3] == '2.4':
554 elif ver[:3] == '2.4':
562 orig_mainloop = wxPython.wxc.wxPyApp_MainLoop
555 orig_mainloop = wxPython.wxc.wxPyApp_MainLoop
563 wxPython.wxc.wxPyApp_MainLoop = dummy_mainloop
556 wxPython.wxc.wxPyApp_MainLoop = dummy_mainloop
564 else:
557 else:
565 warn("Unable to find either wxPython version 2.4 or >= 2.5.")
558 warn("Unable to find either wxPython version 2.4 or >= 2.5.")
566 return orig_mainloop
559 return orig_mainloop
567
560
568 def hijack_gtk():
561 def hijack_gtk():
569 """Modifies pyGTK's mainloop with a dummy so user code does not
562 """Modifies pyGTK's mainloop with a dummy so user code does not
570 block IPython. This function returns the original `gtk.mainloop`
563 block IPython. This function returns the original `gtk.mainloop`
571 function that has been hijacked.
564 function that has been hijacked.
572
565
573 NOTE: Make sure you import this *AFTER* you call
566 NOTE: Make sure you import this *AFTER* you call
574 pygtk.require(...).
567 pygtk.require(...).
575 """
568 """
576 def dummy_mainloop(*args, **kw):
569 def dummy_mainloop(*args, **kw):
577 pass
570 pass
578 import gtk
571 import gtk
579 if gtk.pygtk_version >= (2,4,0): orig_mainloop = gtk.main
572 if gtk.pygtk_version >= (2,4,0): orig_mainloop = gtk.main
580 else: orig_mainloop = gtk.mainloop
573 else: orig_mainloop = gtk.mainloop
581 gtk.mainloop = dummy_mainloop
574 gtk.mainloop = dummy_mainloop
582 gtk.main = dummy_mainloop
575 gtk.main = dummy_mainloop
583 return orig_mainloop
576 return orig_mainloop
584
577
585 #-----------------------------------------------------------------------------
578 #-----------------------------------------------------------------------------
586 # The IPShell* classes below are the ones meant to be run by external code as
579 # The IPShell* classes below are the ones meant to be run by external code as
587 # IPython instances. Note that unless a specific threading strategy is
580 # IPython instances. Note that unless a specific threading strategy is
588 # desired, the factory function start() below should be used instead (it
581 # desired, the factory function start() below should be used instead (it
589 # selects the proper threaded class).
582 # selects the proper threaded class).
590
583
591 class IPShellGTK(threading.Thread):
584 class IPShellGTK(threading.Thread):
592 """Run a gtk mainloop() in a separate thread.
585 """Run a gtk mainloop() in a separate thread.
593
586
594 Python commands can be passed to the thread where they will be executed.
587 Python commands can be passed to the thread where they will be executed.
595 This is implemented by periodically checking for passed code using a
588 This is implemented by periodically checking for passed code using a
596 GTK timeout callback."""
589 GTK timeout callback."""
597
590
598 TIMEOUT = 100 # Millisecond interval between timeouts.
591 TIMEOUT = 100 # Millisecond interval between timeouts.
599
592
600 def __init__(self,argv=None,user_ns=None,debug=1,
593 def __init__(self,argv=None,user_ns=None,debug=1,
601 shell_class=MTInteractiveShell):
594 shell_class=MTInteractiveShell):
602
595
603 import pygtk
596 import pygtk
604 pygtk.require("2.0")
597 pygtk.require("2.0")
605 import gtk
598 import gtk
606
599
607 self.gtk = gtk
600 self.gtk = gtk
608 self.gtk_mainloop = hijack_gtk()
601 self.gtk_mainloop = hijack_gtk()
609
602
610 # Allows us to use both Tk and GTK.
603 # Allows us to use both Tk and GTK.
611 self.tk = get_tk()
604 self.tk = get_tk()
612
605
613 if gtk.pygtk_version >= (2,4,0): mainquit = self.gtk.main_quit
606 if gtk.pygtk_version >= (2,4,0): mainquit = self.gtk.main_quit
614 else: mainquit = self.gtk.mainquit
607 else: mainquit = self.gtk.mainquit
615
608
616 self.IP = make_IPython(argv,user_ns=user_ns,debug=debug,
609 self.IP = make_IPython(argv,user_ns=user_ns,debug=debug,
617 shell_class=shell_class,
610 shell_class=shell_class,
618 on_kill=[mainquit])
611 on_kill=[mainquit])
619 threading.Thread.__init__(self)
612 threading.Thread.__init__(self)
620
613
621 def run(self):
614 def run(self):
622 self.IP.mainloop()
615 self.IP.mainloop()
623 self.IP.kill()
616 self.IP.kill()
624
617
625 def mainloop(self):
618 def mainloop(self):
626
619
627 if self.gtk.pygtk_version >= (2,4,0):
620 if self.gtk.pygtk_version >= (2,4,0):
628 import gobject
621 import gobject
629 gobject.timeout_add(self.TIMEOUT, self.on_timer)
622 gobject.timeout_add(self.TIMEOUT, self.on_timer)
630 else:
623 else:
631 self.gtk.timeout_add(self.TIMEOUT, self.on_timer)
624 self.gtk.timeout_add(self.TIMEOUT, self.on_timer)
632
625
633 if sys.platform != 'win32':
626 if sys.platform != 'win32':
634 try:
627 try:
635 if self.gtk.gtk_version[0] >= 2:
628 if self.gtk.gtk_version[0] >= 2:
636 self.gtk.threads_init()
629 self.gtk.threads_init()
637 except AttributeError:
630 except AttributeError:
638 pass
631 pass
639 except RuntimeError:
632 except RuntimeError:
640 error('Your pyGTK likely has not been compiled with '
633 error('Your pyGTK likely has not been compiled with '
641 'threading support.\n'
634 'threading support.\n'
642 'The exception printout is below.\n'
635 'The exception printout is below.\n'
643 'You can either rebuild pyGTK with threads, or '
636 'You can either rebuild pyGTK with threads, or '
644 'try using \n'
637 'try using \n'
645 'matplotlib with a different backend (like Tk or WX).\n'
638 'matplotlib with a different backend (like Tk or WX).\n'
646 'Note that matplotlib will most likely not work in its '
639 'Note that matplotlib will most likely not work in its '
647 'current state!')
640 'current state!')
648 self.IP.InteractiveTB()
641 self.IP.InteractiveTB()
649 self.start()
642 self.start()
650 self.gtk.threads_enter()
643 self.gtk.threads_enter()
651 self.gtk_mainloop()
644 self.gtk_mainloop()
652 self.gtk.threads_leave()
645 self.gtk.threads_leave()
653 self.join()
646 self.join()
654
647
655 def on_timer(self):
648 def on_timer(self):
656 update_tk(self.tk)
649 update_tk(self.tk)
657 return self.IP.runcode()
650 return self.IP.runcode()
658
651
659
652
660 class IPShellWX(threading.Thread):
653 class IPShellWX(threading.Thread):
661 """Run a wx mainloop() in a separate thread.
654 """Run a wx mainloop() in a separate thread.
662
655
663 Python commands can be passed to the thread where they will be executed.
656 Python commands can be passed to the thread where they will be executed.
664 This is implemented by periodically checking for passed code using a
657 This is implemented by periodically checking for passed code using a
665 GTK timeout callback."""
658 GTK timeout callback."""
666
659
667 TIMEOUT = 100 # Millisecond interval between timeouts.
660 TIMEOUT = 100 # Millisecond interval between timeouts.
668
661
669 def __init__(self,argv=None,user_ns=None,debug=1,
662 def __init__(self,argv=None,user_ns=None,debug=1,
670 shell_class=MTInteractiveShell):
663 shell_class=MTInteractiveShell):
671
664
672 import wxPython.wx as wx
665 import wxPython.wx as wx
673
666
674 threading.Thread.__init__(self)
667 threading.Thread.__init__(self)
675 self.wx = wx
668 self.wx = wx
676 self.wx_mainloop = hijack_wx()
669 self.wx_mainloop = hijack_wx()
677
670
678 # Allows us to use both Tk and GTK.
671 # Allows us to use both Tk and GTK.
679 self.tk = get_tk()
672 self.tk = get_tk()
680
673
681 self.IP = make_IPython(argv,user_ns=user_ns,debug=debug,
674 self.IP = make_IPython(argv,user_ns=user_ns,debug=debug,
682 shell_class=shell_class,
675 shell_class=shell_class,
683 on_kill=[self.wxexit])
676 on_kill=[self.wxexit])
684 self.app = None
677 self.app = None
685
678
686 def wxexit(self, *args):
679 def wxexit(self, *args):
687 if self.app is not None:
680 if self.app is not None:
688 self.app.agent.timer.Stop()
681 self.app.agent.timer.Stop()
689 self.app.ExitMainLoop()
682 self.app.ExitMainLoop()
690
683
691 def run(self):
684 def run(self):
692 self.IP.mainloop()
685 self.IP.mainloop()
693 self.IP.kill()
686 self.IP.kill()
694
687
695 def mainloop(self):
688 def mainloop(self):
696
689
697 self.start()
690 self.start()
698
691
699 class TimerAgent(self.wx.wxMiniFrame):
692 class TimerAgent(self.wx.wxMiniFrame):
700 wx = self.wx
693 wx = self.wx
701 IP = self.IP
694 IP = self.IP
702 tk = self.tk
695 tk = self.tk
703 def __init__(self, parent, interval):
696 def __init__(self, parent, interval):
704 style = self.wx.wxDEFAULT_FRAME_STYLE | self.wx.wxTINY_CAPTION_HORIZ
697 style = self.wx.wxDEFAULT_FRAME_STYLE | self.wx.wxTINY_CAPTION_HORIZ
705 self.wx.wxMiniFrame.__init__(self, parent, -1, ' ', pos=(200, 200),
698 self.wx.wxMiniFrame.__init__(self, parent, -1, ' ', pos=(200, 200),
706 size=(100, 100),style=style)
699 size=(100, 100),style=style)
707 self.Show(False)
700 self.Show(False)
708 self.interval = interval
701 self.interval = interval
709 self.timerId = self.wx.wxNewId()
702 self.timerId = self.wx.wxNewId()
710
703
711 def StartWork(self):
704 def StartWork(self):
712 self.timer = self.wx.wxTimer(self, self.timerId)
705 self.timer = self.wx.wxTimer(self, self.timerId)
713 self.wx.EVT_TIMER(self, self.timerId, self.OnTimer)
706 self.wx.EVT_TIMER(self, self.timerId, self.OnTimer)
714 self.timer.Start(self.interval)
707 self.timer.Start(self.interval)
715
708
716 def OnTimer(self, event):
709 def OnTimer(self, event):
717 update_tk(self.tk)
710 update_tk(self.tk)
718 self.IP.runcode()
711 self.IP.runcode()
719
712
720 class App(self.wx.wxApp):
713 class App(self.wx.wxApp):
721 wx = self.wx
714 wx = self.wx
722 TIMEOUT = self.TIMEOUT
715 TIMEOUT = self.TIMEOUT
723 def OnInit(self):
716 def OnInit(self):
724 'Create the main window and insert the custom frame'
717 'Create the main window and insert the custom frame'
725 self.agent = TimerAgent(None, self.TIMEOUT)
718 self.agent = TimerAgent(None, self.TIMEOUT)
726 self.agent.Show(self.wx.false)
719 self.agent.Show(self.wx.false)
727 self.agent.StartWork()
720 self.agent.StartWork()
728 return self.wx.true
721 return self.wx.true
729
722
730 self.app = App(redirect=False)
723 self.app = App(redirect=False)
731 self.wx_mainloop(self.app)
724 self.wx_mainloop(self.app)
732 self.join()
725 self.join()
733
726
734
727
735 class IPShellQt(threading.Thread):
728 class IPShellQt(threading.Thread):
736 """Run a Qt event loop in a separate thread.
729 """Run a Qt event loop in a separate thread.
737
730
738 Python commands can be passed to the thread where they will be executed.
731 Python commands can be passed to the thread where they will be executed.
739 This is implemented by periodically checking for passed code using a
732 This is implemented by periodically checking for passed code using a
740 Qt timer / slot."""
733 Qt timer / slot."""
741
734
742 TIMEOUT = 100 # Millisecond interval between timeouts.
735 TIMEOUT = 100 # Millisecond interval between timeouts.
743
736
744 def __init__(self,argv=None,user_ns=None,debug=0,
737 def __init__(self,argv=None,user_ns=None,debug=0,
745 shell_class=MTInteractiveShell):
738 shell_class=MTInteractiveShell):
746
739
747 import qt
740 import qt
748
741
749 class newQApplication:
742 class newQApplication:
750 def __init__( self ):
743 def __init__( self ):
751 self.QApplication = qt.QApplication
744 self.QApplication = qt.QApplication
752
745
753 def __call__( *args, **kwargs ):
746 def __call__( *args, **kwargs ):
754 return qt.qApp
747 return qt.qApp
755
748
756 def exec_loop( *args, **kwargs ):
749 def exec_loop( *args, **kwargs ):
757 pass
750 pass
758
751
759 def __getattr__( self, name ):
752 def __getattr__( self, name ):
760 return getattr( self.QApplication, name )
753 return getattr( self.QApplication, name )
761
754
762 qt.QApplication = newQApplication()
755 qt.QApplication = newQApplication()
763
756
764 # Allows us to use both Tk and QT.
757 # Allows us to use both Tk and QT.
765 self.tk = get_tk()
758 self.tk = get_tk()
766
759
767 self.IP = make_IPython(argv,user_ns=user_ns,debug=debug,
760 self.IP = make_IPython(argv,user_ns=user_ns,debug=debug,
768 shell_class=shell_class,
761 shell_class=shell_class,
769 on_kill=[qt.qApp.exit])
762 on_kill=[qt.qApp.exit])
770
763
771 threading.Thread.__init__(self)
764 threading.Thread.__init__(self)
772
765
773 def run(self):
766 def run(self):
774 #sys.excepthook = self.IP.excepthook # dbg
767 #sys.excepthook = self.IP.excepthook # dbg
775 self.IP.mainloop()
768 self.IP.mainloop()
776 self.IP.kill()
769 self.IP.kill()
777
770
778 def mainloop(self):
771 def mainloop(self):
779 import qt, sys
772 import qt, sys
780 if qt.QApplication.startingUp():
773 if qt.QApplication.startingUp():
781 a = qt.QApplication.QApplication( sys.argv )
774 a = qt.QApplication.QApplication( sys.argv )
782 self.timer = qt.QTimer()
775 self.timer = qt.QTimer()
783 qt.QObject.connect( self.timer, qt.SIGNAL( 'timeout()' ), self.on_timer )
776 qt.QObject.connect( self.timer, qt.SIGNAL( 'timeout()' ), self.on_timer )
784
777
785 self.start()
778 self.start()
786 self.timer.start( self.TIMEOUT, True )
779 self.timer.start( self.TIMEOUT, True )
787 while True:
780 while True:
788 if self.IP._kill: break
781 if self.IP._kill: break
789 qt.qApp.exec_loop()
782 qt.qApp.exec_loop()
790 self.join()
783 self.join()
791
784
792 def on_timer(self):
785 def on_timer(self):
793 update_tk(self.tk)
786 update_tk(self.tk)
794 result = self.IP.runcode()
787 result = self.IP.runcode()
795 self.timer.start( self.TIMEOUT, True )
788 self.timer.start( self.TIMEOUT, True )
796 return result
789 return result
797
790
798 # A set of matplotlib public IPython shell classes, for single-threaded
791 # A set of matplotlib public IPython shell classes, for single-threaded
799 # (Tk* and FLTK* backends) and multithreaded (GTK* and WX* backends) use.
792 # (Tk* and FLTK* backends) and multithreaded (GTK* and WX* backends) use.
800 class IPShellMatplotlib(IPShell):
793 class IPShellMatplotlib(IPShell):
801 """Subclass IPShell with MatplotlibShell as the internal shell.
794 """Subclass IPShell with MatplotlibShell as the internal shell.
802
795
803 Single-threaded class, meant for the Tk* and FLTK* backends.
796 Single-threaded class, meant for the Tk* and FLTK* backends.
804
797
805 Having this on a separate class simplifies the external driver code."""
798 Having this on a separate class simplifies the external driver code."""
806
799
807 def __init__(self,argv=None,user_ns=None,debug=1):
800 def __init__(self,argv=None,user_ns=None,debug=1):
808 IPShell.__init__(self,argv,user_ns,debug,shell_class=MatplotlibShell)
801 IPShell.__init__(self,argv,user_ns,debug,shell_class=MatplotlibShell)
809
802
810 class IPShellMatplotlibGTK(IPShellGTK):
803 class IPShellMatplotlibGTK(IPShellGTK):
811 """Subclass IPShellGTK with MatplotlibMTShell as the internal shell.
804 """Subclass IPShellGTK with MatplotlibMTShell as the internal shell.
812
805
813 Multi-threaded class, meant for the GTK* backends."""
806 Multi-threaded class, meant for the GTK* backends."""
814
807
815 def __init__(self,argv=None,user_ns=None,debug=1):
808 def __init__(self,argv=None,user_ns=None,debug=1):
816 IPShellGTK.__init__(self,argv,user_ns,debug,shell_class=MatplotlibMTShell)
809 IPShellGTK.__init__(self,argv,user_ns,debug,shell_class=MatplotlibMTShell)
817
810
818 class IPShellMatplotlibWX(IPShellWX):
811 class IPShellMatplotlibWX(IPShellWX):
819 """Subclass IPShellWX with MatplotlibMTShell as the internal shell.
812 """Subclass IPShellWX with MatplotlibMTShell as the internal shell.
820
813
821 Multi-threaded class, meant for the WX* backends."""
814 Multi-threaded class, meant for the WX* backends."""
822
815
823 def __init__(self,argv=None,user_ns=None,debug=1):
816 def __init__(self,argv=None,user_ns=None,debug=1):
824 IPShellWX.__init__(self,argv,user_ns,debug,shell_class=MatplotlibMTShell)
817 IPShellWX.__init__(self,argv,user_ns,debug,shell_class=MatplotlibMTShell)
825
818
826 class IPShellMatplotlibQt(IPShellQt):
819 class IPShellMatplotlibQt(IPShellQt):
827 """Subclass IPShellQt with MatplotlibMTShell as the internal shell.
820 """Subclass IPShellQt with MatplotlibMTShell as the internal shell.
828
821
829 Multi-threaded class, meant for the Qt* backends."""
822 Multi-threaded class, meant for the Qt* backends."""
830
823
831 def __init__(self,argv=None,user_ns=None,debug=1):
824 def __init__(self,argv=None,user_ns=None,debug=1):
832 IPShellQt.__init__(self,argv,user_ns,debug,shell_class=MatplotlibMTShell)
825 IPShellQt.__init__(self,argv,user_ns,debug,shell_class=MatplotlibMTShell)
833
826
834 #-----------------------------------------------------------------------------
827 #-----------------------------------------------------------------------------
835 # Factory functions to actually start the proper thread-aware shell
828 # Factory functions to actually start the proper thread-aware shell
836
829
837 def _matplotlib_shell_class():
830 def _matplotlib_shell_class():
838 """Factory function to handle shell class selection for matplotlib.
831 """Factory function to handle shell class selection for matplotlib.
839
832
840 The proper shell class to use depends on the matplotlib backend, since
833 The proper shell class to use depends on the matplotlib backend, since
841 each backend requires a different threading strategy."""
834 each backend requires a different threading strategy."""
842
835
843 try:
836 try:
844 import matplotlib
837 import matplotlib
845 except ImportError:
838 except ImportError:
846 error('matplotlib could NOT be imported! Starting normal IPython.')
839 error('matplotlib could NOT be imported! Starting normal IPython.')
847 sh_class = IPShell
840 sh_class = IPShell
848 else:
841 else:
849 backend = matplotlib.rcParams['backend']
842 backend = matplotlib.rcParams['backend']
850 if backend.startswith('GTK'):
843 if backend.startswith('GTK'):
851 sh_class = IPShellMatplotlibGTK
844 sh_class = IPShellMatplotlibGTK
852 elif backend.startswith('WX'):
845 elif backend.startswith('WX'):
853 sh_class = IPShellMatplotlibWX
846 sh_class = IPShellMatplotlibWX
854 elif backend.startswith('Qt'):
847 elif backend.startswith('Qt'):
855 sh_class = IPShellMatplotlibQt
848 sh_class = IPShellMatplotlibQt
856 else:
849 else:
857 sh_class = IPShellMatplotlib
850 sh_class = IPShellMatplotlib
858 #print 'Using %s with the %s backend.' % (sh_class,backend) # dbg
851 #print 'Using %s with the %s backend.' % (sh_class,backend) # dbg
859 return sh_class
852 return sh_class
860
853
861 # This is the one which should be called by external code.
854 # This is the one which should be called by external code.
862 def start():
855 def start():
863 """Return a running shell instance, dealing with threading options.
856 """Return a running shell instance, dealing with threading options.
864
857
865 This is a factory function which will instantiate the proper IPython shell
858 This is a factory function which will instantiate the proper IPython shell
866 based on the user's threading choice. Such a selector is needed because
859 based on the user's threading choice. Such a selector is needed because
867 different GUI toolkits require different thread handling details."""
860 different GUI toolkits require different thread handling details."""
868
861
869 global USE_TK
862 global USE_TK
870 # Crude sys.argv hack to extract the threading options.
863 # Crude sys.argv hack to extract the threading options.
871 if len(sys.argv) > 1:
864 if len(sys.argv) > 1:
872 if len(sys.argv) > 2:
865 if len(sys.argv) > 2:
873 arg2 = sys.argv[2]
866 arg2 = sys.argv[2]
874 if arg2.endswith('-tk'):
867 if arg2.endswith('-tk'):
875 USE_TK = True
868 USE_TK = True
876 arg1 = sys.argv[1]
869 arg1 = sys.argv[1]
877 if arg1.endswith('-gthread'):
870 if arg1.endswith('-gthread'):
878 shell = IPShellGTK
871 shell = IPShellGTK
879 elif arg1.endswith( '-qthread' ):
872 elif arg1.endswith( '-qthread' ):
880 shell = IPShellQt
873 shell = IPShellQt
881 elif arg1.endswith('-wthread'):
874 elif arg1.endswith('-wthread'):
882 shell = IPShellWX
875 shell = IPShellWX
883 elif arg1.endswith('-pylab'):
876 elif arg1.endswith('-pylab'):
884 shell = _matplotlib_shell_class()
877 shell = _matplotlib_shell_class()
885 else:
878 else:
886 shell = IPShell
879 shell = IPShell
887 else:
880 else:
888 shell = IPShell
881 shell = IPShell
889 return shell()
882 return shell()
890
883
891 # Some aliases for backwards compatibility
884 # Some aliases for backwards compatibility
892 IPythonShell = IPShell
885 IPythonShell = IPShell
893 IPythonShellEmbed = IPShellEmbed
886 IPythonShellEmbed = IPShellEmbed
894 #************************ End of file <Shell.py> ***************************
887 #************************ End of file <Shell.py> ***************************
General Comments 0
You need to be logged in to leave comments. Login now