##// END OF EJS Templates
correct the argument to warn function
Srinivas Reddy Thatiparthy -
Show More
@@ -1,322 +1,322 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
7 7 # Copyright (c) IPython Development Team.
8 8 # Distributed under the terms of the Modified BSD License.
9 9
10 10 from __future__ import print_function
11 11
12 12 import sys
13 13 import io as _io
14 14 import tokenize
15 15
16 16 from traitlets.config.configurable import Configurable
17 17 from IPython.utils.py3compat import builtin_mod, cast_unicode_py2
18 18 from traitlets import Instance, Float
19 19 from warnings import warn
20 20
21 21 # TODO: Move the various attributes (cache_size, [others now moved]). Some
22 22 # of these are also attributes of InteractiveShell. They should be on ONE object
23 23 # only and the other objects should ask that one object for their values.
24 24
25 25 class DisplayHook(Configurable):
26 26 """The custom IPython displayhook to replace sys.displayhook.
27 27
28 28 This class does many things, but the basic idea is that it is a callable
29 29 that gets called anytime user code returns a value.
30 30 """
31 31
32 32 shell = Instance('IPython.core.interactiveshell.InteractiveShellABC',
33 33 allow_none=True)
34 34 exec_result = Instance('IPython.core.interactiveshell.ExecutionResult',
35 35 allow_none=True)
36 36 cull_fraction = Float(0.2)
37 37
38 38 def __init__(self, shell=None, cache_size=1000, **kwargs):
39 39 super(DisplayHook, self).__init__(shell=shell, **kwargs)
40 40 cache_size_min = 3
41 41 if cache_size <= 0:
42 42 self.do_full_cache = 0
43 43 cache_size = 0
44 44 elif cache_size < cache_size_min:
45 45 self.do_full_cache = 0
46 46 cache_size = 0
47 47 warn('caching was disabled (min value for cache size is %s).' %
48 cache_size_min,level=3)
48 cache_size_min,stacklevel=3)
49 49 else:
50 50 self.do_full_cache = 1
51 51
52 52 self.cache_size = cache_size
53 53
54 54 # we need a reference to the user-level namespace
55 55 self.shell = shell
56 56
57 57 self._,self.__,self.___ = '','',''
58 58
59 59 # these are deliberately global:
60 60 to_user_ns = {'_':self._,'__':self.__,'___':self.___}
61 61 self.shell.user_ns.update(to_user_ns)
62 62
63 63 @property
64 64 def prompt_count(self):
65 65 return self.shell.execution_count
66 66
67 67 #-------------------------------------------------------------------------
68 68 # Methods used in __call__. Override these methods to modify the behavior
69 69 # of the displayhook.
70 70 #-------------------------------------------------------------------------
71 71
72 72 def check_for_underscore(self):
73 73 """Check if the user has set the '_' variable by hand."""
74 74 # If something injected a '_' variable in __builtin__, delete
75 75 # ipython's automatic one so we don't clobber that. gettext() in
76 76 # particular uses _, so we need to stay away from it.
77 77 if '_' in builtin_mod.__dict__:
78 78 try:
79 79 user_value = self.shell.user_ns['_']
80 80 if user_value is not self._:
81 81 return
82 82 del self.shell.user_ns['_']
83 83 except KeyError:
84 84 pass
85 85
86 86 def quiet(self):
87 87 """Should we silence the display hook because of ';'?"""
88 88 # do not print output if input ends in ';'
89 89
90 90 try:
91 91 cell = cast_unicode_py2(self.shell.history_manager.input_hist_parsed[-1])
92 92 except IndexError:
93 93 # some uses of ipshellembed may fail here
94 94 return False
95 95
96 96 sio = _io.StringIO(cell)
97 97 tokens = list(tokenize.generate_tokens(sio.readline))
98 98
99 99 for token in reversed(tokens):
100 100 if token[0] in (tokenize.ENDMARKER, tokenize.NL, tokenize.NEWLINE, tokenize.COMMENT):
101 101 continue
102 102 if (token[0] == tokenize.OP) and (token[1] == ';'):
103 103 return True
104 104 else:
105 105 return False
106 106
107 107 def start_displayhook(self):
108 108 """Start the displayhook, initializing resources."""
109 109 pass
110 110
111 111 def write_output_prompt(self):
112 112 """Write the output prompt.
113 113
114 114 The default implementation simply writes the prompt to
115 115 ``sys.stdout``.
116 116 """
117 117 # Use write, not print which adds an extra space.
118 118 sys.stdout.write(self.shell.separate_out)
119 119 outprompt = 'Out[{}]: '.format(self.shell.execution_count)
120 120 if self.do_full_cache:
121 121 sys.stdout.write(outprompt)
122 122
123 123 def compute_format_data(self, result):
124 124 """Compute format data of the object to be displayed.
125 125
126 126 The format data is a generalization of the :func:`repr` of an object.
127 127 In the default implementation the format data is a :class:`dict` of
128 128 key value pair where the keys are valid MIME types and the values
129 129 are JSON'able data structure containing the raw data for that MIME
130 130 type. It is up to frontends to determine pick a MIME to to use and
131 131 display that data in an appropriate manner.
132 132
133 133 This method only computes the format data for the object and should
134 134 NOT actually print or write that to a stream.
135 135
136 136 Parameters
137 137 ----------
138 138 result : object
139 139 The Python object passed to the display hook, whose format will be
140 140 computed.
141 141
142 142 Returns
143 143 -------
144 144 (format_dict, md_dict) : dict
145 145 format_dict is a :class:`dict` whose keys are valid MIME types and values are
146 146 JSON'able raw data for that MIME type. It is recommended that
147 147 all return values of this should always include the "text/plain"
148 148 MIME type representation of the object.
149 149 md_dict is a :class:`dict` with the same MIME type keys
150 150 of metadata associated with each output.
151 151
152 152 """
153 153 return self.shell.display_formatter.format(result)
154 154
155 155 # This can be set to True by the write_output_prompt method in a subclass
156 156 prompt_end_newline = False
157 157
158 158 def write_format_data(self, format_dict, md_dict=None):
159 159 """Write the format data dict to the frontend.
160 160
161 161 This default version of this method simply writes the plain text
162 162 representation of the object to ``sys.stdout``. Subclasses should
163 163 override this method to send the entire `format_dict` to the
164 164 frontends.
165 165
166 166 Parameters
167 167 ----------
168 168 format_dict : dict
169 169 The format dict for the object passed to `sys.displayhook`.
170 170 md_dict : dict (optional)
171 171 The metadata dict to be associated with the display data.
172 172 """
173 173 if 'text/plain' not in format_dict:
174 174 # nothing to do
175 175 return
176 176 # We want to print because we want to always make sure we have a
177 177 # newline, even if all the prompt separators are ''. This is the
178 178 # standard IPython behavior.
179 179 result_repr = format_dict['text/plain']
180 180 if '\n' in result_repr:
181 181 # So that multi-line strings line up with the left column of
182 182 # the screen, instead of having the output prompt mess up
183 183 # their first line.
184 184 # We use the prompt template instead of the expanded prompt
185 185 # because the expansion may add ANSI escapes that will interfere
186 186 # with our ability to determine whether or not we should add
187 187 # a newline.
188 188 if not self.prompt_end_newline:
189 189 # But avoid extraneous empty lines.
190 190 result_repr = '\n' + result_repr
191 191
192 192 print(result_repr)
193 193
194 194 def update_user_ns(self, result):
195 195 """Update user_ns with various things like _, __, _1, etc."""
196 196
197 197 # Avoid recursive reference when displaying _oh/Out
198 198 if result is not self.shell.user_ns['_oh']:
199 199 if len(self.shell.user_ns['_oh']) >= self.cache_size and self.do_full_cache:
200 200 self.cull_cache()
201 201
202 202 # Don't overwrite '_' and friends if '_' is in __builtin__
203 203 # (otherwise we cause buggy behavior for things like gettext). and
204 204 # do not overwrite _, __ or ___ if one of these has been assigned
205 205 # by the user.
206 206 update_unders = True
207 207 for unders in ['_'*i for i in range(1,4)]:
208 208 if not unders in self.shell.user_ns:
209 209 continue
210 210 if getattr(self, unders) is not self.shell.user_ns.get(unders):
211 211 update_unders = False
212 212
213 213 self.___ = self.__
214 214 self.__ = self._
215 215 self._ = result
216 216
217 217 if ('_' not in builtin_mod.__dict__) and (update_unders):
218 218 self.shell.push({'_':self._,
219 219 '__':self.__,
220 220 '___':self.___}, interactive=False)
221 221
222 222 # hackish access to top-level namespace to create _1,_2... dynamically
223 223 to_main = {}
224 224 if self.do_full_cache:
225 225 new_result = '_%s' % self.prompt_count
226 226 to_main[new_result] = result
227 227 self.shell.push(to_main, interactive=False)
228 228 self.shell.user_ns['_oh'][self.prompt_count] = result
229 229
230 230 def fill_exec_result(self, result):
231 231 if self.exec_result is not None:
232 232 self.exec_result.result = result
233 233
234 234 def log_output(self, format_dict):
235 235 """Log the output."""
236 236 if 'text/plain' not in format_dict:
237 237 # nothing to do
238 238 return
239 239 if self.shell.logger.log_output:
240 240 self.shell.logger.log_write(format_dict['text/plain'], 'output')
241 241 self.shell.history_manager.output_hist_reprs[self.prompt_count] = \
242 242 format_dict['text/plain']
243 243
244 244 def finish_displayhook(self):
245 245 """Finish up all displayhook activities."""
246 246 sys.stdout.write(self.shell.separate_out2)
247 247 sys.stdout.flush()
248 248
249 249 def __call__(self, result=None):
250 250 """Printing with history cache management.
251 251
252 252 This is invoked everytime the interpreter needs to print, and is
253 253 activated by setting the variable sys.displayhook to it.
254 254 """
255 255 self.check_for_underscore()
256 256 if result is not None and not self.quiet():
257 257 self.start_displayhook()
258 258 self.write_output_prompt()
259 259 format_dict, md_dict = self.compute_format_data(result)
260 260 self.update_user_ns(result)
261 261 self.fill_exec_result(result)
262 262 if format_dict:
263 263 self.write_format_data(format_dict, md_dict)
264 264 self.log_output(format_dict)
265 265 self.finish_displayhook()
266 266
267 267 def cull_cache(self):
268 268 """Output cache is full, cull the oldest entries"""
269 269 oh = self.shell.user_ns.get('_oh', {})
270 270 sz = len(oh)
271 271 cull_count = max(int(sz * self.cull_fraction), 2)
272 272 warn('Output cache limit (currently {sz} entries) hit.\n'
273 273 'Flushing oldest {cull_count} entries.'.format(sz=sz, cull_count=cull_count))
274 274
275 275 for i, n in enumerate(sorted(oh)):
276 276 if i >= cull_count:
277 277 break
278 278 self.shell.user_ns.pop('_%i' % n, None)
279 279 oh.pop(n, None)
280 280
281 281
282 282 def flush(self):
283 283 if not self.do_full_cache:
284 284 raise ValueError("You shouldn't have reached the cache flush "
285 285 "if full caching is not enabled!")
286 286 # delete auto-generated vars from global namespace
287 287
288 288 for n in range(1,self.prompt_count + 1):
289 289 key = '_'+repr(n)
290 290 try:
291 291 del self.shell.user_ns[key]
292 292 except: pass
293 293 # In some embedded circumstances, the user_ns doesn't have the
294 294 # '_oh' key set up.
295 295 oh = self.shell.user_ns.get('_oh', None)
296 296 if oh is not None:
297 297 oh.clear()
298 298
299 299 # Release our own references to objects:
300 300 self._, self.__, self.___ = '', '', ''
301 301
302 302 if '_' not in builtin_mod.__dict__:
303 303 self.shell.user_ns.update({'_':None,'__':None, '___':None})
304 304 import gc
305 305 # TODO: Is this really needed?
306 306 # IronPython blocks here forever
307 307 if sys.platform != "cli":
308 308 gc.collect()
309 309
310 310
311 311 class CapturingDisplayHook(object):
312 312 def __init__(self, shell, outputs=None):
313 313 self.shell = shell
314 314 if outputs is None:
315 315 outputs = []
316 316 self.outputs = outputs
317 317
318 318 def __call__(self, result=None):
319 319 if result is None:
320 320 return
321 321 format_dict, md_dict = self.shell.display_formatter.format(result)
322 322 self.outputs.append((format_dict, md_dict))
General Comments 0
You need to be logged in to leave comments. Login now