From dddf1831d6ba3836eecba3f7ac58883072d56726 2008-08-12 05:39:00
From: Gael Varoquaux <gael.varoquaux@normalesup.org>
Date: 2008-08-12 05:39:00
Subject: [PATCH] Isolate the displayhook created by ipython0. This fixes a test not
passing due to the side-effects of testing the prefilterfrontend.

---

diff --git a/IPython/frontend/prefilterfrontend.py b/IPython/frontend/prefilterfrontend.py
index 42f00b8..3e8bb4a 100644
--- a/IPython/frontend/prefilterfrontend.py
+++ b/IPython/frontend/prefilterfrontend.py
@@ -60,6 +60,7 @@ class PrefilterFrontEnd(LineFrontEndBase):
     
     def __init__(self, *args, **kwargs):
         LineFrontEndBase.__init__(self, *args, **kwargs)
+        self.save_output_hooks()
         # Instanciate an IPython0 interpreter to be able to use the
         # prefiltering.
         self.ipython0 = make_IPython()
@@ -78,6 +79,8 @@ class PrefilterFrontEnd(LineFrontEndBase):
         # in our environment
         self.ipython0.magic_ls = mk_system_call(self.system_call, 
                                                             'ls -CF')
+        # And now clean up the mess created by ipython0
+        self.release_output()
         self.shell.output_trap = RedirectorOutputTrap(
                             out_callback=self.write,
                             err_callback=self.write,
@@ -85,10 +88,6 @@ class PrefilterFrontEnd(LineFrontEndBase):
         self.shell.traceback_trap = SyncTracebackTrap(
                         formatters=self.shell.traceback_trap.formatters,
                             )
-        # Capture and release the outputs, to make sure all the
-        # shadow variables are set
-        self.capture_output()
-        self.release_output()
 
     #--------------------------------------------------------------------------
     # FrontEndBase interface 
@@ -109,18 +108,29 @@ class PrefilterFrontEnd(LineFrontEndBase):
         self.release_output()
 
 
+    def save_output_hooks(self):
+        """ Store all the output hooks we can think of, to be able to
+        restore them. 
+        
+        We need to do this early, as starting the ipython0 instance will
+        screw ouput hooks.
+        """
+        self.__old_cout_write = Term.cout.write
+        self.__old_cerr_write = Term.cerr.write
+        self.__old_stdout = sys.stdout
+        self.__old_stderr= sys.stderr
+        self.__old_help_output = pydoc.help.output
+        self.__old_display_hook = sys.displayhook
+
+
     def capture_output(self):
         """ Capture all the output mechanisms we can think of.
         """
-        self.__old_cout_write = Term.cout.write
-        self.__old_err_write = Term.cerr.write
+        self.save_output_hooks()
         Term.cout.write = self.write
         Term.cerr.write = self.write
-        self.__old_stdout = sys.stdout
-        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
 
 
@@ -128,10 +138,11 @@ class PrefilterFrontEnd(LineFrontEndBase):
         """ Release all the different captures we have made.
         """
         Term.cout.write = self.__old_cout_write
-        Term.cerr.write = self.__old_err_write
+        Term.cerr.write = self.__old_cerr_write
         sys.stdout = self.__old_stdout
         sys.stderr = self.__old_stderr
         pydoc.help.output = self.__old_help_output 
+        sys.displayhook = self.__old_display_hook 
 
 
     def complete(self, line):
diff --git a/IPython/frontend/tests/test_prefilterfrontend.py b/IPython/frontend/tests/test_prefilterfrontend.py
index fa92aea..a48a10c 100644
--- a/IPython/frontend/tests/test_prefilterfrontend.py
+++ b/IPython/frontend/tests/test_prefilterfrontend.py
@@ -15,6 +15,7 @@ __docformat__ = "restructuredtext en"
 from IPython.frontend.prefilterfrontend import PrefilterFrontEnd
 from cStringIO import StringIO
 import string
+import sys
 
 class TestPrefilterFrontEnd(PrefilterFrontEnd):
     
diff --git a/IPython/frontend/wx/console_widget.py b/IPython/frontend/wx/console_widget.py
index 17d81a3..7fd84b3 100644
--- a/IPython/frontend/wx/console_widget.py
+++ b/IPython/frontend/wx/console_widget.py
@@ -133,8 +133,6 @@ class ConsoleWidget(editwindow.EditWindow):
         # XXX: do not put print statements to sys.stdout/sys.stderr in 
         # this method, the print statements will call this method, as 
         # you will end up with an infinit loop
-        if self.debug:
-            print >>sys.__stderr__, text
         title = self.title_pat.split(text)
         if len(title)>1:
             self.title = title[-2]
diff --git a/IPython/frontend/wx/ipythonx.py b/IPython/frontend/wx/ipythonx.py
index ac7bf34..8458a6f 100644
--- a/IPython/frontend/wx/ipythonx.py
+++ b/IPython/frontend/wx/ipythonx.py
@@ -12,7 +12,7 @@ class IPythonXController(WxController):
         bindings.
     """
 
-    debug = False
+    debug = True
 
     def __init__(self, *args, **kwargs):
         WxController.__init__(self, *args, **kwargs)
diff --git a/IPython/frontend/wx/wx_frontend.py b/IPython/frontend/wx/wx_frontend.py
index cf66de6..9e455a4 100644
--- a/IPython/frontend/wx/wx_frontend.py
+++ b/IPython/frontend/wx/wx_frontend.py
@@ -42,12 +42,13 @@ from IPython.frontend.prefilterfrontend import PrefilterFrontEnd
 # Constants 
 #-------------------------------------------------------------------------------
 
-#_COMMAND_BG = '#FAFAF1' # Nice green
-_RUNNING_BUFFER_BG = '#FDFFD3' # Nice yellow
+_COMPLETE_BUFFER_BG = '#FAFAF1' # Nice green
+_INPUT_BUFFER_BG = '#FDFFD3' # Nice yellow
 _ERROR_BG = '#FFF1F1' # Nice red
 
-_RUNNING_BUFFER_MARKER = 31
+_COMPLETE_BUFFER_MARKER = 31
 _ERROR_MARKER = 30
+_INPUT_MARKER = 29
 
 prompt_in1 = \
         '\n\x01\x1b[0;34m\x02In [\x01\x1b[1;34m\x02$number\x01\x1b[0;34m\x02]: \x01\x1b[0m\x02'
@@ -124,6 +125,8 @@ class WxController(ConsoleWidget, PrefilterFrontEnd):
     # while it is being swapped
     _out_buffer_lock = Lock()
 
+    _markers = dict()
+
     #--------------------------------------------------------------------------
     # Public API
     #--------------------------------------------------------------------------
@@ -136,9 +139,12 @@ class WxController(ConsoleWidget, PrefilterFrontEnd):
         ConsoleWidget.__init__(self, parent, id, pos, size, style)
         PrefilterFrontEnd.__init__(self)
 
-        # Marker for running buffer.
-        self.MarkerDefine(_RUNNING_BUFFER_MARKER, stc.STC_MARK_BACKGROUND,
-                                background=_RUNNING_BUFFER_BG)
+        # Marker for complete buffer.
+        self.MarkerDefine(_COMPLETE_BUFFER_MARKER, stc.STC_MARK_BACKGROUND,
+                                background=_COMPLETE_BUFFER_BG)
+        # Marker for current input buffer.
+        self.MarkerDefine(_INPUT_MARKER, stc.STC_MARK_BACKGROUND,
+                                background=_INPUT_BUFFER_BG)
         # Marker for tracebacks.
         self.MarkerDefine(_ERROR_MARKER, stc.STC_MARK_BACKGROUND,
                                 background=_ERROR_BG)
@@ -148,6 +154,10 @@ class WxController(ConsoleWidget, PrefilterFrontEnd):
         self._buffer_flush_timer = wx.Timer(self, BUFFER_FLUSH_TIMER_ID)
         wx.EVT_TIMER(self, BUFFER_FLUSH_TIMER_ID, self._buffer_flush)
 
+        # Inject self in namespace, for debug
+        if self.debug:
+            self.shell.user_ns['self'] = self
+
 
     def raw_input(self, prompt):
         """ A replacement from python's raw_input.
@@ -258,7 +268,9 @@ class WxController(ConsoleWidget, PrefilterFrontEnd):
         end_line = self.current_prompt_line \
                         + max(1,  len(raw_string.split('\n'))-1)
         for i in range(self.current_prompt_line, end_line):
-            self.MarkerAdd(i, _RUNNING_BUFFER_MARKER)
+            if i in self._markers:
+                self.MarkerDeleteHandle(self._markers[i])
+            self._markers[i] = self.MarkerAdd(i, _COMPLETE_BUFFER_MARKER)
         # Update the display:
         wx.Yield()
         self.GotoPos(self.GetLength())
@@ -273,7 +285,7 @@ class WxController(ConsoleWidget, PrefilterFrontEnd):
     
     def release_output(self):
         __builtin__.raw_input = self.__old_raw_input
-        PrefilterFrontEnd.capture_output(self)
+        PrefilterFrontEnd.release_output(self)
 
 
     def after_execute(self):
@@ -288,7 +300,7 @@ class WxController(ConsoleWidget, PrefilterFrontEnd):
         PrefilterFrontEnd.show_traceback(self)
         wx.Yield()
         for i in range(start_line, self.GetCurrentLine()):
-            self.MarkerAdd(i, _ERROR_MARKER)
+            self._markers[i] = self.MarkerAdd(i, _ERROR_MARKER)
 
     
     #--------------------------------------------------------------------------
@@ -403,6 +415,8 @@ class WxController(ConsoleWidget, PrefilterFrontEnd):
         """
         if self.debug:
             print >>sys.__stdout__, repr(self.input_buffer)
+        i = self.GetLineCount()
+        self._markers[i] = self.MarkerAdd(i, _INPUT_MARKER)
         PrefilterFrontEnd._on_enter(self)
 
 
diff --git a/IPython/kernel/core/output_trap.py b/IPython/kernel/core/output_trap.py
index c16571f..3c1b4c2 100644
--- a/IPython/kernel/core/output_trap.py
+++ b/IPython/kernel/core/output_trap.py
@@ -68,10 +68,12 @@ class OutputTrap(object):
         """ Remove the hooks.
         """
 
-        sys.stdout = self._out_save
+        if self.out_set:
+            sys.stdout = self._out_save
         self.out_set = False
 
-        sys.stderr = self._err_save
+        if self.err_set:
+            sys.stderr = self._err_save
         self.err_set = False
 
     def clear(self):