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