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