From 0c7eb96f95bbe19b30171d9a51262ec4a01656f0 2011-03-14 17:17:32
From: Thomas Kluyver <takowl@gmail.com>
Date: 2011-03-14 17:17:32
Subject: [PATCH] Separate 'Out' in user_ns from the output history logging.

---

diff --git a/IPython/core/displayhook.py b/IPython/core/displayhook.py
index 6207f41..a8a8a92 100644
--- a/IPython/core/displayhook.py
+++ b/IPython/core/displayhook.py
@@ -275,13 +275,15 @@ class DisplayHook(Configurable):
                 new_result = '_'+`self.prompt_count`
                 to_main[new_result] = result
                 self.shell.user_ns.update(to_main)
-                # This is a defaultdict of lists, so we can always append
-                self.shell.user_ns['_oh'][self.prompt_count].append(result)
+                self.shell.user_ns['_oh'][self.prompt_count] = result
 
     def log_output(self, format_dict):
         """Log the output."""
         if self.shell.logger.log_output:
             self.shell.logger.log_write(format_dict['text/plain'], 'output')
+        # This is a defaultdict of lists, so we can always append
+        self.shell.history_manager.output_hist_reprs[self.prompt_count]\
+                                    .append(format_dict['text/plain'])
 
     def finish_displayhook(self):
         """Finish up all displayhook activities."""
diff --git a/IPython/core/history.py b/IPython/core/history.py
index fee33d5..73a1c1b 100644
--- a/IPython/core/history.py
+++ b/IPython/core/history.py
@@ -47,8 +47,13 @@ class HistoryManager(Configurable):
     input_hist_raw = List([""])
     # A list of directories visited during session
     dir_hist = List()
-    # A dict of output history, keyed with ints from the shell's execution count
-    output_hist = Instance(defaultdict)
+    # A dict of output history, keyed with ints from the shell's
+    # execution count. If there are several outputs from one command,
+    # only the last one is stored.
+    output_hist = Dict()
+    # Contains all outputs, in lists of reprs.
+    output_hist_reprs = Instance(defaultdict)
+    
     # String holding the path to the history file
     hist_file = Unicode()
     # The SQLite database
@@ -97,7 +102,7 @@ class HistoryManager(Configurable):
         self.new_session()
     
         self._i00, self._i, self._ii, self._iii = '','','',''
-        self.output_hist = defaultdict(list)
+        self.output_hist_reprs = defaultdict(list)
 
         self._exit_commands = set(['Quit', 'quit', 'Exit', 'exit', '%Quit',
                                    '%quit', '%Exit', '%exit'])
@@ -227,8 +232,7 @@ class HistoryManager(Configurable):
         
         for i in range(start, stop):
             if output:
-                output_item = [repr(x) for x in self.output_hist[i]]
-                line = (input_hist[i], output_item)
+                line = (input_hist[i], self.output_hist_reprs.get(i))
             else:
                 line = input_hist[i]
             yield (0, i, line)
@@ -332,9 +336,12 @@ class HistoryManager(Configurable):
         self.shell.user_ns.update(to_main)
         
     def store_output(self, line_num):
-        if (not self.db_log_output) or not self.output_hist[line_num]:
+        """If database output logging is enabled, this saves all the
+        outputs from the indicated prompt number to the database. It's
+        called by run_cell after code has been executed."""
+        if (not self.db_log_output) or not self.output_hist_reprs[line_num]:
             return
-        output = json.dumps([repr(x) for x in self.output_hist[line_num]])
+        output = json.dumps(self.output_hist_reprs[line_num])
         db_row = (self.session_number, line_num, output)
         if self.db_cache_size > 1:
             self.db_output_cache.append(db_row)
diff --git a/IPython/core/tests/test_history.py b/IPython/core/tests/test_history.py
index 5297711..456b505 100644
--- a/IPython/core/tests/test_history.py
+++ b/IPython/core/tests/test_history.py
@@ -38,7 +38,7 @@ def test_history():
             
             ip.history_manager.db_log_output = True
             # Doesn't match the input, but we'll just check it's stored.
-            ip.history_manager.output_hist[3].append("spam")
+            ip.history_manager.output_hist_reprs[3].append("spam")
             ip.history_manager.store_output(3)
             
             nt.assert_equal(ip.history_manager.input_hist_raw, [''] + hist)
@@ -60,7 +60,7 @@ def test_history():
             
             # Check get_hist_tail
             gothist = ip.history_manager.get_hist_tail(4, output=True)
-            expected = [(1, 3, (hist[-1], [repr("spam")])),
+            expected = [(1, 3, (hist[-1], ["spam"])),
                         (2, 1, (newcmds[0], None)),
                         (2, 2, (newcmds[1], None)),
                         (2, 3, (newcmds[2], None)),]
@@ -70,7 +70,7 @@ def test_history():
             gothist = ip.history_manager.get_hist_search("*test*")
             nt.assert_equal(list(gothist), [(1,2,hist[1])] )
             gothist = ip.history_manager.get_hist_search("b*", output=True)
-            nt.assert_equal(list(gothist), [(1,3,(hist[2],[repr("spam")]))] )
+            nt.assert_equal(list(gothist), [(1,3,(hist[2],["spam"]))] )
             
             # Cross testing: check that magic %save can get previous session.
             testfilename = os.path.realpath(os.path.join(tmpdir, "test.py"))