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