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