##// END OF EJS Templates
Catch errors raised by user objects when accessing attributes....
Fernando Perez -
Show More
@@ -1,943 +1,950 b''
1 # encoding: utf-8
1 # encoding: utf-8
2 """
2 """
3 Prefiltering components.
3 Prefiltering components.
4
4
5 Prefilters transform user input before it is exec'd by Python. These
5 Prefilters transform user input before it is exec'd by Python. These
6 transforms are used to implement additional syntax such as !ls and %magic.
6 transforms are used to implement additional syntax such as !ls and %magic.
7
7
8 Authors:
8 Authors:
9
9
10 * Brian Granger
10 * Brian Granger
11 * Fernando Perez
11 * Fernando Perez
12 * Dan Milstein
12 * Dan Milstein
13 * Ville Vainio
13 * Ville Vainio
14 """
14 """
15
15
16 #-----------------------------------------------------------------------------
16 #-----------------------------------------------------------------------------
17 # Copyright (C) 2008-2009 The IPython Development Team
17 # Copyright (C) 2008-2009 The IPython Development Team
18 #
18 #
19 # Distributed under the terms of the BSD License. The full license is in
19 # Distributed under the terms of the BSD License. The full license is in
20 # the file COPYING, distributed as part of this software.
20 # the file COPYING, distributed as part of this software.
21 #-----------------------------------------------------------------------------
21 #-----------------------------------------------------------------------------
22
22
23 #-----------------------------------------------------------------------------
23 #-----------------------------------------------------------------------------
24 # Imports
24 # Imports
25 #-----------------------------------------------------------------------------
25 #-----------------------------------------------------------------------------
26
26
27 import __builtin__
27 import __builtin__
28 import codeop
28 import codeop
29 import re
29 import re
30
30
31 from IPython.core.alias import AliasManager
31 from IPython.core.alias import AliasManager
32 from IPython.core.autocall import IPyAutocall
32 from IPython.core.autocall import IPyAutocall
33 from IPython.config.configurable import Configurable
33 from IPython.config.configurable import Configurable
34 from IPython.core.macro import Macro
34 from IPython.core.macro import Macro
35 from IPython.core.splitinput import split_user_input, LineInfo
35 from IPython.core.splitinput import split_user_input, LineInfo
36 from IPython.core import page
36 from IPython.core import page
37
37
38 from IPython.utils.traitlets import List, Int, Any, Unicode, CBool, Bool, Instance
38 from IPython.utils.traitlets import List, Int, Any, Unicode, CBool, Bool, Instance
39 from IPython.utils.text import make_quoted_expr
39 from IPython.utils.text import make_quoted_expr
40 from IPython.utils.autoattr import auto_attr
40 from IPython.utils.autoattr import auto_attr
41
41
42 #-----------------------------------------------------------------------------
42 #-----------------------------------------------------------------------------
43 # Global utilities, errors and constants
43 # Global utilities, errors and constants
44 #-----------------------------------------------------------------------------
44 #-----------------------------------------------------------------------------
45
45
46 # Warning, these cannot be changed unless various regular expressions
46 # Warning, these cannot be changed unless various regular expressions
47 # are updated in a number of places. Not great, but at least we told you.
47 # are updated in a number of places. Not great, but at least we told you.
48 ESC_SHELL = '!'
48 ESC_SHELL = '!'
49 ESC_SH_CAP = '!!'
49 ESC_SH_CAP = '!!'
50 ESC_HELP = '?'
50 ESC_HELP = '?'
51 ESC_MAGIC = '%'
51 ESC_MAGIC = '%'
52 ESC_QUOTE = ','
52 ESC_QUOTE = ','
53 ESC_QUOTE2 = ';'
53 ESC_QUOTE2 = ';'
54 ESC_PAREN = '/'
54 ESC_PAREN = '/'
55
55
56
56
57 class PrefilterError(Exception):
57 class PrefilterError(Exception):
58 pass
58 pass
59
59
60
60
61 # RegExp to identify potential function names
61 # RegExp to identify potential function names
62 re_fun_name = re.compile(r'[a-zA-Z_]([a-zA-Z0-9_.]*) *$')
62 re_fun_name = re.compile(r'[a-zA-Z_]([a-zA-Z0-9_.]*) *$')
63
63
64 # RegExp to exclude strings with this start from autocalling. In
64 # RegExp to exclude strings with this start from autocalling. In
65 # particular, all binary operators should be excluded, so that if foo is
65 # particular, all binary operators should be excluded, so that if foo is
66 # callable, foo OP bar doesn't become foo(OP bar), which is invalid. The
66 # callable, foo OP bar doesn't become foo(OP bar), which is invalid. The
67 # characters '!=()' don't need to be checked for, as the checkPythonChars
67 # characters '!=()' don't need to be checked for, as the checkPythonChars
68 # routine explicitely does so, to catch direct calls and rebindings of
68 # routine explicitely does so, to catch direct calls and rebindings of
69 # existing names.
69 # existing names.
70
70
71 # Warning: the '-' HAS TO BE AT THE END of the first group, otherwise
71 # Warning: the '-' HAS TO BE AT THE END of the first group, otherwise
72 # it affects the rest of the group in square brackets.
72 # it affects the rest of the group in square brackets.
73 re_exclude_auto = re.compile(r'^[,&^\|\*/\+-]'
73 re_exclude_auto = re.compile(r'^[,&^\|\*/\+-]'
74 r'|^is |^not |^in |^and |^or ')
74 r'|^is |^not |^in |^and |^or ')
75
75
76 # try to catch also methods for stuff in lists/tuples/dicts: off
76 # try to catch also methods for stuff in lists/tuples/dicts: off
77 # (experimental). For this to work, the line_split regexp would need
77 # (experimental). For this to work, the line_split regexp would need
78 # to be modified so it wouldn't break things at '['. That line is
78 # to be modified so it wouldn't break things at '['. That line is
79 # nasty enough that I shouldn't change it until I can test it _well_.
79 # nasty enough that I shouldn't change it until I can test it _well_.
80 #self.re_fun_name = re.compile (r'[a-zA-Z_]([a-zA-Z0-9_.\[\]]*) ?$')
80 #self.re_fun_name = re.compile (r'[a-zA-Z_]([a-zA-Z0-9_.\[\]]*) ?$')
81
81
82
82
83 # Handler Check Utilities
83 # Handler Check Utilities
84 def is_shadowed(identifier, ip):
84 def is_shadowed(identifier, ip):
85 """Is the given identifier defined in one of the namespaces which shadow
85 """Is the given identifier defined in one of the namespaces which shadow
86 the alias and magic namespaces? Note that an identifier is different
86 the alias and magic namespaces? Note that an identifier is different
87 than ifun, because it can not contain a '.' character."""
87 than ifun, because it can not contain a '.' character."""
88 # This is much safer than calling ofind, which can change state
88 # This is much safer than calling ofind, which can change state
89 return (identifier in ip.user_ns \
89 return (identifier in ip.user_ns \
90 or identifier in ip.internal_ns \
90 or identifier in ip.internal_ns \
91 or identifier in ip.ns_table['builtin'])
91 or identifier in ip.ns_table['builtin'])
92
92
93
93
94 #-----------------------------------------------------------------------------
94 #-----------------------------------------------------------------------------
95 # Main Prefilter manager
95 # Main Prefilter manager
96 #-----------------------------------------------------------------------------
96 #-----------------------------------------------------------------------------
97
97
98
98
99 class PrefilterManager(Configurable):
99 class PrefilterManager(Configurable):
100 """Main prefilter component.
100 """Main prefilter component.
101
101
102 The IPython prefilter is run on all user input before it is run. The
102 The IPython prefilter is run on all user input before it is run. The
103 prefilter consumes lines of input and produces transformed lines of
103 prefilter consumes lines of input and produces transformed lines of
104 input.
104 input.
105
105
106 The iplementation consists of two phases:
106 The iplementation consists of two phases:
107
107
108 1. Transformers
108 1. Transformers
109 2. Checkers and handlers
109 2. Checkers and handlers
110
110
111 Over time, we plan on deprecating the checkers and handlers and doing
111 Over time, we plan on deprecating the checkers and handlers and doing
112 everything in the transformers.
112 everything in the transformers.
113
113
114 The transformers are instances of :class:`PrefilterTransformer` and have
114 The transformers are instances of :class:`PrefilterTransformer` and have
115 a single method :meth:`transform` that takes a line and returns a
115 a single method :meth:`transform` that takes a line and returns a
116 transformed line. The transformation can be accomplished using any
116 transformed line. The transformation can be accomplished using any
117 tool, but our current ones use regular expressions for speed. We also
117 tool, but our current ones use regular expressions for speed. We also
118 ship :mod:`pyparsing` in :mod:`IPython.external` for use in transformers.
118 ship :mod:`pyparsing` in :mod:`IPython.external` for use in transformers.
119
119
120 After all the transformers have been run, the line is fed to the checkers,
120 After all the transformers have been run, the line is fed to the checkers,
121 which are instances of :class:`PrefilterChecker`. The line is passed to
121 which are instances of :class:`PrefilterChecker`. The line is passed to
122 the :meth:`check` method, which either returns `None` or a
122 the :meth:`check` method, which either returns `None` or a
123 :class:`PrefilterHandler` instance. If `None` is returned, the other
123 :class:`PrefilterHandler` instance. If `None` is returned, the other
124 checkers are tried. If an :class:`PrefilterHandler` instance is returned,
124 checkers are tried. If an :class:`PrefilterHandler` instance is returned,
125 the line is passed to the :meth:`handle` method of the returned
125 the line is passed to the :meth:`handle` method of the returned
126 handler and no further checkers are tried.
126 handler and no further checkers are tried.
127
127
128 Both transformers and checkers have a `priority` attribute, that determines
128 Both transformers and checkers have a `priority` attribute, that determines
129 the order in which they are called. Smaller priorities are tried first.
129 the order in which they are called. Smaller priorities are tried first.
130
130
131 Both transformers and checkers also have `enabled` attribute, which is
131 Both transformers and checkers also have `enabled` attribute, which is
132 a boolean that determines if the instance is used.
132 a boolean that determines if the instance is used.
133
133
134 Users or developers can change the priority or enabled attribute of
134 Users or developers can change the priority or enabled attribute of
135 transformers or checkers, but they must call the :meth:`sort_checkers`
135 transformers or checkers, but they must call the :meth:`sort_checkers`
136 or :meth:`sort_transformers` method after changing the priority.
136 or :meth:`sort_transformers` method after changing the priority.
137 """
137 """
138
138
139 multi_line_specials = CBool(True, config=True)
139 multi_line_specials = CBool(True, config=True)
140 shell = Instance('IPython.core.interactiveshell.InteractiveShellABC')
140 shell = Instance('IPython.core.interactiveshell.InteractiveShellABC')
141
141
142 def __init__(self, shell=None, config=None):
142 def __init__(self, shell=None, config=None):
143 super(PrefilterManager, self).__init__(shell=shell, config=config)
143 super(PrefilterManager, self).__init__(shell=shell, config=config)
144 self.shell = shell
144 self.shell = shell
145 self.init_transformers()
145 self.init_transformers()
146 self.init_handlers()
146 self.init_handlers()
147 self.init_checkers()
147 self.init_checkers()
148
148
149 #-------------------------------------------------------------------------
149 #-------------------------------------------------------------------------
150 # API for managing transformers
150 # API for managing transformers
151 #-------------------------------------------------------------------------
151 #-------------------------------------------------------------------------
152
152
153 def init_transformers(self):
153 def init_transformers(self):
154 """Create the default transformers."""
154 """Create the default transformers."""
155 self._transformers = []
155 self._transformers = []
156 for transformer_cls in _default_transformers:
156 for transformer_cls in _default_transformers:
157 transformer_cls(
157 transformer_cls(
158 shell=self.shell, prefilter_manager=self, config=self.config
158 shell=self.shell, prefilter_manager=self, config=self.config
159 )
159 )
160
160
161 def sort_transformers(self):
161 def sort_transformers(self):
162 """Sort the transformers by priority.
162 """Sort the transformers by priority.
163
163
164 This must be called after the priority of a transformer is changed.
164 This must be called after the priority of a transformer is changed.
165 The :meth:`register_transformer` method calls this automatically.
165 The :meth:`register_transformer` method calls this automatically.
166 """
166 """
167 self._transformers.sort(key=lambda x: x.priority)
167 self._transformers.sort(key=lambda x: x.priority)
168
168
169 @property
169 @property
170 def transformers(self):
170 def transformers(self):
171 """Return a list of checkers, sorted by priority."""
171 """Return a list of checkers, sorted by priority."""
172 return self._transformers
172 return self._transformers
173
173
174 def register_transformer(self, transformer):
174 def register_transformer(self, transformer):
175 """Register a transformer instance."""
175 """Register a transformer instance."""
176 if transformer not in self._transformers:
176 if transformer not in self._transformers:
177 self._transformers.append(transformer)
177 self._transformers.append(transformer)
178 self.sort_transformers()
178 self.sort_transformers()
179
179
180 def unregister_transformer(self, transformer):
180 def unregister_transformer(self, transformer):
181 """Unregister a transformer instance."""
181 """Unregister a transformer instance."""
182 if transformer in self._transformers:
182 if transformer in self._transformers:
183 self._transformers.remove(transformer)
183 self._transformers.remove(transformer)
184
184
185 #-------------------------------------------------------------------------
185 #-------------------------------------------------------------------------
186 # API for managing checkers
186 # API for managing checkers
187 #-------------------------------------------------------------------------
187 #-------------------------------------------------------------------------
188
188
189 def init_checkers(self):
189 def init_checkers(self):
190 """Create the default checkers."""
190 """Create the default checkers."""
191 self._checkers = []
191 self._checkers = []
192 for checker in _default_checkers:
192 for checker in _default_checkers:
193 checker(
193 checker(
194 shell=self.shell, prefilter_manager=self, config=self.config
194 shell=self.shell, prefilter_manager=self, config=self.config
195 )
195 )
196
196
197 def sort_checkers(self):
197 def sort_checkers(self):
198 """Sort the checkers by priority.
198 """Sort the checkers by priority.
199
199
200 This must be called after the priority of a checker is changed.
200 This must be called after the priority of a checker is changed.
201 The :meth:`register_checker` method calls this automatically.
201 The :meth:`register_checker` method calls this automatically.
202 """
202 """
203 self._checkers.sort(key=lambda x: x.priority)
203 self._checkers.sort(key=lambda x: x.priority)
204
204
205 @property
205 @property
206 def checkers(self):
206 def checkers(self):
207 """Return a list of checkers, sorted by priority."""
207 """Return a list of checkers, sorted by priority."""
208 return self._checkers
208 return self._checkers
209
209
210 def register_checker(self, checker):
210 def register_checker(self, checker):
211 """Register a checker instance."""
211 """Register a checker instance."""
212 if checker not in self._checkers:
212 if checker not in self._checkers:
213 self._checkers.append(checker)
213 self._checkers.append(checker)
214 self.sort_checkers()
214 self.sort_checkers()
215
215
216 def unregister_checker(self, checker):
216 def unregister_checker(self, checker):
217 """Unregister a checker instance."""
217 """Unregister a checker instance."""
218 if checker in self._checkers:
218 if checker in self._checkers:
219 self._checkers.remove(checker)
219 self._checkers.remove(checker)
220
220
221 #-------------------------------------------------------------------------
221 #-------------------------------------------------------------------------
222 # API for managing checkers
222 # API for managing checkers
223 #-------------------------------------------------------------------------
223 #-------------------------------------------------------------------------
224
224
225 def init_handlers(self):
225 def init_handlers(self):
226 """Create the default handlers."""
226 """Create the default handlers."""
227 self._handlers = {}
227 self._handlers = {}
228 self._esc_handlers = {}
228 self._esc_handlers = {}
229 for handler in _default_handlers:
229 for handler in _default_handlers:
230 handler(
230 handler(
231 shell=self.shell, prefilter_manager=self, config=self.config
231 shell=self.shell, prefilter_manager=self, config=self.config
232 )
232 )
233
233
234 @property
234 @property
235 def handlers(self):
235 def handlers(self):
236 """Return a dict of all the handlers."""
236 """Return a dict of all the handlers."""
237 return self._handlers
237 return self._handlers
238
238
239 def register_handler(self, name, handler, esc_strings):
239 def register_handler(self, name, handler, esc_strings):
240 """Register a handler instance by name with esc_strings."""
240 """Register a handler instance by name with esc_strings."""
241 self._handlers[name] = handler
241 self._handlers[name] = handler
242 for esc_str in esc_strings:
242 for esc_str in esc_strings:
243 self._esc_handlers[esc_str] = handler
243 self._esc_handlers[esc_str] = handler
244
244
245 def unregister_handler(self, name, handler, esc_strings):
245 def unregister_handler(self, name, handler, esc_strings):
246 """Unregister a handler instance by name with esc_strings."""
246 """Unregister a handler instance by name with esc_strings."""
247 try:
247 try:
248 del self._handlers[name]
248 del self._handlers[name]
249 except KeyError:
249 except KeyError:
250 pass
250 pass
251 for esc_str in esc_strings:
251 for esc_str in esc_strings:
252 h = self._esc_handlers.get(esc_str)
252 h = self._esc_handlers.get(esc_str)
253 if h is handler:
253 if h is handler:
254 del self._esc_handlers[esc_str]
254 del self._esc_handlers[esc_str]
255
255
256 def get_handler_by_name(self, name):
256 def get_handler_by_name(self, name):
257 """Get a handler by its name."""
257 """Get a handler by its name."""
258 return self._handlers.get(name)
258 return self._handlers.get(name)
259
259
260 def get_handler_by_esc(self, esc_str):
260 def get_handler_by_esc(self, esc_str):
261 """Get a handler by its escape string."""
261 """Get a handler by its escape string."""
262 return self._esc_handlers.get(esc_str)
262 return self._esc_handlers.get(esc_str)
263
263
264 #-------------------------------------------------------------------------
264 #-------------------------------------------------------------------------
265 # Main prefiltering API
265 # Main prefiltering API
266 #-------------------------------------------------------------------------
266 #-------------------------------------------------------------------------
267
267
268 def prefilter_line_info(self, line_info):
268 def prefilter_line_info(self, line_info):
269 """Prefilter a line that has been converted to a LineInfo object.
269 """Prefilter a line that has been converted to a LineInfo object.
270
270
271 This implements the checker/handler part of the prefilter pipe.
271 This implements the checker/handler part of the prefilter pipe.
272 """
272 """
273 # print "prefilter_line_info: ", line_info
273 # print "prefilter_line_info: ", line_info
274 handler = self.find_handler(line_info)
274 handler = self.find_handler(line_info)
275 return handler.handle(line_info)
275 return handler.handle(line_info)
276
276
277 def find_handler(self, line_info):
277 def find_handler(self, line_info):
278 """Find a handler for the line_info by trying checkers."""
278 """Find a handler for the line_info by trying checkers."""
279 for checker in self.checkers:
279 for checker in self.checkers:
280 if checker.enabled:
280 if checker.enabled:
281 handler = checker.check(line_info)
281 handler = checker.check(line_info)
282 if handler:
282 if handler:
283 return handler
283 return handler
284 return self.get_handler_by_name('normal')
284 return self.get_handler_by_name('normal')
285
285
286 def transform_line(self, line, continue_prompt):
286 def transform_line(self, line, continue_prompt):
287 """Calls the enabled transformers in order of increasing priority."""
287 """Calls the enabled transformers in order of increasing priority."""
288 for transformer in self.transformers:
288 for transformer in self.transformers:
289 if transformer.enabled:
289 if transformer.enabled:
290 line = transformer.transform(line, continue_prompt)
290 line = transformer.transform(line, continue_prompt)
291 return line
291 return line
292
292
293 def prefilter_line(self, line, continue_prompt=False):
293 def prefilter_line(self, line, continue_prompt=False):
294 """Prefilter a single input line as text.
294 """Prefilter a single input line as text.
295
295
296 This method prefilters a single line of text by calling the
296 This method prefilters a single line of text by calling the
297 transformers and then the checkers/handlers.
297 transformers and then the checkers/handlers.
298 """
298 """
299
299
300 # print "prefilter_line: ", line, continue_prompt
300 # print "prefilter_line: ", line, continue_prompt
301 # All handlers *must* return a value, even if it's blank ('').
301 # All handlers *must* return a value, even if it's blank ('').
302
302
303 # save the line away in case we crash, so the post-mortem handler can
303 # save the line away in case we crash, so the post-mortem handler can
304 # record it
304 # record it
305 self.shell._last_input_line = line
305 self.shell._last_input_line = line
306
306
307 if not line:
307 if not line:
308 # Return immediately on purely empty lines, so that if the user
308 # Return immediately on purely empty lines, so that if the user
309 # previously typed some whitespace that started a continuation
309 # previously typed some whitespace that started a continuation
310 # prompt, he can break out of that loop with just an empty line.
310 # prompt, he can break out of that loop with just an empty line.
311 # This is how the default python prompt works.
311 # This is how the default python prompt works.
312 return ''
312 return ''
313
313
314 # At this point, we invoke our transformers.
314 # At this point, we invoke our transformers.
315 if not continue_prompt or (continue_prompt and self.multi_line_specials):
315 if not continue_prompt or (continue_prompt and self.multi_line_specials):
316 line = self.transform_line(line, continue_prompt)
316 line = self.transform_line(line, continue_prompt)
317
317
318 # Now we compute line_info for the checkers and handlers
318 # Now we compute line_info for the checkers and handlers
319 line_info = LineInfo(line, continue_prompt)
319 line_info = LineInfo(line, continue_prompt)
320
320
321 # the input history needs to track even empty lines
321 # the input history needs to track even empty lines
322 stripped = line.strip()
322 stripped = line.strip()
323
323
324 normal_handler = self.get_handler_by_name('normal')
324 normal_handler = self.get_handler_by_name('normal')
325 if not stripped:
325 if not stripped:
326 if not continue_prompt:
326 if not continue_prompt:
327 self.shell.displayhook.prompt_count -= 1
327 self.shell.displayhook.prompt_count -= 1
328
328
329 return normal_handler.handle(line_info)
329 return normal_handler.handle(line_info)
330
330
331 # special handlers are only allowed for single line statements
331 # special handlers are only allowed for single line statements
332 if continue_prompt and not self.multi_line_specials:
332 if continue_prompt and not self.multi_line_specials:
333 return normal_handler.handle(line_info)
333 return normal_handler.handle(line_info)
334
334
335 prefiltered = self.prefilter_line_info(line_info)
335 prefiltered = self.prefilter_line_info(line_info)
336 # print "prefiltered line: %r" % prefiltered
336 # print "prefiltered line: %r" % prefiltered
337 return prefiltered
337 return prefiltered
338
338
339 def prefilter_lines(self, lines, continue_prompt=False):
339 def prefilter_lines(self, lines, continue_prompt=False):
340 """Prefilter multiple input lines of text.
340 """Prefilter multiple input lines of text.
341
341
342 This is the main entry point for prefiltering multiple lines of
342 This is the main entry point for prefiltering multiple lines of
343 input. This simply calls :meth:`prefilter_line` for each line of
343 input. This simply calls :meth:`prefilter_line` for each line of
344 input.
344 input.
345
345
346 This covers cases where there are multiple lines in the user entry,
346 This covers cases where there are multiple lines in the user entry,
347 which is the case when the user goes back to a multiline history
347 which is the case when the user goes back to a multiline history
348 entry and presses enter.
348 entry and presses enter.
349 """
349 """
350 llines = lines.rstrip('\n').split('\n')
350 llines = lines.rstrip('\n').split('\n')
351 # We can get multiple lines in one shot, where multiline input 'blends'
351 # We can get multiple lines in one shot, where multiline input 'blends'
352 # into one line, in cases like recalling from the readline history
352 # into one line, in cases like recalling from the readline history
353 # buffer. We need to make sure that in such cases, we correctly
353 # buffer. We need to make sure that in such cases, we correctly
354 # communicate downstream which line is first and which are continuation
354 # communicate downstream which line is first and which are continuation
355 # ones.
355 # ones.
356 if len(llines) > 1:
356 if len(llines) > 1:
357 out = '\n'.join([self.prefilter_line(line, lnum>0)
357 out = '\n'.join([self.prefilter_line(line, lnum>0)
358 for lnum, line in enumerate(llines) ])
358 for lnum, line in enumerate(llines) ])
359 else:
359 else:
360 out = self.prefilter_line(llines[0], continue_prompt)
360 out = self.prefilter_line(llines[0], continue_prompt)
361
361
362 return out
362 return out
363
363
364 #-----------------------------------------------------------------------------
364 #-----------------------------------------------------------------------------
365 # Prefilter transformers
365 # Prefilter transformers
366 #-----------------------------------------------------------------------------
366 #-----------------------------------------------------------------------------
367
367
368
368
369 class PrefilterTransformer(Configurable):
369 class PrefilterTransformer(Configurable):
370 """Transform a line of user input."""
370 """Transform a line of user input."""
371
371
372 priority = Int(100, config=True)
372 priority = Int(100, config=True)
373 # Transformers don't currently use shell or prefilter_manager, but as we
373 # Transformers don't currently use shell or prefilter_manager, but as we
374 # move away from checkers and handlers, they will need them.
374 # move away from checkers and handlers, they will need them.
375 shell = Instance('IPython.core.interactiveshell.InteractiveShellABC')
375 shell = Instance('IPython.core.interactiveshell.InteractiveShellABC')
376 prefilter_manager = Instance('IPython.core.prefilter.PrefilterManager')
376 prefilter_manager = Instance('IPython.core.prefilter.PrefilterManager')
377 enabled = Bool(True, config=True)
377 enabled = Bool(True, config=True)
378
378
379 def __init__(self, shell=None, prefilter_manager=None, config=None):
379 def __init__(self, shell=None, prefilter_manager=None, config=None):
380 super(PrefilterTransformer, self).__init__(
380 super(PrefilterTransformer, self).__init__(
381 shell=shell, prefilter_manager=prefilter_manager, config=config
381 shell=shell, prefilter_manager=prefilter_manager, config=config
382 )
382 )
383 self.prefilter_manager.register_transformer(self)
383 self.prefilter_manager.register_transformer(self)
384
384
385 def transform(self, line, continue_prompt):
385 def transform(self, line, continue_prompt):
386 """Transform a line, returning the new one."""
386 """Transform a line, returning the new one."""
387 return None
387 return None
388
388
389 def __repr__(self):
389 def __repr__(self):
390 return "<%s(priority=%r, enabled=%r)>" % (
390 return "<%s(priority=%r, enabled=%r)>" % (
391 self.__class__.__name__, self.priority, self.enabled)
391 self.__class__.__name__, self.priority, self.enabled)
392
392
393
393
394 _assign_system_re = re.compile(r'(?P<lhs>(\s*)([\w\.]+)((\s*,\s*[\w\.]+)*))'
394 _assign_system_re = re.compile(r'(?P<lhs>(\s*)([\w\.]+)((\s*,\s*[\w\.]+)*))'
395 r'\s*=\s*!(?P<cmd>.*)')
395 r'\s*=\s*!(?P<cmd>.*)')
396
396
397
397
398 class AssignSystemTransformer(PrefilterTransformer):
398 class AssignSystemTransformer(PrefilterTransformer):
399 """Handle the `files = !ls` syntax."""
399 """Handle the `files = !ls` syntax."""
400
400
401 priority = Int(100, config=True)
401 priority = Int(100, config=True)
402
402
403 def transform(self, line, continue_prompt):
403 def transform(self, line, continue_prompt):
404 m = _assign_system_re.match(line)
404 m = _assign_system_re.match(line)
405 if m is not None:
405 if m is not None:
406 cmd = m.group('cmd')
406 cmd = m.group('cmd')
407 lhs = m.group('lhs')
407 lhs = m.group('lhs')
408 expr = make_quoted_expr("sc =%s" % cmd)
408 expr = make_quoted_expr("sc =%s" % cmd)
409 new_line = '%s = get_ipython().magic(%s)' % (lhs, expr)
409 new_line = '%s = get_ipython().magic(%s)' % (lhs, expr)
410 return new_line
410 return new_line
411 return line
411 return line
412
412
413
413
414 _assign_magic_re = re.compile(r'(?P<lhs>(\s*)([\w\.]+)((\s*,\s*[\w\.]+)*))'
414 _assign_magic_re = re.compile(r'(?P<lhs>(\s*)([\w\.]+)((\s*,\s*[\w\.]+)*))'
415 r'\s*=\s*%(?P<cmd>.*)')
415 r'\s*=\s*%(?P<cmd>.*)')
416
416
417 class AssignMagicTransformer(PrefilterTransformer):
417 class AssignMagicTransformer(PrefilterTransformer):
418 """Handle the `a = %who` syntax."""
418 """Handle the `a = %who` syntax."""
419
419
420 priority = Int(200, config=True)
420 priority = Int(200, config=True)
421
421
422 def transform(self, line, continue_prompt):
422 def transform(self, line, continue_prompt):
423 m = _assign_magic_re.match(line)
423 m = _assign_magic_re.match(line)
424 if m is not None:
424 if m is not None:
425 cmd = m.group('cmd')
425 cmd = m.group('cmd')
426 lhs = m.group('lhs')
426 lhs = m.group('lhs')
427 expr = make_quoted_expr(cmd)
427 expr = make_quoted_expr(cmd)
428 new_line = '%s = get_ipython().magic(%s)' % (lhs, expr)
428 new_line = '%s = get_ipython().magic(%s)' % (lhs, expr)
429 return new_line
429 return new_line
430 return line
430 return line
431
431
432
432
433 _classic_prompt_re = re.compile(r'(^[ \t]*>>> |^[ \t]*\.\.\. )')
433 _classic_prompt_re = re.compile(r'(^[ \t]*>>> |^[ \t]*\.\.\. )')
434
434
435 class PyPromptTransformer(PrefilterTransformer):
435 class PyPromptTransformer(PrefilterTransformer):
436 """Handle inputs that start with '>>> ' syntax."""
436 """Handle inputs that start with '>>> ' syntax."""
437
437
438 priority = Int(50, config=True)
438 priority = Int(50, config=True)
439
439
440 def transform(self, line, continue_prompt):
440 def transform(self, line, continue_prompt):
441
441
442 if not line or line.isspace() or line.strip() == '...':
442 if not line or line.isspace() or line.strip() == '...':
443 # This allows us to recognize multiple input prompts separated by
443 # This allows us to recognize multiple input prompts separated by
444 # blank lines and pasted in a single chunk, very common when
444 # blank lines and pasted in a single chunk, very common when
445 # pasting doctests or long tutorial passages.
445 # pasting doctests or long tutorial passages.
446 return ''
446 return ''
447 m = _classic_prompt_re.match(line)
447 m = _classic_prompt_re.match(line)
448 if m:
448 if m:
449 return line[len(m.group(0)):]
449 return line[len(m.group(0)):]
450 else:
450 else:
451 return line
451 return line
452
452
453
453
454 _ipy_prompt_re = re.compile(r'(^[ \t]*In \[\d+\]: |^[ \t]*\ \ \ \.\.\.+: )')
454 _ipy_prompt_re = re.compile(r'(^[ \t]*In \[\d+\]: |^[ \t]*\ \ \ \.\.\.+: )')
455
455
456 class IPyPromptTransformer(PrefilterTransformer):
456 class IPyPromptTransformer(PrefilterTransformer):
457 """Handle inputs that start classic IPython prompt syntax."""
457 """Handle inputs that start classic IPython prompt syntax."""
458
458
459 priority = Int(50, config=True)
459 priority = Int(50, config=True)
460
460
461 def transform(self, line, continue_prompt):
461 def transform(self, line, continue_prompt):
462
462
463 if not line or line.isspace() or line.strip() == '...':
463 if not line or line.isspace() or line.strip() == '...':
464 # This allows us to recognize multiple input prompts separated by
464 # This allows us to recognize multiple input prompts separated by
465 # blank lines and pasted in a single chunk, very common when
465 # blank lines and pasted in a single chunk, very common when
466 # pasting doctests or long tutorial passages.
466 # pasting doctests or long tutorial passages.
467 return ''
467 return ''
468 m = _ipy_prompt_re.match(line)
468 m = _ipy_prompt_re.match(line)
469 if m:
469 if m:
470 return line[len(m.group(0)):]
470 return line[len(m.group(0)):]
471 else:
471 else:
472 return line
472 return line
473
473
474 #-----------------------------------------------------------------------------
474 #-----------------------------------------------------------------------------
475 # Prefilter checkers
475 # Prefilter checkers
476 #-----------------------------------------------------------------------------
476 #-----------------------------------------------------------------------------
477
477
478
478
479 class PrefilterChecker(Configurable):
479 class PrefilterChecker(Configurable):
480 """Inspect an input line and return a handler for that line."""
480 """Inspect an input line and return a handler for that line."""
481
481
482 priority = Int(100, config=True)
482 priority = Int(100, config=True)
483 shell = Instance('IPython.core.interactiveshell.InteractiveShellABC')
483 shell = Instance('IPython.core.interactiveshell.InteractiveShellABC')
484 prefilter_manager = Instance('IPython.core.prefilter.PrefilterManager')
484 prefilter_manager = Instance('IPython.core.prefilter.PrefilterManager')
485 enabled = Bool(True, config=True)
485 enabled = Bool(True, config=True)
486
486
487 def __init__(self, shell=None, prefilter_manager=None, config=None):
487 def __init__(self, shell=None, prefilter_manager=None, config=None):
488 super(PrefilterChecker, self).__init__(
488 super(PrefilterChecker, self).__init__(
489 shell=shell, prefilter_manager=prefilter_manager, config=config
489 shell=shell, prefilter_manager=prefilter_manager, config=config
490 )
490 )
491 self.prefilter_manager.register_checker(self)
491 self.prefilter_manager.register_checker(self)
492
492
493 def check(self, line_info):
493 def check(self, line_info):
494 """Inspect line_info and return a handler instance or None."""
494 """Inspect line_info and return a handler instance or None."""
495 return None
495 return None
496
496
497 def __repr__(self):
497 def __repr__(self):
498 return "<%s(priority=%r, enabled=%r)>" % (
498 return "<%s(priority=%r, enabled=%r)>" % (
499 self.__class__.__name__, self.priority, self.enabled)
499 self.__class__.__name__, self.priority, self.enabled)
500
500
501
501
502 class EmacsChecker(PrefilterChecker):
502 class EmacsChecker(PrefilterChecker):
503
503
504 priority = Int(100, config=True)
504 priority = Int(100, config=True)
505 enabled = Bool(False, config=True)
505 enabled = Bool(False, config=True)
506
506
507 def check(self, line_info):
507 def check(self, line_info):
508 "Emacs ipython-mode tags certain input lines."
508 "Emacs ipython-mode tags certain input lines."
509 if line_info.line.endswith('# PYTHON-MODE'):
509 if line_info.line.endswith('# PYTHON-MODE'):
510 return self.prefilter_manager.get_handler_by_name('emacs')
510 return self.prefilter_manager.get_handler_by_name('emacs')
511 else:
511 else:
512 return None
512 return None
513
513
514
514
515 class ShellEscapeChecker(PrefilterChecker):
515 class ShellEscapeChecker(PrefilterChecker):
516
516
517 priority = Int(200, config=True)
517 priority = Int(200, config=True)
518
518
519 def check(self, line_info):
519 def check(self, line_info):
520 if line_info.line.lstrip().startswith(ESC_SHELL):
520 if line_info.line.lstrip().startswith(ESC_SHELL):
521 return self.prefilter_manager.get_handler_by_name('shell')
521 return self.prefilter_manager.get_handler_by_name('shell')
522
522
523
523
524 class MacroChecker(PrefilterChecker):
524 class MacroChecker(PrefilterChecker):
525
525
526 priority = Int(250, config=True)
526 priority = Int(250, config=True)
527
527
528 def check(self, line_info):
528 def check(self, line_info):
529 obj = self.shell.user_ns.get(line_info.ifun)
529 obj = self.shell.user_ns.get(line_info.ifun)
530 if isinstance(obj, Macro):
530 if isinstance(obj, Macro):
531 return self.prefilter_manager.get_handler_by_name('macro')
531 return self.prefilter_manager.get_handler_by_name('macro')
532 else:
532 else:
533 return None
533 return None
534
534
535
535
536 class IPyAutocallChecker(PrefilterChecker):
536 class IPyAutocallChecker(PrefilterChecker):
537
537
538 priority = Int(300, config=True)
538 priority = Int(300, config=True)
539
539
540 def check(self, line_info):
540 def check(self, line_info):
541 "Instances of IPyAutocall in user_ns get autocalled immediately"
541 "Instances of IPyAutocall in user_ns get autocalled immediately"
542 obj = self.shell.user_ns.get(line_info.ifun, None)
542 obj = self.shell.user_ns.get(line_info.ifun, None)
543 if isinstance(obj, IPyAutocall):
543 if isinstance(obj, IPyAutocall):
544 obj.set_ip(self.shell)
544 obj.set_ip(self.shell)
545 return self.prefilter_manager.get_handler_by_name('auto')
545 return self.prefilter_manager.get_handler_by_name('auto')
546 else:
546 else:
547 return None
547 return None
548
548
549
549
550 class MultiLineMagicChecker(PrefilterChecker):
550 class MultiLineMagicChecker(PrefilterChecker):
551
551
552 priority = Int(400, config=True)
552 priority = Int(400, config=True)
553
553
554 def check(self, line_info):
554 def check(self, line_info):
555 "Allow ! and !! in multi-line statements if multi_line_specials is on"
555 "Allow ! and !! in multi-line statements if multi_line_specials is on"
556 # Note that this one of the only places we check the first character of
556 # Note that this one of the only places we check the first character of
557 # ifun and *not* the pre_char. Also note that the below test matches
557 # ifun and *not* the pre_char. Also note that the below test matches
558 # both ! and !!.
558 # both ! and !!.
559 if line_info.continue_prompt \
559 if line_info.continue_prompt \
560 and self.prefilter_manager.multi_line_specials:
560 and self.prefilter_manager.multi_line_specials:
561 if line_info.esc == ESC_MAGIC:
561 if line_info.esc == ESC_MAGIC:
562 return self.prefilter_manager.get_handler_by_name('magic')
562 return self.prefilter_manager.get_handler_by_name('magic')
563 else:
563 else:
564 return None
564 return None
565
565
566
566
567 class EscCharsChecker(PrefilterChecker):
567 class EscCharsChecker(PrefilterChecker):
568
568
569 priority = Int(500, config=True)
569 priority = Int(500, config=True)
570
570
571 def check(self, line_info):
571 def check(self, line_info):
572 """Check for escape character and return either a handler to handle it,
572 """Check for escape character and return either a handler to handle it,
573 or None if there is no escape char."""
573 or None if there is no escape char."""
574 if line_info.line[-1] == ESC_HELP \
574 if line_info.line[-1] == ESC_HELP \
575 and line_info.esc != ESC_SHELL \
575 and line_info.esc != ESC_SHELL \
576 and line_info.esc != ESC_SH_CAP:
576 and line_info.esc != ESC_SH_CAP:
577 # the ? can be at the end, but *not* for either kind of shell escape,
577 # the ? can be at the end, but *not* for either kind of shell escape,
578 # because a ? can be a vaild final char in a shell cmd
578 # because a ? can be a vaild final char in a shell cmd
579 return self.prefilter_manager.get_handler_by_name('help')
579 return self.prefilter_manager.get_handler_by_name('help')
580 else:
580 else:
581 if line_info.pre:
581 if line_info.pre:
582 return None
582 return None
583 # This returns None like it should if no handler exists
583 # This returns None like it should if no handler exists
584 return self.prefilter_manager.get_handler_by_esc(line_info.esc)
584 return self.prefilter_manager.get_handler_by_esc(line_info.esc)
585
585
586
586
587 class AssignmentChecker(PrefilterChecker):
587 class AssignmentChecker(PrefilterChecker):
588
588
589 priority = Int(600, config=True)
589 priority = Int(600, config=True)
590
590
591 def check(self, line_info):
591 def check(self, line_info):
592 """Check to see if user is assigning to a var for the first time, in
592 """Check to see if user is assigning to a var for the first time, in
593 which case we want to avoid any sort of automagic / autocall games.
593 which case we want to avoid any sort of automagic / autocall games.
594
594
595 This allows users to assign to either alias or magic names true python
595 This allows users to assign to either alias or magic names true python
596 variables (the magic/alias systems always take second seat to true
596 variables (the magic/alias systems always take second seat to true
597 python code). E.g. ls='hi', or ls,that=1,2"""
597 python code). E.g. ls='hi', or ls,that=1,2"""
598 if line_info.the_rest:
598 if line_info.the_rest:
599 if line_info.the_rest[0] in '=,':
599 if line_info.the_rest[0] in '=,':
600 return self.prefilter_manager.get_handler_by_name('normal')
600 return self.prefilter_manager.get_handler_by_name('normal')
601 else:
601 else:
602 return None
602 return None
603
603
604
604
605 class AutoMagicChecker(PrefilterChecker):
605 class AutoMagicChecker(PrefilterChecker):
606
606
607 priority = Int(700, config=True)
607 priority = Int(700, config=True)
608
608
609 def check(self, line_info):
609 def check(self, line_info):
610 """If the ifun is magic, and automagic is on, run it. Note: normal,
610 """If the ifun is magic, and automagic is on, run it. Note: normal,
611 non-auto magic would already have been triggered via '%' in
611 non-auto magic would already have been triggered via '%' in
612 check_esc_chars. This just checks for automagic. Also, before
612 check_esc_chars. This just checks for automagic. Also, before
613 triggering the magic handler, make sure that there is nothing in the
613 triggering the magic handler, make sure that there is nothing in the
614 user namespace which could shadow it."""
614 user namespace which could shadow it."""
615 if not self.shell.automagic or not hasattr(self.shell,'magic_'+line_info.ifun):
615 if not self.shell.automagic or not hasattr(self.shell,'magic_'+line_info.ifun):
616 return None
616 return None
617
617
618 # We have a likely magic method. Make sure we should actually call it.
618 # We have a likely magic method. Make sure we should actually call it.
619 if line_info.continue_prompt and not self.prefilter_manager.multi_line_specials:
619 if line_info.continue_prompt and not self.prefilter_manager.multi_line_specials:
620 return None
620 return None
621
621
622 head = line_info.ifun.split('.',1)[0]
622 head = line_info.ifun.split('.',1)[0]
623 if is_shadowed(head, self.shell):
623 if is_shadowed(head, self.shell):
624 return None
624 return None
625
625
626 return self.prefilter_manager.get_handler_by_name('magic')
626 return self.prefilter_manager.get_handler_by_name('magic')
627
627
628
628
629 class AliasChecker(PrefilterChecker):
629 class AliasChecker(PrefilterChecker):
630
630
631 priority = Int(800, config=True)
631 priority = Int(800, config=True)
632
632
633 def check(self, line_info):
633 def check(self, line_info):
634 "Check if the initital identifier on the line is an alias."
634 "Check if the initital identifier on the line is an alias."
635 # Note: aliases can not contain '.'
635 # Note: aliases can not contain '.'
636 head = line_info.ifun.split('.',1)[0]
636 head = line_info.ifun.split('.',1)[0]
637 if line_info.ifun not in self.shell.alias_manager \
637 if line_info.ifun not in self.shell.alias_manager \
638 or head not in self.shell.alias_manager \
638 or head not in self.shell.alias_manager \
639 or is_shadowed(head, self.shell):
639 or is_shadowed(head, self.shell):
640 return None
640 return None
641
641
642 return self.prefilter_manager.get_handler_by_name('alias')
642 return self.prefilter_manager.get_handler_by_name('alias')
643
643
644
644
645 class PythonOpsChecker(PrefilterChecker):
645 class PythonOpsChecker(PrefilterChecker):
646
646
647 priority = Int(900, config=True)
647 priority = Int(900, config=True)
648
648
649 def check(self, line_info):
649 def check(self, line_info):
650 """If the 'rest' of the line begins with a function call or pretty much
650 """If the 'rest' of the line begins with a function call or pretty much
651 any python operator, we should simply execute the line (regardless of
651 any python operator, we should simply execute the line (regardless of
652 whether or not there's a possible autocall expansion). This avoids
652 whether or not there's a possible autocall expansion). This avoids
653 spurious (and very confusing) geattr() accesses."""
653 spurious (and very confusing) geattr() accesses."""
654 if line_info.the_rest and line_info.the_rest[0] in '!=()<>,+*/%^&|':
654 if line_info.the_rest and line_info.the_rest[0] in '!=()<>,+*/%^&|':
655 return self.prefilter_manager.get_handler_by_name('normal')
655 return self.prefilter_manager.get_handler_by_name('normal')
656 else:
656 else:
657 return None
657 return None
658
658
659
659
660 class AutocallChecker(PrefilterChecker):
660 class AutocallChecker(PrefilterChecker):
661
661
662 priority = Int(1000, config=True)
662 priority = Int(1000, config=True)
663
663
664 def check(self, line_info):
664 def check(self, line_info):
665 "Check if the initial word/function is callable and autocall is on."
665 "Check if the initial word/function is callable and autocall is on."
666 if not self.shell.autocall:
666 if not self.shell.autocall:
667 return None
667 return None
668
668
669 oinfo = line_info.ofind(self.shell) # This can mutate state via getattr
669 oinfo = line_info.ofind(self.shell) # This can mutate state via getattr
670 if not oinfo['found']:
670 if not oinfo['found']:
671 return None
671 return None
672
672
673 if callable(oinfo['obj']) \
673 if callable(oinfo['obj']) \
674 and (not re_exclude_auto.match(line_info.the_rest)) \
674 and (not re_exclude_auto.match(line_info.the_rest)) \
675 and re_fun_name.match(line_info.ifun):
675 and re_fun_name.match(line_info.ifun):
676 return self.prefilter_manager.get_handler_by_name('auto')
676 return self.prefilter_manager.get_handler_by_name('auto')
677 else:
677 else:
678 return None
678 return None
679
679
680
680
681 #-----------------------------------------------------------------------------
681 #-----------------------------------------------------------------------------
682 # Prefilter handlers
682 # Prefilter handlers
683 #-----------------------------------------------------------------------------
683 #-----------------------------------------------------------------------------
684
684
685
685
686 class PrefilterHandler(Configurable):
686 class PrefilterHandler(Configurable):
687
687
688 handler_name = Unicode('normal')
688 handler_name = Unicode('normal')
689 esc_strings = List([])
689 esc_strings = List([])
690 shell = Instance('IPython.core.interactiveshell.InteractiveShellABC')
690 shell = Instance('IPython.core.interactiveshell.InteractiveShellABC')
691 prefilter_manager = Instance('IPython.core.prefilter.PrefilterManager')
691 prefilter_manager = Instance('IPython.core.prefilter.PrefilterManager')
692
692
693 def __init__(self, shell=None, prefilter_manager=None, config=None):
693 def __init__(self, shell=None, prefilter_manager=None, config=None):
694 super(PrefilterHandler, self).__init__(
694 super(PrefilterHandler, self).__init__(
695 shell=shell, prefilter_manager=prefilter_manager, config=config
695 shell=shell, prefilter_manager=prefilter_manager, config=config
696 )
696 )
697 self.prefilter_manager.register_handler(
697 self.prefilter_manager.register_handler(
698 self.handler_name,
698 self.handler_name,
699 self,
699 self,
700 self.esc_strings
700 self.esc_strings
701 )
701 )
702
702
703 def handle(self, line_info):
703 def handle(self, line_info):
704 # print "normal: ", line_info
704 # print "normal: ", line_info
705 """Handle normal input lines. Use as a template for handlers."""
705 """Handle normal input lines. Use as a template for handlers."""
706
706
707 # With autoindent on, we need some way to exit the input loop, and I
707 # With autoindent on, we need some way to exit the input loop, and I
708 # don't want to force the user to have to backspace all the way to
708 # don't want to force the user to have to backspace all the way to
709 # clear the line. The rule will be in this case, that either two
709 # clear the line. The rule will be in this case, that either two
710 # lines of pure whitespace in a row, or a line of pure whitespace but
710 # lines of pure whitespace in a row, or a line of pure whitespace but
711 # of a size different to the indent level, will exit the input loop.
711 # of a size different to the indent level, will exit the input loop.
712 line = line_info.line
712 line = line_info.line
713 continue_prompt = line_info.continue_prompt
713 continue_prompt = line_info.continue_prompt
714
714
715 if (continue_prompt and
715 if (continue_prompt and
716 self.shell.autoindent and
716 self.shell.autoindent and
717 line.isspace() and
717 line.isspace() and
718 0 < abs(len(line) - self.shell.indent_current_nsp) <= 2):
718 0 < abs(len(line) - self.shell.indent_current_nsp) <= 2):
719 line = ''
719 line = ''
720
720
721 return line
721 return line
722
722
723 def __str__(self):
723 def __str__(self):
724 return "<%s(name=%s)>" % (self.__class__.__name__, self.handler_name)
724 return "<%s(name=%s)>" % (self.__class__.__name__, self.handler_name)
725
725
726
726
727 class AliasHandler(PrefilterHandler):
727 class AliasHandler(PrefilterHandler):
728
728
729 handler_name = Unicode('alias')
729 handler_name = Unicode('alias')
730
730
731 def handle(self, line_info):
731 def handle(self, line_info):
732 """Handle alias input lines. """
732 """Handle alias input lines. """
733 transformed = self.shell.alias_manager.expand_aliases(line_info.ifun,line_info.the_rest)
733 transformed = self.shell.alias_manager.expand_aliases(line_info.ifun,line_info.the_rest)
734 # pre is needed, because it carries the leading whitespace. Otherwise
734 # pre is needed, because it carries the leading whitespace. Otherwise
735 # aliases won't work in indented sections.
735 # aliases won't work in indented sections.
736 line_out = '%sget_ipython().system(%s)' % (line_info.pre_whitespace,
736 line_out = '%sget_ipython().system(%s)' % (line_info.pre_whitespace,
737 make_quoted_expr(transformed))
737 make_quoted_expr(transformed))
738
738
739 return line_out
739 return line_out
740
740
741
741
742 class ShellEscapeHandler(PrefilterHandler):
742 class ShellEscapeHandler(PrefilterHandler):
743
743
744 handler_name = Unicode('shell')
744 handler_name = Unicode('shell')
745 esc_strings = List([ESC_SHELL, ESC_SH_CAP])
745 esc_strings = List([ESC_SHELL, ESC_SH_CAP])
746
746
747 def handle(self, line_info):
747 def handle(self, line_info):
748 """Execute the line in a shell, empty return value"""
748 """Execute the line in a shell, empty return value"""
749 magic_handler = self.prefilter_manager.get_handler_by_name('magic')
749 magic_handler = self.prefilter_manager.get_handler_by_name('magic')
750
750
751 line = line_info.line
751 line = line_info.line
752 if line.lstrip().startswith(ESC_SH_CAP):
752 if line.lstrip().startswith(ESC_SH_CAP):
753 # rewrite LineInfo's line, ifun and the_rest to properly hold the
753 # rewrite LineInfo's line, ifun and the_rest to properly hold the
754 # call to %sx and the actual command to be executed, so
754 # call to %sx and the actual command to be executed, so
755 # handle_magic can work correctly. Note that this works even if
755 # handle_magic can work correctly. Note that this works even if
756 # the line is indented, so it handles multi_line_specials
756 # the line is indented, so it handles multi_line_specials
757 # properly.
757 # properly.
758 new_rest = line.lstrip()[2:]
758 new_rest = line.lstrip()[2:]
759 line_info.line = '%ssx %s' % (ESC_MAGIC, new_rest)
759 line_info.line = '%ssx %s' % (ESC_MAGIC, new_rest)
760 line_info.ifun = 'sx'
760 line_info.ifun = 'sx'
761 line_info.the_rest = new_rest
761 line_info.the_rest = new_rest
762 return magic_handler.handle(line_info)
762 return magic_handler.handle(line_info)
763 else:
763 else:
764 cmd = line.lstrip().lstrip(ESC_SHELL)
764 cmd = line.lstrip().lstrip(ESC_SHELL)
765 line_out = '%sget_ipython().system(%s)' % (line_info.pre_whitespace,
765 line_out = '%sget_ipython().system(%s)' % (line_info.pre_whitespace,
766 make_quoted_expr(cmd))
766 make_quoted_expr(cmd))
767 return line_out
767 return line_out
768
768
769
769
770 class MacroHandler(PrefilterHandler):
770 class MacroHandler(PrefilterHandler):
771 handler_name = Unicode("macro")
771 handler_name = Unicode("macro")
772
772
773 def handle(self, line_info):
773 def handle(self, line_info):
774 obj = self.shell.user_ns.get(line_info.ifun)
774 obj = self.shell.user_ns.get(line_info.ifun)
775 pre_space = line_info.pre_whitespace
775 pre_space = line_info.pre_whitespace
776 line_sep = "\n" + pre_space
776 line_sep = "\n" + pre_space
777 return pre_space + line_sep.join(obj.value.splitlines())
777 return pre_space + line_sep.join(obj.value.splitlines())
778
778
779
779
780 class MagicHandler(PrefilterHandler):
780 class MagicHandler(PrefilterHandler):
781
781
782 handler_name = Unicode('magic')
782 handler_name = Unicode('magic')
783 esc_strings = List([ESC_MAGIC])
783 esc_strings = List([ESC_MAGIC])
784
784
785 def handle(self, line_info):
785 def handle(self, line_info):
786 """Execute magic functions."""
786 """Execute magic functions."""
787 ifun = line_info.ifun
787 ifun = line_info.ifun
788 the_rest = line_info.the_rest
788 the_rest = line_info.the_rest
789 cmd = '%sget_ipython().magic(%s)' % (line_info.pre_whitespace,
789 cmd = '%sget_ipython().magic(%s)' % (line_info.pre_whitespace,
790 make_quoted_expr(ifun + " " + the_rest))
790 make_quoted_expr(ifun + " " + the_rest))
791 return cmd
791 return cmd
792
792
793
793
794 class AutoHandler(PrefilterHandler):
794 class AutoHandler(PrefilterHandler):
795
795
796 handler_name = Unicode('auto')
796 handler_name = Unicode('auto')
797 esc_strings = List([ESC_PAREN, ESC_QUOTE, ESC_QUOTE2])
797 esc_strings = List([ESC_PAREN, ESC_QUOTE, ESC_QUOTE2])
798
798
799 def handle(self, line_info):
799 def handle(self, line_info):
800 """Handle lines which can be auto-executed, quoting if requested."""
800 """Handle lines which can be auto-executed, quoting if requested."""
801 line = line_info.line
801 line = line_info.line
802 ifun = line_info.ifun
802 ifun = line_info.ifun
803 the_rest = line_info.the_rest
803 the_rest = line_info.the_rest
804 pre = line_info.pre
804 pre = line_info.pre
805 esc = line_info.esc
805 esc = line_info.esc
806 continue_prompt = line_info.continue_prompt
806 continue_prompt = line_info.continue_prompt
807 obj = line_info.ofind(self)['obj']
807 obj = line_info.ofind(self)['obj']
808 #print 'pre <%s> ifun <%s> rest <%s>' % (pre,ifun,the_rest) # dbg
808 #print 'pre <%s> ifun <%s> rest <%s>' % (pre,ifun,the_rest) # dbg
809
809
810 # This should only be active for single-line input!
810 # This should only be active for single-line input!
811 if continue_prompt:
811 if continue_prompt:
812 return line
812 return line
813
813
814 force_auto = isinstance(obj, IPyAutocall)
814 force_auto = isinstance(obj, IPyAutocall)
815 auto_rewrite = getattr(obj, 'rewrite', True)
815
816 # User objects sometimes raise exceptions on attribute access other
817 # than AttributeError (we've seen it in the past), so it's safest to be
818 # ultra-conservative here and catch all.
819 try:
820 auto_rewrite = obj.rewrite
821 except Exception:
822 auto_rewrite = True
816
823
817 if esc == ESC_QUOTE:
824 if esc == ESC_QUOTE:
818 # Auto-quote splitting on whitespace
825 # Auto-quote splitting on whitespace
819 newcmd = '%s("%s")' % (ifun,'", "'.join(the_rest.split()) )
826 newcmd = '%s("%s")' % (ifun,'", "'.join(the_rest.split()) )
820 elif esc == ESC_QUOTE2:
827 elif esc == ESC_QUOTE2:
821 # Auto-quote whole string
828 # Auto-quote whole string
822 newcmd = '%s("%s")' % (ifun,the_rest)
829 newcmd = '%s("%s")' % (ifun,the_rest)
823 elif esc == ESC_PAREN:
830 elif esc == ESC_PAREN:
824 newcmd = '%s(%s)' % (ifun,",".join(the_rest.split()))
831 newcmd = '%s(%s)' % (ifun,",".join(the_rest.split()))
825 else:
832 else:
826 # Auto-paren.
833 # Auto-paren.
827 # We only apply it to argument-less calls if the autocall
834 # We only apply it to argument-less calls if the autocall
828 # parameter is set to 2. We only need to check that autocall is <
835 # parameter is set to 2. We only need to check that autocall is <
829 # 2, since this function isn't called unless it's at least 1.
836 # 2, since this function isn't called unless it's at least 1.
830 if not the_rest and (self.shell.autocall < 2) and not force_auto:
837 if not the_rest and (self.shell.autocall < 2) and not force_auto:
831 newcmd = '%s %s' % (ifun,the_rest)
838 newcmd = '%s %s' % (ifun,the_rest)
832 auto_rewrite = False
839 auto_rewrite = False
833 else:
840 else:
834 if not force_auto and the_rest.startswith('['):
841 if not force_auto and the_rest.startswith('['):
835 if hasattr(obj,'__getitem__'):
842 if hasattr(obj,'__getitem__'):
836 # Don't autocall in this case: item access for an object
843 # Don't autocall in this case: item access for an object
837 # which is BOTH callable and implements __getitem__.
844 # which is BOTH callable and implements __getitem__.
838 newcmd = '%s %s' % (ifun,the_rest)
845 newcmd = '%s %s' % (ifun,the_rest)
839 auto_rewrite = False
846 auto_rewrite = False
840 else:
847 else:
841 # if the object doesn't support [] access, go ahead and
848 # if the object doesn't support [] access, go ahead and
842 # autocall
849 # autocall
843 newcmd = '%s(%s)' % (ifun.rstrip(),the_rest)
850 newcmd = '%s(%s)' % (ifun.rstrip(),the_rest)
844 elif the_rest.endswith(';'):
851 elif the_rest.endswith(';'):
845 newcmd = '%s(%s);' % (ifun.rstrip(),the_rest[:-1])
852 newcmd = '%s(%s);' % (ifun.rstrip(),the_rest[:-1])
846 else:
853 else:
847 newcmd = '%s(%s)' % (ifun.rstrip(), the_rest)
854 newcmd = '%s(%s)' % (ifun.rstrip(), the_rest)
848
855
849 if auto_rewrite:
856 if auto_rewrite:
850 self.shell.auto_rewrite_input(newcmd)
857 self.shell.auto_rewrite_input(newcmd)
851
858
852 return newcmd
859 return newcmd
853
860
854
861
855 class HelpHandler(PrefilterHandler):
862 class HelpHandler(PrefilterHandler):
856
863
857 handler_name = Unicode('help')
864 handler_name = Unicode('help')
858 esc_strings = List([ESC_HELP])
865 esc_strings = List([ESC_HELP])
859
866
860 def handle(self, line_info):
867 def handle(self, line_info):
861 """Try to get some help for the object.
868 """Try to get some help for the object.
862
869
863 obj? or ?obj -> basic information.
870 obj? or ?obj -> basic information.
864 obj?? or ??obj -> more details.
871 obj?? or ??obj -> more details.
865 """
872 """
866 normal_handler = self.prefilter_manager.get_handler_by_name('normal')
873 normal_handler = self.prefilter_manager.get_handler_by_name('normal')
867 line = line_info.line
874 line = line_info.line
868 # We need to make sure that we don't process lines which would be
875 # We need to make sure that we don't process lines which would be
869 # otherwise valid python, such as "x=1 # what?"
876 # otherwise valid python, such as "x=1 # what?"
870 try:
877 try:
871 codeop.compile_command(line)
878 codeop.compile_command(line)
872 except SyntaxError:
879 except SyntaxError:
873 # We should only handle as help stuff which is NOT valid syntax
880 # We should only handle as help stuff which is NOT valid syntax
874 if line[0]==ESC_HELP:
881 if line[0]==ESC_HELP:
875 line = line[1:]
882 line = line[1:]
876 elif line[-1]==ESC_HELP:
883 elif line[-1]==ESC_HELP:
877 line = line[:-1]
884 line = line[:-1]
878 if line:
885 if line:
879 #print 'line:<%r>' % line # dbg
886 #print 'line:<%r>' % line # dbg
880 self.shell.magic_pinfo(line_info.ifun)
887 self.shell.magic_pinfo(line_info.ifun)
881 else:
888 else:
882 self.shell.show_usage()
889 self.shell.show_usage()
883 return '' # Empty string is needed here!
890 return '' # Empty string is needed here!
884 except:
891 except:
885 raise
892 raise
886 # Pass any other exceptions through to the normal handler
893 # Pass any other exceptions through to the normal handler
887 return normal_handler.handle(line_info)
894 return normal_handler.handle(line_info)
888 else:
895 else:
889 # If the code compiles ok, we should handle it normally
896 # If the code compiles ok, we should handle it normally
890 return normal_handler.handle(line_info)
897 return normal_handler.handle(line_info)
891
898
892
899
893 class EmacsHandler(PrefilterHandler):
900 class EmacsHandler(PrefilterHandler):
894
901
895 handler_name = Unicode('emacs')
902 handler_name = Unicode('emacs')
896 esc_strings = List([])
903 esc_strings = List([])
897
904
898 def handle(self, line_info):
905 def handle(self, line_info):
899 """Handle input lines marked by python-mode."""
906 """Handle input lines marked by python-mode."""
900
907
901 # Currently, nothing is done. Later more functionality can be added
908 # Currently, nothing is done. Later more functionality can be added
902 # here if needed.
909 # here if needed.
903
910
904 # The input cache shouldn't be updated
911 # The input cache shouldn't be updated
905 return line_info.line
912 return line_info.line
906
913
907
914
908 #-----------------------------------------------------------------------------
915 #-----------------------------------------------------------------------------
909 # Defaults
916 # Defaults
910 #-----------------------------------------------------------------------------
917 #-----------------------------------------------------------------------------
911
918
912
919
913 _default_transformers = [
920 _default_transformers = [
914 AssignSystemTransformer,
921 AssignSystemTransformer,
915 AssignMagicTransformer,
922 AssignMagicTransformer,
916 PyPromptTransformer,
923 PyPromptTransformer,
917 IPyPromptTransformer,
924 IPyPromptTransformer,
918 ]
925 ]
919
926
920 _default_checkers = [
927 _default_checkers = [
921 EmacsChecker,
928 EmacsChecker,
922 ShellEscapeChecker,
929 ShellEscapeChecker,
923 MacroChecker,
930 MacroChecker,
924 IPyAutocallChecker,
931 IPyAutocallChecker,
925 MultiLineMagicChecker,
932 MultiLineMagicChecker,
926 EscCharsChecker,
933 EscCharsChecker,
927 AssignmentChecker,
934 AssignmentChecker,
928 AutoMagicChecker,
935 AutoMagicChecker,
929 AliasChecker,
936 AliasChecker,
930 PythonOpsChecker,
937 PythonOpsChecker,
931 AutocallChecker
938 AutocallChecker
932 ]
939 ]
933
940
934 _default_handlers = [
941 _default_handlers = [
935 PrefilterHandler,
942 PrefilterHandler,
936 AliasHandler,
943 AliasHandler,
937 ShellEscapeHandler,
944 ShellEscapeHandler,
938 MacroHandler,
945 MacroHandler,
939 MagicHandler,
946 MagicHandler,
940 AutoHandler,
947 AutoHandler,
941 HelpHandler,
948 HelpHandler,
942 EmacsHandler
949 EmacsHandler
943 ]
950 ]
@@ -1,68 +1,94 b''
1 """Tests for input manipulation machinery."""
1 """Tests for input manipulation machinery."""
2
2
3 #-----------------------------------------------------------------------------
3 #-----------------------------------------------------------------------------
4 # Imports
4 # Imports
5 #-----------------------------------------------------------------------------
5 #-----------------------------------------------------------------------------
6 import nose.tools as nt
6 import nose.tools as nt
7
7
8 from IPython.testing import tools as tt, decorators as dec
8 from IPython.testing import tools as tt, decorators as dec
9 from IPython.testing.globalipapp import get_ipython
9 from IPython.testing.globalipapp import get_ipython
10
10
11 #-----------------------------------------------------------------------------
11 #-----------------------------------------------------------------------------
12 # Tests
12 # Tests
13 #-----------------------------------------------------------------------------
13 #-----------------------------------------------------------------------------
14 ip = get_ipython()
14 ip = get_ipython()
15
15
16 @dec.parametric
16 @dec.parametric
17 def test_prefilter():
17 def test_prefilter():
18 """Test user input conversions"""
18 """Test user input conversions"""
19
19
20 # pairs of (raw, expected correct) input
20 # pairs of (raw, expected correct) input
21 pairs = [ ('2+2','2+2'),
21 pairs = [ ('2+2','2+2'),
22 ('>>> 2+2','2+2'),
22 ('>>> 2+2','2+2'),
23 ('>>> # This is a comment\n'
23 ('>>> # This is a comment\n'
24 '... 2+2',
24 '... 2+2',
25 '# This is a comment\n'
25 '# This is a comment\n'
26 '2+2'),
26 '2+2'),
27 # Some IPython input
27 # Some IPython input
28 ('In [1]: 1', '1'),
28 ('In [1]: 1', '1'),
29 ('In [2]: for i in range(5):\n'
29 ('In [2]: for i in range(5):\n'
30 ' ...: print i,',
30 ' ...: print i,',
31 'for i in range(5):\n'
31 'for i in range(5):\n'
32 ' print i,'),
32 ' print i,'),
33 ]
33 ]
34
34
35 for raw, correct in pairs:
35 for raw, correct in pairs:
36 yield nt.assert_equals(ip.prefilter(raw), correct)
36 yield nt.assert_equals(ip.prefilter(raw), correct)
37
37
38
38 @dec.parametric
39 @dec.parametric
39 def test_autocall_binops():
40 def test_autocall_binops():
40 """See https://github.com/ipython/ipython/issues/81"""
41 """See https://github.com/ipython/ipython/issues/81"""
41 ip.magic('autocall 2')
42 ip.magic('autocall 2')
42 f = lambda x: x
43 f = lambda x: x
43 ip.user_ns['f'] = f
44 ip.user_ns['f'] = f
44 try:
45 try:
45 yield nt.assert_equals(ip.prefilter('f 1'),'f(1)')
46 yield nt.assert_equals(ip.prefilter('f 1'),'f(1)')
46 for t in ['f +1', 'f -1']:
47 for t in ['f +1', 'f -1']:
47 yield nt.assert_equals(ip.prefilter(t), t)
48 yield nt.assert_equals(ip.prefilter(t), t)
48 finally:
49 finally:
49 ip.magic('autocall 0')
50 ip.magic('autocall 0')
50 del ip.user_ns['f']
51 del ip.user_ns['f']
51
52
53
52 @dec.parametric
54 @dec.parametric
53 def test_issue114():
55 def test_issue_114():
54 """Check that multiline string literals don't expand as magic
56 """Check that multiline string literals don't expand as magic
55 see http://github.com/ipython/ipython/issues/#issue/114"""
57 see http://github.com/ipython/ipython/issues/114"""
56
58
57 template = '"""\n%s\n"""'
59 template = '"""\n%s\n"""'
58 # Store the current value of multi_line_specials and turn it off before
60 # Store the current value of multi_line_specials and turn it off before
59 # running test, since it could be true (case in which the test doesn't make
61 # running test, since it could be true (case in which the test doesn't make
60 # sense, as multiline string literals *will* expand as magic in that case).
62 # sense, as multiline string literals *will* expand as magic in that case).
61 msp = ip.prefilter_manager.multi_line_specials
63 msp = ip.prefilter_manager.multi_line_specials
62 ip.prefilter_manager.multi_line_specials = False
64 ip.prefilter_manager.multi_line_specials = False
63 try:
65 try:
64 for mgk in ip.lsmagic():
66 for mgk in ip.lsmagic():
65 raw = template % mgk
67 raw = template % mgk
66 yield nt.assert_equals(ip.prefilter(raw), raw)
68 yield nt.assert_equals(ip.prefilter(raw), raw)
67 finally:
69 finally:
68 ip.prefilter_manager.multi_line_specials = msp
70 ip.prefilter_manager.multi_line_specials = msp
71
72
73 def test_prefilter_attribute_errors():
74 """Capture exceptions thrown by user objects on attribute access.
75
76 See http://github.com/ipython/ipython/issues/988."""
77
78 class X(object):
79 def __getattr__(self, k):
80 raise ValueError('broken object')
81 def __call__(self, x):
82 return x
83
84 # Create a callable broken object
85 ip.user_ns['x'] = X()
86 ip.magic('autocall 2')
87 try:
88 # Even if x throws an attribute error when looking at its rewrite
89 # attribute, we should not crash. So the test here is simply making
90 # the prefilter call and not having an exception.
91 ip.prefilter('x 1')
92 finally:
93 del ip.user_ns['x']
94 ip.magic('autocall 0')
General Comments 0
You need to be logged in to leave comments. Login now