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