--- ipython-0.6.15/IPython/Shell.py 2005-05-31 12:23:20.000000000 -0600 +++ trunk/IPython/Shell.py 2006-01-02 12:40:33.000000000 -0700 @@ -4,7 +4,7 @@ All the matplotlib support code was co-developed with John Hunter, matplotlib's author. -$Id: Shell.py,v 1.47 2005/05/31 18:23:20 fperez Exp $""" +$Id: Shell.py 965 2005-12-28 23:23:09Z fperez $""" #***************************************************************************** # Copyright (C) 2001-2004 Fernando Perez @@ -20,19 +20,18 @@ # Code begins import __main__ import __builtin__ -import sys import os -import code -import threading +import sys import signal +import threading import IPython +from IPython import ultraTB +from IPython.genutils import Term,warn,error,flag_calls from IPython.iplib import InteractiveShell from IPython.ipmaker import make_IPython -from IPython.genutils import Term,warn,error,flag_calls -from IPython.Struct import Struct from IPython.Magic import Magic -from IPython import ultraTB +from IPython.Struct import Struct # global flag to pass around information about Ctrl-C without exceptions KBINT = False @@ -48,10 +47,10 @@ class IPShell: """Create an IPython instance.""" - def __init__(self,argv=None,user_ns=None,debug=1, - shell_class=InteractiveShell): - self.IP = make_IPython(argv,user_ns=user_ns,debug=debug, - shell_class=shell_class) + def __init__(self,argv=None,user_ns=None,user_global_ns=None, + debug=1,shell_class=InteractiveShell): + self.IP = make_IPython(argv,user_ns=user_ns,user_global_ns=user_global_ns, + debug=debug,shell_class=shell_class) def mainloop(self,sys_exit=0,banner=None): self.IP.mainloop(banner) @@ -132,10 +131,6 @@ #self.IP = make_IPython(argv,user_ns=__main__.__dict__) self.IP = make_IPython(argv,rc_override=rc_override,embedded=True) - self.IP.name_space_init() - # mark this as an embedded instance so we know if we get a crash - # post-mortem - self.IP.rc.embedded = 1 # copy our own displayhook also self.sys_displayhook_embed = sys.displayhook # and leave the system's display hook clean @@ -216,8 +211,8 @@ If you need to manually""" - if dummy not in [0,1]: - raise ValueError,'dummy parameter must be 0 or 1' + if dummy not in [0,1,False,True]: + raise ValueError,'dummy parameter must be boolean' self.__dummy_mode = dummy def get_dummy_mode(self): @@ -265,11 +260,16 @@ # McErlean and John Finlay. Modified with corrections by Antoon Pardon, # from the pygtk mailing list, to avoid lockups with system calls. + # class attribute to indicate whether the class supports threads or not. + # Subclasses with thread support should override this as needed. + isthreaded = True + def __init__(self,name,usage=None,rc=Struct(opts=None,args=None), - user_ns = None, banner2='',**kw): + user_ns=None,user_global_ns=None,banner2='',**kw): """Similar to the normal InteractiveShell, but with threading control""" - IPython.iplib.InteractiveShell.__init__(self,name,usage,rc,user_ns,banner2) + InteractiveShell.__init__(self,name,usage,rc,user_ns, + user_global_ns,banner2) # Locking control variable self.thread_ready = threading.Condition() @@ -312,7 +312,6 @@ # Case 3 # Store code in self, so the execution thread can handle it self.thread_ready.acquire() - self.code_to_run_src = source self.code_to_run = code self.thread_ready.wait() # Wait until processed in timeout interval self.thread_ready.release() @@ -400,15 +399,6 @@ self.mpl_use._called = True self.matplotlib = matplotlib - - # Take control of matplotlib's error handling, which can normally - # lock up the python interpreter when raw_input() is called - import matplotlib.backends as backend - backend.error_msg = error - - # we'll handle the mainloop, tell show not to - import matplotlib.backends - matplotlib.backends.show._needmain = False self.mpl_backend = matplotlib.rcParams['backend'] # we also need to block switching of interactive backends by use() @@ -417,9 +407,6 @@ # overwrite the original matplotlib.use with our wrapper matplotlib.use = use - # We need to detect at runtime whether show() is called by the user. - # For this, we wrap it into a decorator which adds a 'called' flag. - backend.draw_if_interactive = flag_calls(backend.draw_if_interactive) # This must be imported last in the matplotlib series, after # backend/interactivity choices have been made @@ -432,6 +419,11 @@ self.pylab = matlab self.pylab_name = 'matlab' + self.pylab.show._needmain = False + # We need to detect at runtime whether show() is called by the user. + # For this, we wrap it into a decorator which adds a 'called' flag. + self.pylab.draw_if_interactive = flag_calls(self.pylab.draw_if_interactive) + # Build a user namespace initialized with matplotlib/matlab features. user_ns = {'__name__':'__main__', '__builtins__' : __builtin__ } @@ -448,7 +440,7 @@ b=""" Welcome to pylab, a matplotlib-based Python environment. For more information, type 'help(pylab)'. - """ +""" return user_ns,b def mplot_exec(self,fname,*where,**kw): @@ -488,17 +480,19 @@ """Single-threaded shell with matplotlib support.""" def __init__(self,name,usage=None,rc=Struct(opts=None,args=None), - user_ns = None, **kw): + user_ns=None,user_global_ns=None,**kw): user_ns,b2 = self._matplotlib_config(name) - InteractiveShell.__init__(self,name,usage,rc,user_ns,banner2=b2,**kw) + InteractiveShell.__init__(self,name,usage,rc,user_ns,user_global_ns, + banner2=b2,**kw) class MatplotlibMTShell(MatplotlibShellBase,MTInteractiveShell): """Multi-threaded shell with matplotlib support.""" def __init__(self,name,usage=None,rc=Struct(opts=None,args=None), - user_ns = None, **kw): + user_ns=None,user_global_ns=None, **kw): user_ns,b2 = self._matplotlib_config(name) - MTInteractiveShell.__init__(self,name,usage,rc,user_ns,banner2=b2,**kw) + MTInteractiveShell.__init__(self,name,usage,rc,user_ns,user_global_ns, + banner2=b2,**kw) #----------------------------------------------------------------------------- # Utility functions for the different GUI enabled IPShell* classes. @@ -569,9 +563,6 @@ """Modifies pyGTK's mainloop with a dummy so user code does not block IPython. This function returns the original `gtk.mainloop` function that has been hijacked. - - NOTE: Make sure you import this *AFTER* you call - pygtk.require(...). """ def dummy_mainloop(*args, **kw): pass @@ -597,11 +588,9 @@ TIMEOUT = 100 # Millisecond interval between timeouts. - def __init__(self,argv=None,user_ns=None,debug=1, - shell_class=MTInteractiveShell): + def __init__(self,argv=None,user_ns=None,user_global_ns=None, + debug=1,shell_class=MTInteractiveShell): - import pygtk - pygtk.require("2.0") import gtk self.gtk = gtk @@ -613,18 +602,33 @@ if gtk.pygtk_version >= (2,4,0): mainquit = self.gtk.main_quit else: mainquit = self.gtk.mainquit - self.IP = make_IPython(argv,user_ns=user_ns,debug=debug, + self.IP = make_IPython(argv,user_ns=user_ns, + user_global_ns=user_global_ns, + debug=debug, shell_class=shell_class, on_kill=[mainquit]) + + # HACK: slot for banner in self; it will be passed to the mainloop + # method only and .run() needs it. The actual value will be set by + # .mainloop(). + self._banner = None + threading.Thread.__init__(self) def run(self): - self.IP.mainloop() + self.IP.mainloop(self._banner) self.IP.kill() - def mainloop(self): + def mainloop(self,sys_exit=0,banner=None): + + self._banner = banner - self.gtk.timeout_add(self.TIMEOUT, self.on_timer) + if self.gtk.pygtk_version >= (2,4,0): + import gobject + gobject.idle_add(self.on_timer) + else: + self.gtk.idle_add(self.on_timer) + if sys.platform != 'win32': try: if self.gtk.gtk_version[0] >= 2: @@ -661,8 +665,8 @@ TIMEOUT = 100 # Millisecond interval between timeouts. - def __init__(self,argv=None,user_ns=None,debug=1, - shell_class=MTInteractiveShell): + def __init__(self,argv=None,user_ns=None,user_global_ns=None, + debug=1,shell_class=MTInteractiveShell): import wxPython.wx as wx @@ -673,9 +677,16 @@ # Allows us to use both Tk and GTK. self.tk = get_tk() - self.IP = make_IPython(argv,user_ns=user_ns,debug=debug, + self.IP = make_IPython(argv,user_ns=user_ns, + user_global_ns=user_global_ns, + debug=debug, shell_class=shell_class, on_kill=[self.wxexit]) + # HACK: slot for banner in self; it will be passed to the mainloop + # method only and .run() needs it. The actual value will be set by + # .mainloop(). + self._banner = None + self.app = None def wxexit(self, *args): @@ -684,10 +695,12 @@ self.app.ExitMainLoop() def run(self): - self.IP.mainloop() + self.IP.mainloop(self._banner) self.IP.kill() - def mainloop(self): + def mainloop(self,sys_exit=0,banner=None): + + self._banner = banner self.start() @@ -736,8 +749,8 @@ TIMEOUT = 100 # Millisecond interval between timeouts. - def __init__(self,argv=None,user_ns=None,debug=0, - shell_class=MTInteractiveShell): + def __init__(self,argv=None,user_ns=None,user_global_ns=None, + debug=0,shell_class=MTInteractiveShell): import qt @@ -759,20 +772,31 @@ # Allows us to use both Tk and QT. self.tk = get_tk() - self.IP = make_IPython(argv,user_ns=user_ns,debug=debug, + self.IP = make_IPython(argv,user_ns=user_ns, + user_global_ns=user_global_ns, + debug=debug, shell_class=shell_class, on_kill=[qt.qApp.exit]) + + # HACK: slot for banner in self; it will be passed to the mainloop + # method only and .run() needs it. The actual value will be set by + # .mainloop(). + self._banner = None + threading.Thread.__init__(self) def run(self): - self.IP.mainloop() + self.IP.mainloop(self._banner) self.IP.kill() - def mainloop(self): + def mainloop(self,sys_exit=0,banner=None): + + import qt + + self._banner = banner - import qt, sys if qt.QApplication.startingUp(): - a = qt.QApplication.QApplication( sys.argv ) + a = qt.QApplication.QApplication(sys.argv) self.timer = qt.QTimer() qt.QObject.connect( self.timer, qt.SIGNAL( 'timeout()' ), self.on_timer ) @@ -798,32 +822,36 @@ Having this on a separate class simplifies the external driver code.""" - def __init__(self,argv=None,user_ns=None,debug=1): - IPShell.__init__(self,argv,user_ns,debug,shell_class=MatplotlibShell) + def __init__(self,argv=None,user_ns=None,user_global_ns=None,debug=1): + IPShell.__init__(self,argv,user_ns,user_global_ns,debug, + shell_class=MatplotlibShell) class IPShellMatplotlibGTK(IPShellGTK): """Subclass IPShellGTK with MatplotlibMTShell as the internal shell. Multi-threaded class, meant for the GTK* backends.""" - def __init__(self,argv=None,user_ns=None,debug=1): - IPShellGTK.__init__(self,argv,user_ns,debug,shell_class=MatplotlibMTShell) + def __init__(self,argv=None,user_ns=None,user_global_ns=None,debug=1): + IPShellGTK.__init__(self,argv,user_ns,user_global_ns,debug, + shell_class=MatplotlibMTShell) class IPShellMatplotlibWX(IPShellWX): """Subclass IPShellWX with MatplotlibMTShell as the internal shell. Multi-threaded class, meant for the WX* backends.""" - def __init__(self,argv=None,user_ns=None,debug=1): - IPShellWX.__init__(self,argv,user_ns,debug,shell_class=MatplotlibMTShell) + def __init__(self,argv=None,user_ns=None,user_global_ns=None,debug=1): + IPShellWX.__init__(self,argv,user_ns,user_global_ns,debug, + shell_class=MatplotlibMTShell) class IPShellMatplotlibQt(IPShellQt): """Subclass IPShellQt with MatplotlibMTShell as the internal shell. Multi-threaded class, meant for the Qt* backends.""" - def __init__(self,argv=None,user_ns=None,debug=1): - IPShellQt.__init__(self,argv,user_ns,debug,shell_class=MatplotlibMTShell) + def __init__(self,argv=None,user_ns=None,user_global_ns=None,debug=1): + IPShellQt.__init__(self,argv,user_ns,user_global_ns,debug, + shell_class=MatplotlibMTShell) #----------------------------------------------------------------------------- # Factory functions to actually start the proper thread-aware shell @@ -862,12 +890,13 @@ global USE_TK # Crude sys.argv hack to extract the threading options. - if len(sys.argv) > 1: - if len(sys.argv) > 2: - arg2 = sys.argv[2] + argv = sys.argv + if len(argv) > 1: + if len(argv) > 2: + arg2 = argv[2] if arg2.endswith('-tk'): USE_TK = True - arg1 = sys.argv[1] + arg1 = argv[1] if arg1.endswith('-gthread'): shell = IPShellGTK elif arg1.endswith( '-qthread' ):