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