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