##// END OF EJS Templates
Merge pull request #1496 from rkern/fix-finalize-displayhook...
Min RK -
r6274:db762d9f merge
parent child Browse files
Show More
@@ -1,265 +1,269 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2 """Displayhook for IPython.
2 """Displayhook for IPython.
3
3
4 This defines a callable class that IPython uses for `sys.displayhook`.
4 This defines a callable class that IPython uses for `sys.displayhook`.
5
5
6 Authors:
6 Authors:
7
7
8 * Fernando Perez
8 * Fernando Perez
9 * Brian Granger
9 * Brian Granger
10 * Robert Kern
10 * Robert Kern
11 """
11 """
12
12
13 #-----------------------------------------------------------------------------
13 #-----------------------------------------------------------------------------
14 # Copyright (C) 2008-2011 The IPython Development Team
14 # Copyright (C) 2008-2011 The IPython Development Team
15 # Copyright (C) 2001-2007 Fernando Perez <fperez@colorado.edu>
15 # Copyright (C) 2001-2007 Fernando Perez <fperez@colorado.edu>
16 #
16 #
17 # Distributed under the terms of the BSD License. The full license is in
17 # Distributed under the terms of the BSD License. The full license is in
18 # the file COPYING, distributed as part of this software.
18 # the file COPYING, distributed as part of this software.
19 #-----------------------------------------------------------------------------
19 #-----------------------------------------------------------------------------
20
20
21 #-----------------------------------------------------------------------------
21 #-----------------------------------------------------------------------------
22 # Imports
22 # Imports
23 #-----------------------------------------------------------------------------
23 #-----------------------------------------------------------------------------
24
24
25 import __builtin__
25 import __builtin__
26
26
27 from IPython.config.configurable import Configurable
27 from IPython.config.configurable import Configurable
28 from IPython.utils import io
28 from IPython.utils import io
29 from IPython.utils.traitlets import Instance, List
29 from IPython.utils.traitlets import Instance, List
30 from IPython.utils.warn import warn
30 from IPython.utils.warn import warn
31
31
32 #-----------------------------------------------------------------------------
32 #-----------------------------------------------------------------------------
33 # Main displayhook class
33 # Main displayhook class
34 #-----------------------------------------------------------------------------
34 #-----------------------------------------------------------------------------
35
35
36 # TODO: Move the various attributes (cache_size, [others now moved]). Some
36 # TODO: Move the various attributes (cache_size, [others now moved]). Some
37 # of these are also attributes of InteractiveShell. They should be on ONE object
37 # of these are also attributes of InteractiveShell. They should be on ONE object
38 # only and the other objects should ask that one object for their values.
38 # only and the other objects should ask that one object for their values.
39
39
40 class DisplayHook(Configurable):
40 class DisplayHook(Configurable):
41 """The custom IPython displayhook to replace sys.displayhook.
41 """The custom IPython displayhook to replace sys.displayhook.
42
42
43 This class does many things, but the basic idea is that it is a callable
43 This class does many things, but the basic idea is that it is a callable
44 that gets called anytime user code returns a value.
44 that gets called anytime user code returns a value.
45 """
45 """
46
46
47 shell = Instance('IPython.core.interactiveshell.InteractiveShellABC')
47 shell = Instance('IPython.core.interactiveshell.InteractiveShellABC')
48
48
49 def __init__(self, shell=None, cache_size=1000, config=None):
49 def __init__(self, shell=None, cache_size=1000, config=None):
50 super(DisplayHook, self).__init__(shell=shell, config=config)
50 super(DisplayHook, self).__init__(shell=shell, config=config)
51
51
52 cache_size_min = 3
52 cache_size_min = 3
53 if cache_size <= 0:
53 if cache_size <= 0:
54 self.do_full_cache = 0
54 self.do_full_cache = 0
55 cache_size = 0
55 cache_size = 0
56 elif cache_size < cache_size_min:
56 elif cache_size < cache_size_min:
57 self.do_full_cache = 0
57 self.do_full_cache = 0
58 cache_size = 0
58 cache_size = 0
59 warn('caching was disabled (min value for cache size is %s).' %
59 warn('caching was disabled (min value for cache size is %s).' %
60 cache_size_min,level=3)
60 cache_size_min,level=3)
61 else:
61 else:
62 self.do_full_cache = 1
62 self.do_full_cache = 1
63
63
64 self.cache_size = cache_size
64 self.cache_size = cache_size
65
65
66 # we need a reference to the user-level namespace
66 # we need a reference to the user-level namespace
67 self.shell = shell
67 self.shell = shell
68
68
69 self._,self.__,self.___ = '','',''
69 self._,self.__,self.___ = '','',''
70
70
71 # these are deliberately global:
71 # these are deliberately global:
72 to_user_ns = {'_':self._,'__':self.__,'___':self.___}
72 to_user_ns = {'_':self._,'__':self.__,'___':self.___}
73 self.shell.user_ns.update(to_user_ns)
73 self.shell.user_ns.update(to_user_ns)
74
74
75 @property
75 @property
76 def prompt_count(self):
76 def prompt_count(self):
77 return self.shell.execution_count
77 return self.shell.execution_count
78
78
79 #-------------------------------------------------------------------------
79 #-------------------------------------------------------------------------
80 # Methods used in __call__. Override these methods to modify the behavior
80 # Methods used in __call__. Override these methods to modify the behavior
81 # of the displayhook.
81 # of the displayhook.
82 #-------------------------------------------------------------------------
82 #-------------------------------------------------------------------------
83
83
84 def check_for_underscore(self):
84 def check_for_underscore(self):
85 """Check if the user has set the '_' variable by hand."""
85 """Check if the user has set the '_' variable by hand."""
86 # If something injected a '_' variable in __builtin__, delete
86 # If something injected a '_' variable in __builtin__, delete
87 # ipython's automatic one so we don't clobber that. gettext() in
87 # ipython's automatic one so we don't clobber that. gettext() in
88 # particular uses _, so we need to stay away from it.
88 # particular uses _, so we need to stay away from it.
89 if '_' in __builtin__.__dict__:
89 if '_' in __builtin__.__dict__:
90 try:
90 try:
91 del self.shell.user_ns['_']
91 del self.shell.user_ns['_']
92 except KeyError:
92 except KeyError:
93 pass
93 pass
94
94
95 def quiet(self):
95 def quiet(self):
96 """Should we silence the display hook because of ';'?"""
96 """Should we silence the display hook because of ';'?"""
97 # do not print output if input ends in ';'
97 # do not print output if input ends in ';'
98 try:
98 try:
99 cell = self.shell.history_manager.input_hist_parsed[self.prompt_count]
99 cell = self.shell.history_manager.input_hist_parsed[self.prompt_count]
100 if cell.rstrip().endswith(';'):
100 if cell.rstrip().endswith(';'):
101 return True
101 return True
102 except IndexError:
102 except IndexError:
103 # some uses of ipshellembed may fail here
103 # some uses of ipshellembed may fail here
104 pass
104 pass
105 return False
105 return False
106
106
107 def start_displayhook(self):
107 def start_displayhook(self):
108 """Start the displayhook, initializing resources."""
108 """Start the displayhook, initializing resources."""
109 pass
109 pass
110
110
111 def write_output_prompt(self):
111 def write_output_prompt(self):
112 """Write the output prompt.
112 """Write the output prompt.
113
113
114 The default implementation simply writes the prompt to
114 The default implementation simply writes the prompt to
115 ``io.stdout``.
115 ``io.stdout``.
116 """
116 """
117 # Use write, not print which adds an extra space.
117 # Use write, not print which adds an extra space.
118 io.stdout.write(self.shell.separate_out)
118 io.stdout.write(self.shell.separate_out)
119 outprompt = self.shell.prompt_manager.render('out')
119 outprompt = self.shell.prompt_manager.render('out')
120 if self.do_full_cache:
120 if self.do_full_cache:
121 io.stdout.write(outprompt)
121 io.stdout.write(outprompt)
122
122
123 def compute_format_data(self, result):
123 def compute_format_data(self, result):
124 """Compute format data of the object to be displayed.
124 """Compute format data of the object to be displayed.
125
125
126 The format data is a generalization of the :func:`repr` of an object.
126 The format data is a generalization of the :func:`repr` of an object.
127 In the default implementation the format data is a :class:`dict` of
127 In the default implementation the format data is a :class:`dict` of
128 key value pair where the keys are valid MIME types and the values
128 key value pair where the keys are valid MIME types and the values
129 are JSON'able data structure containing the raw data for that MIME
129 are JSON'able data structure containing the raw data for that MIME
130 type. It is up to frontends to determine pick a MIME to to use and
130 type. It is up to frontends to determine pick a MIME to to use and
131 display that data in an appropriate manner.
131 display that data in an appropriate manner.
132
132
133 This method only computes the format data for the object and should
133 This method only computes the format data for the object and should
134 NOT actually print or write that to a stream.
134 NOT actually print or write that to a stream.
135
135
136 Parameters
136 Parameters
137 ----------
137 ----------
138 result : object
138 result : object
139 The Python object passed to the display hook, whose format will be
139 The Python object passed to the display hook, whose format will be
140 computed.
140 computed.
141
141
142 Returns
142 Returns
143 -------
143 -------
144 format_data : dict
144 format_data : dict
145 A :class:`dict` whose keys are valid MIME types and values are
145 A :class:`dict` whose keys are valid MIME types and values are
146 JSON'able raw data for that MIME type. It is recommended that
146 JSON'able raw data for that MIME type. It is recommended that
147 all return values of this should always include the "text/plain"
147 all return values of this should always include the "text/plain"
148 MIME type representation of the object.
148 MIME type representation of the object.
149 """
149 """
150 return self.shell.display_formatter.format(result)
150 return self.shell.display_formatter.format(result)
151
151
152 def write_format_data(self, format_dict):
152 def write_format_data(self, format_dict):
153 """Write the format data dict to the frontend.
153 """Write the format data dict to the frontend.
154
154
155 This default version of this method simply writes the plain text
155 This default version of this method simply writes the plain text
156 representation of the object to ``io.stdout``. Subclasses should
156 representation of the object to ``io.stdout``. Subclasses should
157 override this method to send the entire `format_dict` to the
157 override this method to send the entire `format_dict` to the
158 frontends.
158 frontends.
159
159
160 Parameters
160 Parameters
161 ----------
161 ----------
162 format_dict : dict
162 format_dict : dict
163 The format dict for the object passed to `sys.displayhook`.
163 The format dict for the object passed to `sys.displayhook`.
164 """
164 """
165 # We want to print because we want to always make sure we have a
165 # We want to print because we want to always make sure we have a
166 # newline, even if all the prompt separators are ''. This is the
166 # newline, even if all the prompt separators are ''. This is the
167 # standard IPython behavior.
167 # standard IPython behavior.
168 result_repr = format_dict['text/plain']
168 result_repr = format_dict['text/plain']
169 if '\n' in result_repr:
169 if '\n' in result_repr:
170 # So that multi-line strings line up with the left column of
170 # So that multi-line strings line up with the left column of
171 # the screen, instead of having the output prompt mess up
171 # the screen, instead of having the output prompt mess up
172 # their first line.
172 # their first line.
173 # We use the prompt template instead of the expanded prompt
173 # We use the prompt template instead of the expanded prompt
174 # because the expansion may add ANSI escapes that will interfere
174 # because the expansion may add ANSI escapes that will interfere
175 # with our ability to determine whether or not we should add
175 # with our ability to determine whether or not we should add
176 # a newline.
176 # a newline.
177 prompt_template = self.shell.prompt_manager.out_template
177 prompt_template = self.shell.prompt_manager.out_template
178 if prompt_template and not prompt_template.endswith('\n'):
178 if prompt_template and not prompt_template.endswith('\n'):
179 # But avoid extraneous empty lines.
179 # But avoid extraneous empty lines.
180 result_repr = '\n' + result_repr
180 result_repr = '\n' + result_repr
181
181
182 print >>io.stdout, result_repr
182 print >>io.stdout, result_repr
183
183
184 def update_user_ns(self, result):
184 def update_user_ns(self, result):
185 """Update user_ns with various things like _, __, _1, etc."""
185 """Update user_ns with various things like _, __, _1, etc."""
186
186
187 # Avoid recursive reference when displaying _oh/Out
187 # Avoid recursive reference when displaying _oh/Out
188 if result is not self.shell.user_ns['_oh']:
188 if result is not self.shell.user_ns['_oh']:
189 if len(self.shell.user_ns['_oh']) >= self.cache_size and self.do_full_cache:
189 if len(self.shell.user_ns['_oh']) >= self.cache_size and self.do_full_cache:
190 warn('Output cache limit (currently '+
190 warn('Output cache limit (currently '+
191 `self.cache_size`+' entries) hit.\n'
191 `self.cache_size`+' entries) hit.\n'
192 'Flushing cache and resetting history counter...\n'
192 'Flushing cache and resetting history counter...\n'
193 'The only history variables available will be _,__,___ and _1\n'
193 'The only history variables available will be _,__,___ and _1\n'
194 'with the current result.')
194 'with the current result.')
195
195
196 self.flush()
196 self.flush()
197 # Don't overwrite '_' and friends if '_' is in __builtin__ (otherwise
197 # Don't overwrite '_' and friends if '_' is in __builtin__ (otherwise
198 # we cause buggy behavior for things like gettext).
198 # we cause buggy behavior for things like gettext).
199
199
200 if '_' not in __builtin__.__dict__:
200 if '_' not in __builtin__.__dict__:
201 self.___ = self.__
201 self.___ = self.__
202 self.__ = self._
202 self.__ = self._
203 self._ = result
203 self._ = result
204 self.shell.push({'_':self._,
204 self.shell.push({'_':self._,
205 '__':self.__,
205 '__':self.__,
206 '___':self.___}, interactive=False)
206 '___':self.___}, interactive=False)
207
207
208 # hackish access to top-level namespace to create _1,_2... dynamically
208 # hackish access to top-level namespace to create _1,_2... dynamically
209 to_main = {}
209 to_main = {}
210 if self.do_full_cache:
210 if self.do_full_cache:
211 new_result = '_'+`self.prompt_count`
211 new_result = '_'+`self.prompt_count`
212 to_main[new_result] = result
212 to_main[new_result] = result
213 self.shell.push(to_main, interactive=False)
213 self.shell.push(to_main, interactive=False)
214 self.shell.user_ns['_oh'][self.prompt_count] = result
214 self.shell.user_ns['_oh'][self.prompt_count] = result
215
215
216 def log_output(self, format_dict):
216 def log_output(self, format_dict):
217 """Log the output."""
217 """Log the output."""
218 if self.shell.logger.log_output:
218 if self.shell.logger.log_output:
219 self.shell.logger.log_write(format_dict['text/plain'], 'output')
219 self.shell.logger.log_write(format_dict['text/plain'], 'output')
220 self.shell.history_manager.output_hist_reprs[self.prompt_count] = \
220 self.shell.history_manager.output_hist_reprs[self.prompt_count] = \
221 format_dict['text/plain']
221 format_dict['text/plain']
222
222
223 def finish_displayhook(self):
223 def finish_displayhook(self):
224 """Finish up all displayhook activities."""
224 """Finish up all displayhook activities."""
225 io.stdout.write(self.shell.separate_out2)
225 io.stdout.write(self.shell.separate_out2)
226 io.stdout.flush()
226 io.stdout.flush()
227
227
228 def __call__(self, result=None):
228 def __call__(self, result=None):
229 """Printing with history cache management.
229 """Printing with history cache management.
230
230
231 This is invoked everytime the interpreter needs to print, and is
231 This is invoked everytime the interpreter needs to print, and is
232 activated by setting the variable sys.displayhook to it.
232 activated by setting the variable sys.displayhook to it.
233 """
233 """
234 self.check_for_underscore()
234 self.check_for_underscore()
235 if result is not None and not self.quiet():
235 if result is not None and not self.quiet():
236 self.start_displayhook()
236 self.start_displayhook()
237 self.write_output_prompt()
237 self.write_output_prompt()
238 format_dict = self.compute_format_data(result)
238 format_dict = self.compute_format_data(result)
239 self.write_format_data(format_dict)
239 self.write_format_data(format_dict)
240 self.update_user_ns(result)
240 self.update_user_ns(result)
241 self.log_output(format_dict)
241 self.log_output(format_dict)
242 self.finish_displayhook()
242 self.finish_displayhook()
243
243
244 def flush(self):
244 def flush(self):
245 if not self.do_full_cache:
245 if not self.do_full_cache:
246 raise ValueError,"You shouldn't have reached the cache flush "\
246 raise ValueError,"You shouldn't have reached the cache flush "\
247 "if full caching is not enabled!"
247 "if full caching is not enabled!"
248 # delete auto-generated vars from global namespace
248 # delete auto-generated vars from global namespace
249
249
250 for n in range(1,self.prompt_count + 1):
250 for n in range(1,self.prompt_count + 1):
251 key = '_'+`n`
251 key = '_'+`n`
252 try:
252 try:
253 del self.shell.user_ns[key]
253 del self.shell.user_ns[key]
254 except: pass
254 except: pass
255 self.shell.user_ns['_oh'].clear()
255 # In some embedded circumstances, the user_ns doesn't have the
256 # '_oh' key set up.
257 oh = self.shell.user_ns.get('_oh', None)
258 if oh is not None:
259 oh.clear()
256
260
257 # Release our own references to objects:
261 # Release our own references to objects:
258 self._, self.__, self.___ = '', '', ''
262 self._, self.__, self.___ = '', '', ''
259
263
260 if '_' not in __builtin__.__dict__:
264 if '_' not in __builtin__.__dict__:
261 self.shell.user_ns.update({'_':None,'__':None, '___':None})
265 self.shell.user_ns.update({'_':None,'__':None, '___':None})
262 import gc
266 import gc
263 # TODO: Is this really needed?
267 # TODO: Is this really needed?
264 gc.collect()
268 gc.collect()
265
269
General Comments 0
You need to be logged in to leave comments. Login now