##// END OF EJS Templates
Fix comment typo in prefilter.py
Jonathan Frederic -
Show More
@@ -1,715 +1,715 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 from keyword import iskeyword
27 from keyword import iskeyword
28 import re
28 import re
29
29
30 from IPython.core.autocall import IPyAutocall
30 from IPython.core.autocall import IPyAutocall
31 from IPython.config.configurable import Configurable
31 from IPython.config.configurable import Configurable
32 from IPython.core.inputsplitter import (
32 from IPython.core.inputsplitter import (
33 ESC_MAGIC,
33 ESC_MAGIC,
34 ESC_QUOTE,
34 ESC_QUOTE,
35 ESC_QUOTE2,
35 ESC_QUOTE2,
36 ESC_PAREN,
36 ESC_PAREN,
37 )
37 )
38 from IPython.core.macro import Macro
38 from IPython.core.macro import Macro
39 from IPython.core.splitinput import LineInfo
39 from IPython.core.splitinput import LineInfo
40
40
41 from IPython.utils.traitlets import (
41 from IPython.utils.traitlets import (
42 List, Integer, Unicode, CBool, Bool, Instance, CRegExp
42 List, Integer, Unicode, CBool, Bool, Instance, CRegExp
43 )
43 )
44
44
45 #-----------------------------------------------------------------------------
45 #-----------------------------------------------------------------------------
46 # Global utilities, errors and constants
46 # Global utilities, errors and constants
47 #-----------------------------------------------------------------------------
47 #-----------------------------------------------------------------------------
48
48
49
49
50 class PrefilterError(Exception):
50 class PrefilterError(Exception):
51 pass
51 pass
52
52
53
53
54 # RegExp to identify potential function names
54 # RegExp to identify potential function names
55 re_fun_name = re.compile(r'[a-zA-Z_]([a-zA-Z0-9_.]*) *$')
55 re_fun_name = re.compile(r'[a-zA-Z_]([a-zA-Z0-9_.]*) *$')
56
56
57 # RegExp to exclude strings with this start from autocalling. In
57 # RegExp to exclude strings with this start from autocalling. In
58 # particular, all binary operators should be excluded, so that if foo is
58 # particular, all binary operators should be excluded, so that if foo is
59 # callable, foo OP bar doesn't become foo(OP bar), which is invalid. The
59 # callable, foo OP bar doesn't become foo(OP bar), which is invalid. The
60 # characters '!=()' don't need to be checked for, as the checkPythonChars
60 # characters '!=()' don't need to be checked for, as the checkPythonChars
61 # routine explicitely does so, to catch direct calls and rebindings of
61 # routine explicitely does so, to catch direct calls and rebindings of
62 # existing names.
62 # existing names.
63
63
64 # Warning: the '-' HAS TO BE AT THE END of the first group, otherwise
64 # Warning: the '-' HAS TO BE AT THE END of the first group, otherwise
65 # it affects the rest of the group in square brackets.
65 # it affects the rest of the group in square brackets.
66 re_exclude_auto = re.compile(r'^[,&^\|\*/\+-]'
66 re_exclude_auto = re.compile(r'^[,&^\|\*/\+-]'
67 r'|^is |^not |^in |^and |^or ')
67 r'|^is |^not |^in |^and |^or ')
68
68
69 # try to catch also methods for stuff in lists/tuples/dicts: off
69 # try to catch also methods for stuff in lists/tuples/dicts: off
70 # (experimental). For this to work, the line_split regexp would need
70 # (experimental). For this to work, the line_split regexp would need
71 # to be modified so it wouldn't break things at '['. That line is
71 # to be modified so it wouldn't break things at '['. That line is
72 # nasty enough that I shouldn't change it until I can test it _well_.
72 # nasty enough that I shouldn't change it until I can test it _well_.
73 #self.re_fun_name = re.compile (r'[a-zA-Z_]([a-zA-Z0-9_.\[\]]*) ?$')
73 #self.re_fun_name = re.compile (r'[a-zA-Z_]([a-zA-Z0-9_.\[\]]*) ?$')
74
74
75
75
76 # Handler Check Utilities
76 # Handler Check Utilities
77 def is_shadowed(identifier, ip):
77 def is_shadowed(identifier, ip):
78 """Is the given identifier defined in one of the namespaces which shadow
78 """Is the given identifier defined in one of the namespaces which shadow
79 the alias and magic namespaces? Note that an identifier is different
79 the alias and magic namespaces? Note that an identifier is different
80 than ifun, because it can not contain a '.' character."""
80 than ifun, because it can not contain a '.' character."""
81 # This is much safer than calling ofind, which can change state
81 # This is much safer than calling ofind, which can change state
82 return (identifier in ip.user_ns \
82 return (identifier in ip.user_ns \
83 or identifier in ip.user_global_ns \
83 or identifier in ip.user_global_ns \
84 or identifier in ip.ns_table['builtin']\
84 or identifier in ip.ns_table['builtin']\
85 or iskeyword(identifier))
85 or iskeyword(identifier))
86
86
87
87
88 #-----------------------------------------------------------------------------
88 #-----------------------------------------------------------------------------
89 # Main Prefilter manager
89 # Main Prefilter manager
90 #-----------------------------------------------------------------------------
90 #-----------------------------------------------------------------------------
91
91
92
92
93 class PrefilterManager(Configurable):
93 class PrefilterManager(Configurable):
94 """Main prefilter component.
94 """Main prefilter component.
95
95
96 The IPython prefilter is run on all user input before it is run. The
96 The IPython prefilter is run on all user input before it is run. The
97 prefilter consumes lines of input and produces transformed lines of
97 prefilter consumes lines of input and produces transformed lines of
98 input.
98 input.
99
99
100 The iplementation consists of two phases:
100 The iplementation consists of two phases:
101
101
102 1. Transformers
102 1. Transformers
103 2. Checkers and handlers
103 2. Checkers and handlers
104
104
105 Over time, we plan on deprecating the checkers and handlers and doing
105 Over time, we plan on deprecating the checkers and handlers and doing
106 everything in the transformers.
106 everything in the transformers.
107
107
108 The transformers are instances of :class:`PrefilterTransformer` and have
108 The transformers are instances of :class:`PrefilterTransformer` and have
109 a single method :meth:`transform` that takes a line and returns a
109 a single method :meth:`transform` that takes a line and returns a
110 transformed line. The transformation can be accomplished using any
110 transformed line. The transformation can be accomplished using any
111 tool, but our current ones use regular expressions for speed.
111 tool, but our current ones use regular expressions for speed.
112
112
113 After all the transformers have been run, the line is fed to the checkers,
113 After all the transformers have been run, the line is fed to the checkers,
114 which are instances of :class:`PrefilterChecker`. The line is passed to
114 which are instances of :class:`PrefilterChecker`. The line is passed to
115 the :meth:`check` method, which either returns `None` or a
115 the :meth:`check` method, which either returns `None` or a
116 :class:`PrefilterHandler` instance. If `None` is returned, the other
116 :class:`PrefilterHandler` instance. If `None` is returned, the other
117 checkers are tried. If an :class:`PrefilterHandler` instance is returned,
117 checkers are tried. If an :class:`PrefilterHandler` instance is returned,
118 the line is passed to the :meth:`handle` method of the returned
118 the line is passed to the :meth:`handle` method of the returned
119 handler and no further checkers are tried.
119 handler and no further checkers are tried.
120
120
121 Both transformers and checkers have a `priority` attribute, that determines
121 Both transformers and checkers have a `priority` attribute, that determines
122 the order in which they are called. Smaller priorities are tried first.
122 the order in which they are called. Smaller priorities are tried first.
123
123
124 Both transformers and checkers also have `enabled` attribute, which is
124 Both transformers and checkers also have `enabled` attribute, which is
125 a boolean that determines if the instance is used.
125 a boolean that determines if the instance is used.
126
126
127 Users or developers can change the priority or enabled attribute of
127 Users or developers can change the priority or enabled attribute of
128 transformers or checkers, but they must call the :meth:`sort_checkers`
128 transformers or checkers, but they must call the :meth:`sort_checkers`
129 or :meth:`sort_transformers` method after changing the priority.
129 or :meth:`sort_transformers` method after changing the priority.
130 """
130 """
131
131
132 multi_line_specials = CBool(True, config=True)
132 multi_line_specials = CBool(True, config=True)
133 shell = Instance('IPython.core.interactiveshell.InteractiveShellABC')
133 shell = Instance('IPython.core.interactiveshell.InteractiveShellABC')
134
134
135 def __init__(self, shell=None, **kwargs):
135 def __init__(self, shell=None, **kwargs):
136 super(PrefilterManager, self).__init__(shell=shell, **kwargs)
136 super(PrefilterManager, self).__init__(shell=shell, **kwargs)
137 self.shell = shell
137 self.shell = shell
138 self.init_transformers()
138 self.init_transformers()
139 self.init_handlers()
139 self.init_handlers()
140 self.init_checkers()
140 self.init_checkers()
141
141
142 #-------------------------------------------------------------------------
142 #-------------------------------------------------------------------------
143 # API for managing transformers
143 # API for managing transformers
144 #-------------------------------------------------------------------------
144 #-------------------------------------------------------------------------
145
145
146 def init_transformers(self):
146 def init_transformers(self):
147 """Create the default transformers."""
147 """Create the default transformers."""
148 self._transformers = []
148 self._transformers = []
149 for transformer_cls in _default_transformers:
149 for transformer_cls in _default_transformers:
150 transformer_cls(
150 transformer_cls(
151 shell=self.shell, prefilter_manager=self, parent=self
151 shell=self.shell, prefilter_manager=self, parent=self
152 )
152 )
153
153
154 def sort_transformers(self):
154 def sort_transformers(self):
155 """Sort the transformers by priority.
155 """Sort the transformers by priority.
156
156
157 This must be called after the priority of a transformer is changed.
157 This must be called after the priority of a transformer is changed.
158 The :meth:`register_transformer` method calls this automatically.
158 The :meth:`register_transformer` method calls this automatically.
159 """
159 """
160 self._transformers.sort(key=lambda x: x.priority)
160 self._transformers.sort(key=lambda x: x.priority)
161
161
162 @property
162 @property
163 def transformers(self):
163 def transformers(self):
164 """Return a list of checkers, sorted by priority."""
164 """Return a list of checkers, sorted by priority."""
165 return self._transformers
165 return self._transformers
166
166
167 def register_transformer(self, transformer):
167 def register_transformer(self, transformer):
168 """Register a transformer instance."""
168 """Register a transformer instance."""
169 if transformer not in self._transformers:
169 if transformer not in self._transformers:
170 self._transformers.append(transformer)
170 self._transformers.append(transformer)
171 self.sort_transformers()
171 self.sort_transformers()
172
172
173 def unregister_transformer(self, transformer):
173 def unregister_transformer(self, transformer):
174 """Unregister a transformer instance."""
174 """Unregister a transformer instance."""
175 if transformer in self._transformers:
175 if transformer in self._transformers:
176 self._transformers.remove(transformer)
176 self._transformers.remove(transformer)
177
177
178 #-------------------------------------------------------------------------
178 #-------------------------------------------------------------------------
179 # API for managing checkers
179 # API for managing checkers
180 #-------------------------------------------------------------------------
180 #-------------------------------------------------------------------------
181
181
182 def init_checkers(self):
182 def init_checkers(self):
183 """Create the default checkers."""
183 """Create the default checkers."""
184 self._checkers = []
184 self._checkers = []
185 for checker in _default_checkers:
185 for checker in _default_checkers:
186 checker(
186 checker(
187 shell=self.shell, prefilter_manager=self, parent=self
187 shell=self.shell, prefilter_manager=self, parent=self
188 )
188 )
189
189
190 def sort_checkers(self):
190 def sort_checkers(self):
191 """Sort the checkers by priority.
191 """Sort the checkers by priority.
192
192
193 This must be called after the priority of a checker is changed.
193 This must be called after the priority of a checker is changed.
194 The :meth:`register_checker` method calls this automatically.
194 The :meth:`register_checker` method calls this automatically.
195 """
195 """
196 self._checkers.sort(key=lambda x: x.priority)
196 self._checkers.sort(key=lambda x: x.priority)
197
197
198 @property
198 @property
199 def checkers(self):
199 def checkers(self):
200 """Return a list of checkers, sorted by priority."""
200 """Return a list of checkers, sorted by priority."""
201 return self._checkers
201 return self._checkers
202
202
203 def register_checker(self, checker):
203 def register_checker(self, checker):
204 """Register a checker instance."""
204 """Register a checker instance."""
205 if checker not in self._checkers:
205 if checker not in self._checkers:
206 self._checkers.append(checker)
206 self._checkers.append(checker)
207 self.sort_checkers()
207 self.sort_checkers()
208
208
209 def unregister_checker(self, checker):
209 def unregister_checker(self, checker):
210 """Unregister a checker instance."""
210 """Unregister a checker instance."""
211 if checker in self._checkers:
211 if checker in self._checkers:
212 self._checkers.remove(checker)
212 self._checkers.remove(checker)
213
213
214 #-------------------------------------------------------------------------
214 #-------------------------------------------------------------------------
215 # API for managing checkers
215 # API for managing handlers
216 #-------------------------------------------------------------------------
216 #-------------------------------------------------------------------------
217
217
218 def init_handlers(self):
218 def init_handlers(self):
219 """Create the default handlers."""
219 """Create the default handlers."""
220 self._handlers = {}
220 self._handlers = {}
221 self._esc_handlers = {}
221 self._esc_handlers = {}
222 for handler in _default_handlers:
222 for handler in _default_handlers:
223 handler(
223 handler(
224 shell=self.shell, prefilter_manager=self, parent=self
224 shell=self.shell, prefilter_manager=self, parent=self
225 )
225 )
226
226
227 @property
227 @property
228 def handlers(self):
228 def handlers(self):
229 """Return a dict of all the handlers."""
229 """Return a dict of all the handlers."""
230 return self._handlers
230 return self._handlers
231
231
232 def register_handler(self, name, handler, esc_strings):
232 def register_handler(self, name, handler, esc_strings):
233 """Register a handler instance by name with esc_strings."""
233 """Register a handler instance by name with esc_strings."""
234 self._handlers[name] = handler
234 self._handlers[name] = handler
235 for esc_str in esc_strings:
235 for esc_str in esc_strings:
236 self._esc_handlers[esc_str] = handler
236 self._esc_handlers[esc_str] = handler
237
237
238 def unregister_handler(self, name, handler, esc_strings):
238 def unregister_handler(self, name, handler, esc_strings):
239 """Unregister a handler instance by name with esc_strings."""
239 """Unregister a handler instance by name with esc_strings."""
240 try:
240 try:
241 del self._handlers[name]
241 del self._handlers[name]
242 except KeyError:
242 except KeyError:
243 pass
243 pass
244 for esc_str in esc_strings:
244 for esc_str in esc_strings:
245 h = self._esc_handlers.get(esc_str)
245 h = self._esc_handlers.get(esc_str)
246 if h is handler:
246 if h is handler:
247 del self._esc_handlers[esc_str]
247 del self._esc_handlers[esc_str]
248
248
249 def get_handler_by_name(self, name):
249 def get_handler_by_name(self, name):
250 """Get a handler by its name."""
250 """Get a handler by its name."""
251 return self._handlers.get(name)
251 return self._handlers.get(name)
252
252
253 def get_handler_by_esc(self, esc_str):
253 def get_handler_by_esc(self, esc_str):
254 """Get a handler by its escape string."""
254 """Get a handler by its escape string."""
255 return self._esc_handlers.get(esc_str)
255 return self._esc_handlers.get(esc_str)
256
256
257 #-------------------------------------------------------------------------
257 #-------------------------------------------------------------------------
258 # Main prefiltering API
258 # Main prefiltering API
259 #-------------------------------------------------------------------------
259 #-------------------------------------------------------------------------
260
260
261 def prefilter_line_info(self, line_info):
261 def prefilter_line_info(self, line_info):
262 """Prefilter a line that has been converted to a LineInfo object.
262 """Prefilter a line that has been converted to a LineInfo object.
263
263
264 This implements the checker/handler part of the prefilter pipe.
264 This implements the checker/handler part of the prefilter pipe.
265 """
265 """
266 # print "prefilter_line_info: ", line_info
266 # print "prefilter_line_info: ", line_info
267 handler = self.find_handler(line_info)
267 handler = self.find_handler(line_info)
268 return handler.handle(line_info)
268 return handler.handle(line_info)
269
269
270 def find_handler(self, line_info):
270 def find_handler(self, line_info):
271 """Find a handler for the line_info by trying checkers."""
271 """Find a handler for the line_info by trying checkers."""
272 for checker in self.checkers:
272 for checker in self.checkers:
273 if checker.enabled:
273 if checker.enabled:
274 handler = checker.check(line_info)
274 handler = checker.check(line_info)
275 if handler:
275 if handler:
276 return handler
276 return handler
277 return self.get_handler_by_name('normal')
277 return self.get_handler_by_name('normal')
278
278
279 def transform_line(self, line, continue_prompt):
279 def transform_line(self, line, continue_prompt):
280 """Calls the enabled transformers in order of increasing priority."""
280 """Calls the enabled transformers in order of increasing priority."""
281 for transformer in self.transformers:
281 for transformer in self.transformers:
282 if transformer.enabled:
282 if transformer.enabled:
283 line = transformer.transform(line, continue_prompt)
283 line = transformer.transform(line, continue_prompt)
284 return line
284 return line
285
285
286 def prefilter_line(self, line, continue_prompt=False):
286 def prefilter_line(self, line, continue_prompt=False):
287 """Prefilter a single input line as text.
287 """Prefilter a single input line as text.
288
288
289 This method prefilters a single line of text by calling the
289 This method prefilters a single line of text by calling the
290 transformers and then the checkers/handlers.
290 transformers and then the checkers/handlers.
291 """
291 """
292
292
293 # print "prefilter_line: ", line, continue_prompt
293 # print "prefilter_line: ", line, continue_prompt
294 # All handlers *must* return a value, even if it's blank ('').
294 # All handlers *must* return a value, even if it's blank ('').
295
295
296 # save the line away in case we crash, so the post-mortem handler can
296 # save the line away in case we crash, so the post-mortem handler can
297 # record it
297 # record it
298 self.shell._last_input_line = line
298 self.shell._last_input_line = line
299
299
300 if not line:
300 if not line:
301 # Return immediately on purely empty lines, so that if the user
301 # Return immediately on purely empty lines, so that if the user
302 # previously typed some whitespace that started a continuation
302 # previously typed some whitespace that started a continuation
303 # prompt, he can break out of that loop with just an empty line.
303 # prompt, he can break out of that loop with just an empty line.
304 # This is how the default python prompt works.
304 # This is how the default python prompt works.
305 return ''
305 return ''
306
306
307 # At this point, we invoke our transformers.
307 # At this point, we invoke our transformers.
308 if not continue_prompt or (continue_prompt and self.multi_line_specials):
308 if not continue_prompt or (continue_prompt and self.multi_line_specials):
309 line = self.transform_line(line, continue_prompt)
309 line = self.transform_line(line, continue_prompt)
310
310
311 # Now we compute line_info for the checkers and handlers
311 # Now we compute line_info for the checkers and handlers
312 line_info = LineInfo(line, continue_prompt)
312 line_info = LineInfo(line, continue_prompt)
313
313
314 # the input history needs to track even empty lines
314 # the input history needs to track even empty lines
315 stripped = line.strip()
315 stripped = line.strip()
316
316
317 normal_handler = self.get_handler_by_name('normal')
317 normal_handler = self.get_handler_by_name('normal')
318 if not stripped:
318 if not stripped:
319 return normal_handler.handle(line_info)
319 return normal_handler.handle(line_info)
320
320
321 # special handlers are only allowed for single line statements
321 # special handlers are only allowed for single line statements
322 if continue_prompt and not self.multi_line_specials:
322 if continue_prompt and not self.multi_line_specials:
323 return normal_handler.handle(line_info)
323 return normal_handler.handle(line_info)
324
324
325 prefiltered = self.prefilter_line_info(line_info)
325 prefiltered = self.prefilter_line_info(line_info)
326 # print "prefiltered line: %r" % prefiltered
326 # print "prefiltered line: %r" % prefiltered
327 return prefiltered
327 return prefiltered
328
328
329 def prefilter_lines(self, lines, continue_prompt=False):
329 def prefilter_lines(self, lines, continue_prompt=False):
330 """Prefilter multiple input lines of text.
330 """Prefilter multiple input lines of text.
331
331
332 This is the main entry point for prefiltering multiple lines of
332 This is the main entry point for prefiltering multiple lines of
333 input. This simply calls :meth:`prefilter_line` for each line of
333 input. This simply calls :meth:`prefilter_line` for each line of
334 input.
334 input.
335
335
336 This covers cases where there are multiple lines in the user entry,
336 This covers cases where there are multiple lines in the user entry,
337 which is the case when the user goes back to a multiline history
337 which is the case when the user goes back to a multiline history
338 entry and presses enter.
338 entry and presses enter.
339 """
339 """
340 llines = lines.rstrip('\n').split('\n')
340 llines = lines.rstrip('\n').split('\n')
341 # We can get multiple lines in one shot, where multiline input 'blends'
341 # We can get multiple lines in one shot, where multiline input 'blends'
342 # into one line, in cases like recalling from the readline history
342 # into one line, in cases like recalling from the readline history
343 # buffer. We need to make sure that in such cases, we correctly
343 # buffer. We need to make sure that in such cases, we correctly
344 # communicate downstream which line is first and which are continuation
344 # communicate downstream which line is first and which are continuation
345 # ones.
345 # ones.
346 if len(llines) > 1:
346 if len(llines) > 1:
347 out = '\n'.join([self.prefilter_line(line, lnum>0)
347 out = '\n'.join([self.prefilter_line(line, lnum>0)
348 for lnum, line in enumerate(llines) ])
348 for lnum, line in enumerate(llines) ])
349 else:
349 else:
350 out = self.prefilter_line(llines[0], continue_prompt)
350 out = self.prefilter_line(llines[0], continue_prompt)
351
351
352 return out
352 return out
353
353
354 #-----------------------------------------------------------------------------
354 #-----------------------------------------------------------------------------
355 # Prefilter transformers
355 # Prefilter transformers
356 #-----------------------------------------------------------------------------
356 #-----------------------------------------------------------------------------
357
357
358
358
359 class PrefilterTransformer(Configurable):
359 class PrefilterTransformer(Configurable):
360 """Transform a line of user input."""
360 """Transform a line of user input."""
361
361
362 priority = Integer(100, config=True)
362 priority = Integer(100, config=True)
363 # Transformers don't currently use shell or prefilter_manager, but as we
363 # Transformers don't currently use shell or prefilter_manager, but as we
364 # move away from checkers and handlers, they will need them.
364 # move away from checkers and handlers, they will need them.
365 shell = Instance('IPython.core.interactiveshell.InteractiveShellABC')
365 shell = Instance('IPython.core.interactiveshell.InteractiveShellABC')
366 prefilter_manager = Instance('IPython.core.prefilter.PrefilterManager')
366 prefilter_manager = Instance('IPython.core.prefilter.PrefilterManager')
367 enabled = Bool(True, config=True)
367 enabled = Bool(True, config=True)
368
368
369 def __init__(self, shell=None, prefilter_manager=None, **kwargs):
369 def __init__(self, shell=None, prefilter_manager=None, **kwargs):
370 super(PrefilterTransformer, self).__init__(
370 super(PrefilterTransformer, self).__init__(
371 shell=shell, prefilter_manager=prefilter_manager, **kwargs
371 shell=shell, prefilter_manager=prefilter_manager, **kwargs
372 )
372 )
373 self.prefilter_manager.register_transformer(self)
373 self.prefilter_manager.register_transformer(self)
374
374
375 def transform(self, line, continue_prompt):
375 def transform(self, line, continue_prompt):
376 """Transform a line, returning the new one."""
376 """Transform a line, returning the new one."""
377 return None
377 return None
378
378
379 def __repr__(self):
379 def __repr__(self):
380 return "<%s(priority=%r, enabled=%r)>" % (
380 return "<%s(priority=%r, enabled=%r)>" % (
381 self.__class__.__name__, self.priority, self.enabled)
381 self.__class__.__name__, self.priority, self.enabled)
382
382
383
383
384 #-----------------------------------------------------------------------------
384 #-----------------------------------------------------------------------------
385 # Prefilter checkers
385 # Prefilter checkers
386 #-----------------------------------------------------------------------------
386 #-----------------------------------------------------------------------------
387
387
388
388
389 class PrefilterChecker(Configurable):
389 class PrefilterChecker(Configurable):
390 """Inspect an input line and return a handler for that line."""
390 """Inspect an input line and return a handler for that line."""
391
391
392 priority = Integer(100, config=True)
392 priority = Integer(100, config=True)
393 shell = Instance('IPython.core.interactiveshell.InteractiveShellABC')
393 shell = Instance('IPython.core.interactiveshell.InteractiveShellABC')
394 prefilter_manager = Instance('IPython.core.prefilter.PrefilterManager')
394 prefilter_manager = Instance('IPython.core.prefilter.PrefilterManager')
395 enabled = Bool(True, config=True)
395 enabled = Bool(True, config=True)
396
396
397 def __init__(self, shell=None, prefilter_manager=None, **kwargs):
397 def __init__(self, shell=None, prefilter_manager=None, **kwargs):
398 super(PrefilterChecker, self).__init__(
398 super(PrefilterChecker, self).__init__(
399 shell=shell, prefilter_manager=prefilter_manager, **kwargs
399 shell=shell, prefilter_manager=prefilter_manager, **kwargs
400 )
400 )
401 self.prefilter_manager.register_checker(self)
401 self.prefilter_manager.register_checker(self)
402
402
403 def check(self, line_info):
403 def check(self, line_info):
404 """Inspect line_info and return a handler instance or None."""
404 """Inspect line_info and return a handler instance or None."""
405 return None
405 return None
406
406
407 def __repr__(self):
407 def __repr__(self):
408 return "<%s(priority=%r, enabled=%r)>" % (
408 return "<%s(priority=%r, enabled=%r)>" % (
409 self.__class__.__name__, self.priority, self.enabled)
409 self.__class__.__name__, self.priority, self.enabled)
410
410
411
411
412 class EmacsChecker(PrefilterChecker):
412 class EmacsChecker(PrefilterChecker):
413
413
414 priority = Integer(100, config=True)
414 priority = Integer(100, config=True)
415 enabled = Bool(False, config=True)
415 enabled = Bool(False, config=True)
416
416
417 def check(self, line_info):
417 def check(self, line_info):
418 "Emacs ipython-mode tags certain input lines."
418 "Emacs ipython-mode tags certain input lines."
419 if line_info.line.endswith('# PYTHON-MODE'):
419 if line_info.line.endswith('# PYTHON-MODE'):
420 return self.prefilter_manager.get_handler_by_name('emacs')
420 return self.prefilter_manager.get_handler_by_name('emacs')
421 else:
421 else:
422 return None
422 return None
423
423
424
424
425 class MacroChecker(PrefilterChecker):
425 class MacroChecker(PrefilterChecker):
426
426
427 priority = Integer(250, config=True)
427 priority = Integer(250, config=True)
428
428
429 def check(self, line_info):
429 def check(self, line_info):
430 obj = self.shell.user_ns.get(line_info.ifun)
430 obj = self.shell.user_ns.get(line_info.ifun)
431 if isinstance(obj, Macro):
431 if isinstance(obj, Macro):
432 return self.prefilter_manager.get_handler_by_name('macro')
432 return self.prefilter_manager.get_handler_by_name('macro')
433 else:
433 else:
434 return None
434 return None
435
435
436
436
437 class IPyAutocallChecker(PrefilterChecker):
437 class IPyAutocallChecker(PrefilterChecker):
438
438
439 priority = Integer(300, config=True)
439 priority = Integer(300, config=True)
440
440
441 def check(self, line_info):
441 def check(self, line_info):
442 "Instances of IPyAutocall in user_ns get autocalled immediately"
442 "Instances of IPyAutocall in user_ns get autocalled immediately"
443 obj = self.shell.user_ns.get(line_info.ifun, None)
443 obj = self.shell.user_ns.get(line_info.ifun, None)
444 if isinstance(obj, IPyAutocall):
444 if isinstance(obj, IPyAutocall):
445 obj.set_ip(self.shell)
445 obj.set_ip(self.shell)
446 return self.prefilter_manager.get_handler_by_name('auto')
446 return self.prefilter_manager.get_handler_by_name('auto')
447 else:
447 else:
448 return None
448 return None
449
449
450
450
451 class AssignmentChecker(PrefilterChecker):
451 class AssignmentChecker(PrefilterChecker):
452
452
453 priority = Integer(600, config=True)
453 priority = Integer(600, config=True)
454
454
455 def check(self, line_info):
455 def check(self, line_info):
456 """Check to see if user is assigning to a var for the first time, in
456 """Check to see if user is assigning to a var for the first time, in
457 which case we want to avoid any sort of automagic / autocall games.
457 which case we want to avoid any sort of automagic / autocall games.
458
458
459 This allows users to assign to either alias or magic names true python
459 This allows users to assign to either alias or magic names true python
460 variables (the magic/alias systems always take second seat to true
460 variables (the magic/alias systems always take second seat to true
461 python code). E.g. ls='hi', or ls,that=1,2"""
461 python code). E.g. ls='hi', or ls,that=1,2"""
462 if line_info.the_rest:
462 if line_info.the_rest:
463 if line_info.the_rest[0] in '=,':
463 if line_info.the_rest[0] in '=,':
464 return self.prefilter_manager.get_handler_by_name('normal')
464 return self.prefilter_manager.get_handler_by_name('normal')
465 else:
465 else:
466 return None
466 return None
467
467
468
468
469 class AutoMagicChecker(PrefilterChecker):
469 class AutoMagicChecker(PrefilterChecker):
470
470
471 priority = Integer(700, config=True)
471 priority = Integer(700, config=True)
472
472
473 def check(self, line_info):
473 def check(self, line_info):
474 """If the ifun is magic, and automagic is on, run it. Note: normal,
474 """If the ifun is magic, and automagic is on, run it. Note: normal,
475 non-auto magic would already have been triggered via '%' in
475 non-auto magic would already have been triggered via '%' in
476 check_esc_chars. This just checks for automagic. Also, before
476 check_esc_chars. This just checks for automagic. Also, before
477 triggering the magic handler, make sure that there is nothing in the
477 triggering the magic handler, make sure that there is nothing in the
478 user namespace which could shadow it."""
478 user namespace which could shadow it."""
479 if not self.shell.automagic or not self.shell.find_magic(line_info.ifun):
479 if not self.shell.automagic or not self.shell.find_magic(line_info.ifun):
480 return None
480 return None
481
481
482 # We have a likely magic method. Make sure we should actually call it.
482 # We have a likely magic method. Make sure we should actually call it.
483 if line_info.continue_prompt and not self.prefilter_manager.multi_line_specials:
483 if line_info.continue_prompt and not self.prefilter_manager.multi_line_specials:
484 return None
484 return None
485
485
486 head = line_info.ifun.split('.',1)[0]
486 head = line_info.ifun.split('.',1)[0]
487 if is_shadowed(head, self.shell):
487 if is_shadowed(head, self.shell):
488 return None
488 return None
489
489
490 return self.prefilter_manager.get_handler_by_name('magic')
490 return self.prefilter_manager.get_handler_by_name('magic')
491
491
492
492
493 class PythonOpsChecker(PrefilterChecker):
493 class PythonOpsChecker(PrefilterChecker):
494
494
495 priority = Integer(900, config=True)
495 priority = Integer(900, config=True)
496
496
497 def check(self, line_info):
497 def check(self, line_info):
498 """If the 'rest' of the line begins with a function call or pretty much
498 """If the 'rest' of the line begins with a function call or pretty much
499 any python operator, we should simply execute the line (regardless of
499 any python operator, we should simply execute the line (regardless of
500 whether or not there's a possible autocall expansion). This avoids
500 whether or not there's a possible autocall expansion). This avoids
501 spurious (and very confusing) geattr() accesses."""
501 spurious (and very confusing) geattr() accesses."""
502 if line_info.the_rest and line_info.the_rest[0] in '!=()<>,+*/%^&|':
502 if line_info.the_rest and line_info.the_rest[0] in '!=()<>,+*/%^&|':
503 return self.prefilter_manager.get_handler_by_name('normal')
503 return self.prefilter_manager.get_handler_by_name('normal')
504 else:
504 else:
505 return None
505 return None
506
506
507
507
508 class AutocallChecker(PrefilterChecker):
508 class AutocallChecker(PrefilterChecker):
509
509
510 priority = Integer(1000, config=True)
510 priority = Integer(1000, config=True)
511
511
512 function_name_regexp = CRegExp(re_fun_name, config=True,
512 function_name_regexp = CRegExp(re_fun_name, config=True,
513 help="RegExp to identify potential function names.")
513 help="RegExp to identify potential function names.")
514 exclude_regexp = CRegExp(re_exclude_auto, config=True,
514 exclude_regexp = CRegExp(re_exclude_auto, config=True,
515 help="RegExp to exclude strings with this start from autocalling.")
515 help="RegExp to exclude strings with this start from autocalling.")
516
516
517 def check(self, line_info):
517 def check(self, line_info):
518 "Check if the initial word/function is callable and autocall is on."
518 "Check if the initial word/function is callable and autocall is on."
519 if not self.shell.autocall:
519 if not self.shell.autocall:
520 return None
520 return None
521
521
522 oinfo = line_info.ofind(self.shell) # This can mutate state via getattr
522 oinfo = line_info.ofind(self.shell) # This can mutate state via getattr
523 if not oinfo['found']:
523 if not oinfo['found']:
524 return None
524 return None
525
525
526 if callable(oinfo['obj']) \
526 if callable(oinfo['obj']) \
527 and (not self.exclude_regexp.match(line_info.the_rest)) \
527 and (not self.exclude_regexp.match(line_info.the_rest)) \
528 and self.function_name_regexp.match(line_info.ifun):
528 and self.function_name_regexp.match(line_info.ifun):
529 return self.prefilter_manager.get_handler_by_name('auto')
529 return self.prefilter_manager.get_handler_by_name('auto')
530 else:
530 else:
531 return None
531 return None
532
532
533
533
534 #-----------------------------------------------------------------------------
534 #-----------------------------------------------------------------------------
535 # Prefilter handlers
535 # Prefilter handlers
536 #-----------------------------------------------------------------------------
536 #-----------------------------------------------------------------------------
537
537
538
538
539 class PrefilterHandler(Configurable):
539 class PrefilterHandler(Configurable):
540
540
541 handler_name = Unicode('normal')
541 handler_name = Unicode('normal')
542 esc_strings = List([])
542 esc_strings = List([])
543 shell = Instance('IPython.core.interactiveshell.InteractiveShellABC')
543 shell = Instance('IPython.core.interactiveshell.InteractiveShellABC')
544 prefilter_manager = Instance('IPython.core.prefilter.PrefilterManager')
544 prefilter_manager = Instance('IPython.core.prefilter.PrefilterManager')
545
545
546 def __init__(self, shell=None, prefilter_manager=None, **kwargs):
546 def __init__(self, shell=None, prefilter_manager=None, **kwargs):
547 super(PrefilterHandler, self).__init__(
547 super(PrefilterHandler, self).__init__(
548 shell=shell, prefilter_manager=prefilter_manager, **kwargs
548 shell=shell, prefilter_manager=prefilter_manager, **kwargs
549 )
549 )
550 self.prefilter_manager.register_handler(
550 self.prefilter_manager.register_handler(
551 self.handler_name,
551 self.handler_name,
552 self,
552 self,
553 self.esc_strings
553 self.esc_strings
554 )
554 )
555
555
556 def handle(self, line_info):
556 def handle(self, line_info):
557 # print "normal: ", line_info
557 # print "normal: ", line_info
558 """Handle normal input lines. Use as a template for handlers."""
558 """Handle normal input lines. Use as a template for handlers."""
559
559
560 # With autoindent on, we need some way to exit the input loop, and I
560 # With autoindent on, we need some way to exit the input loop, and I
561 # don't want to force the user to have to backspace all the way to
561 # don't want to force the user to have to backspace all the way to
562 # clear the line. The rule will be in this case, that either two
562 # clear the line. The rule will be in this case, that either two
563 # lines of pure whitespace in a row, or a line of pure whitespace but
563 # lines of pure whitespace in a row, or a line of pure whitespace but
564 # of a size different to the indent level, will exit the input loop.
564 # of a size different to the indent level, will exit the input loop.
565 line = line_info.line
565 line = line_info.line
566 continue_prompt = line_info.continue_prompt
566 continue_prompt = line_info.continue_prompt
567
567
568 if (continue_prompt and
568 if (continue_prompt and
569 self.shell.autoindent and
569 self.shell.autoindent and
570 line.isspace() and
570 line.isspace() and
571 0 < abs(len(line) - self.shell.indent_current_nsp) <= 2):
571 0 < abs(len(line) - self.shell.indent_current_nsp) <= 2):
572 line = ''
572 line = ''
573
573
574 return line
574 return line
575
575
576 def __str__(self):
576 def __str__(self):
577 return "<%s(name=%s)>" % (self.__class__.__name__, self.handler_name)
577 return "<%s(name=%s)>" % (self.__class__.__name__, self.handler_name)
578
578
579
579
580 class MacroHandler(PrefilterHandler):
580 class MacroHandler(PrefilterHandler):
581 handler_name = Unicode("macro")
581 handler_name = Unicode("macro")
582
582
583 def handle(self, line_info):
583 def handle(self, line_info):
584 obj = self.shell.user_ns.get(line_info.ifun)
584 obj = self.shell.user_ns.get(line_info.ifun)
585 pre_space = line_info.pre_whitespace
585 pre_space = line_info.pre_whitespace
586 line_sep = "\n" + pre_space
586 line_sep = "\n" + pre_space
587 return pre_space + line_sep.join(obj.value.splitlines())
587 return pre_space + line_sep.join(obj.value.splitlines())
588
588
589
589
590 class MagicHandler(PrefilterHandler):
590 class MagicHandler(PrefilterHandler):
591
591
592 handler_name = Unicode('magic')
592 handler_name = Unicode('magic')
593 esc_strings = List([ESC_MAGIC])
593 esc_strings = List([ESC_MAGIC])
594
594
595 def handle(self, line_info):
595 def handle(self, line_info):
596 """Execute magic functions."""
596 """Execute magic functions."""
597 ifun = line_info.ifun
597 ifun = line_info.ifun
598 the_rest = line_info.the_rest
598 the_rest = line_info.the_rest
599 cmd = '%sget_ipython().magic(%r)' % (line_info.pre_whitespace,
599 cmd = '%sget_ipython().magic(%r)' % (line_info.pre_whitespace,
600 (ifun + " " + the_rest))
600 (ifun + " " + the_rest))
601 return cmd
601 return cmd
602
602
603
603
604 class AutoHandler(PrefilterHandler):
604 class AutoHandler(PrefilterHandler):
605
605
606 handler_name = Unicode('auto')
606 handler_name = Unicode('auto')
607 esc_strings = List([ESC_PAREN, ESC_QUOTE, ESC_QUOTE2])
607 esc_strings = List([ESC_PAREN, ESC_QUOTE, ESC_QUOTE2])
608
608
609 def handle(self, line_info):
609 def handle(self, line_info):
610 """Handle lines which can be auto-executed, quoting if requested."""
610 """Handle lines which can be auto-executed, quoting if requested."""
611 line = line_info.line
611 line = line_info.line
612 ifun = line_info.ifun
612 ifun = line_info.ifun
613 the_rest = line_info.the_rest
613 the_rest = line_info.the_rest
614 pre = line_info.pre
614 pre = line_info.pre
615 esc = line_info.esc
615 esc = line_info.esc
616 continue_prompt = line_info.continue_prompt
616 continue_prompt = line_info.continue_prompt
617 obj = line_info.ofind(self.shell)['obj']
617 obj = line_info.ofind(self.shell)['obj']
618 #print 'pre <%s> ifun <%s> rest <%s>' % (pre,ifun,the_rest) # dbg
618 #print 'pre <%s> ifun <%s> rest <%s>' % (pre,ifun,the_rest) # dbg
619
619
620 # This should only be active for single-line input!
620 # This should only be active for single-line input!
621 if continue_prompt:
621 if continue_prompt:
622 return line
622 return line
623
623
624 force_auto = isinstance(obj, IPyAutocall)
624 force_auto = isinstance(obj, IPyAutocall)
625
625
626 # User objects sometimes raise exceptions on attribute access other
626 # User objects sometimes raise exceptions on attribute access other
627 # than AttributeError (we've seen it in the past), so it's safest to be
627 # than AttributeError (we've seen it in the past), so it's safest to be
628 # ultra-conservative here and catch all.
628 # ultra-conservative here and catch all.
629 try:
629 try:
630 auto_rewrite = obj.rewrite
630 auto_rewrite = obj.rewrite
631 except Exception:
631 except Exception:
632 auto_rewrite = True
632 auto_rewrite = True
633
633
634 if esc == ESC_QUOTE:
634 if esc == ESC_QUOTE:
635 # Auto-quote splitting on whitespace
635 # Auto-quote splitting on whitespace
636 newcmd = '%s("%s")' % (ifun,'", "'.join(the_rest.split()) )
636 newcmd = '%s("%s")' % (ifun,'", "'.join(the_rest.split()) )
637 elif esc == ESC_QUOTE2:
637 elif esc == ESC_QUOTE2:
638 # Auto-quote whole string
638 # Auto-quote whole string
639 newcmd = '%s("%s")' % (ifun,the_rest)
639 newcmd = '%s("%s")' % (ifun,the_rest)
640 elif esc == ESC_PAREN:
640 elif esc == ESC_PAREN:
641 newcmd = '%s(%s)' % (ifun,",".join(the_rest.split()))
641 newcmd = '%s(%s)' % (ifun,",".join(the_rest.split()))
642 else:
642 else:
643 # Auto-paren.
643 # Auto-paren.
644 if force_auto:
644 if force_auto:
645 # Don't rewrite if it is already a call.
645 # Don't rewrite if it is already a call.
646 do_rewrite = not the_rest.startswith('(')
646 do_rewrite = not the_rest.startswith('(')
647 else:
647 else:
648 if not the_rest:
648 if not the_rest:
649 # We only apply it to argument-less calls if the autocall
649 # We only apply it to argument-less calls if the autocall
650 # parameter is set to 2.
650 # parameter is set to 2.
651 do_rewrite = (self.shell.autocall >= 2)
651 do_rewrite = (self.shell.autocall >= 2)
652 elif the_rest.startswith('[') and hasattr(obj, '__getitem__'):
652 elif the_rest.startswith('[') and hasattr(obj, '__getitem__'):
653 # Don't autocall in this case: item access for an object
653 # Don't autocall in this case: item access for an object
654 # which is BOTH callable and implements __getitem__.
654 # which is BOTH callable and implements __getitem__.
655 do_rewrite = False
655 do_rewrite = False
656 else:
656 else:
657 do_rewrite = True
657 do_rewrite = True
658
658
659 # Figure out the rewritten command
659 # Figure out the rewritten command
660 if do_rewrite:
660 if do_rewrite:
661 if the_rest.endswith(';'):
661 if the_rest.endswith(';'):
662 newcmd = '%s(%s);' % (ifun.rstrip(),the_rest[:-1])
662 newcmd = '%s(%s);' % (ifun.rstrip(),the_rest[:-1])
663 else:
663 else:
664 newcmd = '%s(%s)' % (ifun.rstrip(), the_rest)
664 newcmd = '%s(%s)' % (ifun.rstrip(), the_rest)
665 else:
665 else:
666 normal_handler = self.prefilter_manager.get_handler_by_name('normal')
666 normal_handler = self.prefilter_manager.get_handler_by_name('normal')
667 return normal_handler.handle(line_info)
667 return normal_handler.handle(line_info)
668
668
669 # Display the rewritten call
669 # Display the rewritten call
670 if auto_rewrite:
670 if auto_rewrite:
671 self.shell.auto_rewrite_input(newcmd)
671 self.shell.auto_rewrite_input(newcmd)
672
672
673 return newcmd
673 return newcmd
674
674
675
675
676 class EmacsHandler(PrefilterHandler):
676 class EmacsHandler(PrefilterHandler):
677
677
678 handler_name = Unicode('emacs')
678 handler_name = Unicode('emacs')
679 esc_strings = List([])
679 esc_strings = List([])
680
680
681 def handle(self, line_info):
681 def handle(self, line_info):
682 """Handle input lines marked by python-mode."""
682 """Handle input lines marked by python-mode."""
683
683
684 # Currently, nothing is done. Later more functionality can be added
684 # Currently, nothing is done. Later more functionality can be added
685 # here if needed.
685 # here if needed.
686
686
687 # The input cache shouldn't be updated
687 # The input cache shouldn't be updated
688 return line_info.line
688 return line_info.line
689
689
690
690
691 #-----------------------------------------------------------------------------
691 #-----------------------------------------------------------------------------
692 # Defaults
692 # Defaults
693 #-----------------------------------------------------------------------------
693 #-----------------------------------------------------------------------------
694
694
695
695
696 _default_transformers = [
696 _default_transformers = [
697 ]
697 ]
698
698
699 _default_checkers = [
699 _default_checkers = [
700 EmacsChecker,
700 EmacsChecker,
701 MacroChecker,
701 MacroChecker,
702 IPyAutocallChecker,
702 IPyAutocallChecker,
703 AssignmentChecker,
703 AssignmentChecker,
704 AutoMagicChecker,
704 AutoMagicChecker,
705 PythonOpsChecker,
705 PythonOpsChecker,
706 AutocallChecker
706 AutocallChecker
707 ]
707 ]
708
708
709 _default_handlers = [
709 _default_handlers = [
710 PrefilterHandler,
710 PrefilterHandler,
711 MacroHandler,
711 MacroHandler,
712 MagicHandler,
712 MagicHandler,
713 AutoHandler,
713 AutoHandler,
714 EmacsHandler
714 EmacsHandler
715 ]
715 ]
General Comments 0
You need to be logged in to leave comments. Login now