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