From cbcea26bada208e06fb07a748ec990b7d2b62ce6 2008-07-21 04:10:45 From: Gael Varoquaux Date: 2008-07-21 04:10:45 Subject: [PATCH] Add demo app. Add callback for exit to the ipython0 code. --- diff --git a/IPython/Extensions/ipy_legacy.py b/IPython/Extensions/ipy_legacy.py index e59a5db..2807dfd 100644 --- a/IPython/Extensions/ipy_legacy.py +++ b/IPython/Extensions/ipy_legacy.py @@ -49,7 +49,7 @@ ip.expose_magic("rehash", magic_rehash) def magic_Quit(self, parameter_s=''): """Exit IPython without confirmation (like %Exit).""" - self.shell.exit_now = True + self.shell.ask_exit() ip.expose_magic("Quit", magic_Quit) diff --git a/IPython/Magic.py b/IPython/Magic.py index f1c0162..09ec82a 100644 --- a/IPython/Magic.py +++ b/IPython/Magic.py @@ -2459,7 +2459,7 @@ Defaulting color scheme to 'NoColor'""" def magic_Exit(self, parameter_s=''): """Exit IPython without confirmation.""" - self.shell.exit_now = True + self.shell.ask_exit() #...................................................................... # Functions to implement unix shell-type things diff --git a/IPython/frontend/prefilterfrontend.py b/IPython/frontend/prefilterfrontend.py index b92d333..feda2c9 100644 --- a/IPython/frontend/prefilterfrontend.py +++ b/IPython/frontend/prefilterfrontend.py @@ -24,6 +24,7 @@ from IPython.ipapi import IPApi from IPython.kernel.core.sync_output_trap import SyncOutputTrap from IPython.genutils import Term +import pydoc #------------------------------------------------------------------------------- # Utility functions (temporary, should be moved out of here) @@ -71,9 +72,10 @@ class PrefilterFrontEnd(LineFrontEndBase): # terminal self.shell.output_trap = SyncOutputTrap(write_out=self.write, write_err=self.write) - - import pydoc - pydoc.help.output = self.shell.output_trap.out + # Capture and release the outputs, to make sure all the + # shadow variables are set + self.capture_output() + self.release_output() def prefilter_input(self, input_string): @@ -105,8 +107,15 @@ class PrefilterFrontEnd(LineFrontEndBase): self.release_output() + def execute(self, python_string, raw_string=None): + self.capture_output() + LineFrontEndBase.execute(self, python_string, + raw_string=raw_string) + self.release_output() + + def capture_output(self): - """ Capture all the output mechanism we can think of. + """ Capture all the output mechanisms we can think of. """ self.__old_cout_write = Term.cout.write self.__old_err_write = Term.cerr.write @@ -116,16 +125,18 @@ class PrefilterFrontEnd(LineFrontEndBase): self.__old_stderr= sys.stderr sys.stdout = Term.cout sys.stderr = Term.cerr + self.__old_help_output = pydoc.help.output + pydoc.help.output = self.shell.output_trap.out def release_output(self): - """ Release all the different captures we have made, - and flush the buffers. + """ Release all the different captures we have made. """ Term.cout.write = self.__old_cout_write Term.cerr.write = self.__old_err_write sys.stdout = self.__old_stdout sys.stderr = self.__old_stderr + pydoc.help.output = self.__old_help_output def complete(self, line): @@ -139,3 +150,8 @@ class PrefilterFrontEnd(LineFrontEndBase): return line, completions + def do_exit(self): + """ Exit the shell, cleanup and save the history. + """ + self.ipython0.atexit_operations() + diff --git a/IPython/frontend/wx/wipython.py b/IPython/frontend/wx/wipython.py new file mode 100644 index 0000000..b67964f --- /dev/null +++ b/IPython/frontend/wx/wipython.py @@ -0,0 +1,80 @@ +""" +Entry point for a simple application giving a graphical frontend to +ipython. +""" + +import wx +from wx_frontend import WxController + +class WIPythonController(WxController): + """ Sub class of WxController that adds some application-specific + bindings. + """ + + def __init__(self, *args, **kwargs): + WxController.__init__(self, *args, **kwargs) + self.ipython0.ask_exit = self.do_exit + + + def _on_key_down(self, event, skip=True): + # Intercept Ctrl-D to quit + if event.KeyCode == ord('D') and event.ControlDown() and \ + self.get_current_edit_buffer()=='': + wx.CallAfter(self.ask_exit) + else: + WxController._on_key_down(self, event, skip=skip) + + + def ask_exit(self): + """ Ask the user whether to exit. + """ + self.write('\n') + self.capture_output() + self.ipython0.shell.exit() + self.release_output() + wx.Yield() + if not self.ipython0.exit_now: + self.new_prompt(self.prompt % (self.last_result['number'] + 1)) + + + def do_exit(self): + """ Exits the interpreter, kills the windows. + """ + WxController.do_exit(self) + # Remove the callbacks, to avoid PyDeadObjectErrors + do_nothing = lambda *args, **kwargs: True + self.release_output() + self._on_key_down = do_nothing + self._on_key_up = do_nothing + self._on_enter = do_nothing + self.after_execute = do_nothing + wx.Yield() + wx.CallAfter(self.Parent.Destroy) + + + +class WIPython(wx.Frame): + """ Main frame of the WIPython app. + """ + + def __init__(self, parent, id, title): + wx.Frame.__init__(self, parent, id, title, size=(300,250)) + self._sizer = wx.BoxSizer(wx.VERTICAL) + self.shell = WIPythonController(self) + self._sizer.Add(self.shell, 1, wx.EXPAND) + self.SetSizer(self._sizer) + self.SetAutoLayout(1) + self.Show(True) + + +def main(): + app = wx.PySimpleApp() + frame = WIPython(None, wx.ID_ANY, 'WIpython') + frame.shell.SetFocus() + frame.shell.app = app + frame.SetSize((680, 460)) + + app.MainLoop() + +if __name__ == '__main__': + main() diff --git a/IPython/frontend/wx/wx_frontend.py b/IPython/frontend/wx/wx_frontend.py index 3123b4e..0af67d1 100644 --- a/IPython/frontend/wx/wx_frontend.py +++ b/IPython/frontend/wx/wx_frontend.py @@ -151,10 +151,18 @@ class WxController(PrefilterFrontEnd, ConsoleWidget): #self.SetSelection(self.GetLength()-1, self.GetLength()) #self.ReplaceSelection('') self.GotoPos(self.GetLength()) + PrefilterFrontEnd.execute(self, python_string, raw_string=raw_string) + + + def capture_output(self): self.__old_raw_input = __builtin__.raw_input __builtin__.raw_input = self.raw_input - PrefilterFrontEnd.execute(self, python_string, raw_string=raw_string) + PrefilterFrontEnd.capture_output(self) + + + def release_output(self): __builtin__.raw_input = self.__old_raw_input + PrefilterFrontEnd.capture_output(self) def after_execute(self): diff --git a/IPython/iplib.py b/IPython/iplib.py index 4355beb..df9df2c 100644 --- a/IPython/iplib.py +++ b/IPython/iplib.py @@ -734,7 +734,7 @@ class InteractiveShell(object,Magic): batchrun = True # without -i option, exit after running the batch file if batchrun and not self.rc.interact: - self.exit_now = True + self.ask_exit() def add_builtins(self): """Store ipython references into the builtin namespace. @@ -1590,7 +1590,7 @@ want to merge them back into the new files.""" % locals() #sys.argv = ['-c'] self.push(self.prefilter(self.rc.c, False)) if not self.rc.interact: - self.exit_now = True + self.ask_exit() def embed_mainloop(self,header='',local_ns=None,global_ns=None,stack_depth=0): """Embeds IPython into a running python program. @@ -1752,7 +1752,8 @@ want to merge them back into the new files.""" % locals() if self.has_readline: self.readline_startup_hook(self.pre_readline) - # exit_now is set by a call to %Exit or %Quit + # exit_now is set by a call to %Exit or %Quit, through the + # ask_exit callback. while not self.exit_now: self.hooks.pre_prompt_hook() @@ -2157,7 +2158,7 @@ want to merge them back into the new files.""" % locals() except ValueError: warn("\n********\nYou or a %run:ed script called sys.stdin.close()" " or sys.stdout.close()!\nExiting IPython!") - self.exit_now = True + self.ask_exit() return "" # Try to be reasonably smart about not re-indenting pasted input more @@ -2507,16 +2508,20 @@ want to merge them back into the new files.""" % locals() """Write a string to the default error output""" Term.cerr.write(data) + def ask_exit(self): + """ Call for exiting. Can be overiden and used as a callback. """ + self.exit_now = True + def exit(self): """Handle interactive exit. - This method sets the exit_now attribute.""" + This method calls the ask_exit callback.""" if self.rc.confirm_exit: if self.ask_yes_no('Do you really want to exit ([y]/n)?','y'): - self.exit_now = True + self.ask_exit() else: - self.exit_now = True + self.ask_exit() def safe_execfile(self,fname,*where,**kw): """A safe version of the builtin execfile().