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