##// END OF EJS Templates
Work around bug in pprint.pformat. Closes gh-148
Fernando Perez -
Show More
@@ -1,288 +1,292 b''
1 1 # -*- coding: utf-8 -*-
2 2 """Displayhook for IPython.
3 3
4 4 Authors:
5 5
6 6 * Fernando Perez
7 7 * Brian Granger
8 8 """
9 9
10 10 #-----------------------------------------------------------------------------
11 11 # Copyright (C) 2008-2010 The IPython Development Team
12 12 # Copyright (C) 2001-2007 Fernando Perez <fperez@colorado.edu>
13 13 #
14 14 # Distributed under the terms of the BSD License. The full license is in
15 15 # the file COPYING, distributed as part of this software.
16 16 #-----------------------------------------------------------------------------
17 17
18 18 #-----------------------------------------------------------------------------
19 19 # Imports
20 20 #-----------------------------------------------------------------------------
21 21
22 22 import __builtin__
23 23 from pprint import PrettyPrinter
24 24 pformat = PrettyPrinter().pformat
25 25
26 26 from IPython.config.configurable import Configurable
27 27 from IPython.core import prompts
28 28 import IPython.utils.generics
29 29 import IPython.utils.io
30 30 from IPython.utils.traitlets import Instance, Int
31 31 from IPython.utils.warn import warn
32 32
33 33 #-----------------------------------------------------------------------------
34 34 # Main displayhook class
35 35 #-----------------------------------------------------------------------------
36 36
37 37 # TODO: The DisplayHook class should be split into two classes, one that
38 38 # manages the prompts and their synchronization and another that just does the
39 39 # displayhook logic and calls into the prompt manager.
40 40
41 41 # TODO: Move the various attributes (cache_size, colors, input_sep,
42 42 # output_sep, output_sep2, ps1, ps2, ps_out, pad_left). Some of these are also
43 43 # attributes of InteractiveShell. They should be on ONE object only and the
44 44 # other objects should ask that one object for their values.
45 45
46 46 class DisplayHook(Configurable):
47 47 """The custom IPython displayhook to replace sys.displayhook.
48 48
49 49 This class does many things, but the basic idea is that it is a callable
50 50 that gets called anytime user code returns a value.
51 51
52 52 Currently this class does more than just the displayhook logic and that
53 53 extra logic should eventually be moved out of here.
54 54 """
55 55
56 56 shell = Instance('IPython.core.interactiveshell.InteractiveShellABC')
57 57 # Each call to the In[] prompt raises it by 1, even the first.
58 58 prompt_count = Int(0)
59 59
60 60 def __init__(self, shell=None, cache_size=1000,
61 61 colors='NoColor', input_sep='\n',
62 62 output_sep='\n', output_sep2='',
63 63 ps1 = None, ps2 = None, ps_out = None, pad_left=True,
64 64 config=None):
65 65 super(DisplayHook, self).__init__(shell=shell, config=config)
66 66
67 67 cache_size_min = 3
68 68 if cache_size <= 0:
69 69 self.do_full_cache = 0
70 70 cache_size = 0
71 71 elif cache_size < cache_size_min:
72 72 self.do_full_cache = 0
73 73 cache_size = 0
74 74 warn('caching was disabled (min value for cache size is %s).' %
75 75 cache_size_min,level=3)
76 76 else:
77 77 self.do_full_cache = 1
78 78
79 79 self.cache_size = cache_size
80 80 self.input_sep = input_sep
81 81
82 82 # we need a reference to the user-level namespace
83 83 self.shell = shell
84 84
85 85 # Set input prompt strings and colors
86 86 if cache_size == 0:
87 87 if ps1.find('%n') > -1 or ps1.find(r'\#') > -1 \
88 88 or ps1.find(r'\N') > -1:
89 89 ps1 = '>>> '
90 90 if ps2.find('%n') > -1 or ps2.find(r'\#') > -1 \
91 91 or ps2.find(r'\N') > -1:
92 92 ps2 = '... '
93 93 self.ps1_str = self._set_prompt_str(ps1,'In [\\#]: ','>>> ')
94 94 self.ps2_str = self._set_prompt_str(ps2,' .\\D.: ','... ')
95 95 self.ps_out_str = self._set_prompt_str(ps_out,'Out[\\#]: ','')
96 96
97 97 self.color_table = prompts.PromptColors
98 98 self.prompt1 = prompts.Prompt1(self,sep=input_sep,prompt=self.ps1_str,
99 99 pad_left=pad_left)
100 100 self.prompt2 = prompts.Prompt2(self,prompt=self.ps2_str,pad_left=pad_left)
101 101 self.prompt_out = prompts.PromptOut(self,sep='',prompt=self.ps_out_str,
102 102 pad_left=pad_left)
103 103 self.set_colors(colors)
104 104
105 105 # Store the last prompt string each time, we need it for aligning
106 106 # continuation and auto-rewrite prompts
107 107 self.last_prompt = ''
108 108 self.output_sep = output_sep
109 109 self.output_sep2 = output_sep2
110 110 self._,self.__,self.___ = '','',''
111 111 self.pprint_types = map(type,[(),[],{}])
112 112
113 113 # these are deliberately global:
114 114 to_user_ns = {'_':self._,'__':self.__,'___':self.___}
115 115 self.shell.user_ns.update(to_user_ns)
116 116
117 117 def _set_prompt_str(self,p_str,cache_def,no_cache_def):
118 118 if p_str is None:
119 119 if self.do_full_cache:
120 120 return cache_def
121 121 else:
122 122 return no_cache_def
123 123 else:
124 124 return p_str
125 125
126 126 def set_colors(self, colors):
127 127 """Set the active color scheme and configure colors for the three
128 128 prompt subsystems."""
129 129
130 130 # FIXME: This modifying of the global prompts.prompt_specials needs
131 131 # to be fixed. We need to refactor all of the prompts stuff to use
132 132 # proper configuration and traits notifications.
133 133 if colors.lower()=='nocolor':
134 134 prompts.prompt_specials = prompts.prompt_specials_nocolor
135 135 else:
136 136 prompts.prompt_specials = prompts.prompt_specials_color
137 137
138 138 self.color_table.set_active_scheme(colors)
139 139 self.prompt1.set_colors()
140 140 self.prompt2.set_colors()
141 141 self.prompt_out.set_colors()
142 142
143 143 #-------------------------------------------------------------------------
144 144 # Methods used in __call__. Override these methods to modify the behavior
145 145 # of the displayhook.
146 146 #-------------------------------------------------------------------------
147 147
148 148 def check_for_underscore(self):
149 149 """Check if the user has set the '_' variable by hand."""
150 150 # If something injected a '_' variable in __builtin__, delete
151 151 # ipython's automatic one so we don't clobber that. gettext() in
152 152 # particular uses _, so we need to stay away from it.
153 153 if '_' in __builtin__.__dict__:
154 154 try:
155 155 del self.shell.user_ns['_']
156 156 except KeyError:
157 157 pass
158 158
159 159 def quiet(self):
160 160 """Should we silence the display hook because of ';'?"""
161 161 # do not print output if input ends in ';'
162 162 try:
163 163 if self.shell.input_hist[self.prompt_count].endswith(';\n'):
164 164 return True
165 165 except IndexError:
166 166 # some uses of ipshellembed may fail here
167 167 pass
168 168 return False
169 169
170 170 def start_displayhook(self):
171 171 """Start the displayhook, initializing resources."""
172 172 pass
173 173
174 174 def write_output_prompt(self):
175 175 """Write the output prompt."""
176 176 # Use write, not print which adds an extra space.
177 177 IPython.utils.io.Term.cout.write(self.output_sep)
178 178 outprompt = str(self.prompt_out)
179 179 if self.do_full_cache:
180 180 IPython.utils.io.Term.cout.write(outprompt)
181 181
182 182 # TODO: Make this method an extension point. The previous implementation
183 183 # has both a result_display hook as well as a result_display generic
184 184 # function to customize the repr on a per class basis. We need to rethink
185 185 # the hooks mechanism before doing this though.
186 186 def compute_result_repr(self, result):
187 187 """Compute and return the repr of the object to be displayed.
188 188
189 189 This method only compute the string form of the repr and should NOT
190 190 actual print or write that to a stream. This method may also transform
191 191 the result itself, but the default implementation passes the original
192 192 through.
193 193 """
194 194 try:
195 195 if self.shell.pprint:
196 try:
196 197 result_repr = pformat(result)
198 except:
199 # Work around possible bugs in pformat
200 result_repr = repr(result)
197 201 if '\n' in result_repr:
198 202 # So that multi-line strings line up with the left column of
199 203 # the screen, instead of having the output prompt mess up
200 204 # their first line.
201 205 result_repr = '\n' + result_repr
202 206 else:
203 207 result_repr = repr(result)
204 208 except TypeError:
205 209 # This happens when result.__repr__ doesn't return a string,
206 210 # such as when it returns None.
207 211 result_repr = '\n'
208 212 return result, result_repr
209 213
210 214 def write_result_repr(self, result_repr):
211 215 # We want to print because we want to always make sure we have a
212 216 # newline, even if all the prompt separators are ''. This is the
213 217 # standard IPython behavior.
214 218 print >>IPython.utils.io.Term.cout, result_repr
215 219
216 220 def update_user_ns(self, result):
217 221 """Update user_ns with various things like _, __, _1, etc."""
218 222
219 223 # Avoid recursive reference when displaying _oh/Out
220 224 if result is not self.shell.user_ns['_oh']:
221 225 if len(self.shell.user_ns['_oh']) >= self.cache_size and self.do_full_cache:
222 226 warn('Output cache limit (currently '+
223 227 `self.cache_size`+' entries) hit.\n'
224 228 'Flushing cache and resetting history counter...\n'
225 229 'The only history variables available will be _,__,___ and _1\n'
226 230 'with the current result.')
227 231
228 232 self.flush()
229 233 # Don't overwrite '_' and friends if '_' is in __builtin__ (otherwise
230 234 # we cause buggy behavior for things like gettext).
231 235 if '_' not in __builtin__.__dict__:
232 236 self.___ = self.__
233 237 self.__ = self._
234 238 self._ = result
235 239 self.shell.user_ns.update({'_':self._,'__':self.__,'___':self.___})
236 240
237 241 # hackish access to top-level namespace to create _1,_2... dynamically
238 242 to_main = {}
239 243 if self.do_full_cache:
240 244 new_result = '_'+`self.prompt_count`
241 245 to_main[new_result] = result
242 246 self.shell.user_ns.update(to_main)
243 247 self.shell.user_ns['_oh'][self.prompt_count] = result
244 248
245 249 def log_output(self, result):
246 250 """Log the output."""
247 251 if self.shell.logger.log_output:
248 252 self.shell.logger.log_write(repr(result),'output')
249 253
250 254 def finish_displayhook(self):
251 255 """Finish up all displayhook activities."""
252 256 IPython.utils.io.Term.cout.write(self.output_sep2)
253 257 IPython.utils.io.Term.cout.flush()
254 258
255 259 def __call__(self, result=None):
256 260 """Printing with history cache management.
257 261
258 262 This is invoked everytime the interpreter needs to print, and is
259 263 activated by setting the variable sys.displayhook to it.
260 264 """
261 265 self.check_for_underscore()
262 266 if result is not None and not self.quiet():
263 267 self.start_displayhook()
264 268 self.write_output_prompt()
265 269 result, result_repr = self.compute_result_repr(result)
266 270 self.write_result_repr(result_repr)
267 271 self.update_user_ns(result)
268 272 self.log_output(result)
269 273 self.finish_displayhook()
270 274
271 275 def flush(self):
272 276 if not self.do_full_cache:
273 277 raise ValueError,"You shouldn't have reached the cache flush "\
274 278 "if full caching is not enabled!"
275 279 # delete auto-generated vars from global namespace
276 280
277 281 for n in range(1,self.prompt_count + 1):
278 282 key = '_'+`n`
279 283 try:
280 284 del self.shell.user_ns[key]
281 285 except: pass
282 286 self.shell.user_ns['_oh'].clear()
283 287
284 288 if '_' not in __builtin__.__dict__:
285 289 self.shell.user_ns.update({'_':None,'__':None, '___':None})
286 290 import gc
287 291 gc.collect() # xxx needed?
288 292
@@ -1,259 +1,263 b''
1 1 """hooks for IPython.
2 2
3 3 In Python, it is possible to overwrite any method of any object if you really
4 4 want to. But IPython exposes a few 'hooks', methods which are _designed_ to
5 5 be overwritten by users for customization purposes. This module defines the
6 6 default versions of all such hooks, which get used by IPython if not
7 7 overridden by the user.
8 8
9 9 hooks are simple functions, but they should be declared with 'self' as their
10 10 first argument, because when activated they are registered into IPython as
11 11 instance methods. The self argument will be the IPython running instance
12 12 itself, so hooks have full access to the entire IPython object.
13 13
14 14 If you wish to define a new hook and activate it, you need to put the
15 15 necessary code into a python file which can be either imported or execfile()'d
16 16 from within your ipythonrc configuration.
17 17
18 18 For example, suppose that you have a module called 'myiphooks' in your
19 19 PYTHONPATH, which contains the following definition:
20 20
21 21 import os
22 22 from IPython.core import ipapi
23 23 ip = ipapi.get()
24 24
25 25 def calljed(self,filename, linenum):
26 26 "My editor hook calls the jed editor directly."
27 27 print "Calling my own editor, jed ..."
28 28 if os.system('jed +%d %s' % (linenum,filename)) != 0:
29 29 raise TryNext()
30 30
31 31 ip.set_hook('editor', calljed)
32 32
33 33 You can then enable the functionality by doing 'import myiphooks'
34 34 somewhere in your configuration files or ipython command line.
35 35 """
36 36
37 37 #*****************************************************************************
38 38 # Copyright (C) 2005 Fernando Perez. <fperez@colorado.edu>
39 39 #
40 40 # Distributed under the terms of the BSD License. The full license is in
41 41 # the file COPYING, distributed as part of this software.
42 42 #*****************************************************************************
43 43
44 44 import os, bisect
45 45 import sys
46 46
47 47 from IPython.core.error import TryNext
48 48 import IPython.utils.io
49 49
50 50 # List here all the default hooks. For now it's just the editor functions
51 51 # but over time we'll move here all the public API for user-accessible things.
52 52
53 53 __all__ = ['editor', 'fix_error_editor', 'synchronize_with_editor',
54 54 'input_prefilter', 'shutdown_hook', 'late_startup_hook',
55 55 'generate_prompt', 'show_in_pager','pre_prompt_hook',
56 56 'pre_runcode_hook', 'clipboard_get']
57 57
58 58 def editor(self,filename, linenum=None):
59 59 """Open the default editor at the given filename and linenumber.
60 60
61 61 This is IPython's default editor hook, you can use it as an example to
62 62 write your own modified one. To set your own editor function as the
63 63 new editor hook, call ip.set_hook('editor',yourfunc)."""
64 64
65 65 # IPython configures a default editor at startup by reading $EDITOR from
66 66 # the environment, and falling back on vi (unix) or notepad (win32).
67 67 editor = self.editor
68 68
69 69 # marker for at which line to open the file (for existing objects)
70 70 if linenum is None or editor=='notepad':
71 71 linemark = ''
72 72 else:
73 73 linemark = '+%d' % int(linenum)
74 74
75 75 # Enclose in quotes if necessary and legal
76 76 if ' ' in editor and os.path.isfile(editor) and editor[0] != '"':
77 77 editor = '"%s"' % editor
78 78
79 79 # Call the actual editor
80 80 if os.system('%s %s %s' % (editor,linemark,filename)) != 0:
81 81 raise TryNext()
82 82
83 83 import tempfile
84 84 def fix_error_editor(self,filename,linenum,column,msg):
85 85 """Open the editor at the given filename, linenumber, column and
86 86 show an error message. This is used for correcting syntax errors.
87 87 The current implementation only has special support for the VIM editor,
88 88 and falls back on the 'editor' hook if VIM is not used.
89 89
90 90 Call ip.set_hook('fix_error_editor',youfunc) to use your own function,
91 91 """
92 92 def vim_quickfix_file():
93 93 t = tempfile.NamedTemporaryFile()
94 94 t.write('%s:%d:%d:%s\n' % (filename,linenum,column,msg))
95 95 t.flush()
96 96 return t
97 97 if os.path.basename(self.editor) != 'vim':
98 98 self.hooks.editor(filename,linenum)
99 99 return
100 100 t = vim_quickfix_file()
101 101 try:
102 102 if os.system('vim --cmd "set errorformat=%f:%l:%c:%m" -q ' + t.name):
103 103 raise TryNext()
104 104 finally:
105 105 t.close()
106 106
107 107
108 108 def synchronize_with_editor(self, filename, linenum, column):
109 109 pass
110 110
111 111
112 112 class CommandChainDispatcher:
113 113 """ Dispatch calls to a chain of commands until some func can handle it
114 114
115 115 Usage: instantiate, execute "add" to add commands (with optional
116 116 priority), execute normally via f() calling mechanism.
117 117
118 118 """
119 119 def __init__(self,commands=None):
120 120 if commands is None:
121 121 self.chain = []
122 122 else:
123 123 self.chain = commands
124 124
125 125
126 126 def __call__(self,*args, **kw):
127 127 """ Command chain is called just like normal func.
128 128
129 129 This will call all funcs in chain with the same args as were given to this
130 130 function, and return the result of first func that didn't raise
131 131 TryNext """
132 132
133 133 for prio,cmd in self.chain:
134 134 #print "prio",prio,"cmd",cmd #dbg
135 135 try:
136 136 return cmd(*args, **kw)
137 137 except TryNext, exc:
138 138 if exc.args or exc.kwargs:
139 139 args = exc.args
140 140 kw = exc.kwargs
141 141 # if no function will accept it, raise TryNext up to the caller
142 142 raise TryNext
143 143
144 144 def __str__(self):
145 145 return str(self.chain)
146 146
147 147 def add(self, func, priority=0):
148 148 """ Add a func to the cmd chain with given priority """
149 149 bisect.insort(self.chain,(priority,func))
150 150
151 151 def __iter__(self):
152 152 """ Return all objects in chain.
153 153
154 154 Handy if the objects are not callable.
155 155 """
156 156 return iter(self.chain)
157 157
158 158
159 159 def result_display(self,arg):
160 160 """ Default display hook.
161 161
162 162 Called for displaying the result to the user.
163 163 """
164 164
165 165 if self.pprint:
166 try:
166 167 out = pformat(arg)
168 except:
169 # Work around possible bugs in pformat
170 out = repr(arg)
167 171 if '\n' in out:
168 172 # So that multi-line strings line up with the left column of
169 173 # the screen, instead of having the output prompt mess up
170 174 # their first line.
171 175 IPython.utils.io.Term.cout.write('\n')
172 176 print >>IPython.utils.io.Term.cout, out
173 177 else:
174 178 # By default, the interactive prompt uses repr() to display results,
175 179 # so we should honor this. Users who'd rather use a different
176 180 # mechanism can easily override this hook.
177 181 print >>IPython.utils.io.Term.cout, repr(arg)
178 182 # the default display hook doesn't manipulate the value to put in history
179 183 return None
180 184
181 185
182 186 def input_prefilter(self,line):
183 187 """ Default input prefilter
184 188
185 189 This returns the line as unchanged, so that the interpreter
186 190 knows that nothing was done and proceeds with "classic" prefiltering
187 191 (%magics, !shell commands etc.).
188 192
189 193 Note that leading whitespace is not passed to this hook. Prefilter
190 194 can't alter indentation.
191 195
192 196 """
193 197 #print "attempt to rewrite",line #dbg
194 198 return line
195 199
196 200
197 201 def shutdown_hook(self):
198 202 """ default shutdown hook
199 203
200 204 Typically, shotdown hooks should raise TryNext so all shutdown ops are done
201 205 """
202 206
203 207 #print "default shutdown hook ok" # dbg
204 208 return
205 209
206 210
207 211 def late_startup_hook(self):
208 212 """ Executed after ipython has been constructed and configured
209 213
210 214 """
211 215 #print "default startup hook ok" # dbg
212 216
213 217
214 218 def generate_prompt(self, is_continuation):
215 219 """ calculate and return a string with the prompt to display """
216 220 if is_continuation:
217 221 return str(self.displayhook.prompt2)
218 222 return str(self.displayhook.prompt1)
219 223
220 224
221 225 def show_in_pager(self,s):
222 226 """ Run a string through pager """
223 227 # raising TryNext here will use the default paging functionality
224 228 raise TryNext
225 229
226 230
227 231 def pre_prompt_hook(self):
228 232 """ Run before displaying the next prompt
229 233
230 234 Use this e.g. to display output from asynchronous operations (in order
231 235 to not mess up text entry)
232 236 """
233 237
234 238 return None
235 239
236 240
237 241 def pre_runcode_hook(self):
238 242 """ Executed before running the (prefiltered) code in IPython """
239 243 return None
240 244
241 245
242 246 def clipboard_get(self):
243 247 """ Get text from the clipboard.
244 248 """
245 249 from IPython.lib.clipboard import (
246 250 osx_clipboard_get, tkinter_clipboard_get,
247 251 win32_clipboard_get
248 252 )
249 253 if sys.platform == 'win32':
250 254 chain = [win32_clipboard_get, tkinter_clipboard_get]
251 255 elif sys.platform == 'darwin':
252 256 chain = [osx_clipboard_get, tkinter_clipboard_get]
253 257 else:
254 258 chain = [tkinter_clipboard_get]
255 259 dispatcher = CommandChainDispatcher()
256 260 for func in chain:
257 261 dispatcher.add(func)
258 262 text = dispatcher()
259 263 return text
General Comments 0
You need to be logged in to leave comments. Login now