##// END OF EJS Templates
Connect storing output in database to DisplayHook.log_output
Thomas Kluyver -
Show More
@@ -1,324 +1,328 b''
1 1 # -*- coding: utf-8 -*-
2 2 """Displayhook for IPython.
3 3
4 4 This defines a callable class that IPython uses for `sys.displayhook`.
5 5
6 6 Authors:
7 7
8 8 * Fernando Perez
9 9 * Brian Granger
10 10 * Robert Kern
11 11 """
12 12
13 13 #-----------------------------------------------------------------------------
14 14 # Copyright (C) 2008-2010 The IPython Development Team
15 15 # Copyright (C) 2001-2007 Fernando Perez <fperez@colorado.edu>
16 16 #
17 17 # Distributed under the terms of the BSD License. The full license is in
18 18 # the file COPYING, distributed as part of this software.
19 19 #-----------------------------------------------------------------------------
20 20
21 21 #-----------------------------------------------------------------------------
22 22 # Imports
23 23 #-----------------------------------------------------------------------------
24 24
25 25 import __builtin__
26 26
27 27 from IPython.config.configurable import Configurable
28 28 from IPython.core import prompts
29 29 import IPython.utils.generics
30 30 import IPython.utils.io
31 31 from IPython.utils.traitlets import Instance, List
32 32 from IPython.utils.warn import warn
33 33
34 34 #-----------------------------------------------------------------------------
35 35 # Main displayhook class
36 36 #-----------------------------------------------------------------------------
37 37
38 38 # TODO: The DisplayHook class should be split into two classes, one that
39 39 # manages the prompts and their synchronization and another that just does the
40 40 # displayhook logic and calls into the prompt manager.
41 41
42 42 # TODO: Move the various attributes (cache_size, colors, input_sep,
43 43 # output_sep, output_sep2, ps1, ps2, ps_out, pad_left). Some of these are also
44 44 # attributes of InteractiveShell. They should be on ONE object only and the
45 45 # other objects should ask that one object for their values.
46 46
47 47 class DisplayHook(Configurable):
48 48 """The custom IPython displayhook to replace sys.displayhook.
49 49
50 50 This class does many things, but the basic idea is that it is a callable
51 51 that gets called anytime user code returns a value.
52 52
53 53 Currently this class does more than just the displayhook logic and that
54 54 extra logic should eventually be moved out of here.
55 55 """
56 56
57 57 shell = Instance('IPython.core.interactiveshell.InteractiveShellABC')
58 58
59 59 def __init__(self, shell=None, cache_size=1000,
60 60 colors='NoColor', input_sep='\n',
61 61 output_sep='\n', output_sep2='',
62 62 ps1 = None, ps2 = None, ps_out = None, pad_left=True,
63 63 config=None):
64 64 super(DisplayHook, self).__init__(shell=shell, config=config)
65 65
66 66 cache_size_min = 3
67 67 if cache_size <= 0:
68 68 self.do_full_cache = 0
69 69 cache_size = 0
70 70 elif cache_size < cache_size_min:
71 71 self.do_full_cache = 0
72 72 cache_size = 0
73 73 warn('caching was disabled (min value for cache size is %s).' %
74 74 cache_size_min,level=3)
75 75 else:
76 76 self.do_full_cache = 1
77 77
78 78 self.cache_size = cache_size
79 79 self.input_sep = input_sep
80 80
81 81 # we need a reference to the user-level namespace
82 82 self.shell = shell
83 83
84 84 # Set input prompt strings and colors
85 85 if cache_size == 0:
86 86 if ps1.find('%n') > -1 or ps1.find(r'\#') > -1 \
87 87 or ps1.find(r'\N') > -1:
88 88 ps1 = '>>> '
89 89 if ps2.find('%n') > -1 or ps2.find(r'\#') > -1 \
90 90 or ps2.find(r'\N') > -1:
91 91 ps2 = '... '
92 92 self.ps1_str = self._set_prompt_str(ps1,'In [\\#]: ','>>> ')
93 93 self.ps2_str = self._set_prompt_str(ps2,' .\\D.: ','... ')
94 94 self.ps_out_str = self._set_prompt_str(ps_out,'Out[\\#]: ','')
95 95
96 96 self.color_table = prompts.PromptColors
97 97 self.prompt1 = prompts.Prompt1(self,sep=input_sep,prompt=self.ps1_str,
98 98 pad_left=pad_left)
99 99 self.prompt2 = prompts.Prompt2(self,prompt=self.ps2_str,pad_left=pad_left)
100 100 self.prompt_out = prompts.PromptOut(self,sep='',prompt=self.ps_out_str,
101 101 pad_left=pad_left)
102 102 self.set_colors(colors)
103 103
104 104 # Store the last prompt string each time, we need it for aligning
105 105 # continuation and auto-rewrite prompts
106 106 self.last_prompt = ''
107 107 self.output_sep = output_sep
108 108 self.output_sep2 = output_sep2
109 109 self._,self.__,self.___ = '','',''
110 110
111 111 # these are deliberately global:
112 112 to_user_ns = {'_':self._,'__':self.__,'___':self.___}
113 113 self.shell.user_ns.update(to_user_ns)
114 114
115 115 @property
116 116 def prompt_count(self):
117 117 return self.shell.execution_count
118 118
119 119 def _set_prompt_str(self,p_str,cache_def,no_cache_def):
120 120 if p_str is None:
121 121 if self.do_full_cache:
122 122 return cache_def
123 123 else:
124 124 return no_cache_def
125 125 else:
126 126 return p_str
127 127
128 128 def set_colors(self, colors):
129 129 """Set the active color scheme and configure colors for the three
130 130 prompt subsystems."""
131 131
132 132 # FIXME: This modifying of the global prompts.prompt_specials needs
133 133 # to be fixed. We need to refactor all of the prompts stuff to use
134 134 # proper configuration and traits notifications.
135 135 if colors.lower()=='nocolor':
136 136 prompts.prompt_specials = prompts.prompt_specials_nocolor
137 137 else:
138 138 prompts.prompt_specials = prompts.prompt_specials_color
139 139
140 140 self.color_table.set_active_scheme(colors)
141 141 self.prompt1.set_colors()
142 142 self.prompt2.set_colors()
143 143 self.prompt_out.set_colors()
144 144
145 145 #-------------------------------------------------------------------------
146 146 # Methods used in __call__. Override these methods to modify the behavior
147 147 # of the displayhook.
148 148 #-------------------------------------------------------------------------
149 149
150 150 def check_for_underscore(self):
151 151 """Check if the user has set the '_' variable by hand."""
152 152 # If something injected a '_' variable in __builtin__, delete
153 153 # ipython's automatic one so we don't clobber that. gettext() in
154 154 # particular uses _, so we need to stay away from it.
155 155 if '_' in __builtin__.__dict__:
156 156 try:
157 157 del self.shell.user_ns['_']
158 158 except KeyError:
159 159 pass
160 160
161 161 def quiet(self):
162 162 """Should we silence the display hook because of ';'?"""
163 163 # do not print output if input ends in ';'
164 164 try:
165 165 if self.shell.history_manager.input_hist_parsed[self.prompt_count].endswith(';\n'):
166 166 return True
167 167 except IndexError:
168 168 # some uses of ipshellembed may fail here
169 169 pass
170 170 return False
171 171
172 172 def start_displayhook(self):
173 173 """Start the displayhook, initializing resources."""
174 174 pass
175 175
176 176 def write_output_prompt(self):
177 177 """Write the output prompt.
178 178
179 179 The default implementation simply writes the prompt to
180 180 ``io.Term.cout``.
181 181 """
182 182 # Use write, not print which adds an extra space.
183 183 IPython.utils.io.Term.cout.write(self.output_sep)
184 184 outprompt = str(self.prompt_out)
185 185 if self.do_full_cache:
186 186 IPython.utils.io.Term.cout.write(outprompt)
187 187
188 188 def compute_format_data(self, result):
189 189 """Compute format data of the object to be displayed.
190 190
191 191 The format data is a generalization of the :func:`repr` of an object.
192 192 In the default implementation the format data is a :class:`dict` of
193 193 key value pair where the keys are valid MIME types and the values
194 194 are JSON'able data structure containing the raw data for that MIME
195 195 type. It is up to frontends to determine pick a MIME to to use and
196 196 display that data in an appropriate manner.
197 197
198 198 This method only computes the format data for the object and should
199 199 NOT actually print or write that to a stream.
200 200
201 201 Parameters
202 202 ----------
203 203 result : object
204 204 The Python object passed to the display hook, whose format will be
205 205 computed.
206 206
207 207 Returns
208 208 -------
209 209 format_data : dict
210 210 A :class:`dict` whose keys are valid MIME types and values are
211 211 JSON'able raw data for that MIME type. It is recommended that
212 212 all return values of this should always include the "text/plain"
213 213 MIME type representation of the object.
214 214 """
215 215 return self.shell.display_formatter.format(result)
216 216
217 217 def write_format_data(self, format_dict):
218 218 """Write the format data dict to the frontend.
219 219
220 220 This default version of this method simply writes the plain text
221 221 representation of the object to ``io.Term.cout``. Subclasses should
222 222 override this method to send the entire `format_dict` to the
223 223 frontends.
224 224
225 225 Parameters
226 226 ----------
227 227 format_dict : dict
228 228 The format dict for the object passed to `sys.displayhook`.
229 229 """
230 230 # We want to print because we want to always make sure we have a
231 231 # newline, even if all the prompt separators are ''. This is the
232 232 # standard IPython behavior.
233 233 result_repr = format_dict['text/plain']
234 234 if '\n' in result_repr:
235 235 # So that multi-line strings line up with the left column of
236 236 # the screen, instead of having the output prompt mess up
237 237 # their first line.
238 238 # We use the ps_out_str template instead of the expanded prompt
239 239 # because the expansion may add ANSI escapes that will interfere
240 240 # with our ability to determine whether or not we should add
241 241 # a newline.
242 242 if self.ps_out_str and not self.ps_out_str.endswith('\n'):
243 243 # But avoid extraneous empty lines.
244 244 result_repr = '\n' + result_repr
245 245
246 246 print >>IPython.utils.io.Term.cout, result_repr
247 247
248 248 def update_user_ns(self, result):
249 249 """Update user_ns with various things like _, __, _1, etc."""
250 250
251 251 # Avoid recursive reference when displaying _oh/Out
252 252 if result is not self.shell.user_ns['_oh']:
253 253 if len(self.shell.user_ns['_oh']) >= self.cache_size and self.do_full_cache:
254 254 warn('Output cache limit (currently '+
255 255 `self.cache_size`+' entries) hit.\n'
256 256 'Flushing cache and resetting history counter...\n'
257 257 'The only history variables available will be _,__,___ and _1\n'
258 258 'with the current result.')
259 259
260 260 self.flush()
261 261 # Don't overwrite '_' and friends if '_' is in __builtin__ (otherwise
262 262 # we cause buggy behavior for things like gettext).
263 263
264 264 if '_' not in __builtin__.__dict__:
265 265 self.___ = self.__
266 266 self.__ = self._
267 267 self._ = result
268 268 self.shell.user_ns.update({'_':self._,
269 269 '__':self.__,
270 270 '___':self.___})
271 271
272 272 # hackish access to top-level namespace to create _1,_2... dynamically
273 273 to_main = {}
274 274 if self.do_full_cache:
275 275 new_result = '_'+`self.prompt_count`
276 276 to_main[new_result] = result
277 277 self.shell.user_ns.update(to_main)
278 278 self.shell.user_ns['_oh'][self.prompt_count] = result
279 279
280 def log_output(self, result):
280 def log_output(self, format_dict):
281 281 """Log the output."""
282 282 if self.shell.logger.log_output:
283 self.shell.logger.log_write(repr(result), 'output')
283 self.shell.logger.log_write(format_dict['text/plain'], 'output')
284 # Write output to the database. Does nothing unless history
285 # output logging is enabled.
286 self.shell.history_manager.store_output(self.prompt_count,
287 format_dict['text/plain'])
284 288
285 289 def finish_displayhook(self):
286 290 """Finish up all displayhook activities."""
287 291 IPython.utils.io.Term.cout.write(self.output_sep2)
288 292 IPython.utils.io.Term.cout.flush()
289 293
290 294 def __call__(self, result=None):
291 295 """Printing with history cache management.
292 296
293 297 This is invoked everytime the interpreter needs to print, and is
294 298 activated by setting the variable sys.displayhook to it.
295 299 """
296 300 self.check_for_underscore()
297 301 if result is not None and not self.quiet():
298 302 self.start_displayhook()
299 303 self.write_output_prompt()
300 304 format_dict = self.compute_format_data(result)
301 305 self.write_format_data(format_dict)
302 306 self.update_user_ns(result)
303 self.log_output(result)
307 self.log_output(format_dict)
304 308 self.finish_displayhook()
305 309
306 310 def flush(self):
307 311 if not self.do_full_cache:
308 312 raise ValueError,"You shouldn't have reached the cache flush "\
309 313 "if full caching is not enabled!"
310 314 # delete auto-generated vars from global namespace
311 315
312 316 for n in range(1,self.prompt_count + 1):
313 317 key = '_'+`n`
314 318 try:
315 319 del self.shell.user_ns[key]
316 320 except: pass
317 321 self.shell.user_ns['_oh'].clear()
318 322
319 323 if '_' not in __builtin__.__dict__:
320 324 self.shell.user_ns.update({'_':None,'__':None, '___':None})
321 325 import gc
322 326 # TODO: Is this really needed?
323 327 gc.collect()
324 328
General Comments 0
You need to be logged in to leave comments. Login now