##// END OF EJS Templates
Reuse common code for inputsplitter and prefilter.
Thomas Kluyver -
Show More
@@ -0,0 +1,26 b''
1 from IPython.core.splitinput import split_user_input
2 from IPython.testing import tools as tt
3
4 tests = [
5 ('x=1', ('', '', 'x', '=1')),
6 ('?', ('', '?', '', '')),
7 ('??', ('', '??', '', '')),
8 (' ?', (' ', '?', '', '')),
9 (' ??', (' ', '??', '', '')),
10 ('??x', ('', '??', 'x', '')),
11 ('?x=1', ('', '?', 'x', '=1')),
12 ('!ls', ('', '!', 'ls', '')),
13 (' !ls', (' ', '!', 'ls', '')),
14 ('!!ls', ('', '!!', 'ls', '')),
15 (' !!ls', (' ', '!!', 'ls', '')),
16 (',ls', ('', ',', 'ls', '')),
17 (';ls', ('', ';', 'ls', '')),
18 (' ;ls', (' ', ';', 'ls', '')),
19 ('f.g(x)', ('', '', 'f.g', '(x)')),
20 ('f.g (x)', ('', '', 'f.g', '(x)')),
21 ('?%hist', ('', '?', '%hist', '')),
22 ('?x*', ('', '?', 'x*', '')),
23 ]
24
25 def test_split_user_input():
26 return tt.check_pairs(split_user_input, tests)
@@ -1,892 +1,770 b''
1 1 """Analysis of text input into executable blocks.
2 2
3 3 The main class in this module, :class:`InputSplitter`, is designed to break
4 4 input from either interactive, line-by-line environments or block-based ones,
5 5 into standalone blocks that can be executed by Python as 'single' statements
6 6 (thus triggering sys.displayhook).
7 7
8 8 A companion, :class:`IPythonInputSplitter`, provides the same functionality but
9 9 with full support for the extended IPython syntax (magics, system calls, etc).
10 10
11 11 For more details, see the class docstring below.
12 12
13 13 Syntax Transformations
14 14 ----------------------
15 15
16 16 One of the main jobs of the code in this file is to apply all syntax
17 17 transformations that make up 'the IPython language', i.e. magics, shell
18 18 escapes, etc. All transformations should be implemented as *fully stateless*
19 19 entities, that simply take one line as their input and return a line.
20 20 Internally for implementation purposes they may be a normal function or a
21 21 callable object, but the only input they receive will be a single line and they
22 22 should only return a line, without holding any data-dependent state between
23 23 calls.
24 24
25 25 As an example, the EscapedTransformer is a class so we can more clearly group
26 26 together the functionality of dispatching to individual functions based on the
27 27 starting escape character, but the only method for public use is its call
28 28 method.
29 29
30 30
31 31 ToDo
32 32 ----
33 33
34 34 - Should we make push() actually raise an exception once push_accepts_more()
35 35 returns False?
36 36
37 37 - Naming cleanups. The tr_* names aren't the most elegant, though now they are
38 38 at least just attributes of a class so not really very exposed.
39 39
40 40 - Think about the best way to support dynamic things: automagic, autocall,
41 41 macros, etc.
42 42
43 43 - Think of a better heuristic for the application of the transforms in
44 44 IPythonInputSplitter.push() than looking at the buffer ending in ':'. Idea:
45 45 track indentation change events (indent, dedent, nothing) and apply them only
46 46 if the indentation went up, but not otherwise.
47 47
48 48 - Think of the cleanest way for supporting user-specified transformations (the
49 49 user prefilters we had before).
50 50
51 51 Authors
52 52 -------
53 53
54 54 * Fernando Perez
55 55 * Brian Granger
56 56 """
57 57 #-----------------------------------------------------------------------------
58 58 # Copyright (C) 2010 The IPython Development Team
59 59 #
60 60 # Distributed under the terms of the BSD License. The full license is in
61 61 # the file COPYING, distributed as part of this software.
62 62 #-----------------------------------------------------------------------------
63 63 from __future__ import print_function
64 64
65 65 #-----------------------------------------------------------------------------
66 66 # Imports
67 67 #-----------------------------------------------------------------------------
68 68 # stdlib
69 69 import ast
70 70 import codeop
71 71 import re
72 72 import sys
73 73 import tokenize
74 74 from StringIO import StringIO
75 75
76 76 # IPython modules
77 from IPython.core.splitinput import split_user_input, LineInfo
77 78 from IPython.utils.text import make_quoted_expr
78 79 from IPython.utils.py3compat import cast_unicode
79 80
80 81 #-----------------------------------------------------------------------------
81 82 # Globals
82 83 #-----------------------------------------------------------------------------
83 84
84 85 # The escape sequences that define the syntax transformations IPython will
85 86 # apply to user input. These can NOT be just changed here: many regular
86 87 # expressions and other parts of the code may use their hardcoded values, and
87 88 # for all intents and purposes they constitute the 'IPython syntax', so they
88 89 # should be considered fixed.
89 90
90 91 ESC_SHELL = '!' # Send line to underlying system shell
91 92 ESC_SH_CAP = '!!' # Send line to system shell and capture output
92 93 ESC_HELP = '?' # Find information about object
93 94 ESC_HELP2 = '??' # Find extra-detailed information about object
94 95 ESC_MAGIC = '%' # Call magic function
95 96 ESC_QUOTE = ',' # Split args on whitespace, quote each as string and call
96 97 ESC_QUOTE2 = ';' # Quote all args as a single string, call
97 98 ESC_PAREN = '/' # Call first argument with rest of line as arguments
98 99
99 100 #-----------------------------------------------------------------------------
100 101 # Utilities
101 102 #-----------------------------------------------------------------------------
102 103
103 104 # FIXME: These are general-purpose utilities that later can be moved to the
104 105 # general ward. Kept here for now because we're being very strict about test
105 106 # coverage with this code, and this lets us ensure that we keep 100% coverage
106 107 # while developing.
107 108
108 109 # compiled regexps for autoindent management
109 110 dedent_re = re.compile('|'.join([
110 111 r'^\s+raise(\s.*)?$', # raise statement (+ space + other stuff, maybe)
111 112 r'^\s+raise\([^\)]*\).*$', # wacky raise with immediate open paren
112 113 r'^\s+return(\s.*)?$', # normal return (+ space + other stuff, maybe)
113 114 r'^\s+return\([^\)]*\).*$', # wacky return with immediate open paren
114 115 r'^\s+pass\s*$' # pass (optionally followed by trailing spaces)
115 116 ]))
116 117 ini_spaces_re = re.compile(r'^([ \t\r\f\v]+)')
117 118
118 119 # regexp to match pure comment lines so we don't accidentally insert 'if 1:'
119 120 # before pure comments
120 121 comment_line_re = re.compile('^\s*\#')
121 122
122 123
123 124 def num_ini_spaces(s):
124 125 """Return the number of initial spaces in a string.
125 126
126 127 Note that tabs are counted as a single space. For now, we do *not* support
127 128 mixing of tabs and spaces in the user's input.
128 129
129 130 Parameters
130 131 ----------
131 132 s : string
132 133
133 134 Returns
134 135 -------
135 136 n : int
136 137 """
137 138
138 139 ini_spaces = ini_spaces_re.match(s)
139 140 if ini_spaces:
140 141 return ini_spaces.end()
141 142 else:
142 143 return 0
143 144
144 145
145 146 def remove_comments(src):
146 147 """Remove all comments from input source.
147 148
148 149 Note: comments are NOT recognized inside of strings!
149 150
150 151 Parameters
151 152 ----------
152 153 src : string
153 154 A single or multiline input string.
154 155
155 156 Returns
156 157 -------
157 158 String with all Python comments removed.
158 159 """
159 160
160 161 return re.sub('#.*', '', src)
161 162
162 163 def has_comment(src):
163 164 """Indicate whether an input line has (i.e. ends in, or is) a comment.
164 165
165 166 This uses tokenize, so it can distinguish comments from # inside strings.
166 167
167 168 Parameters
168 169 ----------
169 170 src : string
170 171 A single line input string.
171 172
172 173 Returns
173 174 -------
174 175 Boolean: True if source has a comment.
175 176 """
176 177 readline = StringIO(src).readline
177 178 toktypes = set()
178 179 try:
179 180 for t in tokenize.generate_tokens(readline):
180 181 toktypes.add(t[0])
181 182 except tokenize.TokenError:
182 183 pass
183 184 return(tokenize.COMMENT in toktypes)
184 185
185 186
186 187 def get_input_encoding():
187 188 """Return the default standard input encoding.
188 189
189 190 If sys.stdin has no encoding, 'ascii' is returned."""
190 191 # There are strange environments for which sys.stdin.encoding is None. We
191 192 # ensure that a valid encoding is returned.
192 193 encoding = getattr(sys.stdin, 'encoding', None)
193 194 if encoding is None:
194 195 encoding = 'ascii'
195 196 return encoding
196 197
197 198 #-----------------------------------------------------------------------------
198 199 # Classes and functions for normal Python syntax handling
199 200 #-----------------------------------------------------------------------------
200 201
201 202 class InputSplitter(object):
202 203 """An object that can accumulate lines of Python source before execution.
203 204
204 205 This object is designed to be fed python source line-by-line, using
205 206 :meth:`push`. It will return on each push whether the currently pushed
206 207 code could be executed already. In addition, it provides a method called
207 208 :meth:`push_accepts_more` that can be used to query whether more input
208 209 can be pushed into a single interactive block.
209 210
210 211 This is a simple example of how an interactive terminal-based client can use
211 212 this tool::
212 213
213 214 isp = InputSplitter()
214 215 while isp.push_accepts_more():
215 216 indent = ' '*isp.indent_spaces
216 217 prompt = '>>> ' + indent
217 218 line = indent + raw_input(prompt)
218 219 isp.push(line)
219 220 print 'Input source was:\n', isp.source_reset(),
220 221 """
221 222 # Number of spaces of indentation computed from input that has been pushed
222 223 # so far. This is the attributes callers should query to get the current
223 224 # indentation level, in order to provide auto-indent facilities.
224 225 indent_spaces = 0
225 226 # String, indicating the default input encoding. It is computed by default
226 227 # at initialization time via get_input_encoding(), but it can be reset by a
227 228 # client with specific knowledge of the encoding.
228 229 encoding = ''
229 230 # String where the current full source input is stored, properly encoded.
230 231 # Reading this attribute is the normal way of querying the currently pushed
231 232 # source code, that has been properly encoded.
232 233 source = ''
233 234 # Code object corresponding to the current source. It is automatically
234 235 # synced to the source, so it can be queried at any time to obtain the code
235 236 # object; it will be None if the source doesn't compile to valid Python.
236 237 code = None
237 238 # Input mode
238 239 input_mode = 'line'
239 240
240 241 # Private attributes
241 242
242 243 # List with lines of input accumulated so far
243 244 _buffer = None
244 245 # Command compiler
245 246 _compile = None
246 247 # Mark when input has changed indentation all the way back to flush-left
247 248 _full_dedent = False
248 249 # Boolean indicating whether the current block is complete
249 250 _is_complete = None
250 251
251 252 def __init__(self, input_mode=None):
252 253 """Create a new InputSplitter instance.
253 254
254 255 Parameters
255 256 ----------
256 257 input_mode : str
257 258
258 259 One of ['line', 'cell']; default is 'line'.
259 260
260 261 The input_mode parameter controls how new inputs are used when fed via
261 262 the :meth:`push` method:
262 263
263 264 - 'line': meant for line-oriented clients, inputs are appended one at a
264 265 time to the internal buffer and the whole buffer is compiled.
265 266
266 267 - 'cell': meant for clients that can edit multi-line 'cells' of text at
267 268 a time. A cell can contain one or more blocks that can be compile in
268 269 'single' mode by Python. In this mode, each new input new input
269 270 completely replaces all prior inputs. Cell mode is thus equivalent
270 271 to prepending a full reset() to every push() call.
271 272 """
272 273 self._buffer = []
273 274 self._compile = codeop.CommandCompiler()
274 275 self.encoding = get_input_encoding()
275 276 self.input_mode = InputSplitter.input_mode if input_mode is None \
276 277 else input_mode
277 278
278 279 def reset(self):
279 280 """Reset the input buffer and associated state."""
280 281 self.indent_spaces = 0
281 282 self._buffer[:] = []
282 283 self.source = ''
283 284 self.code = None
284 285 self._is_complete = False
285 286 self._full_dedent = False
286 287
287 288 def source_reset(self):
288 289 """Return the input source and perform a full reset.
289 290 """
290 291 out = self.source
291 292 self.reset()
292 293 return out
293 294
294 295 def push(self, lines):
295 296 """Push one or more lines of input.
296 297
297 298 This stores the given lines and returns a status code indicating
298 299 whether the code forms a complete Python block or not.
299 300
300 301 Any exceptions generated in compilation are swallowed, but if an
301 302 exception was produced, the method returns True.
302 303
303 304 Parameters
304 305 ----------
305 306 lines : string
306 307 One or more lines of Python input.
307 308
308 309 Returns
309 310 -------
310 311 is_complete : boolean
311 312 True if the current input source (the result of the current input
312 313 plus prior inputs) forms a complete Python execution block. Note that
313 314 this value is also stored as a private attribute (_is_complete), so it
314 315 can be queried at any time.
315 316 """
316 317 if self.input_mode == 'cell':
317 318 self.reset()
318 319
319 320 self._store(lines)
320 321 source = self.source
321 322
322 323 # Before calling _compile(), reset the code object to None so that if an
323 324 # exception is raised in compilation, we don't mislead by having
324 325 # inconsistent code/source attributes.
325 326 self.code, self._is_complete = None, None
326 327
327 328 # Honor termination lines properly
328 329 if source.rstrip().endswith('\\'):
329 330 return False
330 331
331 332 self._update_indent(lines)
332 333 try:
333 334 self.code = self._compile(source, symbol="exec")
334 335 # Invalid syntax can produce any of a number of different errors from
335 336 # inside the compiler, so we have to catch them all. Syntax errors
336 337 # immediately produce a 'ready' block, so the invalid Python can be
337 338 # sent to the kernel for evaluation with possible ipython
338 339 # special-syntax conversion.
339 340 except (SyntaxError, OverflowError, ValueError, TypeError,
340 341 MemoryError):
341 342 self._is_complete = True
342 343 else:
343 344 # Compilation didn't produce any exceptions (though it may not have
344 345 # given a complete code object)
345 346 self._is_complete = self.code is not None
346 347
347 348 return self._is_complete
348 349
349 350 def push_accepts_more(self):
350 351 """Return whether a block of interactive input can accept more input.
351 352
352 353 This method is meant to be used by line-oriented frontends, who need to
353 354 guess whether a block is complete or not based solely on prior and
354 355 current input lines. The InputSplitter considers it has a complete
355 356 interactive block and will not accept more input only when either a
356 357 SyntaxError is raised, or *all* of the following are true:
357 358
358 359 1. The input compiles to a complete statement.
359 360
360 361 2. The indentation level is flush-left (because if we are indented,
361 362 like inside a function definition or for loop, we need to keep
362 363 reading new input).
363 364
364 365 3. There is one extra line consisting only of whitespace.
365 366
366 367 Because of condition #3, this method should be used only by
367 368 *line-oriented* frontends, since it means that intermediate blank lines
368 369 are not allowed in function definitions (or any other indented block).
369 370
370 371 If the current input produces a syntax error, this method immediately
371 372 returns False but does *not* raise the syntax error exception, as
372 373 typically clients will want to send invalid syntax to an execution
373 374 backend which might convert the invalid syntax into valid Python via
374 375 one of the dynamic IPython mechanisms.
375 376 """
376 377
377 378 # With incomplete input, unconditionally accept more
378 379 if not self._is_complete:
379 380 return True
380 381
381 382 # If we already have complete input and we're flush left, the answer
382 383 # depends. In line mode, if there hasn't been any indentation,
383 384 # that's it. If we've come back from some indentation, we need
384 385 # the blank final line to finish.
385 386 # In cell mode, we need to check how many blocks the input so far
386 387 # compiles into, because if there's already more than one full
387 388 # independent block of input, then the client has entered full
388 389 # 'cell' mode and is feeding lines that each is complete. In this
389 390 # case we should then keep accepting. The Qt terminal-like console
390 391 # does precisely this, to provide the convenience of terminal-like
391 392 # input of single expressions, but allowing the user (with a
392 393 # separate keystroke) to switch to 'cell' mode and type multiple
393 394 # expressions in one shot.
394 395 if self.indent_spaces==0:
395 396 if self.input_mode=='line':
396 397 if not self._full_dedent:
397 398 return False
398 399 else:
399 400 try:
400 401 code_ast = ast.parse(u''.join(self._buffer))
401 402 except Exception:
402 403 return False
403 404 else:
404 405 if len(code_ast.body) == 1:
405 406 return False
406 407
407 408 # When input is complete, then termination is marked by an extra blank
408 409 # line at the end.
409 410 last_line = self.source.splitlines()[-1]
410 411 return bool(last_line and not last_line.isspace())
411 412
412 413 #------------------------------------------------------------------------
413 414 # Private interface
414 415 #------------------------------------------------------------------------
415 416
416 417 def _find_indent(self, line):
417 418 """Compute the new indentation level for a single line.
418 419
419 420 Parameters
420 421 ----------
421 422 line : str
422 423 A single new line of non-whitespace, non-comment Python input.
423 424
424 425 Returns
425 426 -------
426 427 indent_spaces : int
427 428 New value for the indent level (it may be equal to self.indent_spaces
428 429 if indentation doesn't change.
429 430
430 431 full_dedent : boolean
431 432 Whether the new line causes a full flush-left dedent.
432 433 """
433 434 indent_spaces = self.indent_spaces
434 435 full_dedent = self._full_dedent
435 436
436 437 inisp = num_ini_spaces(line)
437 438 if inisp < indent_spaces:
438 439 indent_spaces = inisp
439 440 if indent_spaces <= 0:
440 441 #print 'Full dedent in text',self.source # dbg
441 442 full_dedent = True
442 443
443 444 if line.rstrip()[-1] == ':':
444 445 indent_spaces += 4
445 446 elif dedent_re.match(line):
446 447 indent_spaces -= 4
447 448 if indent_spaces <= 0:
448 449 full_dedent = True
449 450
450 451 # Safety
451 452 if indent_spaces < 0:
452 453 indent_spaces = 0
453 454 #print 'safety' # dbg
454 455
455 456 return indent_spaces, full_dedent
456 457
457 458 def _update_indent(self, lines):
458 459 for line in remove_comments(lines).splitlines():
459 460 if line and not line.isspace():
460 461 self.indent_spaces, self._full_dedent = self._find_indent(line)
461 462
462 463 def _store(self, lines, buffer=None, store='source'):
463 464 """Store one or more lines of input.
464 465
465 466 If input lines are not newline-terminated, a newline is automatically
466 467 appended."""
467 468
468 469 if buffer is None:
469 470 buffer = self._buffer
470 471
471 472 if lines.endswith('\n'):
472 473 buffer.append(lines)
473 474 else:
474 475 buffer.append(lines+'\n')
475 476 setattr(self, store, self._set_source(buffer))
476 477
477 478 def _set_source(self, buffer):
478 479 return u''.join(buffer)
479 480
480 481
481 482 #-----------------------------------------------------------------------------
482 483 # Functions and classes for IPython-specific syntactic support
483 484 #-----------------------------------------------------------------------------
484 485
485 # RegExp for splitting line contents into pre-char//first word-method//rest.
486 # For clarity, each group in on one line.
487
488 line_split = re.compile("""
489 ^(\s*) # any leading space
490 ([,;/%]|!!?|\?\??) # escape character or characters
491 \s*(%?[\w\.\*]*) # function/method, possibly with leading %
492 # to correctly treat things like '?%magic'
493 (\s+.*$|$) # rest of line
494 """, re.VERBOSE)
495
496
497 def split_user_input(line):
498 """Split user input into early whitespace, esc-char, function part and rest.
499
500 This is currently handles lines with '=' in them in a very inconsistent
501 manner.
502
503 Examples
504 ========
505 >>> split_user_input('x=1')
506 ('', '', 'x=1', '')
507 >>> split_user_input('?')
508 ('', '?', '', '')
509 >>> split_user_input('??')
510 ('', '??', '', '')
511 >>> split_user_input(' ?')
512 (' ', '?', '', '')
513 >>> split_user_input(' ??')
514 (' ', '??', '', '')
515 >>> split_user_input('??x')
516 ('', '??', 'x', '')
517 >>> split_user_input('?x=1')
518 ('', '', '?x=1', '')
519 >>> split_user_input('!ls')
520 ('', '!', 'ls', '')
521 >>> split_user_input(' !ls')
522 (' ', '!', 'ls', '')
523 >>> split_user_input('!!ls')
524 ('', '!!', 'ls', '')
525 >>> split_user_input(' !!ls')
526 (' ', '!!', 'ls', '')
527 >>> split_user_input(',ls')
528 ('', ',', 'ls', '')
529 >>> split_user_input(';ls')
530 ('', ';', 'ls', '')
531 >>> split_user_input(' ;ls')
532 (' ', ';', 'ls', '')
533 >>> split_user_input('f.g(x)')
534 ('', '', 'f.g(x)', '')
535 >>> split_user_input('f.g (x)')
536 ('', '', 'f.g', '(x)')
537 >>> split_user_input('?%hist')
538 ('', '?', '%hist', '')
539 >>> split_user_input('?x*')
540 ('', '?', 'x*', '')
541 """
542 match = line_split.match(line)
543 if match:
544 lspace, esc, fpart, rest = match.groups()
545 else:
546 # print "match failed for line '%s'" % line
547 try:
548 fpart, rest = line.split(None, 1)
549 except ValueError:
550 # print "split failed for line '%s'" % line
551 fpart, rest = line,''
552 lspace = re.match('^(\s*)(.*)', line).groups()[0]
553 esc = ''
554
555 # fpart has to be a valid python identifier, so it better be only pure
556 # ascii, no unicode:
557 try:
558 fpart = fpart.encode('ascii')
559 except UnicodeEncodeError:
560 lspace = unicode(lspace)
561 rest = fpart + u' ' + rest
562 fpart = u''
563
564 #print 'line:<%s>' % line # dbg
565 #print 'esc <%s> fpart <%s> rest <%s>' % (esc,fpart.strip(),rest) # dbg
566 return lspace, esc, fpart.strip(), rest.lstrip()
567
568
569 486 # The escaped translators ALL receive a line where their own escape has been
570 487 # stripped. Only '?' is valid at the end of the line, all others can only be
571 488 # placed at the start.
572 489
573 class LineInfo(object):
574 """A single line of input and associated info.
575
576 This is a utility class that mostly wraps the output of
577 :func:`split_user_input` into a convenient object to be passed around
578 during input transformations.
579
580 Includes the following as properties:
581
582 line
583 The original, raw line
584
585 lspace
586 Any early whitespace before actual text starts.
587
588 esc
589 The initial esc character (or characters, for double-char escapes like
590 '??' or '!!').
591
592 fpart
593 The 'function part', which is basically the maximal initial sequence
594 of valid python identifiers and the '.' character. This is what is
595 checked for alias and magic transformations, used for auto-calling,
596 etc.
597
598 rest
599 Everything else on the line.
600 """
601 def __init__(self, line):
602 self.line = line
603 self.lspace, self.esc, self.fpart, self.rest = \
604 split_user_input(line)
605
606 def __str__(self):
607 return "LineInfo [%s|%s|%s|%s]" % (self.lspace, self.esc,
608 self.fpart, self.rest)
609
610
611 490 # Transformations of the special syntaxes that don't rely on an explicit escape
612 491 # character but instead on patterns on the input line
613 492
614 493 # The core transformations are implemented as standalone functions that can be
615 494 # tested and validated in isolation. Each of these uses a regexp, we
616 495 # pre-compile these and keep them close to each function definition for clarity
617 496
618 497 _assign_system_re = re.compile(r'(?P<lhs>(\s*)([\w\.]+)((\s*,\s*[\w\.]+)*))'
619 498 r'\s*=\s*!\s*(?P<cmd>.*)')
620 499
621 500 def transform_assign_system(line):
622 501 """Handle the `files = !ls` syntax."""
623 502 m = _assign_system_re.match(line)
624 503 if m is not None:
625 504 cmd = m.group('cmd')
626 505 lhs = m.group('lhs')
627 506 expr = make_quoted_expr(cmd)
628 507 new_line = '%s = get_ipython().getoutput(%s)' % (lhs, expr)
629 508 return new_line
630 509 return line
631 510
632 511
633 512 _assign_magic_re = re.compile(r'(?P<lhs>(\s*)([\w\.]+)((\s*,\s*[\w\.]+)*))'
634 513 r'\s*=\s*%\s*(?P<cmd>.*)')
635 514
636 515 def transform_assign_magic(line):
637 516 """Handle the `a = %who` syntax."""
638 517 m = _assign_magic_re.match(line)
639 518 if m is not None:
640 519 cmd = m.group('cmd')
641 520 lhs = m.group('lhs')
642 521 expr = make_quoted_expr(cmd)
643 522 new_line = '%s = get_ipython().magic(%s)' % (lhs, expr)
644 523 return new_line
645 524 return line
646 525
647 526
648 527 _classic_prompt_re = re.compile(r'^([ \t]*>>> |^[ \t]*\.\.\. )')
649 528
650 529 def transform_classic_prompt(line):
651 530 """Handle inputs that start with '>>> ' syntax."""
652 531
653 532 if not line or line.isspace():
654 533 return line
655 534 m = _classic_prompt_re.match(line)
656 535 if m:
657 536 return line[len(m.group(0)):]
658 537 else:
659 538 return line
660 539
661 540
662 541 _ipy_prompt_re = re.compile(r'^([ \t]*In \[\d+\]: |^[ \t]*\ \ \ \.\.\.+: )')
663 542
664 543 def transform_ipy_prompt(line):
665 544 """Handle inputs that start classic IPython prompt syntax."""
666 545
667 546 if not line or line.isspace():
668 547 return line
669 548 #print 'LINE: %r' % line # dbg
670 549 m = _ipy_prompt_re.match(line)
671 550 if m:
672 551 #print 'MATCH! %r -> %r' % (line, line[len(m.group(0)):]) # dbg
673 552 return line[len(m.group(0)):]
674 553 else:
675 554 return line
676 555
677 556
678 557 def _make_help_call(target, esc, lspace, next_input=None):
679 558 """Prepares a pinfo(2)/psearch call from a target name and the escape
680 559 (i.e. ? or ??)"""
681 560 method = 'pinfo2' if esc == '??' \
682 561 else 'psearch' if '*' in target \
683 562 else 'pinfo'
684 563
685 564 if next_input:
686 565 tpl = '%sget_ipython().magic(u"%s %s", next_input=%s)'
687 566 return tpl % (lspace, method, target, make_quoted_expr(next_input))
688 567 else:
689 568 return '%sget_ipython().magic(u"%s %s")' % (lspace, method, target)
690 569
691 570 _initial_space_re = re.compile(r'\s*')
692 571 _help_end_re = re.compile(r"""(%?
693 [a-zA-Z_*][a-zA-Z0-9_*]* # Variable name
694 (\.[a-zA-Z_*][a-zA-Z0-9_*]*)* # .etc.etc
572 [a-zA-Z_*][\w*]* # Variable name
573 (\.[a-zA-Z_*][\w*]*)* # .etc.etc
695 574 )
696 (\?\??)$ # ? or ??""",
575 (\?\??)$ # ? or ??""",
697 576 re.VERBOSE)
698 577 def transform_help_end(line):
699 578 """Translate lines with ?/?? at the end"""
700 579 m = _help_end_re.search(line)
701 580 if m is None or has_comment(line):
702 581 return line
703 582 target = m.group(1)
704 583 esc = m.group(3)
705 584 lspace = _initial_space_re.match(line).group(0)
706 newline = _make_help_call(target, esc, lspace)
707 585
708 586 # If we're mid-command, put it back on the next prompt for the user.
709 587 next_input = line.rstrip('?') if line.strip() != m.group(0) else None
710 588
711 589 return _make_help_call(target, esc, lspace, next_input)
712 590
713 591
714 592 class EscapedTransformer(object):
715 593 """Class to transform lines that are explicitly escaped out."""
716 594
717 595 def __init__(self):
718 596 tr = { ESC_SHELL : self._tr_system,
719 597 ESC_SH_CAP : self._tr_system2,
720 598 ESC_HELP : self._tr_help,
721 599 ESC_HELP2 : self._tr_help,
722 600 ESC_MAGIC : self._tr_magic,
723 601 ESC_QUOTE : self._tr_quote,
724 602 ESC_QUOTE2 : self._tr_quote2,
725 603 ESC_PAREN : self._tr_paren }
726 604 self.tr = tr
727 605
728 606 # Support for syntax transformations that use explicit escapes typed by the
729 607 # user at the beginning of a line
730 608 @staticmethod
731 609 def _tr_system(line_info):
732 610 "Translate lines escaped with: !"
733 611 cmd = line_info.line.lstrip().lstrip(ESC_SHELL)
734 return '%sget_ipython().system(%s)' % (line_info.lspace,
612 return '%sget_ipython().system(%s)' % (line_info.pre,
735 613 make_quoted_expr(cmd))
736 614
737 615 @staticmethod
738 616 def _tr_system2(line_info):
739 617 "Translate lines escaped with: !!"
740 618 cmd = line_info.line.lstrip()[2:]
741 return '%sget_ipython().getoutput(%s)' % (line_info.lspace,
619 return '%sget_ipython().getoutput(%s)' % (line_info.pre,
742 620 make_quoted_expr(cmd))
743 621
744 622 @staticmethod
745 623 def _tr_help(line_info):
746 624 "Translate lines escaped with: ?/??"
747 625 # A naked help line should just fire the intro help screen
748 626 if not line_info.line[1:]:
749 627 return 'get_ipython().show_usage()'
750 628
751 return _make_help_call(line_info.fpart, line_info.esc, line_info.lspace)
629 return _make_help_call(line_info.ifun, line_info.esc, line_info.pre)
752 630
753 631 @staticmethod
754 632 def _tr_magic(line_info):
755 633 "Translate lines escaped with: %"
756 634 tpl = '%sget_ipython().magic(%s)'
757 cmd = make_quoted_expr(' '.join([line_info.fpart,
758 line_info.rest]).strip())
759 return tpl % (line_info.lspace, cmd)
635 cmd = make_quoted_expr(' '.join([line_info.ifun,
636 line_info.the_rest]).strip())
637 return tpl % (line_info.pre, cmd)
760 638
761 639 @staticmethod
762 640 def _tr_quote(line_info):
763 641 "Translate lines escaped with: ,"
764 return '%s%s("%s")' % (line_info.lspace, line_info.fpart,
765 '", "'.join(line_info.rest.split()) )
642 return '%s%s("%s")' % (line_info.pre, line_info.ifun,
643 '", "'.join(line_info.the_rest.split()) )
766 644
767 645 @staticmethod
768 646 def _tr_quote2(line_info):
769 647 "Translate lines escaped with: ;"
770 return '%s%s("%s")' % (line_info.lspace, line_info.fpart,
771 line_info.rest)
648 return '%s%s("%s")' % (line_info.pre, line_info.ifun,
649 line_info.the_rest)
772 650
773 651 @staticmethod
774 652 def _tr_paren(line_info):
775 653 "Translate lines escaped with: /"
776 return '%s%s(%s)' % (line_info.lspace, line_info.fpart,
777 ", ".join(line_info.rest.split()))
654 return '%s%s(%s)' % (line_info.pre, line_info.ifun,
655 ", ".join(line_info.the_rest.split()))
778 656
779 657 def __call__(self, line):
780 658 """Class to transform lines that are explicitly escaped out.
781 659
782 660 This calls the above _tr_* static methods for the actual line
783 661 translations."""
784 662
785 663 # Empty lines just get returned unmodified
786 664 if not line or line.isspace():
787 665 return line
788 666
789 667 # Get line endpoints, where the escapes can be
790 668 line_info = LineInfo(line)
791 669
792 670 if not line_info.esc in self.tr:
793 671 # If we don't recognize the escape, don't modify the line
794 672 return line
795 673
796 674 return self.tr[line_info.esc](line_info)
797 675
798 676
799 677 # A function-looking object to be used by the rest of the code. The purpose of
800 678 # the class in this case is to organize related functionality, more than to
801 679 # manage state.
802 680 transform_escaped = EscapedTransformer()
803 681
804 682
805 683 class IPythonInputSplitter(InputSplitter):
806 684 """An input splitter that recognizes all of IPython's special syntax."""
807 685
808 686 # String with raw, untransformed input.
809 687 source_raw = ''
810 688
811 689 # Private attributes
812 690
813 691 # List with lines of raw input accumulated so far.
814 692 _buffer_raw = None
815 693
816 694 def __init__(self, input_mode=None):
817 695 InputSplitter.__init__(self, input_mode)
818 696 self._buffer_raw = []
819 697
820 698 def reset(self):
821 699 """Reset the input buffer and associated state."""
822 700 InputSplitter.reset(self)
823 701 self._buffer_raw[:] = []
824 702 self.source_raw = ''
825 703
826 704 def source_raw_reset(self):
827 705 """Return input and raw source and perform a full reset.
828 706 """
829 707 out = self.source
830 708 out_r = self.source_raw
831 709 self.reset()
832 710 return out, out_r
833 711
834 712 def push(self, lines):
835 713 """Push one or more lines of IPython input.
836 714 """
837 715 if not lines:
838 716 return super(IPythonInputSplitter, self).push(lines)
839 717
840 718 # We must ensure all input is pure unicode
841 719 lines = cast_unicode(lines, self.encoding)
842 720
843 721 lines_list = lines.splitlines()
844 722
845 723 transforms = [transform_ipy_prompt, transform_classic_prompt,
846 transform_escaped, transform_help_end,
724 transform_help_end, transform_escaped,
847 725 transform_assign_system, transform_assign_magic]
848 726
849 727 # Transform logic
850 728 #
851 729 # We only apply the line transformers to the input if we have either no
852 730 # input yet, or complete input, or if the last line of the buffer ends
853 731 # with ':' (opening an indented block). This prevents the accidental
854 732 # transformation of escapes inside multiline expressions like
855 733 # triple-quoted strings or parenthesized expressions.
856 734 #
857 735 # The last heuristic, while ugly, ensures that the first line of an
858 736 # indented block is correctly transformed.
859 737 #
860 738 # FIXME: try to find a cleaner approach for this last bit.
861 739
862 740 # If we were in 'block' mode, since we're going to pump the parent
863 741 # class by hand line by line, we need to temporarily switch out to
864 742 # 'line' mode, do a single manual reset and then feed the lines one
865 743 # by one. Note that this only matters if the input has more than one
866 744 # line.
867 745 changed_input_mode = False
868 746
869 747 if self.input_mode == 'cell':
870 748 self.reset()
871 749 changed_input_mode = True
872 750 saved_input_mode = 'cell'
873 751 self.input_mode = 'line'
874 752
875 753 # Store raw source before applying any transformations to it. Note
876 754 # that this must be done *after* the reset() call that would otherwise
877 755 # flush the buffer.
878 756 self._store(lines, self._buffer_raw, 'source_raw')
879 757
880 758 try:
881 759 push = super(IPythonInputSplitter, self).push
882 760 for line in lines_list:
883 761 if self._is_complete or not self._buffer or \
884 762 (self._buffer and self._buffer[-1].rstrip().endswith(':')):
885 763 for f in transforms:
886 764 line = f(line)
887 765
888 766 out = push(line)
889 767 finally:
890 768 if changed_input_mode:
891 769 self.input_mode = saved_input_mode
892 770 return out
@@ -1,1015 +1,943 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 from IPython.core.splitinput import split_user_input
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 # The LineInfo class used throughout
96 #-----------------------------------------------------------------------------
97
98
99 class LineInfo(object):
100 """A single line of input and associated info.
101
102 Includes the following as properties:
103
104 line
105 The original, raw line
106
107 continue_prompt
108 Is this line a continuation in a sequence of multiline input?
109
110 pre
111 The initial esc character or whitespace.
112
113 pre_char
114 The escape character(s) in pre or the empty string if there isn't one.
115 Note that '!!' is a possible value for pre_char. Otherwise it will
116 always be a single character.
117
118 pre_whitespace
119 The leading whitespace from pre if it exists. If there is a pre_char,
120 this is just ''.
121
122 ifun
123 The 'function part', which is basically the maximal initial sequence
124 of valid python identifiers and the '.' character. This is what is
125 checked for alias and magic transformations, used for auto-calling,
126 etc.
127
128 the_rest
129 Everything else on the line.
130 """
131 def __init__(self, line, continue_prompt):
132 self.line = line
133 self.continue_prompt = continue_prompt
134 self.pre, self.esc, self.ifun, self.the_rest = split_user_input(line)
135
136 self.pre_char = self.pre.strip()
137 if self.pre_char:
138 self.pre_whitespace = '' # No whitespace allowd before esc chars
139 else:
140 self.pre_whitespace = self.pre
141
142 self._oinfo = None
143
144 def ofind(self, ip):
145 """Do a full, attribute-walking lookup of the ifun in the various
146 namespaces for the given IPython InteractiveShell instance.
147
148 Return a dict with keys: found,obj,ospace,ismagic
149
150 Note: can cause state changes because of calling getattr, but should
151 only be run if autocall is on and if the line hasn't matched any
152 other, less dangerous handlers.
153
154 Does cache the results of the call, so can be called multiple times
155 without worrying about *further* damaging state.
156 """
157 if not self._oinfo:
158 # ip.shell._ofind is actually on the Magic class!
159 self._oinfo = ip.shell._ofind(self.ifun)
160 return self._oinfo
161
162 def __str__(self):
163 return "Lineinfo [%s|%s|%s]" %(self.pre, self.ifun, self.the_rest)
164
165
166 #-----------------------------------------------------------------------------
167 95 # Main Prefilter manager
168 96 #-----------------------------------------------------------------------------
169 97
170 98
171 99 class PrefilterManager(Configurable):
172 100 """Main prefilter component.
173 101
174 102 The IPython prefilter is run on all user input before it is run. The
175 103 prefilter consumes lines of input and produces transformed lines of
176 104 input.
177 105
178 106 The iplementation consists of two phases:
179 107
180 108 1. Transformers
181 109 2. Checkers and handlers
182 110
183 111 Over time, we plan on deprecating the checkers and handlers and doing
184 112 everything in the transformers.
185 113
186 114 The transformers are instances of :class:`PrefilterTransformer` and have
187 115 a single method :meth:`transform` that takes a line and returns a
188 116 transformed line. The transformation can be accomplished using any
189 117 tool, but our current ones use regular expressions for speed. We also
190 118 ship :mod:`pyparsing` in :mod:`IPython.external` for use in transformers.
191 119
192 120 After all the transformers have been run, the line is fed to the checkers,
193 121 which are instances of :class:`PrefilterChecker`. The line is passed to
194 122 the :meth:`check` method, which either returns `None` or a
195 123 :class:`PrefilterHandler` instance. If `None` is returned, the other
196 124 checkers are tried. If an :class:`PrefilterHandler` instance is returned,
197 125 the line is passed to the :meth:`handle` method of the returned
198 126 handler and no further checkers are tried.
199 127
200 128 Both transformers and checkers have a `priority` attribute, that determines
201 129 the order in which they are called. Smaller priorities are tried first.
202 130
203 131 Both transformers and checkers also have `enabled` attribute, which is
204 132 a boolean that determines if the instance is used.
205 133
206 134 Users or developers can change the priority or enabled attribute of
207 135 transformers or checkers, but they must call the :meth:`sort_checkers`
208 136 or :meth:`sort_transformers` method after changing the priority.
209 137 """
210 138
211 139 multi_line_specials = CBool(True, config=True)
212 140 shell = Instance('IPython.core.interactiveshell.InteractiveShellABC')
213 141
214 142 def __init__(self, shell=None, config=None):
215 143 super(PrefilterManager, self).__init__(shell=shell, config=config)
216 144 self.shell = shell
217 145 self.init_transformers()
218 146 self.init_handlers()
219 147 self.init_checkers()
220 148
221 149 #-------------------------------------------------------------------------
222 150 # API for managing transformers
223 151 #-------------------------------------------------------------------------
224 152
225 153 def init_transformers(self):
226 154 """Create the default transformers."""
227 155 self._transformers = []
228 156 for transformer_cls in _default_transformers:
229 157 transformer_cls(
230 158 shell=self.shell, prefilter_manager=self, config=self.config
231 159 )
232 160
233 161 def sort_transformers(self):
234 162 """Sort the transformers by priority.
235 163
236 164 This must be called after the priority of a transformer is changed.
237 165 The :meth:`register_transformer` method calls this automatically.
238 166 """
239 167 self._transformers.sort(key=lambda x: x.priority)
240 168
241 169 @property
242 170 def transformers(self):
243 171 """Return a list of checkers, sorted by priority."""
244 172 return self._transformers
245 173
246 174 def register_transformer(self, transformer):
247 175 """Register a transformer instance."""
248 176 if transformer not in self._transformers:
249 177 self._transformers.append(transformer)
250 178 self.sort_transformers()
251 179
252 180 def unregister_transformer(self, transformer):
253 181 """Unregister a transformer instance."""
254 182 if transformer in self._transformers:
255 183 self._transformers.remove(transformer)
256 184
257 185 #-------------------------------------------------------------------------
258 186 # API for managing checkers
259 187 #-------------------------------------------------------------------------
260 188
261 189 def init_checkers(self):
262 190 """Create the default checkers."""
263 191 self._checkers = []
264 192 for checker in _default_checkers:
265 193 checker(
266 194 shell=self.shell, prefilter_manager=self, config=self.config
267 195 )
268 196
269 197 def sort_checkers(self):
270 198 """Sort the checkers by priority.
271 199
272 200 This must be called after the priority of a checker is changed.
273 201 The :meth:`register_checker` method calls this automatically.
274 202 """
275 203 self._checkers.sort(key=lambda x: x.priority)
276 204
277 205 @property
278 206 def checkers(self):
279 207 """Return a list of checkers, sorted by priority."""
280 208 return self._checkers
281 209
282 210 def register_checker(self, checker):
283 211 """Register a checker instance."""
284 212 if checker not in self._checkers:
285 213 self._checkers.append(checker)
286 214 self.sort_checkers()
287 215
288 216 def unregister_checker(self, checker):
289 217 """Unregister a checker instance."""
290 218 if checker in self._checkers:
291 219 self._checkers.remove(checker)
292 220
293 221 #-------------------------------------------------------------------------
294 222 # API for managing checkers
295 223 #-------------------------------------------------------------------------
296 224
297 225 def init_handlers(self):
298 226 """Create the default handlers."""
299 227 self._handlers = {}
300 228 self._esc_handlers = {}
301 229 for handler in _default_handlers:
302 230 handler(
303 231 shell=self.shell, prefilter_manager=self, config=self.config
304 232 )
305 233
306 234 @property
307 235 def handlers(self):
308 236 """Return a dict of all the handlers."""
309 237 return self._handlers
310 238
311 239 def register_handler(self, name, handler, esc_strings):
312 240 """Register a handler instance by name with esc_strings."""
313 241 self._handlers[name] = handler
314 242 for esc_str in esc_strings:
315 243 self._esc_handlers[esc_str] = handler
316 244
317 245 def unregister_handler(self, name, handler, esc_strings):
318 246 """Unregister a handler instance by name with esc_strings."""
319 247 try:
320 248 del self._handlers[name]
321 249 except KeyError:
322 250 pass
323 251 for esc_str in esc_strings:
324 252 h = self._esc_handlers.get(esc_str)
325 253 if h is handler:
326 254 del self._esc_handlers[esc_str]
327 255
328 256 def get_handler_by_name(self, name):
329 257 """Get a handler by its name."""
330 258 return self._handlers.get(name)
331 259
332 260 def get_handler_by_esc(self, esc_str):
333 261 """Get a handler by its escape string."""
334 262 return self._esc_handlers.get(esc_str)
335 263
336 264 #-------------------------------------------------------------------------
337 265 # Main prefiltering API
338 266 #-------------------------------------------------------------------------
339 267
340 268 def prefilter_line_info(self, line_info):
341 269 """Prefilter a line that has been converted to a LineInfo object.
342 270
343 271 This implements the checker/handler part of the prefilter pipe.
344 272 """
345 273 # print "prefilter_line_info: ", line_info
346 274 handler = self.find_handler(line_info)
347 275 return handler.handle(line_info)
348 276
349 277 def find_handler(self, line_info):
350 278 """Find a handler for the line_info by trying checkers."""
351 279 for checker in self.checkers:
352 280 if checker.enabled:
353 281 handler = checker.check(line_info)
354 282 if handler:
355 283 return handler
356 284 return self.get_handler_by_name('normal')
357 285
358 286 def transform_line(self, line, continue_prompt):
359 287 """Calls the enabled transformers in order of increasing priority."""
360 288 for transformer in self.transformers:
361 289 if transformer.enabled:
362 290 line = transformer.transform(line, continue_prompt)
363 291 return line
364 292
365 293 def prefilter_line(self, line, continue_prompt=False):
366 294 """Prefilter a single input line as text.
367 295
368 296 This method prefilters a single line of text by calling the
369 297 transformers and then the checkers/handlers.
370 298 """
371 299
372 300 # print "prefilter_line: ", line, continue_prompt
373 301 # All handlers *must* return a value, even if it's blank ('').
374 302
375 303 # save the line away in case we crash, so the post-mortem handler can
376 304 # record it
377 305 self.shell._last_input_line = line
378 306
379 307 if not line:
380 308 # Return immediately on purely empty lines, so that if the user
381 309 # previously typed some whitespace that started a continuation
382 310 # prompt, he can break out of that loop with just an empty line.
383 311 # This is how the default python prompt works.
384 312 return ''
385 313
386 314 # At this point, we invoke our transformers.
387 315 if not continue_prompt or (continue_prompt and self.multi_line_specials):
388 316 line = self.transform_line(line, continue_prompt)
389 317
390 318 # Now we compute line_info for the checkers and handlers
391 319 line_info = LineInfo(line, continue_prompt)
392 320
393 321 # the input history needs to track even empty lines
394 322 stripped = line.strip()
395 323
396 324 normal_handler = self.get_handler_by_name('normal')
397 325 if not stripped:
398 326 if not continue_prompt:
399 327 self.shell.displayhook.prompt_count -= 1
400 328
401 329 return normal_handler.handle(line_info)
402 330
403 331 # special handlers are only allowed for single line statements
404 332 if continue_prompt and not self.multi_line_specials:
405 333 return normal_handler.handle(line_info)
406 334
407 335 prefiltered = self.prefilter_line_info(line_info)
408 336 # print "prefiltered line: %r" % prefiltered
409 337 return prefiltered
410 338
411 339 def prefilter_lines(self, lines, continue_prompt=False):
412 340 """Prefilter multiple input lines of text.
413 341
414 342 This is the main entry point for prefiltering multiple lines of
415 343 input. This simply calls :meth:`prefilter_line` for each line of
416 344 input.
417 345
418 346 This covers cases where there are multiple lines in the user entry,
419 347 which is the case when the user goes back to a multiline history
420 348 entry and presses enter.
421 349 """
422 350 llines = lines.rstrip('\n').split('\n')
423 351 # We can get multiple lines in one shot, where multiline input 'blends'
424 352 # into one line, in cases like recalling from the readline history
425 353 # buffer. We need to make sure that in such cases, we correctly
426 354 # communicate downstream which line is first and which are continuation
427 355 # ones.
428 356 if len(llines) > 1:
429 357 out = '\n'.join([self.prefilter_line(line, lnum>0)
430 358 for lnum, line in enumerate(llines) ])
431 359 else:
432 360 out = self.prefilter_line(llines[0], continue_prompt)
433 361
434 362 return out
435 363
436 364 #-----------------------------------------------------------------------------
437 365 # Prefilter transformers
438 366 #-----------------------------------------------------------------------------
439 367
440 368
441 369 class PrefilterTransformer(Configurable):
442 370 """Transform a line of user input."""
443 371
444 372 priority = Int(100, config=True)
445 373 # Transformers don't currently use shell or prefilter_manager, but as we
446 374 # move away from checkers and handlers, they will need them.
447 375 shell = Instance('IPython.core.interactiveshell.InteractiveShellABC')
448 376 prefilter_manager = Instance('IPython.core.prefilter.PrefilterManager')
449 377 enabled = Bool(True, config=True)
450 378
451 379 def __init__(self, shell=None, prefilter_manager=None, config=None):
452 380 super(PrefilterTransformer, self).__init__(
453 381 shell=shell, prefilter_manager=prefilter_manager, config=config
454 382 )
455 383 self.prefilter_manager.register_transformer(self)
456 384
457 385 def transform(self, line, continue_prompt):
458 386 """Transform a line, returning the new one."""
459 387 return None
460 388
461 389 def __repr__(self):
462 390 return "<%s(priority=%r, enabled=%r)>" % (
463 391 self.__class__.__name__, self.priority, self.enabled)
464 392
465 393
466 394 _assign_system_re = re.compile(r'(?P<lhs>(\s*)([\w\.]+)((\s*,\s*[\w\.]+)*))'
467 395 r'\s*=\s*!(?P<cmd>.*)')
468 396
469 397
470 398 class AssignSystemTransformer(PrefilterTransformer):
471 399 """Handle the `files = !ls` syntax."""
472 400
473 401 priority = Int(100, config=True)
474 402
475 403 def transform(self, line, continue_prompt):
476 404 m = _assign_system_re.match(line)
477 405 if m is not None:
478 406 cmd = m.group('cmd')
479 407 lhs = m.group('lhs')
480 408 expr = make_quoted_expr("sc =%s" % cmd)
481 409 new_line = '%s = get_ipython().magic(%s)' % (lhs, expr)
482 410 return new_line
483 411 return line
484 412
485 413
486 414 _assign_magic_re = re.compile(r'(?P<lhs>(\s*)([\w\.]+)((\s*,\s*[\w\.]+)*))'
487 415 r'\s*=\s*%(?P<cmd>.*)')
488 416
489 417 class AssignMagicTransformer(PrefilterTransformer):
490 418 """Handle the `a = %who` syntax."""
491 419
492 420 priority = Int(200, config=True)
493 421
494 422 def transform(self, line, continue_prompt):
495 423 m = _assign_magic_re.match(line)
496 424 if m is not None:
497 425 cmd = m.group('cmd')
498 426 lhs = m.group('lhs')
499 427 expr = make_quoted_expr(cmd)
500 428 new_line = '%s = get_ipython().magic(%s)' % (lhs, expr)
501 429 return new_line
502 430 return line
503 431
504 432
505 433 _classic_prompt_re = re.compile(r'(^[ \t]*>>> |^[ \t]*\.\.\. )')
506 434
507 435 class PyPromptTransformer(PrefilterTransformer):
508 436 """Handle inputs that start with '>>> ' syntax."""
509 437
510 438 priority = Int(50, config=True)
511 439
512 440 def transform(self, line, continue_prompt):
513 441
514 442 if not line or line.isspace() or line.strip() == '...':
515 443 # This allows us to recognize multiple input prompts separated by
516 444 # blank lines and pasted in a single chunk, very common when
517 445 # pasting doctests or long tutorial passages.
518 446 return ''
519 447 m = _classic_prompt_re.match(line)
520 448 if m:
521 449 return line[len(m.group(0)):]
522 450 else:
523 451 return line
524 452
525 453
526 454 _ipy_prompt_re = re.compile(r'(^[ \t]*In \[\d+\]: |^[ \t]*\ \ \ \.\.\.+: )')
527 455
528 456 class IPyPromptTransformer(PrefilterTransformer):
529 457 """Handle inputs that start classic IPython prompt syntax."""
530 458
531 459 priority = Int(50, config=True)
532 460
533 461 def transform(self, line, continue_prompt):
534 462
535 463 if not line or line.isspace() or line.strip() == '...':
536 464 # This allows us to recognize multiple input prompts separated by
537 465 # blank lines and pasted in a single chunk, very common when
538 466 # pasting doctests or long tutorial passages.
539 467 return ''
540 468 m = _ipy_prompt_re.match(line)
541 469 if m:
542 470 return line[len(m.group(0)):]
543 471 else:
544 472 return line
545 473
546 474 #-----------------------------------------------------------------------------
547 475 # Prefilter checkers
548 476 #-----------------------------------------------------------------------------
549 477
550 478
551 479 class PrefilterChecker(Configurable):
552 480 """Inspect an input line and return a handler for that line."""
553 481
554 482 priority = Int(100, config=True)
555 483 shell = Instance('IPython.core.interactiveshell.InteractiveShellABC')
556 484 prefilter_manager = Instance('IPython.core.prefilter.PrefilterManager')
557 485 enabled = Bool(True, config=True)
558 486
559 487 def __init__(self, shell=None, prefilter_manager=None, config=None):
560 488 super(PrefilterChecker, self).__init__(
561 489 shell=shell, prefilter_manager=prefilter_manager, config=config
562 490 )
563 491 self.prefilter_manager.register_checker(self)
564 492
565 493 def check(self, line_info):
566 494 """Inspect line_info and return a handler instance or None."""
567 495 return None
568 496
569 497 def __repr__(self):
570 498 return "<%s(priority=%r, enabled=%r)>" % (
571 499 self.__class__.__name__, self.priority, self.enabled)
572 500
573 501
574 502 class EmacsChecker(PrefilterChecker):
575 503
576 504 priority = Int(100, config=True)
577 505 enabled = Bool(False, config=True)
578 506
579 507 def check(self, line_info):
580 508 "Emacs ipython-mode tags certain input lines."
581 509 if line_info.line.endswith('# PYTHON-MODE'):
582 510 return self.prefilter_manager.get_handler_by_name('emacs')
583 511 else:
584 512 return None
585 513
586 514
587 515 class ShellEscapeChecker(PrefilterChecker):
588 516
589 517 priority = Int(200, config=True)
590 518
591 519 def check(self, line_info):
592 520 if line_info.line.lstrip().startswith(ESC_SHELL):
593 521 return self.prefilter_manager.get_handler_by_name('shell')
594 522
595 523
596 524 class MacroChecker(PrefilterChecker):
597 525
598 526 priority = Int(250, config=True)
599 527
600 528 def check(self, line_info):
601 529 obj = self.shell.user_ns.get(line_info.ifun)
602 530 if isinstance(obj, Macro):
603 531 return self.prefilter_manager.get_handler_by_name('macro')
604 532 else:
605 533 return None
606 534
607 535
608 536 class IPyAutocallChecker(PrefilterChecker):
609 537
610 538 priority = Int(300, config=True)
611 539
612 540 def check(self, line_info):
613 541 "Instances of IPyAutocall in user_ns get autocalled immediately"
614 542 obj = self.shell.user_ns.get(line_info.ifun, None)
615 543 if isinstance(obj, IPyAutocall):
616 544 obj.set_ip(self.shell)
617 545 return self.prefilter_manager.get_handler_by_name('auto')
618 546 else:
619 547 return None
620 548
621 549
622 550 class MultiLineMagicChecker(PrefilterChecker):
623 551
624 552 priority = Int(400, config=True)
625 553
626 554 def check(self, line_info):
627 555 "Allow ! and !! in multi-line statements if multi_line_specials is on"
628 556 # Note that this one of the only places we check the first character of
629 557 # ifun and *not* the pre_char. Also note that the below test matches
630 558 # both ! and !!.
631 559 if line_info.continue_prompt \
632 560 and self.prefilter_manager.multi_line_specials:
633 561 if line_info.esc == ESC_MAGIC:
634 562 return self.prefilter_manager.get_handler_by_name('magic')
635 563 else:
636 564 return None
637 565
638 566
639 567 class EscCharsChecker(PrefilterChecker):
640 568
641 569 priority = Int(500, config=True)
642 570
643 571 def check(self, line_info):
644 572 """Check for escape character and return either a handler to handle it,
645 573 or None if there is no escape char."""
646 574 if line_info.line[-1] == ESC_HELP \
647 575 and line_info.esc != ESC_SHELL \
648 576 and line_info.esc != ESC_SH_CAP:
649 577 # the ? can be at the end, but *not* for either kind of shell escape,
650 578 # because a ? can be a vaild final char in a shell cmd
651 579 return self.prefilter_manager.get_handler_by_name('help')
652 580 else:
653 581 if line_info.pre:
654 582 return None
655 583 # This returns None like it should if no handler exists
656 584 return self.prefilter_manager.get_handler_by_esc(line_info.esc)
657 585
658 586
659 587 class AssignmentChecker(PrefilterChecker):
660 588
661 589 priority = Int(600, config=True)
662 590
663 591 def check(self, line_info):
664 592 """Check to see if user is assigning to a var for the first time, in
665 593 which case we want to avoid any sort of automagic / autocall games.
666 594
667 595 This allows users to assign to either alias or magic names true python
668 596 variables (the magic/alias systems always take second seat to true
669 597 python code). E.g. ls='hi', or ls,that=1,2"""
670 598 if line_info.the_rest:
671 599 if line_info.the_rest[0] in '=,':
672 600 return self.prefilter_manager.get_handler_by_name('normal')
673 601 else:
674 602 return None
675 603
676 604
677 605 class AutoMagicChecker(PrefilterChecker):
678 606
679 607 priority = Int(700, config=True)
680 608
681 609 def check(self, line_info):
682 610 """If the ifun is magic, and automagic is on, run it. Note: normal,
683 611 non-auto magic would already have been triggered via '%' in
684 612 check_esc_chars. This just checks for automagic. Also, before
685 613 triggering the magic handler, make sure that there is nothing in the
686 614 user namespace which could shadow it."""
687 615 if not self.shell.automagic or not hasattr(self.shell,'magic_'+line_info.ifun):
688 616 return None
689 617
690 618 # We have a likely magic method. Make sure we should actually call it.
691 619 if line_info.continue_prompt and not self.prefilter_manager.multi_line_specials:
692 620 return None
693 621
694 622 head = line_info.ifun.split('.',1)[0]
695 623 if is_shadowed(head, self.shell):
696 624 return None
697 625
698 626 return self.prefilter_manager.get_handler_by_name('magic')
699 627
700 628
701 629 class AliasChecker(PrefilterChecker):
702 630
703 631 priority = Int(800, config=True)
704 632
705 633 def check(self, line_info):
706 634 "Check if the initital identifier on the line is an alias."
707 635 # Note: aliases can not contain '.'
708 636 head = line_info.ifun.split('.',1)[0]
709 637 if line_info.ifun not in self.shell.alias_manager \
710 638 or head not in self.shell.alias_manager \
711 639 or is_shadowed(head, self.shell):
712 640 return None
713 641
714 642 return self.prefilter_manager.get_handler_by_name('alias')
715 643
716 644
717 645 class PythonOpsChecker(PrefilterChecker):
718 646
719 647 priority = Int(900, config=True)
720 648
721 649 def check(self, line_info):
722 650 """If the 'rest' of the line begins with a function call or pretty much
723 651 any python operator, we should simply execute the line (regardless of
724 652 whether or not there's a possible autocall expansion). This avoids
725 653 spurious (and very confusing) geattr() accesses."""
726 654 if line_info.the_rest and line_info.the_rest[0] in '!=()<>,+*/%^&|':
727 655 return self.prefilter_manager.get_handler_by_name('normal')
728 656 else:
729 657 return None
730 658
731 659
732 660 class AutocallChecker(PrefilterChecker):
733 661
734 662 priority = Int(1000, config=True)
735 663
736 664 def check(self, line_info):
737 665 "Check if the initial word/function is callable and autocall is on."
738 666 if not self.shell.autocall:
739 667 return None
740 668
741 669 oinfo = line_info.ofind(self.shell) # This can mutate state via getattr
742 670 if not oinfo['found']:
743 671 return None
744 672
745 673 if callable(oinfo['obj']) \
746 674 and (not re_exclude_auto.match(line_info.the_rest)) \
747 675 and re_fun_name.match(line_info.ifun):
748 676 return self.prefilter_manager.get_handler_by_name('auto')
749 677 else:
750 678 return None
751 679
752 680
753 681 #-----------------------------------------------------------------------------
754 682 # Prefilter handlers
755 683 #-----------------------------------------------------------------------------
756 684
757 685
758 686 class PrefilterHandler(Configurable):
759 687
760 688 handler_name = Unicode('normal')
761 689 esc_strings = List([])
762 690 shell = Instance('IPython.core.interactiveshell.InteractiveShellABC')
763 691 prefilter_manager = Instance('IPython.core.prefilter.PrefilterManager')
764 692
765 693 def __init__(self, shell=None, prefilter_manager=None, config=None):
766 694 super(PrefilterHandler, self).__init__(
767 695 shell=shell, prefilter_manager=prefilter_manager, config=config
768 696 )
769 697 self.prefilter_manager.register_handler(
770 698 self.handler_name,
771 699 self,
772 700 self.esc_strings
773 701 )
774 702
775 703 def handle(self, line_info):
776 704 # print "normal: ", line_info
777 705 """Handle normal input lines. Use as a template for handlers."""
778 706
779 707 # With autoindent on, we need some way to exit the input loop, and I
780 708 # don't want to force the user to have to backspace all the way to
781 709 # clear the line. The rule will be in this case, that either two
782 710 # lines of pure whitespace in a row, or a line of pure whitespace but
783 711 # of a size different to the indent level, will exit the input loop.
784 712 line = line_info.line
785 713 continue_prompt = line_info.continue_prompt
786 714
787 715 if (continue_prompt and
788 716 self.shell.autoindent and
789 717 line.isspace() and
790 718 0 < abs(len(line) - self.shell.indent_current_nsp) <= 2):
791 719 line = ''
792 720
793 721 return line
794 722
795 723 def __str__(self):
796 724 return "<%s(name=%s)>" % (self.__class__.__name__, self.handler_name)
797 725
798 726
799 727 class AliasHandler(PrefilterHandler):
800 728
801 729 handler_name = Unicode('alias')
802 730
803 731 def handle(self, line_info):
804 732 """Handle alias input lines. """
805 733 transformed = self.shell.alias_manager.expand_aliases(line_info.ifun,line_info.the_rest)
806 734 # pre is needed, because it carries the leading whitespace. Otherwise
807 735 # aliases won't work in indented sections.
808 736 line_out = '%sget_ipython().system(%s)' % (line_info.pre_whitespace,
809 737 make_quoted_expr(transformed))
810 738
811 739 return line_out
812 740
813 741
814 742 class ShellEscapeHandler(PrefilterHandler):
815 743
816 744 handler_name = Unicode('shell')
817 745 esc_strings = List([ESC_SHELL, ESC_SH_CAP])
818 746
819 747 def handle(self, line_info):
820 748 """Execute the line in a shell, empty return value"""
821 749 magic_handler = self.prefilter_manager.get_handler_by_name('magic')
822 750
823 751 line = line_info.line
824 752 if line.lstrip().startswith(ESC_SH_CAP):
825 753 # rewrite LineInfo's line, ifun and the_rest to properly hold the
826 754 # call to %sx and the actual command to be executed, so
827 755 # handle_magic can work correctly. Note that this works even if
828 756 # the line is indented, so it handles multi_line_specials
829 757 # properly.
830 758 new_rest = line.lstrip()[2:]
831 759 line_info.line = '%ssx %s' % (ESC_MAGIC, new_rest)
832 760 line_info.ifun = 'sx'
833 761 line_info.the_rest = new_rest
834 762 return magic_handler.handle(line_info)
835 763 else:
836 764 cmd = line.lstrip().lstrip(ESC_SHELL)
837 765 line_out = '%sget_ipython().system(%s)' % (line_info.pre_whitespace,
838 766 make_quoted_expr(cmd))
839 767 return line_out
840 768
841 769
842 770 class MacroHandler(PrefilterHandler):
843 771 handler_name = Unicode("macro")
844 772
845 773 def handle(self, line_info):
846 774 obj = self.shell.user_ns.get(line_info.ifun)
847 775 pre_space = line_info.pre_whitespace
848 776 line_sep = "\n" + pre_space
849 777 return pre_space + line_sep.join(obj.value.splitlines())
850 778
851 779
852 780 class MagicHandler(PrefilterHandler):
853 781
854 782 handler_name = Unicode('magic')
855 783 esc_strings = List([ESC_MAGIC])
856 784
857 785 def handle(self, line_info):
858 786 """Execute magic functions."""
859 787 ifun = line_info.ifun
860 788 the_rest = line_info.the_rest
861 789 cmd = '%sget_ipython().magic(%s)' % (line_info.pre_whitespace,
862 790 make_quoted_expr(ifun + " " + the_rest))
863 791 return cmd
864 792
865 793
866 794 class AutoHandler(PrefilterHandler):
867 795
868 796 handler_name = Unicode('auto')
869 797 esc_strings = List([ESC_PAREN, ESC_QUOTE, ESC_QUOTE2])
870 798
871 799 def handle(self, line_info):
872 800 """Handle lines which can be auto-executed, quoting if requested."""
873 801 line = line_info.line
874 802 ifun = line_info.ifun
875 803 the_rest = line_info.the_rest
876 804 pre = line_info.pre
877 805 esc = line_info.esc
878 806 continue_prompt = line_info.continue_prompt
879 807 obj = line_info.ofind(self)['obj']
880 808 #print 'pre <%s> ifun <%s> rest <%s>' % (pre,ifun,the_rest) # dbg
881 809
882 810 # This should only be active for single-line input!
883 811 if continue_prompt:
884 812 return line
885 813
886 814 force_auto = isinstance(obj, IPyAutocall)
887 815 auto_rewrite = getattr(obj, 'rewrite', True)
888 816
889 817 if esc == ESC_QUOTE:
890 818 # Auto-quote splitting on whitespace
891 819 newcmd = '%s("%s")' % (ifun,'", "'.join(the_rest.split()) )
892 820 elif esc == ESC_QUOTE2:
893 821 # Auto-quote whole string
894 822 newcmd = '%s("%s")' % (ifun,the_rest)
895 823 elif esc == ESC_PAREN:
896 824 newcmd = '%s(%s)' % (ifun,",".join(the_rest.split()))
897 825 else:
898 826 # Auto-paren.
899 827 # We only apply it to argument-less calls if the autocall
900 828 # parameter is set to 2. We only need to check that autocall is <
901 829 # 2, since this function isn't called unless it's at least 1.
902 830 if not the_rest and (self.shell.autocall < 2) and not force_auto:
903 831 newcmd = '%s %s' % (ifun,the_rest)
904 832 auto_rewrite = False
905 833 else:
906 834 if not force_auto and the_rest.startswith('['):
907 835 if hasattr(obj,'__getitem__'):
908 836 # Don't autocall in this case: item access for an object
909 837 # which is BOTH callable and implements __getitem__.
910 838 newcmd = '%s %s' % (ifun,the_rest)
911 839 auto_rewrite = False
912 840 else:
913 841 # if the object doesn't support [] access, go ahead and
914 842 # autocall
915 843 newcmd = '%s(%s)' % (ifun.rstrip(),the_rest)
916 844 elif the_rest.endswith(';'):
917 845 newcmd = '%s(%s);' % (ifun.rstrip(),the_rest[:-1])
918 846 else:
919 847 newcmd = '%s(%s)' % (ifun.rstrip(), the_rest)
920 848
921 849 if auto_rewrite:
922 850 self.shell.auto_rewrite_input(newcmd)
923 851
924 852 return newcmd
925 853
926 854
927 855 class HelpHandler(PrefilterHandler):
928 856
929 857 handler_name = Unicode('help')
930 858 esc_strings = List([ESC_HELP])
931 859
932 860 def handle(self, line_info):
933 861 """Try to get some help for the object.
934 862
935 863 obj? or ?obj -> basic information.
936 864 obj?? or ??obj -> more details.
937 865 """
938 866 normal_handler = self.prefilter_manager.get_handler_by_name('normal')
939 867 line = line_info.line
940 868 # We need to make sure that we don't process lines which would be
941 869 # otherwise valid python, such as "x=1 # what?"
942 870 try:
943 871 codeop.compile_command(line)
944 872 except SyntaxError:
945 873 # We should only handle as help stuff which is NOT valid syntax
946 874 if line[0]==ESC_HELP:
947 875 line = line[1:]
948 876 elif line[-1]==ESC_HELP:
949 877 line = line[:-1]
950 878 if line:
951 879 #print 'line:<%r>' % line # dbg
952 880 self.shell.magic_pinfo(line_info.ifun)
953 881 else:
954 882 self.shell.show_usage()
955 883 return '' # Empty string is needed here!
956 884 except:
957 885 raise
958 886 # Pass any other exceptions through to the normal handler
959 887 return normal_handler.handle(line_info)
960 888 else:
961 889 # If the code compiles ok, we should handle it normally
962 890 return normal_handler.handle(line_info)
963 891
964 892
965 893 class EmacsHandler(PrefilterHandler):
966 894
967 895 handler_name = Unicode('emacs')
968 896 esc_strings = List([])
969 897
970 898 def handle(self, line_info):
971 899 """Handle input lines marked by python-mode."""
972 900
973 901 # Currently, nothing is done. Later more functionality can be added
974 902 # here if needed.
975 903
976 904 # The input cache shouldn't be updated
977 905 return line_info.line
978 906
979 907
980 908 #-----------------------------------------------------------------------------
981 909 # Defaults
982 910 #-----------------------------------------------------------------------------
983 911
984 912
985 913 _default_transformers = [
986 914 AssignSystemTransformer,
987 915 AssignMagicTransformer,
988 916 PyPromptTransformer,
989 917 IPyPromptTransformer,
990 918 ]
991 919
992 920 _default_checkers = [
993 921 EmacsChecker,
994 922 ShellEscapeChecker,
995 923 MacroChecker,
996 924 IPyAutocallChecker,
997 925 MultiLineMagicChecker,
998 926 EscCharsChecker,
999 927 AssignmentChecker,
1000 928 AutoMagicChecker,
1001 929 AliasChecker,
1002 930 PythonOpsChecker,
1003 931 AutocallChecker
1004 932 ]
1005 933
1006 934 _default_handlers = [
1007 935 PrefilterHandler,
1008 936 AliasHandler,
1009 937 ShellEscapeHandler,
1010 938 MacroHandler,
1011 939 MagicHandler,
1012 940 AutoHandler,
1013 941 HelpHandler,
1014 942 EmacsHandler
1015 943 ]
@@ -1,86 +1,138 b''
1 1 # encoding: utf-8
2 2 """
3 Simple utility for splitting user input.
3 Simple utility for splitting user input. This is used by both inputsplitter and
4 prefilter.
4 5
5 6 Authors:
6 7
7 8 * Brian Granger
8 9 * Fernando Perez
9 10 """
10 11
11 12 #-----------------------------------------------------------------------------
12 13 # Copyright (C) 2008-2009 The IPython Development Team
13 14 #
14 15 # Distributed under the terms of the BSD License. The full license is in
15 16 # the file COPYING, distributed as part of this software.
16 17 #-----------------------------------------------------------------------------
17 18
18 19 #-----------------------------------------------------------------------------
19 20 # Imports
20 21 #-----------------------------------------------------------------------------
21 22
22 23 import re
23 24 import sys
24 25
25 26 from IPython.utils import py3compat
26 27
27 28 #-----------------------------------------------------------------------------
28 29 # Main function
29 30 #-----------------------------------------------------------------------------
30 31
31
32 32 # RegExp for splitting line contents into pre-char//first word-method//rest.
33 33 # For clarity, each group in on one line.
34 34
35 # WARNING: update the regexp if the escapes in interactiveshell are changed, as they
36 # are hardwired in.
35 # WARNING: update the regexp if the escapes in interactiveshell are changed, as
36 # they are hardwired in.
37 37
38 38 # Although it's not solely driven by the regex, note that:
39 39 # ,;/% only trigger if they are the first character on the line
40 40 # ! and !! trigger if they are first char(s) *or* follow an indent
41 41 # ? triggers as first or last char.
42 42
43 # The four parts of the regex are:
44 # 1) pre: initial whitespace
45 # 2) esc: escape character
46 # 3) ifun: first word/method (mix of \w and '.')
47 # 4) the_rest: rest of line (separated from ifun by space if non-empty)
48 line_split = re.compile(r'^(\s*)'
49 r'([,;/%?]|!!?)?'
50 r'\s*([\w\.]+)'
51 r'(.*$|$)')
52
53 # r'[\w\.]+'
54 # r'\s*=\s*%.*'
43 line_split = re.compile("""
44 ^(\s*) # any leading space
45 ([,;/%]|!!?|\?\??)? # escape character or characters
46 \s*(%?[\w\.\*]*) # function/method, possibly with leading %
47 # to correctly treat things like '?%magic'
48 (.*?$|$) # rest of line
49 """, re.VERBOSE)
55 50
56 51 def split_user_input(line, pattern=None):
57 """Split user input into pre-char/whitespace, function part and rest.
58
59 This is currently handles lines with '=' in them in a very inconsistent
60 manner.
52 """Split user input into initial whitespace, escape character, function part
53 and the rest.
61 54 """
62 55 # We need to ensure that the rest of this routine deals only with unicode
63 56 line = py3compat.cast_unicode(line, sys.stdin.encoding or 'utf-8')
64 57
65 58 if pattern is None:
66 59 pattern = line_split
67 60 match = pattern.match(line)
68 61 if not match:
69 62 # print "match failed for line '%s'" % line
70 63 try:
71 64 ifun, the_rest = line.split(None,1)
72 65 except ValueError:
73 66 # print "split failed for line '%s'" % line
74 67 ifun, the_rest = line, u''
75 68 pre = re.match('^(\s*)(.*)',line).groups()[0]
76 69 esc = ""
77 70 else:
78 71 pre, esc, ifun, the_rest = match.groups()
79
80 if not py3compat.isidentifier(ifun, dotted=True):
81 the_rest = ifun + u' ' + the_rest
82 ifun = u''
83 72
84 73 #print 'line:<%s>' % line # dbg
85 74 #print 'pre <%s> ifun <%s> rest <%s>' % (pre,ifun.strip(),the_rest) # dbg
86 return pre, esc, ifun.strip(), the_rest.lstrip()
75 return pre, esc or '', ifun.strip(), the_rest.lstrip()
76
77 class LineInfo(object):
78 """A single line of input and associated info.
79
80 Includes the following as properties:
81
82 line
83 The original, raw line
84
85 continue_prompt
86 Is this line a continuation in a sequence of multiline input?
87
88 pre
89 Any leading whitespace.
90
91 esc
92 The escape character(s) in pre or the empty string if there isn't one.
93 Note that '!!' and '??' are possible values for esc. Otherwise it will
94 always be a single character.
95
96 ifun
97 The 'function part', which is basically the maximal initial sequence
98 of valid python identifiers and the '.' character. This is what is
99 checked for alias and magic transformations, used for auto-calling,
100 etc. In contrast to Python identifiers, it may start with "%" and contain
101 "*".
102
103 the_rest
104 Everything else on the line.
105 """
106 def __init__(self, line, continue_prompt=False):
107 self.line = line
108 self.continue_prompt = continue_prompt
109 self.pre, self.esc, self.ifun, self.the_rest = split_user_input(line)
110
111 self.pre_char = self.pre.strip()
112 if self.pre_char:
113 self.pre_whitespace = '' # No whitespace allowd before esc chars
114 else:
115 self.pre_whitespace = self.pre
116
117 self._oinfo = None
118
119 def ofind(self, ip):
120 """Do a full, attribute-walking lookup of the ifun in the various
121 namespaces for the given IPython InteractiveShell instance.
122
123 Return a dict with keys: found,obj,ospace,ismagic
124
125 Note: can cause state changes because of calling getattr, but should
126 only be run if autocall is on and if the line hasn't matched any
127 other, less dangerous handlers.
128
129 Does cache the results of the call, so can be called multiple times
130 without worrying about *further* damaging state.
131 """
132 if not self._oinfo:
133 # ip.shell._ofind is actually on the Magic class!
134 self._oinfo = ip.shell._ofind(self.ifun)
135 return self._oinfo
136
137 def __str__(self):
138 return "LineInfo [%s|%s|%s|%s]" %(self.pre, self.esc, self.ifun, self.the_rest)
@@ -1,698 +1,698 b''
1 1 # -*- coding: utf-8 -*-
2 2 """Tests for the inputsplitter module.
3 3
4 4 Authors
5 5 -------
6 6 * Fernando Perez
7 7 * Robert Kern
8 8 """
9 9 #-----------------------------------------------------------------------------
10 10 # Copyright (C) 2010 The IPython Development Team
11 11 #
12 12 # Distributed under the terms of the BSD License. The full license is in
13 13 # the file COPYING, distributed as part of this software.
14 14 #-----------------------------------------------------------------------------
15 15
16 16 #-----------------------------------------------------------------------------
17 17 # Imports
18 18 #-----------------------------------------------------------------------------
19 19 # stdlib
20 20 import unittest
21 21 import sys
22 22
23 23 # Third party
24 24 import nose.tools as nt
25 25
26 26 # Our own
27 27 from IPython.core import inputsplitter as isp
28 28 from IPython.testing import tools as tt
29 29
30 30 #-----------------------------------------------------------------------------
31 31 # Semi-complete examples (also used as tests)
32 32 #-----------------------------------------------------------------------------
33 33
34 34 # Note: at the bottom, there's a slightly more complete version of this that
35 35 # can be useful during development of code here.
36 36
37 37 def mini_interactive_loop(input_func):
38 38 """Minimal example of the logic of an interactive interpreter loop.
39 39
40 40 This serves as an example, and it is used by the test system with a fake
41 41 raw_input that simulates interactive input."""
42 42
43 43 from IPython.core.inputsplitter import InputSplitter
44 44
45 45 isp = InputSplitter()
46 46 # In practice, this input loop would be wrapped in an outside loop to read
47 47 # input indefinitely, until some exit/quit command was issued. Here we
48 48 # only illustrate the basic inner loop.
49 49 while isp.push_accepts_more():
50 50 indent = ' '*isp.indent_spaces
51 51 prompt = '>>> ' + indent
52 52 line = indent + input_func(prompt)
53 53 isp.push(line)
54 54
55 55 # Here we just return input so we can use it in a test suite, but a real
56 56 # interpreter would instead send it for execution somewhere.
57 57 src = isp.source_reset()
58 58 #print 'Input source was:\n', src # dbg
59 59 return src
60 60
61 61 #-----------------------------------------------------------------------------
62 62 # Test utilities, just for local use
63 63 #-----------------------------------------------------------------------------
64 64
65 65 def assemble(block):
66 66 """Assemble a block into multi-line sub-blocks."""
67 67 return ['\n'.join(sub_block)+'\n' for sub_block in block]
68 68
69 69
70 70 def pseudo_input(lines):
71 71 """Return a function that acts like raw_input but feeds the input list."""
72 72 ilines = iter(lines)
73 73 def raw_in(prompt):
74 74 try:
75 75 return next(ilines)
76 76 except StopIteration:
77 77 return ''
78 78 return raw_in
79 79
80 80 #-----------------------------------------------------------------------------
81 81 # Tests
82 82 #-----------------------------------------------------------------------------
83 83 def test_spaces():
84 84 tests = [('', 0),
85 85 (' ', 1),
86 86 ('\n', 0),
87 87 (' \n', 1),
88 88 ('x', 0),
89 89 (' x', 1),
90 90 (' x',2),
91 91 (' x',4),
92 92 # Note: tabs are counted as a single whitespace!
93 93 ('\tx', 1),
94 94 ('\t x', 2),
95 95 ]
96 96 tt.check_pairs(isp.num_ini_spaces, tests)
97 97
98 98
99 99 def test_remove_comments():
100 100 tests = [('text', 'text'),
101 101 ('text # comment', 'text '),
102 102 ('text # comment\n', 'text \n'),
103 103 ('text # comment \n', 'text \n'),
104 104 ('line # c \nline\n','line \nline\n'),
105 105 ('line # c \nline#c2 \nline\nline #c\n\n',
106 106 'line \nline\nline\nline \n\n'),
107 107 ]
108 108 tt.check_pairs(isp.remove_comments, tests)
109 109
110 110 def test_has_comment():
111 111 tests = [('text', False),
112 112 ('text #comment', True),
113 113 ('text #comment\n', True),
114 114 ('#comment', True),
115 115 ('#comment\n', True),
116 116 ('a = "#string"', False),
117 117 ('a = "#string" # comment', True),
118 118 ('a #comment not "string"', True),
119 119 ]
120 120 tt.check_pairs(isp.has_comment, tests)
121 121
122 122
123 123 def test_get_input_encoding():
124 124 encoding = isp.get_input_encoding()
125 125 nt.assert_true(isinstance(encoding, basestring))
126 126 # simple-minded check that at least encoding a simple string works with the
127 127 # encoding we got.
128 128 nt.assert_equal(u'test'.encode(encoding), b'test')
129 129
130 130
131 131 class NoInputEncodingTestCase(unittest.TestCase):
132 132 def setUp(self):
133 133 self.old_stdin = sys.stdin
134 134 class X: pass
135 135 fake_stdin = X()
136 136 sys.stdin = fake_stdin
137 137
138 138 def test(self):
139 139 # Verify that if sys.stdin has no 'encoding' attribute we do the right
140 140 # thing
141 141 enc = isp.get_input_encoding()
142 142 self.assertEqual(enc, 'ascii')
143 143
144 144 def tearDown(self):
145 145 sys.stdin = self.old_stdin
146 146
147 147
148 148 class InputSplitterTestCase(unittest.TestCase):
149 149 def setUp(self):
150 150 self.isp = isp.InputSplitter()
151 151
152 152 def test_reset(self):
153 153 isp = self.isp
154 154 isp.push('x=1')
155 155 isp.reset()
156 156 self.assertEqual(isp._buffer, [])
157 157 self.assertEqual(isp.indent_spaces, 0)
158 158 self.assertEqual(isp.source, '')
159 159 self.assertEqual(isp.code, None)
160 160 self.assertEqual(isp._is_complete, False)
161 161
162 162 def test_source(self):
163 163 self.isp._store('1')
164 164 self.isp._store('2')
165 165 self.assertEqual(self.isp.source, '1\n2\n')
166 166 self.assertTrue(len(self.isp._buffer)>0)
167 167 self.assertEqual(self.isp.source_reset(), '1\n2\n')
168 168 self.assertEqual(self.isp._buffer, [])
169 169 self.assertEqual(self.isp.source, '')
170 170
171 171 def test_indent(self):
172 172 isp = self.isp # shorthand
173 173 isp.push('x=1')
174 174 self.assertEqual(isp.indent_spaces, 0)
175 175 isp.push('if 1:\n x=1')
176 176 self.assertEqual(isp.indent_spaces, 4)
177 177 isp.push('y=2\n')
178 178 self.assertEqual(isp.indent_spaces, 0)
179 179
180 180 def test_indent2(self):
181 181 # In cell mode, inputs must be fed in whole blocks, so skip this test
182 182 if self.isp.input_mode == 'cell': return
183 183
184 184 isp = self.isp
185 185 isp.push('if 1:')
186 186 self.assertEqual(isp.indent_spaces, 4)
187 187 isp.push(' x=1')
188 188 self.assertEqual(isp.indent_spaces, 4)
189 189 # Blank lines shouldn't change the indent level
190 190 isp.push(' '*2)
191 191 self.assertEqual(isp.indent_spaces, 4)
192 192
193 193 def test_indent3(self):
194 194 # In cell mode, inputs must be fed in whole blocks, so skip this test
195 195 if self.isp.input_mode == 'cell': return
196 196
197 197 isp = self.isp
198 198 # When a multiline statement contains parens or multiline strings, we
199 199 # shouldn't get confused.
200 200 isp.push("if 1:")
201 201 isp.push(" x = (1+\n 2)")
202 202 self.assertEqual(isp.indent_spaces, 4)
203 203
204 204 def test_indent4(self):
205 205 # In cell mode, inputs must be fed in whole blocks, so skip this test
206 206 if self.isp.input_mode == 'cell': return
207 207
208 208 isp = self.isp
209 209 # whitespace after ':' should not screw up indent level
210 210 isp.push('if 1: \n x=1')
211 211 self.assertEqual(isp.indent_spaces, 4)
212 212 isp.push('y=2\n')
213 213 self.assertEqual(isp.indent_spaces, 0)
214 214 isp.push('if 1:\t\n x=1')
215 215 self.assertEqual(isp.indent_spaces, 4)
216 216 isp.push('y=2\n')
217 217 self.assertEqual(isp.indent_spaces, 0)
218 218
219 219 def test_dedent_pass(self):
220 220 isp = self.isp # shorthand
221 221 # should NOT cause dedent
222 222 isp.push('if 1:\n passes = 5')
223 223 self.assertEqual(isp.indent_spaces, 4)
224 224 isp.push('if 1:\n pass')
225 225 self.assertEqual(isp.indent_spaces, 0)
226 226 isp.push('if 1:\n pass ')
227 227 self.assertEqual(isp.indent_spaces, 0)
228 228
229 229 def test_dedent_raise(self):
230 230 isp = self.isp # shorthand
231 231 # should NOT cause dedent
232 232 isp.push('if 1:\n raised = 4')
233 233 self.assertEqual(isp.indent_spaces, 4)
234 234 isp.push('if 1:\n raise TypeError()')
235 235 self.assertEqual(isp.indent_spaces, 0)
236 236 isp.push('if 1:\n raise')
237 237 self.assertEqual(isp.indent_spaces, 0)
238 238 isp.push('if 1:\n raise ')
239 239 self.assertEqual(isp.indent_spaces, 0)
240 240
241 241 def test_dedent_return(self):
242 242 isp = self.isp # shorthand
243 243 # should NOT cause dedent
244 244 isp.push('if 1:\n returning = 4')
245 245 self.assertEqual(isp.indent_spaces, 4)
246 246 isp.push('if 1:\n return 5 + 493')
247 247 self.assertEqual(isp.indent_spaces, 0)
248 248 isp.push('if 1:\n return')
249 249 self.assertEqual(isp.indent_spaces, 0)
250 250 isp.push('if 1:\n return ')
251 251 self.assertEqual(isp.indent_spaces, 0)
252 252 isp.push('if 1:\n return(0)')
253 253 self.assertEqual(isp.indent_spaces, 0)
254 254
255 255 def test_push(self):
256 256 isp = self.isp
257 257 self.assertTrue(isp.push('x=1'))
258 258
259 259 def test_push2(self):
260 260 isp = self.isp
261 261 self.assertFalse(isp.push('if 1:'))
262 262 for line in [' x=1', '# a comment', ' y=2']:
263 263 self.assertTrue(isp.push(line))
264 264
265 265 def test_push3(self):
266 266 isp = self.isp
267 267 isp.push('if True:')
268 268 isp.push(' a = 1')
269 269 self.assertFalse(isp.push('b = [1,'))
270 270
271 271 def test_replace_mode(self):
272 272 isp = self.isp
273 273 isp.input_mode = 'cell'
274 274 isp.push('x=1')
275 275 self.assertEqual(isp.source, 'x=1\n')
276 276 isp.push('x=2')
277 277 self.assertEqual(isp.source, 'x=2\n')
278 278
279 279 def test_push_accepts_more(self):
280 280 isp = self.isp
281 281 isp.push('x=1')
282 282 self.assertFalse(isp.push_accepts_more())
283 283
284 284 def test_push_accepts_more2(self):
285 285 # In cell mode, inputs must be fed in whole blocks, so skip this test
286 286 if self.isp.input_mode == 'cell': return
287 287
288 288 isp = self.isp
289 289 isp.push('if 1:')
290 290 self.assertTrue(isp.push_accepts_more())
291 291 isp.push(' x=1')
292 292 self.assertTrue(isp.push_accepts_more())
293 293 isp.push('')
294 294 self.assertFalse(isp.push_accepts_more())
295 295
296 296 def test_push_accepts_more3(self):
297 297 isp = self.isp
298 298 isp.push("x = (2+\n3)")
299 299 self.assertFalse(isp.push_accepts_more())
300 300
301 301 def test_push_accepts_more4(self):
302 302 # In cell mode, inputs must be fed in whole blocks, so skip this test
303 303 if self.isp.input_mode == 'cell': return
304 304
305 305 isp = self.isp
306 306 # When a multiline statement contains parens or multiline strings, we
307 307 # shouldn't get confused.
308 308 # FIXME: we should be able to better handle de-dents in statements like
309 309 # multiline strings and multiline expressions (continued with \ or
310 310 # parens). Right now we aren't handling the indentation tracking quite
311 311 # correctly with this, though in practice it may not be too much of a
312 312 # problem. We'll need to see.
313 313 isp.push("if 1:")
314 314 isp.push(" x = (2+")
315 315 isp.push(" 3)")
316 316 self.assertTrue(isp.push_accepts_more())
317 317 isp.push(" y = 3")
318 318 self.assertTrue(isp.push_accepts_more())
319 319 isp.push('')
320 320 self.assertFalse(isp.push_accepts_more())
321 321
322 322 def test_push_accepts_more5(self):
323 323 # In cell mode, inputs must be fed in whole blocks, so skip this test
324 324 if self.isp.input_mode == 'cell': return
325 325
326 326 isp = self.isp
327 327 isp.push('try:')
328 328 isp.push(' a = 5')
329 329 isp.push('except:')
330 330 isp.push(' raise')
331 331 self.assertTrue(isp.push_accepts_more())
332 332
333 333 def test_continuation(self):
334 334 isp = self.isp
335 335 isp.push("import os, \\")
336 336 self.assertTrue(isp.push_accepts_more())
337 337 isp.push("sys")
338 338 self.assertFalse(isp.push_accepts_more())
339 339
340 340 def test_syntax_error(self):
341 341 isp = self.isp
342 342 # Syntax errors immediately produce a 'ready' block, so the invalid
343 343 # Python can be sent to the kernel for evaluation with possible ipython
344 344 # special-syntax conversion.
345 345 isp.push('run foo')
346 346 self.assertFalse(isp.push_accepts_more())
347 347
348 348 def test_unicode(self):
349 349 self.isp.push(u"PΓ©rez")
350 350 self.isp.push(u'\xc3\xa9')
351 351 self.isp.push(u"u'\xc3\xa9'")
352 352
353 353 class InteractiveLoopTestCase(unittest.TestCase):
354 354 """Tests for an interactive loop like a python shell.
355 355 """
356 356 def check_ns(self, lines, ns):
357 357 """Validate that the given input lines produce the resulting namespace.
358 358
359 359 Note: the input lines are given exactly as they would be typed in an
360 360 auto-indenting environment, as mini_interactive_loop above already does
361 361 auto-indenting and prepends spaces to the input.
362 362 """
363 363 src = mini_interactive_loop(pseudo_input(lines))
364 364 test_ns = {}
365 365 exec src in test_ns
366 366 # We can't check that the provided ns is identical to the test_ns,
367 367 # because Python fills test_ns with extra keys (copyright, etc). But
368 368 # we can check that the given dict is *contained* in test_ns
369 369 for k,v in ns.iteritems():
370 370 self.assertEqual(test_ns[k], v)
371 371
372 372 def test_simple(self):
373 373 self.check_ns(['x=1'], dict(x=1))
374 374
375 375 def test_simple2(self):
376 376 self.check_ns(['if 1:', 'x=2'], dict(x=2))
377 377
378 378 def test_xy(self):
379 379 self.check_ns(['x=1; y=2'], dict(x=1, y=2))
380 380
381 381 def test_abc(self):
382 382 self.check_ns(['if 1:','a=1','b=2','c=3'], dict(a=1, b=2, c=3))
383 383
384 384 def test_multi(self):
385 385 self.check_ns(['x =(1+','1+','2)'], dict(x=4))
386 386
387 387
388 388 def test_LineInfo():
389 389 """Simple test for LineInfo construction and str()"""
390 390 linfo = isp.LineInfo(' %cd /home')
391 391 nt.assert_equals(str(linfo), 'LineInfo [ |%|cd|/home]')
392 392
393 393
394 394 def test_split_user_input():
395 395 """Unicode test - split_user_input already has good doctests"""
396 396 line = u"PΓ©rez Fernando"
397 parts = isp.split_user_input(line)
398 397 parts_expected = (u'', u'', u'', line)
399 nt.assert_equal(parts, parts_expected)
398 tt.check_pairs(isp.split_user_input, [(line, parts_expected),])
400 399
401 400
402 401 # Transformer tests
403 402 def transform_checker(tests, func):
404 403 """Utility to loop over test inputs"""
405 404 for inp, tr in tests:
406 405 nt.assert_equals(func(inp), tr)
407 406
408 407 # Data for all the syntax tests in the form of lists of pairs of
409 408 # raw/transformed input. We store it here as a global dict so that we can use
410 409 # it both within single-function tests and also to validate the behavior of the
411 410 # larger objects
412 411
413 412 syntax = \
414 413 dict(assign_system =
415 414 [('a =! ls', 'a = get_ipython().getoutput(u"ls")'),
416 415 ('b = !ls', 'b = get_ipython().getoutput(u"ls")'),
417 416 ('x=1', 'x=1'), # normal input is unmodified
418 417 (' ',' '), # blank lines are kept intact
419 418 ],
420 419
421 420 assign_magic =
422 421 [('a =% who', 'a = get_ipython().magic(u"who")'),
423 422 ('b = %who', 'b = get_ipython().magic(u"who")'),
424 423 ('x=1', 'x=1'), # normal input is unmodified
425 424 (' ',' '), # blank lines are kept intact
426 425 ],
427 426
428 427 classic_prompt =
429 428 [('>>> x=1', 'x=1'),
430 429 ('x=1', 'x=1'), # normal input is unmodified
431 430 (' ', ' '), # blank lines are kept intact
432 431 ('... ', ''), # continuation prompts
433 432 ],
434 433
435 434 ipy_prompt =
436 435 [('In [1]: x=1', 'x=1'),
437 436 ('x=1', 'x=1'), # normal input is unmodified
438 437 (' ',' '), # blank lines are kept intact
439 438 (' ....: ', ''), # continuation prompts
440 439 ],
441 440
442 441 # Tests for the escape transformer to leave normal code alone
443 442 escaped_noesc =
444 443 [ (' ', ' '),
445 444 ('x=1', 'x=1'),
446 445 ],
447 446
448 447 # System calls
449 448 escaped_shell =
450 449 [ ('!ls', 'get_ipython().system(u"ls")'),
451 450 # Double-escape shell, this means to capture the output of the
452 451 # subprocess and return it
453 452 ('!!ls', 'get_ipython().getoutput(u"ls")'),
454 453 ],
455 454
456 455 # Help/object info
457 456 escaped_help =
458 457 [ ('?', 'get_ipython().show_usage()'),
459 458 ('?x1', 'get_ipython().magic(u"pinfo x1")'),
460 459 ('??x2', 'get_ipython().magic(u"pinfo2 x2")'),
461 460 ('?a.*s', 'get_ipython().magic(u"psearch a.*s")'),
462 461 ('?%hist', 'get_ipython().magic(u"pinfo %hist")'),
463 462 ('?abc = qwe', 'get_ipython().magic(u"pinfo abc")'),
464 463 ],
465 464
466 465 end_help =
467 466 [ ('x3?', 'get_ipython().magic(u"pinfo x3")'),
468 467 ('x4??', 'get_ipython().magic(u"pinfo2 x4")'),
469 468 ('%hist?', 'get_ipython().magic(u"pinfo %hist")'),
470 469 ('f*?', 'get_ipython().magic(u"psearch f*")'),
471 470 ('ax.*aspe*?', 'get_ipython().magic(u"psearch ax.*aspe*")'),
472 471 ('a = abc?', 'get_ipython().magic(u"pinfo abc", next_input=u"a = abc")'),
473 472 ('a = abc.qe??', 'get_ipython().magic(u"pinfo2 abc.qe", next_input=u"a = abc.qe")'),
474 473 ('a = *.items?', 'get_ipython().magic(u"psearch *.items", next_input=u"a = *.items")'),
475 474 ('plot(a?', 'get_ipython().magic(u"pinfo a", next_input=u"plot(a")'),
476 475 ('a*2 #comment?', 'a*2 #comment?'),
477 476 ],
478 477
479 478 # Explicit magic calls
480 479 escaped_magic =
481 480 [ ('%cd', 'get_ipython().magic(u"cd")'),
482 481 ('%cd /home', 'get_ipython().magic(u"cd /home")'),
483 482 (' %magic', ' get_ipython().magic(u"magic")'),
484 483 ],
485 484
486 485 # Quoting with separate arguments
487 486 escaped_quote =
488 487 [ (',f', 'f("")'),
489 488 (',f x', 'f("x")'),
490 489 (' ,f y', ' f("y")'),
491 490 (',f a b', 'f("a", "b")'),
492 491 ],
493 492
494 493 # Quoting with single argument
495 494 escaped_quote2 =
496 495 [ (';f', 'f("")'),
497 496 (';f x', 'f("x")'),
498 497 (' ;f y', ' f("y")'),
499 498 (';f a b', 'f("a b")'),
500 499 ],
501 500
502 501 # Simply apply parens
503 502 escaped_paren =
504 503 [ ('/f', 'f()'),
505 504 ('/f x', 'f(x)'),
506 505 (' /f y', ' f(y)'),
507 506 ('/f a b', 'f(a, b)'),
508 507 ],
509 508
510 509 # Check that we transform prompts before other transforms
511 510 mixed =
512 511 [ ('In [1]: %lsmagic', 'get_ipython().magic(u"lsmagic")'),
513 512 ('>>> %lsmagic', 'get_ipython().magic(u"lsmagic")'),
514 513 ('In [2]: !ls', 'get_ipython().system(u"ls")'),
515 514 ('In [3]: abs?', 'get_ipython().magic(u"pinfo abs")'),
516 515 ('In [4]: b = %who', 'b = get_ipython().magic(u"who")'),
517 516 ],
518 517 )
519 518
520 519 # multiline syntax examples. Each of these should be a list of lists, with
521 520 # each entry itself having pairs of raw/transformed input. The union (with
522 521 # '\n'.join() of the transformed inputs is what the splitter should produce
523 522 # when fed the raw lines one at a time via push.
524 523 syntax_ml = \
525 524 dict(classic_prompt =
526 525 [ [('>>> for i in range(10):','for i in range(10):'),
527 526 ('... print i',' print i'),
528 527 ('... ', ''),
529 528 ],
530 529 ],
531 530
532 531 ipy_prompt =
533 532 [ [('In [24]: for i in range(10):','for i in range(10):'),
534 533 (' ....: print i',' print i'),
535 534 (' ....: ', ''),
536 535 ],
537 536 ],
538 537 )
539 538
540 539
541 540 def test_assign_system():
542 541 tt.check_pairs(isp.transform_assign_system, syntax['assign_system'])
543 542
544 543
545 544 def test_assign_magic():
546 545 tt.check_pairs(isp.transform_assign_magic, syntax['assign_magic'])
547 546
548 547
549 548 def test_classic_prompt():
550 549 transform_checker(syntax['classic_prompt'], isp.transform_classic_prompt)
551 550 for example in syntax_ml['classic_prompt']:
552 551 transform_checker(example, isp.transform_classic_prompt)
553 552
554 553
555 554 def test_ipy_prompt():
556 555 transform_checker(syntax['ipy_prompt'], isp.transform_ipy_prompt)
557 556 for example in syntax_ml['ipy_prompt']:
558 557 transform_checker(example, isp.transform_ipy_prompt)
559 558
560 559 def test_end_help():
561 560 tt.check_pairs(isp.transform_help_end, syntax['end_help'])
562 561
563 562 def test_escaped_noesc():
564 563 tt.check_pairs(isp.transform_escaped, syntax['escaped_noesc'])
565 564
566 565
567 566 def test_escaped_shell():
568 567 tt.check_pairs(isp.transform_escaped, syntax['escaped_shell'])
569 568
570 569
571 570 def test_escaped_help():
572 571 tt.check_pairs(isp.transform_escaped, syntax['escaped_help'])
573 572
574 573
575 574 def test_escaped_magic():
576 575 tt.check_pairs(isp.transform_escaped, syntax['escaped_magic'])
577 576
578 577
579 578 def test_escaped_quote():
580 579 tt.check_pairs(isp.transform_escaped, syntax['escaped_quote'])
581 580
582 581
583 582 def test_escaped_quote2():
584 583 tt.check_pairs(isp.transform_escaped, syntax['escaped_quote2'])
585 584
586 585
587 586 def test_escaped_paren():
588 587 tt.check_pairs(isp.transform_escaped, syntax['escaped_paren'])
589 588
590 589
591 590 class IPythonInputTestCase(InputSplitterTestCase):
592 591 """By just creating a new class whose .isp is a different instance, we
593 592 re-run the same test battery on the new input splitter.
594 593
595 594 In addition, this runs the tests over the syntax and syntax_ml dicts that
596 595 were tested by individual functions, as part of the OO interface.
597 596
598 597 It also makes some checks on the raw buffer storage.
599 598 """
600 599
601 600 def setUp(self):
602 601 self.isp = isp.IPythonInputSplitter(input_mode='line')
603 602
604 603 def test_syntax(self):
605 604 """Call all single-line syntax tests from the main object"""
606 605 isp = self.isp
607 606 for example in syntax.itervalues():
608 607 for raw, out_t in example:
609 608 if raw.startswith(' '):
610 609 continue
611 610
612 611 isp.push(raw)
613 612 out, out_raw = isp.source_raw_reset()
614 self.assertEqual(out.rstrip(), out_t)
613 self.assertEqual(out.rstrip(), out_t,
614 tt.pair_fail_msg.format("inputsplitter",raw, out_t, out))
615 615 self.assertEqual(out_raw.rstrip(), raw.rstrip())
616 616
617 617 def test_syntax_multiline(self):
618 618 isp = self.isp
619 619 for example in syntax_ml.itervalues():
620 620 out_t_parts = []
621 621 raw_parts = []
622 622 for line_pairs in example:
623 623 for lraw, out_t_part in line_pairs:
624 624 isp.push(lraw)
625 625 out_t_parts.append(out_t_part)
626 626 raw_parts.append(lraw)
627 627
628 628 out, out_raw = isp.source_raw_reset()
629 629 out_t = '\n'.join(out_t_parts).rstrip()
630 630 raw = '\n'.join(raw_parts).rstrip()
631 631 self.assertEqual(out.rstrip(), out_t)
632 632 self.assertEqual(out_raw.rstrip(), raw)
633 633
634 634
635 635 class BlockIPythonInputTestCase(IPythonInputTestCase):
636 636
637 637 # Deactivate tests that don't make sense for the block mode
638 638 test_push3 = test_split = lambda s: None
639 639
640 640 def setUp(self):
641 641 self.isp = isp.IPythonInputSplitter(input_mode='cell')
642 642
643 643 def test_syntax_multiline(self):
644 644 isp = self.isp
645 645 for example in syntax_ml.itervalues():
646 646 raw_parts = []
647 647 out_t_parts = []
648 648 for line_pairs in example:
649 649 for raw, out_t_part in line_pairs:
650 650 raw_parts.append(raw)
651 651 out_t_parts.append(out_t_part)
652 652
653 653 raw = '\n'.join(raw_parts)
654 654 out_t = '\n'.join(out_t_parts)
655 655
656 656 isp.push(raw)
657 657 out, out_raw = isp.source_raw_reset()
658 658 # Match ignoring trailing whitespace
659 659 self.assertEqual(out.rstrip(), out_t.rstrip())
660 660 self.assertEqual(out_raw.rstrip(), raw.rstrip())
661 661
662 662
663 663 #-----------------------------------------------------------------------------
664 664 # Main - use as a script, mostly for developer experiments
665 665 #-----------------------------------------------------------------------------
666 666
667 667 if __name__ == '__main__':
668 668 # A simple demo for interactive experimentation. This code will not get
669 669 # picked up by any test suite.
670 670 from IPython.core.inputsplitter import InputSplitter, IPythonInputSplitter
671 671
672 672 # configure here the syntax to use, prompt and whether to autoindent
673 673 #isp, start_prompt = InputSplitter(), '>>> '
674 674 isp, start_prompt = IPythonInputSplitter(), 'In> '
675 675
676 676 autoindent = True
677 677 #autoindent = False
678 678
679 679 try:
680 680 while True:
681 681 prompt = start_prompt
682 682 while isp.push_accepts_more():
683 683 indent = ' '*isp.indent_spaces
684 684 if autoindent:
685 685 line = indent + raw_input(prompt+indent)
686 686 else:
687 687 line = raw_input(prompt)
688 688 isp.push(line)
689 689 prompt = '... '
690 690
691 691 # Here we just return input so we can use it in a test suite, but a
692 692 # real interpreter would instead send it for execution somewhere.
693 693 #src = isp.source; raise EOFError # dbg
694 694 src, raw = isp.source_raw_reset()
695 695 print 'Input source was:\n', src
696 696 print 'Raw source was:\n', raw
697 697 except EOFError:
698 698 print 'Bye'
@@ -1,345 +1,345 b''
1 1 """Generic testing tools that do NOT depend on Twisted.
2 2
3 3 In particular, this module exposes a set of top-level assert* functions that
4 4 can be used in place of nose.tools.assert* in method generators (the ones in
5 5 nose can not, at least as of nose 0.10.4).
6 6
7 7 Note: our testing package contains testing.util, which does depend on Twisted
8 8 and provides utilities for tests that manage Deferreds. All testing support
9 9 tools that only depend on nose, IPython or the standard library should go here
10 10 instead.
11 11
12 12
13 13 Authors
14 14 -------
15 15 - Fernando Perez <Fernando.Perez@berkeley.edu>
16 16 """
17 17
18 18 from __future__ import absolute_import
19 19
20 20 #-----------------------------------------------------------------------------
21 21 # Copyright (C) 2009 The IPython Development Team
22 22 #
23 23 # Distributed under the terms of the BSD License. The full license is in
24 24 # the file COPYING, distributed as part of this software.
25 25 #-----------------------------------------------------------------------------
26 26
27 27 #-----------------------------------------------------------------------------
28 28 # Imports
29 29 #-----------------------------------------------------------------------------
30 30
31 31 import os
32 32 import re
33 33 import sys
34 34 import tempfile
35 35
36 36 from contextlib import contextmanager
37 37
38 38 try:
39 39 # These tools are used by parts of the runtime, so we make the nose
40 40 # dependency optional at this point. Nose is a hard dependency to run the
41 41 # test suite, but NOT to use ipython itself.
42 42 import nose.tools as nt
43 43 has_nose = True
44 44 except ImportError:
45 45 has_nose = False
46 46
47 47 from IPython.config.loader import Config
48 48 from IPython.utils.process import find_cmd, getoutputerror
49 49 from IPython.utils.text import list_strings
50 50 from IPython.utils.io import temp_pyfile
51 51
52 52 from . import decorators as dec
53 53 from . import skipdoctest
54 54
55 55 #-----------------------------------------------------------------------------
56 56 # Globals
57 57 #-----------------------------------------------------------------------------
58 58
59 59 # Make a bunch of nose.tools assert wrappers that can be used in test
60 60 # generators. This will expose an assert* function for each one in nose.tools.
61 61
62 62 _tpl = """
63 63 def %(name)s(*a,**kw):
64 64 return nt.%(name)s(*a,**kw)
65 65 """
66 66
67 67 if has_nose:
68 68 for _x in [a for a in dir(nt) if a.startswith('assert')]:
69 69 exec _tpl % dict(name=_x)
70 70
71 71 #-----------------------------------------------------------------------------
72 72 # Functions and classes
73 73 #-----------------------------------------------------------------------------
74 74
75 75 # The docstring for full_path doctests differently on win32 (different path
76 76 # separator) so just skip the doctest there. The example remains informative.
77 77 doctest_deco = skipdoctest.skip_doctest if sys.platform == 'win32' else dec.null_deco
78 78
79 79 @doctest_deco
80 80 def full_path(startPath,files):
81 81 """Make full paths for all the listed files, based on startPath.
82 82
83 83 Only the base part of startPath is kept, since this routine is typically
84 84 used with a script's __file__ variable as startPath. The base of startPath
85 85 is then prepended to all the listed files, forming the output list.
86 86
87 87 Parameters
88 88 ----------
89 89 startPath : string
90 90 Initial path to use as the base for the results. This path is split
91 91 using os.path.split() and only its first component is kept.
92 92
93 93 files : string or list
94 94 One or more files.
95 95
96 96 Examples
97 97 --------
98 98
99 99 >>> full_path('/foo/bar.py',['a.txt','b.txt'])
100 100 ['/foo/a.txt', '/foo/b.txt']
101 101
102 102 >>> full_path('/foo',['a.txt','b.txt'])
103 103 ['/a.txt', '/b.txt']
104 104
105 105 If a single file is given, the output is still a list:
106 106 >>> full_path('/foo','a.txt')
107 107 ['/a.txt']
108 108 """
109 109
110 110 files = list_strings(files)
111 111 base = os.path.split(startPath)[0]
112 112 return [ os.path.join(base,f) for f in files ]
113 113
114 114
115 115 def parse_test_output(txt):
116 116 """Parse the output of a test run and return errors, failures.
117 117
118 118 Parameters
119 119 ----------
120 120 txt : str
121 121 Text output of a test run, assumed to contain a line of one of the
122 122 following forms::
123 123 'FAILED (errors=1)'
124 124 'FAILED (failures=1)'
125 125 'FAILED (errors=1, failures=1)'
126 126
127 127 Returns
128 128 -------
129 129 nerr, nfail: number of errors and failures.
130 130 """
131 131
132 132 err_m = re.search(r'^FAILED \(errors=(\d+)\)', txt, re.MULTILINE)
133 133 if err_m:
134 134 nerr = int(err_m.group(1))
135 135 nfail = 0
136 136 return nerr, nfail
137 137
138 138 fail_m = re.search(r'^FAILED \(failures=(\d+)\)', txt, re.MULTILINE)
139 139 if fail_m:
140 140 nerr = 0
141 141 nfail = int(fail_m.group(1))
142 142 return nerr, nfail
143 143
144 144 both_m = re.search(r'^FAILED \(errors=(\d+), failures=(\d+)\)', txt,
145 145 re.MULTILINE)
146 146 if both_m:
147 147 nerr = int(both_m.group(1))
148 148 nfail = int(both_m.group(2))
149 149 return nerr, nfail
150 150
151 151 # If the input didn't match any of these forms, assume no error/failures
152 152 return 0, 0
153 153
154 154
155 155 # So nose doesn't think this is a test
156 156 parse_test_output.__test__ = False
157 157
158 158
159 159 def default_argv():
160 160 """Return a valid default argv for creating testing instances of ipython"""
161 161
162 162 return ['--quick', # so no config file is loaded
163 163 # Other defaults to minimize side effects on stdout
164 164 '--colors=NoColor', '--no-term-title','--no-banner',
165 165 '--autocall=0']
166 166
167 167
168 168 def default_config():
169 169 """Return a config object with good defaults for testing."""
170 170 config = Config()
171 171 config.TerminalInteractiveShell.colors = 'NoColor'
172 172 config.TerminalTerminalInteractiveShell.term_title = False,
173 173 config.TerminalInteractiveShell.autocall = 0
174 174 config.HistoryManager.hist_file = tempfile.mktemp(u'test_hist.sqlite')
175 175 config.HistoryManager.db_cache_size = 10000
176 176 return config
177 177
178 178
179 179 def ipexec(fname, options=None):
180 180 """Utility to call 'ipython filename'.
181 181
182 182 Starts IPython witha minimal and safe configuration to make startup as fast
183 183 as possible.
184 184
185 185 Note that this starts IPython in a subprocess!
186 186
187 187 Parameters
188 188 ----------
189 189 fname : str
190 190 Name of file to be executed (should have .py or .ipy extension).
191 191
192 192 options : optional, list
193 193 Extra command-line flags to be passed to IPython.
194 194
195 195 Returns
196 196 -------
197 197 (stdout, stderr) of ipython subprocess.
198 198 """
199 199 if options is None: options = []
200 200
201 201 # For these subprocess calls, eliminate all prompt printing so we only see
202 202 # output from script execution
203 203 prompt_opts = [ '--InteractiveShell.prompt_in1=""',
204 204 '--InteractiveShell.prompt_in2=""',
205 205 '--InteractiveShell.prompt_out=""'
206 206 ]
207 207 cmdargs = ' '.join(default_argv() + prompt_opts + options)
208 208
209 209 _ip = get_ipython()
210 210 test_dir = os.path.dirname(__file__)
211 211
212 212 ipython_cmd = find_cmd('ipython')
213 213 # Absolute path for filename
214 214 full_fname = os.path.join(test_dir, fname)
215 215 full_cmd = '%s %s %s' % (ipython_cmd, cmdargs, full_fname)
216 216 #print >> sys.stderr, 'FULL CMD:', full_cmd # dbg
217 217 out = getoutputerror(full_cmd)
218 218 # `import readline` causes 'ESC[?1034h' to be the first output sometimes,
219 219 # so strip that off the front of the first line if it is found
220 220 if out:
221 221 first = out[0]
222 222 m = re.match(r'\x1b\[[^h]+h', first)
223 223 if m:
224 224 # strip initial readline escape
225 225 out = list(out)
226 226 out[0] = first[len(m.group()):]
227 227 out = tuple(out)
228 228 return out
229 229
230 230
231 231 def ipexec_validate(fname, expected_out, expected_err='',
232 232 options=None):
233 233 """Utility to call 'ipython filename' and validate output/error.
234 234
235 235 This function raises an AssertionError if the validation fails.
236 236
237 237 Note that this starts IPython in a subprocess!
238 238
239 239 Parameters
240 240 ----------
241 241 fname : str
242 242 Name of the file to be executed (should have .py or .ipy extension).
243 243
244 244 expected_out : str
245 245 Expected stdout of the process.
246 246
247 247 expected_err : optional, str
248 248 Expected stderr of the process.
249 249
250 250 options : optional, list
251 251 Extra command-line flags to be passed to IPython.
252 252
253 253 Returns
254 254 -------
255 255 None
256 256 """
257 257
258 258 import nose.tools as nt
259 259
260 260 out, err = ipexec(fname)
261 261 #print 'OUT', out # dbg
262 262 #print 'ERR', err # dbg
263 263 # If there are any errors, we must check those befor stdout, as they may be
264 264 # more informative than simply having an empty stdout.
265 265 if err:
266 266 if expected_err:
267 267 nt.assert_equals(err.strip(), expected_err.strip())
268 268 else:
269 269 raise ValueError('Running file %r produced error: %r' %
270 270 (fname, err))
271 271 # If no errors or output on stderr was expected, match stdout
272 272 nt.assert_equals(out.strip(), expected_out.strip())
273 273
274 274
275 275 class TempFileMixin(object):
276 276 """Utility class to create temporary Python/IPython files.
277 277
278 278 Meant as a mixin class for test cases."""
279 279
280 280 def mktmp(self, src, ext='.py'):
281 281 """Make a valid python temp file."""
282 282 fname, f = temp_pyfile(src, ext)
283 283 self.tmpfile = f
284 284 self.fname = fname
285 285
286 286 def tearDown(self):
287 287 if hasattr(self, 'tmpfile'):
288 288 # If the tmpfile wasn't made because of skipped tests, like in
289 289 # win32, there's nothing to cleanup.
290 290 self.tmpfile.close()
291 291 try:
292 292 os.unlink(self.fname)
293 293 except:
294 294 # On Windows, even though we close the file, we still can't
295 295 # delete it. I have no clue why
296 296 pass
297 297
298 pair_fail_msg = ("Testing function {0}\n\n"
298 pair_fail_msg = ("Testing {0}\n\n"
299 299 "In:\n"
300 300 " {1!r}\n"
301 301 "Expected:\n"
302 302 " {2!r}\n"
303 303 "Got:\n"
304 304 " {3!r}\n")
305 305 def check_pairs(func, pairs):
306 306 """Utility function for the common case of checking a function with a
307 307 sequence of input/output pairs.
308 308
309 309 Parameters
310 310 ----------
311 311 func : callable
312 312 The function to be tested. Should accept a single argument.
313 313 pairs : iterable
314 314 A list of (input, expected_output) tuples.
315 315
316 316 Returns
317 317 -------
318 318 None. Raises an AssertionError if any output does not match the expected
319 319 value.
320 320 """
321 name = getattr(func, "func_name", getattr(func, "__name__", "<unknown>"))
321 322 for inp, expected in pairs:
322 323 out = func(inp)
323 assert out == expected, pair_fail_msg.format(func.func_name, inp, expected, out)
324 assert out == expected, pair_fail_msg.format(name, inp, expected, out)
324 325
325 326 @contextmanager
326 327 def mute_warn():
327 328 from IPython.utils import warn
328 329 save_warn = warn.warn
329 330 warn.warn = lambda *a, **kw: None
330 331 try:
331 332 yield
332 333 finally:
333 334 warn.warn = save_warn
334 335
335 336 @contextmanager
336 337 def make_tempfile(name):
337 338 """ Create an empty, named, temporary file for the duration of the context.
338 339 """
339 340 f = open(name, 'w')
340 341 f.close()
341 342 try:
342 343 yield
343 344 finally:
344 345 os.unlink(name)
345
General Comments 0
You need to be logged in to leave comments. Login now