##// END OF EJS Templates
Return command to the next prompt if help was called halfway through a command. Also, ? at the end of a comment should not trigger help.
Thomas Kluyver -
Show More
@@ -1,862 +1,889 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 import tokenize
74 from StringIO import StringIO
73 75
74 76 # IPython modules
75 77 from IPython.utils.text import make_quoted_expr
76 78
77 79 #-----------------------------------------------------------------------------
78 80 # Globals
79 81 #-----------------------------------------------------------------------------
80 82
81 83 # The escape sequences that define the syntax transformations IPython will
82 84 # apply to user input. These can NOT be just changed here: many regular
83 85 # expressions and other parts of the code may use their hardcoded values, and
84 86 # for all intents and purposes they constitute the 'IPython syntax', so they
85 87 # should be considered fixed.
86 88
87 89 ESC_SHELL = '!' # Send line to underlying system shell
88 90 ESC_SH_CAP = '!!' # Send line to system shell and capture output
89 91 ESC_HELP = '?' # Find information about object
90 92 ESC_HELP2 = '??' # Find extra-detailed information about object
91 93 ESC_MAGIC = '%' # Call magic function
92 94 ESC_QUOTE = ',' # Split args on whitespace, quote each as string and call
93 95 ESC_QUOTE2 = ';' # Quote all args as a single string, call
94 96 ESC_PAREN = '/' # Call first argument with rest of line as arguments
95 97
96 98 #-----------------------------------------------------------------------------
97 99 # Utilities
98 100 #-----------------------------------------------------------------------------
99 101
100 102 # FIXME: These are general-purpose utilities that later can be moved to the
101 103 # general ward. Kept here for now because we're being very strict about test
102 104 # coverage with this code, and this lets us ensure that we keep 100% coverage
103 105 # while developing.
104 106
105 107 # compiled regexps for autoindent management
106 108 dedent_re = re.compile('|'.join([
107 109 r'^\s+raise(\s.*)?$', # raise statement (+ space + other stuff, maybe)
108 110 r'^\s+raise\([^\)]*\).*$', # wacky raise with immediate open paren
109 111 r'^\s+return(\s.*)?$', # normal return (+ space + other stuff, maybe)
110 112 r'^\s+return\([^\)]*\).*$', # wacky return with immediate open paren
111 113 r'^\s+pass\s*$' # pass (optionally followed by trailing spaces)
112 114 ]))
113 115 ini_spaces_re = re.compile(r'^([ \t\r\f\v]+)')
114 116
115 117 # regexp to match pure comment lines so we don't accidentally insert 'if 1:'
116 118 # before pure comments
117 119 comment_line_re = re.compile('^\s*\#')
118 120
119 121
120 122 def num_ini_spaces(s):
121 123 """Return the number of initial spaces in a string.
122 124
123 125 Note that tabs are counted as a single space. For now, we do *not* support
124 126 mixing of tabs and spaces in the user's input.
125 127
126 128 Parameters
127 129 ----------
128 130 s : string
129 131
130 132 Returns
131 133 -------
132 134 n : int
133 135 """
134 136
135 137 ini_spaces = ini_spaces_re.match(s)
136 138 if ini_spaces:
137 139 return ini_spaces.end()
138 140 else:
139 141 return 0
140 142
141 143
142 144 def remove_comments(src):
143 145 """Remove all comments from input source.
144 146
145 147 Note: comments are NOT recognized inside of strings!
146 148
147 149 Parameters
148 150 ----------
149 151 src : string
150 152 A single or multiline input string.
151 153
152 154 Returns
153 155 -------
154 156 String with all Python comments removed.
155 157 """
156 158
157 159 return re.sub('#.*', '', src)
160
161 def has_comment(src):
162 """Indicate whether an input line has (i.e. ends in, or is) a comment.
163
164 This uses tokenize, so it can distinguish comments from # inside strings.
165
166 Parameters
167 ----------
168 src : string
169 A single line input string.
170
171 Returns
172 -------
173 Boolean: True if source has a comment.
174 """
175 readline = StringIO(src).readline
176 toktypes = set(t[0] for t in tokenize.generate_tokens(readline))
177 return(tokenize.COMMENT in toktypes)
158 178
159 179
160 180 def get_input_encoding():
161 181 """Return the default standard input encoding.
162 182
163 183 If sys.stdin has no encoding, 'ascii' is returned."""
164 184 # There are strange environments for which sys.stdin.encoding is None. We
165 185 # ensure that a valid encoding is returned.
166 186 encoding = getattr(sys.stdin, 'encoding', None)
167 187 if encoding is None:
168 188 encoding = 'ascii'
169 189 return encoding
170 190
171 191 #-----------------------------------------------------------------------------
172 192 # Classes and functions for normal Python syntax handling
173 193 #-----------------------------------------------------------------------------
174 194
175 195 class InputSplitter(object):
176 196 """An object that can accumulate lines of Python source before execution.
177 197
178 198 This object is designed to be fed python source line-by-line, using
179 199 :meth:`push`. It will return on each push whether the currently pushed
180 200 code could be executed already. In addition, it provides a method called
181 201 :meth:`push_accepts_more` that can be used to query whether more input
182 202 can be pushed into a single interactive block.
183 203
184 204 This is a simple example of how an interactive terminal-based client can use
185 205 this tool::
186 206
187 207 isp = InputSplitter()
188 208 while isp.push_accepts_more():
189 209 indent = ' '*isp.indent_spaces
190 210 prompt = '>>> ' + indent
191 211 line = indent + raw_input(prompt)
192 212 isp.push(line)
193 213 print 'Input source was:\n', isp.source_reset(),
194 214 """
195 215 # Number of spaces of indentation computed from input that has been pushed
196 216 # so far. This is the attributes callers should query to get the current
197 217 # indentation level, in order to provide auto-indent facilities.
198 218 indent_spaces = 0
199 219 # String, indicating the default input encoding. It is computed by default
200 220 # at initialization time via get_input_encoding(), but it can be reset by a
201 221 # client with specific knowledge of the encoding.
202 222 encoding = ''
203 223 # String where the current full source input is stored, properly encoded.
204 224 # Reading this attribute is the normal way of querying the currently pushed
205 225 # source code, that has been properly encoded.
206 226 source = ''
207 227 # Code object corresponding to the current source. It is automatically
208 228 # synced to the source, so it can be queried at any time to obtain the code
209 229 # object; it will be None if the source doesn't compile to valid Python.
210 230 code = None
211 231 # Input mode
212 232 input_mode = 'line'
213 233
214 234 # Private attributes
215 235
216 236 # List with lines of input accumulated so far
217 237 _buffer = None
218 238 # Command compiler
219 239 _compile = None
220 240 # Mark when input has changed indentation all the way back to flush-left
221 241 _full_dedent = False
222 242 # Boolean indicating whether the current block is complete
223 243 _is_complete = None
224 244
225 245 def __init__(self, input_mode=None):
226 246 """Create a new InputSplitter instance.
227 247
228 248 Parameters
229 249 ----------
230 250 input_mode : str
231 251
232 252 One of ['line', 'cell']; default is 'line'.
233 253
234 254 The input_mode parameter controls how new inputs are used when fed via
235 255 the :meth:`push` method:
236 256
237 257 - 'line': meant for line-oriented clients, inputs are appended one at a
238 258 time to the internal buffer and the whole buffer is compiled.
239 259
240 260 - 'cell': meant for clients that can edit multi-line 'cells' of text at
241 261 a time. A cell can contain one or more blocks that can be compile in
242 262 'single' mode by Python. In this mode, each new input new input
243 263 completely replaces all prior inputs. Cell mode is thus equivalent
244 264 to prepending a full reset() to every push() call.
245 265 """
246 266 self._buffer = []
247 267 self._compile = codeop.CommandCompiler()
248 268 self.encoding = get_input_encoding()
249 269 self.input_mode = InputSplitter.input_mode if input_mode is None \
250 270 else input_mode
251 271
252 272 def reset(self):
253 273 """Reset the input buffer and associated state."""
254 274 self.indent_spaces = 0
255 275 self._buffer[:] = []
256 276 self.source = ''
257 277 self.code = None
258 278 self._is_complete = False
259 279 self._full_dedent = False
260 280
261 281 def source_reset(self):
262 282 """Return the input source and perform a full reset.
263 283 """
264 284 out = self.source
265 285 self.reset()
266 286 return out
267 287
268 288 def push(self, lines):
269 289 """Push one or more lines of input.
270 290
271 291 This stores the given lines and returns a status code indicating
272 292 whether the code forms a complete Python block or not.
273 293
274 294 Any exceptions generated in compilation are swallowed, but if an
275 295 exception was produced, the method returns True.
276 296
277 297 Parameters
278 298 ----------
279 299 lines : string
280 300 One or more lines of Python input.
281 301
282 302 Returns
283 303 -------
284 304 is_complete : boolean
285 305 True if the current input source (the result of the current input
286 306 plus prior inputs) forms a complete Python execution block. Note that
287 307 this value is also stored as a private attribute (_is_complete), so it
288 308 can be queried at any time.
289 309 """
290 310 if self.input_mode == 'cell':
291 311 self.reset()
292 312
293 313 self._store(lines)
294 314 source = self.source
295 315
296 316 # Before calling _compile(), reset the code object to None so that if an
297 317 # exception is raised in compilation, we don't mislead by having
298 318 # inconsistent code/source attributes.
299 319 self.code, self._is_complete = None, None
300 320
301 321 # Honor termination lines properly
302 322 if source.rstrip().endswith('\\'):
303 323 return False
304 324
305 325 self._update_indent(lines)
306 326 try:
307 327 self.code = self._compile(source, symbol="exec")
308 328 # Invalid syntax can produce any of a number of different errors from
309 329 # inside the compiler, so we have to catch them all. Syntax errors
310 330 # immediately produce a 'ready' block, so the invalid Python can be
311 331 # sent to the kernel for evaluation with possible ipython
312 332 # special-syntax conversion.
313 333 except (SyntaxError, OverflowError, ValueError, TypeError,
314 334 MemoryError):
315 335 self._is_complete = True
316 336 else:
317 337 # Compilation didn't produce any exceptions (though it may not have
318 338 # given a complete code object)
319 339 self._is_complete = self.code is not None
320 340
321 341 return self._is_complete
322 342
323 343 def push_accepts_more(self):
324 344 """Return whether a block of interactive input can accept more input.
325 345
326 346 This method is meant to be used by line-oriented frontends, who need to
327 347 guess whether a block is complete or not based solely on prior and
328 348 current input lines. The InputSplitter considers it has a complete
329 349 interactive block and will not accept more input only when either a
330 350 SyntaxError is raised, or *all* of the following are true:
331 351
332 352 1. The input compiles to a complete statement.
333 353
334 354 2. The indentation level is flush-left (because if we are indented,
335 355 like inside a function definition or for loop, we need to keep
336 356 reading new input).
337 357
338 358 3. There is one extra line consisting only of whitespace.
339 359
340 360 Because of condition #3, this method should be used only by
341 361 *line-oriented* frontends, since it means that intermediate blank lines
342 362 are not allowed in function definitions (or any other indented block).
343 363
344 364 Block-oriented frontends that have a separate keyboard event to
345 365 indicate execution should use the :meth:`split_blocks` method instead.
346 366
347 367 If the current input produces a syntax error, this method immediately
348 368 returns False but does *not* raise the syntax error exception, as
349 369 typically clients will want to send invalid syntax to an execution
350 370 backend which might convert the invalid syntax into valid Python via
351 371 one of the dynamic IPython mechanisms.
352 372 """
353 373
354 374 # With incomplete input, unconditionally accept more
355 375 if not self._is_complete:
356 376 return True
357 377
358 378 # If we already have complete input and we're flush left, the answer
359 379 # depends. In line mode, if there hasn't been any indentation,
360 380 # that's it. If we've come back from some indentation, we need
361 381 # the blank final line to finish.
362 382 # In cell mode, we need to check how many blocks the input so far
363 383 # compiles into, because if there's already more than one full
364 384 # independent block of input, then the client has entered full
365 385 # 'cell' mode and is feeding lines that each is complete. In this
366 386 # case we should then keep accepting. The Qt terminal-like console
367 387 # does precisely this, to provide the convenience of terminal-like
368 388 # input of single expressions, but allowing the user (with a
369 389 # separate keystroke) to switch to 'cell' mode and type multiple
370 390 # expressions in one shot.
371 391 if self.indent_spaces==0:
372 392 if self.input_mode=='line':
373 393 if not self._full_dedent:
374 394 return False
375 395 else:
376 396 try:
377 397 code_ast = ast.parse(u''.join(self._buffer))
378 398 except Exception:
379 399 return False
380 400 else:
381 401 if len(code_ast.body) == 1:
382 402 return False
383 403
384 404 # When input is complete, then termination is marked by an extra blank
385 405 # line at the end.
386 406 last_line = self.source.splitlines()[-1]
387 407 return bool(last_line and not last_line.isspace())
388 408
389 409 #------------------------------------------------------------------------
390 410 # Private interface
391 411 #------------------------------------------------------------------------
392 412
393 413 def _find_indent(self, line):
394 414 """Compute the new indentation level for a single line.
395 415
396 416 Parameters
397 417 ----------
398 418 line : str
399 419 A single new line of non-whitespace, non-comment Python input.
400 420
401 421 Returns
402 422 -------
403 423 indent_spaces : int
404 424 New value for the indent level (it may be equal to self.indent_spaces
405 425 if indentation doesn't change.
406 426
407 427 full_dedent : boolean
408 428 Whether the new line causes a full flush-left dedent.
409 429 """
410 430 indent_spaces = self.indent_spaces
411 431 full_dedent = self._full_dedent
412 432
413 433 inisp = num_ini_spaces(line)
414 434 if inisp < indent_spaces:
415 435 indent_spaces = inisp
416 436 if indent_spaces <= 0:
417 437 #print 'Full dedent in text',self.source # dbg
418 438 full_dedent = True
419 439
420 440 if line[-1] == ':':
421 441 indent_spaces += 4
422 442 elif dedent_re.match(line):
423 443 indent_spaces -= 4
424 444 if indent_spaces <= 0:
425 445 full_dedent = True
426 446
427 447 # Safety
428 448 if indent_spaces < 0:
429 449 indent_spaces = 0
430 450 #print 'safety' # dbg
431 451
432 452 return indent_spaces, full_dedent
433 453
434 454 def _update_indent(self, lines):
435 455 for line in remove_comments(lines).splitlines():
436 456 if line and not line.isspace():
437 457 self.indent_spaces, self._full_dedent = self._find_indent(line)
438 458
439 459 def _store(self, lines, buffer=None, store='source'):
440 460 """Store one or more lines of input.
441 461
442 462 If input lines are not newline-terminated, a newline is automatically
443 463 appended."""
444 464
445 465 if buffer is None:
446 466 buffer = self._buffer
447 467
448 468 if lines.endswith('\n'):
449 469 buffer.append(lines)
450 470 else:
451 471 buffer.append(lines+'\n')
452 472 setattr(self, store, self._set_source(buffer))
453 473
454 474 def _set_source(self, buffer):
455 475 return u''.join(buffer)
456 476
457 477
458 478 #-----------------------------------------------------------------------------
459 479 # Functions and classes for IPython-specific syntactic support
460 480 #-----------------------------------------------------------------------------
461 481
462 482 # RegExp for splitting line contents into pre-char//first word-method//rest.
463 483 # For clarity, each group in on one line.
464 484
465 485 line_split = re.compile("""
466 486 ^(\s*) # any leading space
467 487 ([,;/%]|!!?|\?\??) # escape character or characters
468 488 \s*(%?[\w\.\*]*) # function/method, possibly with leading %
469 489 # to correctly treat things like '?%magic'
470 490 (\s+.*$|$) # rest of line
471 491 """, re.VERBOSE)
472 492
473 493
474 494 def split_user_input(line):
475 495 """Split user input into early whitespace, esc-char, function part and rest.
476 496
477 497 This is currently handles lines with '=' in them in a very inconsistent
478 498 manner.
479 499
480 500 Examples
481 501 ========
482 502 >>> split_user_input('x=1')
483 503 ('', '', 'x=1', '')
484 504 >>> split_user_input('?')
485 505 ('', '?', '', '')
486 506 >>> split_user_input('??')
487 507 ('', '??', '', '')
488 508 >>> split_user_input(' ?')
489 509 (' ', '?', '', '')
490 510 >>> split_user_input(' ??')
491 511 (' ', '??', '', '')
492 512 >>> split_user_input('??x')
493 513 ('', '??', 'x', '')
494 514 >>> split_user_input('?x=1')
495 515 ('', '', '?x=1', '')
496 516 >>> split_user_input('!ls')
497 517 ('', '!', 'ls', '')
498 518 >>> split_user_input(' !ls')
499 519 (' ', '!', 'ls', '')
500 520 >>> split_user_input('!!ls')
501 521 ('', '!!', 'ls', '')
502 522 >>> split_user_input(' !!ls')
503 523 (' ', '!!', 'ls', '')
504 524 >>> split_user_input(',ls')
505 525 ('', ',', 'ls', '')
506 526 >>> split_user_input(';ls')
507 527 ('', ';', 'ls', '')
508 528 >>> split_user_input(' ;ls')
509 529 (' ', ';', 'ls', '')
510 530 >>> split_user_input('f.g(x)')
511 531 ('', '', 'f.g(x)', '')
512 532 >>> split_user_input('f.g (x)')
513 533 ('', '', 'f.g', '(x)')
514 534 >>> split_user_input('?%hist')
515 535 ('', '?', '%hist', '')
516 536 >>> split_user_input('?x*')
517 537 ('', '?', 'x*', '')
518 538 """
519 539 match = line_split.match(line)
520 540 if match:
521 541 lspace, esc, fpart, rest = match.groups()
522 542 else:
523 543 # print "match failed for line '%s'" % line
524 544 try:
525 545 fpart, rest = line.split(None, 1)
526 546 except ValueError:
527 547 # print "split failed for line '%s'" % line
528 548 fpart, rest = line,''
529 549 lspace = re.match('^(\s*)(.*)', line).groups()[0]
530 550 esc = ''
531 551
532 552 # fpart has to be a valid python identifier, so it better be only pure
533 553 # ascii, no unicode:
534 554 try:
535 555 fpart = fpart.encode('ascii')
536 556 except UnicodeEncodeError:
537 557 lspace = unicode(lspace)
538 558 rest = fpart + u' ' + rest
539 559 fpart = u''
540 560
541 561 #print 'line:<%s>' % line # dbg
542 562 #print 'esc <%s> fpart <%s> rest <%s>' % (esc,fpart.strip(),rest) # dbg
543 563 return lspace, esc, fpart.strip(), rest.lstrip()
544 564
545 565
546 566 # The escaped translators ALL receive a line where their own escape has been
547 567 # stripped. Only '?' is valid at the end of the line, all others can only be
548 568 # placed at the start.
549 569
550 570 class LineInfo(object):
551 571 """A single line of input and associated info.
552 572
553 573 This is a utility class that mostly wraps the output of
554 574 :func:`split_user_input` into a convenient object to be passed around
555 575 during input transformations.
556 576
557 577 Includes the following as properties:
558 578
559 579 line
560 580 The original, raw line
561 581
562 582 lspace
563 583 Any early whitespace before actual text starts.
564 584
565 585 esc
566 586 The initial esc character (or characters, for double-char escapes like
567 587 '??' or '!!').
568 588
569 589 fpart
570 590 The 'function part', which is basically the maximal initial sequence
571 591 of valid python identifiers and the '.' character. This is what is
572 592 checked for alias and magic transformations, used for auto-calling,
573 593 etc.
574 594
575 595 rest
576 596 Everything else on the line.
577 597 """
578 598 def __init__(self, line):
579 599 self.line = line
580 600 self.lspace, self.esc, self.fpart, self.rest = \
581 601 split_user_input(line)
582 602
583 603 def __str__(self):
584 604 return "LineInfo [%s|%s|%s|%s]" % (self.lspace, self.esc,
585 605 self.fpart, self.rest)
586 606
587 607
588 608 # Transformations of the special syntaxes that don't rely on an explicit escape
589 609 # character but instead on patterns on the input line
590 610
591 611 # The core transformations are implemented as standalone functions that can be
592 612 # tested and validated in isolation. Each of these uses a regexp, we
593 613 # pre-compile these and keep them close to each function definition for clarity
594 614
595 615 _assign_system_re = re.compile(r'(?P<lhs>(\s*)([\w\.]+)((\s*,\s*[\w\.]+)*))'
596 616 r'\s*=\s*!\s*(?P<cmd>.*)')
597 617
598 618 def transform_assign_system(line):
599 619 """Handle the `files = !ls` syntax."""
600 620 m = _assign_system_re.match(line)
601 621 if m is not None:
602 622 cmd = m.group('cmd')
603 623 lhs = m.group('lhs')
604 624 expr = make_quoted_expr(cmd)
605 625 new_line = '%s = get_ipython().getoutput(%s)' % (lhs, expr)
606 626 return new_line
607 627 return line
608 628
609 629
610 630 _assign_magic_re = re.compile(r'(?P<lhs>(\s*)([\w\.]+)((\s*,\s*[\w\.]+)*))'
611 631 r'\s*=\s*%\s*(?P<cmd>.*)')
612 632
613 633 def transform_assign_magic(line):
614 634 """Handle the `a = %who` syntax."""
615 635 m = _assign_magic_re.match(line)
616 636 if m is not None:
617 637 cmd = m.group('cmd')
618 638 lhs = m.group('lhs')
619 639 expr = make_quoted_expr(cmd)
620 640 new_line = '%s = get_ipython().magic(%s)' % (lhs, expr)
621 641 return new_line
622 642 return line
623 643
624 644
625 645 _classic_prompt_re = re.compile(r'^([ \t]*>>> |^[ \t]*\.\.\. )')
626 646
627 647 def transform_classic_prompt(line):
628 648 """Handle inputs that start with '>>> ' syntax."""
629 649
630 650 if not line or line.isspace():
631 651 return line
632 652 m = _classic_prompt_re.match(line)
633 653 if m:
634 654 return line[len(m.group(0)):]
635 655 else:
636 656 return line
637 657
638 658
639 659 _ipy_prompt_re = re.compile(r'^([ \t]*In \[\d+\]: |^[ \t]*\ \ \ \.\.\.+: )')
640 660
641 661 def transform_ipy_prompt(line):
642 662 """Handle inputs that start classic IPython prompt syntax."""
643 663
644 664 if not line or line.isspace():
645 665 return line
646 666 #print 'LINE: %r' % line # dbg
647 667 m = _ipy_prompt_re.match(line)
648 668 if m:
649 669 #print 'MATCH! %r -> %r' % (line, line[len(m.group(0)):]) # dbg
650 670 return line[len(m.group(0)):]
651 671 else:
652 672 return line
653 673
654 674
655 675 def _make_help_call(target, esc, lspace):
656 676 """Prepares a pinfo(2)/psearch call from a target name and the escape
657 677 (i.e. ? or ??)"""
658 678 method = 'pinfo2' if esc == '??' \
659 679 else 'psearch' if '*' in target \
660 680 else 'pinfo'
661 681
662 682 tpl = '%sget_ipython().magic(u"%s %s")'
663 683 return tpl % (lspace, method, target)
664 684
665 685 _initial_space_re = re.compile(r'\s*')
666 686 _help_end_re = re.compile(r"""(%?
667 687 [a-zA-Z_*][a-zA-Z0-9_*]* # Variable name
668 688 (\.[a-zA-Z_*][a-zA-Z0-9_*]*)* # .etc.etc
669 689 )
670 690 (\?\??)$ # ? or ??""",
671 691 re.VERBOSE)
672 692 def transform_help_end(line):
673 693 """Translate lines with ?/?? at the end"""
674 694 m = _help_end_re.search(line)
675 if m is None:
695 if m is None or has_comment(line):
676 696 return line
677 697 target = m.group(1)
678 698 esc = m.group(3)
679 699 lspace = _initial_space_re.match(line).group(0)
680 return _make_help_call(target, esc, lspace)
700 newline = _make_help_call(target, esc, lspace)
701
702 # If we're mid-command, put it back on the next prompt for the user.
703 if line.strip() != m.group(0):
704 newline += "; get_ipython().set_next_input(%s)" % \
705 make_quoted_expr(line.rstrip('?'))
706
707 return newline
681 708
682 709
683 710 class EscapedTransformer(object):
684 711 """Class to transform lines that are explicitly escaped out."""
685 712
686 713 def __init__(self):
687 714 tr = { ESC_SHELL : self._tr_system,
688 715 ESC_SH_CAP : self._tr_system2,
689 716 ESC_HELP : self._tr_help,
690 717 ESC_HELP2 : self._tr_help,
691 718 ESC_MAGIC : self._tr_magic,
692 719 ESC_QUOTE : self._tr_quote,
693 720 ESC_QUOTE2 : self._tr_quote2,
694 721 ESC_PAREN : self._tr_paren }
695 722 self.tr = tr
696 723
697 724 # Support for syntax transformations that use explicit escapes typed by the
698 725 # user at the beginning of a line
699 726 @staticmethod
700 727 def _tr_system(line_info):
701 728 "Translate lines escaped with: !"
702 729 cmd = line_info.line.lstrip().lstrip(ESC_SHELL)
703 730 return '%sget_ipython().system(%s)' % (line_info.lspace,
704 731 make_quoted_expr(cmd))
705 732
706 733 @staticmethod
707 734 def _tr_system2(line_info):
708 735 "Translate lines escaped with: !!"
709 736 cmd = line_info.line.lstrip()[2:]
710 737 return '%sget_ipython().getoutput(%s)' % (line_info.lspace,
711 738 make_quoted_expr(cmd))
712 739
713 740 @staticmethod
714 741 def _tr_help(line_info):
715 742 "Translate lines escaped with: ?/??"
716 743 # A naked help line should just fire the intro help screen
717 744 if not line_info.line[1:]:
718 745 return 'get_ipython().show_usage()'
719 746
720 747 return _make_help_call(line_info.fpart, line_info.esc, line_info.lspace)
721 748
722 749 @staticmethod
723 750 def _tr_magic(line_info):
724 751 "Translate lines escaped with: %"
725 752 tpl = '%sget_ipython().magic(%s)'
726 753 cmd = make_quoted_expr(' '.join([line_info.fpart,
727 754 line_info.rest]).strip())
728 755 return tpl % (line_info.lspace, cmd)
729 756
730 757 @staticmethod
731 758 def _tr_quote(line_info):
732 759 "Translate lines escaped with: ,"
733 760 return '%s%s("%s")' % (line_info.lspace, line_info.fpart,
734 761 '", "'.join(line_info.rest.split()) )
735 762
736 763 @staticmethod
737 764 def _tr_quote2(line_info):
738 765 "Translate lines escaped with: ;"
739 766 return '%s%s("%s")' % (line_info.lspace, line_info.fpart,
740 767 line_info.rest)
741 768
742 769 @staticmethod
743 770 def _tr_paren(line_info):
744 771 "Translate lines escaped with: /"
745 772 return '%s%s(%s)' % (line_info.lspace, line_info.fpart,
746 773 ", ".join(line_info.rest.split()))
747 774
748 775 def __call__(self, line):
749 776 """Class to transform lines that are explicitly escaped out.
750 777
751 778 This calls the above _tr_* static methods for the actual line
752 779 translations."""
753 780
754 781 # Empty lines just get returned unmodified
755 782 if not line or line.isspace():
756 783 return line
757 784
758 785 # Get line endpoints, where the escapes can be
759 786 line_info = LineInfo(line)
760 787
761 788 if not line_info.esc in self.tr:
762 789 # If we don't recognize the escape, don't modify the line
763 790 return line
764 791
765 792 return self.tr[line_info.esc](line_info)
766 793
767 794
768 795 # A function-looking object to be used by the rest of the code. The purpose of
769 796 # the class in this case is to organize related functionality, more than to
770 797 # manage state.
771 798 transform_escaped = EscapedTransformer()
772 799
773 800
774 801 class IPythonInputSplitter(InputSplitter):
775 802 """An input splitter that recognizes all of IPython's special syntax."""
776 803
777 804 # String with raw, untransformed input.
778 805 source_raw = ''
779 806
780 807 # Private attributes
781 808
782 809 # List with lines of raw input accumulated so far.
783 810 _buffer_raw = None
784 811
785 812 def __init__(self, input_mode=None):
786 813 InputSplitter.__init__(self, input_mode)
787 814 self._buffer_raw = []
788 815
789 816 def reset(self):
790 817 """Reset the input buffer and associated state."""
791 818 InputSplitter.reset(self)
792 819 self._buffer_raw[:] = []
793 820 self.source_raw = ''
794 821
795 822 def source_raw_reset(self):
796 823 """Return input and raw source and perform a full reset.
797 824 """
798 825 out = self.source
799 826 out_r = self.source_raw
800 827 self.reset()
801 828 return out, out_r
802 829
803 830 def push(self, lines):
804 831 """Push one or more lines of IPython input.
805 832 """
806 833 if not lines:
807 834 return super(IPythonInputSplitter, self).push(lines)
808 835
809 836 # We must ensure all input is pure unicode
810 837 if type(lines)==str:
811 838 lines = lines.decode(self.encoding)
812 839
813 840 lines_list = lines.splitlines()
814 841
815 842 transforms = [transform_ipy_prompt, transform_classic_prompt,
816 843 transform_escaped, transform_help_end,
817 844 transform_assign_system, transform_assign_magic]
818 845
819 846 # Transform logic
820 847 #
821 848 # We only apply the line transformers to the input if we have either no
822 849 # input yet, or complete input, or if the last line of the buffer ends
823 850 # with ':' (opening an indented block). This prevents the accidental
824 851 # transformation of escapes inside multiline expressions like
825 852 # triple-quoted strings or parenthesized expressions.
826 853 #
827 854 # The last heuristic, while ugly, ensures that the first line of an
828 855 # indented block is correctly transformed.
829 856 #
830 857 # FIXME: try to find a cleaner approach for this last bit.
831 858
832 859 # If we were in 'block' mode, since we're going to pump the parent
833 860 # class by hand line by line, we need to temporarily switch out to
834 861 # 'line' mode, do a single manual reset and then feed the lines one
835 862 # by one. Note that this only matters if the input has more than one
836 863 # line.
837 864 changed_input_mode = False
838 865
839 866 if self.input_mode == 'cell':
840 867 self.reset()
841 868 changed_input_mode = True
842 869 saved_input_mode = 'cell'
843 870 self.input_mode = 'line'
844 871
845 872 # Store raw source before applying any transformations to it. Note
846 873 # that this must be done *after* the reset() call that would otherwise
847 874 # flush the buffer.
848 875 self._store(lines, self._buffer_raw, 'source_raw')
849 876
850 877 try:
851 878 push = super(IPythonInputSplitter, self).push
852 879 for line in lines_list:
853 880 if self._is_complete or not self._buffer or \
854 881 (self._buffer and self._buffer[-1].rstrip().endswith(':')):
855 882 for f in transforms:
856 883 line = f(line)
857 884
858 885 out = push(line)
859 886 finally:
860 887 if changed_input_mode:
861 888 self.input_mode = saved_input_mode
862 889 return out
@@ -1,672 +1,682 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 from IPython.testing import tools as tt
28 29
29 30 #-----------------------------------------------------------------------------
30 31 # Semi-complete examples (also used as tests)
31 32 #-----------------------------------------------------------------------------
32 33
33 34 # Note: at the bottom, there's a slightly more complete version of this that
34 35 # can be useful during development of code here.
35 36
36 37 def mini_interactive_loop(input_func):
37 38 """Minimal example of the logic of an interactive interpreter loop.
38 39
39 40 This serves as an example, and it is used by the test system with a fake
40 41 raw_input that simulates interactive input."""
41 42
42 43 from IPython.core.inputsplitter import InputSplitter
43 44
44 45 isp = InputSplitter()
45 46 # In practice, this input loop would be wrapped in an outside loop to read
46 47 # input indefinitely, until some exit/quit command was issued. Here we
47 48 # only illustrate the basic inner loop.
48 49 while isp.push_accepts_more():
49 50 indent = ' '*isp.indent_spaces
50 51 prompt = '>>> ' + indent
51 52 line = indent + input_func(prompt)
52 53 isp.push(line)
53 54
54 55 # Here we just return input so we can use it in a test suite, but a real
55 56 # interpreter would instead send it for execution somewhere.
56 57 src = isp.source_reset()
57 58 #print 'Input source was:\n', src # dbg
58 59 return src
59 60
60 61 #-----------------------------------------------------------------------------
61 62 # Test utilities, just for local use
62 63 #-----------------------------------------------------------------------------
63 64
64 65 def assemble(block):
65 66 """Assemble a block into multi-line sub-blocks."""
66 67 return ['\n'.join(sub_block)+'\n' for sub_block in block]
67 68
68 69
69 70 def pseudo_input(lines):
70 71 """Return a function that acts like raw_input but feeds the input list."""
71 72 ilines = iter(lines)
72 73 def raw_in(prompt):
73 74 try:
74 75 return next(ilines)
75 76 except StopIteration:
76 77 return ''
77 78 return raw_in
78 79
79 80 #-----------------------------------------------------------------------------
80 81 # Tests
81 82 #-----------------------------------------------------------------------------
82 83 def test_spaces():
83 84 tests = [('', 0),
84 85 (' ', 1),
85 86 ('\n', 0),
86 87 (' \n', 1),
87 88 ('x', 0),
88 89 (' x', 1),
89 90 (' x',2),
90 91 (' x',4),
91 92 # Note: tabs are counted as a single whitespace!
92 93 ('\tx', 1),
93 94 ('\t x', 2),
94 95 ]
95
96 for s, nsp in tests:
97 nt.assert_equal(isp.num_ini_spaces(s), nsp)
96 tt.check_pairs(isp.num_ini_spaces, tests)
98 97
99 98
100 99 def test_remove_comments():
101 100 tests = [('text', 'text'),
102 101 ('text # comment', 'text '),
103 102 ('text # comment\n', 'text \n'),
104 103 ('text # comment \n', 'text \n'),
105 104 ('line # c \nline\n','line \nline\n'),
106 105 ('line # c \nline#c2 \nline\nline #c\n\n',
107 106 'line \nline\nline\nline \n\n'),
108 107 ]
109
110 for inp, out in tests:
111 nt.assert_equal(isp.remove_comments(inp), out)
108 tt.check_pairs(isp.remove_comments, tests)
109
110 def test_has_comment():
111 tests = [('text', False),
112 ('text #comment', True),
113 ('text #comment\n', True),
114 ('#comment', True),
115 ('#comment\n', True),
116 ('a = "#string"', False),
117 ('a = "#string" # comment', True),
118 ('a #comment not "string"', True),
119 ]
120 tt.check_pairs(isp.has_comment, tests)
112 121
113 122
114 123 def test_get_input_encoding():
115 124 encoding = isp.get_input_encoding()
116 125 nt.assert_true(isinstance(encoding, basestring))
117 126 # simple-minded check that at least encoding a simple string works with the
118 127 # encoding we got.
119 128 nt.assert_equal('test'.encode(encoding), 'test')
120 129
121 130
122 131 class NoInputEncodingTestCase(unittest.TestCase):
123 132 def setUp(self):
124 133 self.old_stdin = sys.stdin
125 134 class X: pass
126 135 fake_stdin = X()
127 136 sys.stdin = fake_stdin
128 137
129 138 def test(self):
130 139 # Verify that if sys.stdin has no 'encoding' attribute we do the right
131 140 # thing
132 141 enc = isp.get_input_encoding()
133 142 self.assertEqual(enc, 'ascii')
134 143
135 144 def tearDown(self):
136 145 sys.stdin = self.old_stdin
137 146
138 147
139 148 class InputSplitterTestCase(unittest.TestCase):
140 149 def setUp(self):
141 150 self.isp = isp.InputSplitter()
142 151
143 152 def test_reset(self):
144 153 isp = self.isp
145 154 isp.push('x=1')
146 155 isp.reset()
147 156 self.assertEqual(isp._buffer, [])
148 157 self.assertEqual(isp.indent_spaces, 0)
149 158 self.assertEqual(isp.source, '')
150 159 self.assertEqual(isp.code, None)
151 160 self.assertEqual(isp._is_complete, False)
152 161
153 162 def test_source(self):
154 163 self.isp._store('1')
155 164 self.isp._store('2')
156 165 self.assertEqual(self.isp.source, '1\n2\n')
157 166 self.assertTrue(len(self.isp._buffer)>0)
158 167 self.assertEqual(self.isp.source_reset(), '1\n2\n')
159 168 self.assertEqual(self.isp._buffer, [])
160 169 self.assertEqual(self.isp.source, '')
161 170
162 171 def test_indent(self):
163 172 isp = self.isp # shorthand
164 173 isp.push('x=1')
165 174 self.assertEqual(isp.indent_spaces, 0)
166 175 isp.push('if 1:\n x=1')
167 176 self.assertEqual(isp.indent_spaces, 4)
168 177 isp.push('y=2\n')
169 178 self.assertEqual(isp.indent_spaces, 0)
170 179
171 180 def test_indent2(self):
172 181 # In cell mode, inputs must be fed in whole blocks, so skip this test
173 182 if self.isp.input_mode == 'cell': return
174 183
175 184 isp = self.isp
176 185 isp.push('if 1:')
177 186 self.assertEqual(isp.indent_spaces, 4)
178 187 isp.push(' x=1')
179 188 self.assertEqual(isp.indent_spaces, 4)
180 189 # Blank lines shouldn't change the indent level
181 190 isp.push(' '*2)
182 191 self.assertEqual(isp.indent_spaces, 4)
183 192
184 193 def test_indent3(self):
185 194 # In cell mode, inputs must be fed in whole blocks, so skip this test
186 195 if self.isp.input_mode == 'cell': return
187 196
188 197 isp = self.isp
189 198 # When a multiline statement contains parens or multiline strings, we
190 199 # shouldn't get confused.
191 200 isp.push("if 1:")
192 201 isp.push(" x = (1+\n 2)")
193 202 self.assertEqual(isp.indent_spaces, 4)
194 203
195 204 def test_dedent_pass(self):
196 205 isp = self.isp # shorthand
197 206 # should NOT cause dedent
198 207 isp.push('if 1:\n passes = 5')
199 208 self.assertEqual(isp.indent_spaces, 4)
200 209 isp.push('if 1:\n pass')
201 210 self.assertEqual(isp.indent_spaces, 0)
202 211 isp.push('if 1:\n pass ')
203 212 self.assertEqual(isp.indent_spaces, 0)
204 213
205 214 def test_dedent_raise(self):
206 215 isp = self.isp # shorthand
207 216 # should NOT cause dedent
208 217 isp.push('if 1:\n raised = 4')
209 218 self.assertEqual(isp.indent_spaces, 4)
210 219 isp.push('if 1:\n raise TypeError()')
211 220 self.assertEqual(isp.indent_spaces, 0)
212 221 isp.push('if 1:\n raise')
213 222 self.assertEqual(isp.indent_spaces, 0)
214 223 isp.push('if 1:\n raise ')
215 224 self.assertEqual(isp.indent_spaces, 0)
216 225
217 226 def test_dedent_return(self):
218 227 isp = self.isp # shorthand
219 228 # should NOT cause dedent
220 229 isp.push('if 1:\n returning = 4')
221 230 self.assertEqual(isp.indent_spaces, 4)
222 231 isp.push('if 1:\n return 5 + 493')
223 232 self.assertEqual(isp.indent_spaces, 0)
224 233 isp.push('if 1:\n return')
225 234 self.assertEqual(isp.indent_spaces, 0)
226 235 isp.push('if 1:\n return ')
227 236 self.assertEqual(isp.indent_spaces, 0)
228 237 isp.push('if 1:\n return(0)')
229 238 self.assertEqual(isp.indent_spaces, 0)
230 239
231 240 def test_push(self):
232 241 isp = self.isp
233 242 self.assertTrue(isp.push('x=1'))
234 243
235 244 def test_push2(self):
236 245 isp = self.isp
237 246 self.assertFalse(isp.push('if 1:'))
238 247 for line in [' x=1', '# a comment', ' y=2']:
239 248 self.assertTrue(isp.push(line))
240 249
241 250 def test_push3(self):
242 251 isp = self.isp
243 252 isp.push('if True:')
244 253 isp.push(' a = 1')
245 254 self.assertFalse(isp.push('b = [1,'))
246 255
247 256 def test_replace_mode(self):
248 257 isp = self.isp
249 258 isp.input_mode = 'cell'
250 259 isp.push('x=1')
251 260 self.assertEqual(isp.source, 'x=1\n')
252 261 isp.push('x=2')
253 262 self.assertEqual(isp.source, 'x=2\n')
254 263
255 264 def test_push_accepts_more(self):
256 265 isp = self.isp
257 266 isp.push('x=1')
258 267 self.assertFalse(isp.push_accepts_more())
259 268
260 269 def test_push_accepts_more2(self):
261 270 # In cell mode, inputs must be fed in whole blocks, so skip this test
262 271 if self.isp.input_mode == 'cell': return
263 272
264 273 isp = self.isp
265 274 isp.push('if 1:')
266 275 self.assertTrue(isp.push_accepts_more())
267 276 isp.push(' x=1')
268 277 self.assertTrue(isp.push_accepts_more())
269 278 isp.push('')
270 279 self.assertFalse(isp.push_accepts_more())
271 280
272 281 def test_push_accepts_more3(self):
273 282 isp = self.isp
274 283 isp.push("x = (2+\n3)")
275 284 self.assertFalse(isp.push_accepts_more())
276 285
277 286 def test_push_accepts_more4(self):
278 287 # In cell mode, inputs must be fed in whole blocks, so skip this test
279 288 if self.isp.input_mode == 'cell': return
280 289
281 290 isp = self.isp
282 291 # When a multiline statement contains parens or multiline strings, we
283 292 # shouldn't get confused.
284 293 # FIXME: we should be able to better handle de-dents in statements like
285 294 # multiline strings and multiline expressions (continued with \ or
286 295 # parens). Right now we aren't handling the indentation tracking quite
287 296 # correctly with this, though in practice it may not be too much of a
288 297 # problem. We'll need to see.
289 298 isp.push("if 1:")
290 299 isp.push(" x = (2+")
291 300 isp.push(" 3)")
292 301 self.assertTrue(isp.push_accepts_more())
293 302 isp.push(" y = 3")
294 303 self.assertTrue(isp.push_accepts_more())
295 304 isp.push('')
296 305 self.assertFalse(isp.push_accepts_more())
297 306
298 307 def test_push_accepts_more5(self):
299 308 # In cell mode, inputs must be fed in whole blocks, so skip this test
300 309 if self.isp.input_mode == 'cell': return
301 310
302 311 isp = self.isp
303 312 isp.push('try:')
304 313 isp.push(' a = 5')
305 314 isp.push('except:')
306 315 isp.push(' raise')
307 316 self.assertTrue(isp.push_accepts_more())
308 317
309 318 def test_continuation(self):
310 319 isp = self.isp
311 320 isp.push("import os, \\")
312 321 self.assertTrue(isp.push_accepts_more())
313 322 isp.push("sys")
314 323 self.assertFalse(isp.push_accepts_more())
315 324
316 325 def test_syntax_error(self):
317 326 isp = self.isp
318 327 # Syntax errors immediately produce a 'ready' block, so the invalid
319 328 # Python can be sent to the kernel for evaluation with possible ipython
320 329 # special-syntax conversion.
321 330 isp.push('run foo')
322 331 self.assertFalse(isp.push_accepts_more())
323 332
324 333 def test_unicode(self):
325 334 self.isp.push(u"PΓ©rez")
326 335 self.isp.push(u'\xc3\xa9')
327 336 self.isp.push(u"u'\xc3\xa9'")
328 337
329 338 class InteractiveLoopTestCase(unittest.TestCase):
330 339 """Tests for an interactive loop like a python shell.
331 340 """
332 341 def check_ns(self, lines, ns):
333 342 """Validate that the given input lines produce the resulting namespace.
334 343
335 344 Note: the input lines are given exactly as they would be typed in an
336 345 auto-indenting environment, as mini_interactive_loop above already does
337 346 auto-indenting and prepends spaces to the input.
338 347 """
339 348 src = mini_interactive_loop(pseudo_input(lines))
340 349 test_ns = {}
341 350 exec src in test_ns
342 351 # We can't check that the provided ns is identical to the test_ns,
343 352 # because Python fills test_ns with extra keys (copyright, etc). But
344 353 # we can check that the given dict is *contained* in test_ns
345 354 for k,v in ns.iteritems():
346 355 self.assertEqual(test_ns[k], v)
347 356
348 357 def test_simple(self):
349 358 self.check_ns(['x=1'], dict(x=1))
350 359
351 360 def test_simple2(self):
352 361 self.check_ns(['if 1:', 'x=2'], dict(x=2))
353 362
354 363 def test_xy(self):
355 364 self.check_ns(['x=1; y=2'], dict(x=1, y=2))
356 365
357 366 def test_abc(self):
358 367 self.check_ns(['if 1:','a=1','b=2','c=3'], dict(a=1, b=2, c=3))
359 368
360 369 def test_multi(self):
361 370 self.check_ns(['x =(1+','1+','2)'], dict(x=4))
362 371
363 372
364 373 def test_LineInfo():
365 374 """Simple test for LineInfo construction and str()"""
366 375 linfo = isp.LineInfo(' %cd /home')
367 376 nt.assert_equals(str(linfo), 'LineInfo [ |%|cd|/home]')
368 377
369 378
370 379 def test_split_user_input():
371 380 """Unicode test - split_user_input already has good doctests"""
372 381 line = u"PΓ©rez Fernando"
373 382 parts = isp.split_user_input(line)
374 383 parts_expected = (u'', u'', u'', line)
375 384 nt.assert_equal(parts, parts_expected)
376 385
377 386
378 387 # Transformer tests
379 388 def transform_checker(tests, func):
380 389 """Utility to loop over test inputs"""
381 390 for inp, tr in tests:
382 391 nt.assert_equals(func(inp), tr)
383 392
384 393 # Data for all the syntax tests in the form of lists of pairs of
385 394 # raw/transformed input. We store it here as a global dict so that we can use
386 395 # it both within single-function tests and also to validate the behavior of the
387 396 # larger objects
388 397
389 398 syntax = \
390 399 dict(assign_system =
391 400 [('a =! ls', 'a = get_ipython().getoutput(u"ls")'),
392 401 ('b = !ls', 'b = get_ipython().getoutput(u"ls")'),
393 402 ('x=1', 'x=1'), # normal input is unmodified
394 403 (' ',' '), # blank lines are kept intact
395 404 ],
396 405
397 406 assign_magic =
398 407 [('a =% who', 'a = get_ipython().magic(u"who")'),
399 408 ('b = %who', 'b = get_ipython().magic(u"who")'),
400 409 ('x=1', 'x=1'), # normal input is unmodified
401 410 (' ',' '), # blank lines are kept intact
402 411 ],
403 412
404 413 classic_prompt =
405 414 [('>>> x=1', 'x=1'),
406 415 ('x=1', 'x=1'), # normal input is unmodified
407 416 (' ', ' '), # blank lines are kept intact
408 417 ('... ', ''), # continuation prompts
409 418 ],
410 419
411 420 ipy_prompt =
412 421 [('In [1]: x=1', 'x=1'),
413 422 ('x=1', 'x=1'), # normal input is unmodified
414 423 (' ',' '), # blank lines are kept intact
415 424 (' ....: ', ''), # continuation prompts
416 425 ],
417 426
418 427 # Tests for the escape transformer to leave normal code alone
419 428 escaped_noesc =
420 429 [ (' ', ' '),
421 430 ('x=1', 'x=1'),
422 431 ],
423 432
424 433 # System calls
425 434 escaped_shell =
426 435 [ ('!ls', 'get_ipython().system(u"ls")'),
427 436 # Double-escape shell, this means to capture the output of the
428 437 # subprocess and return it
429 438 ('!!ls', 'get_ipython().getoutput(u"ls")'),
430 439 ],
431 440
432 441 # Help/object info
433 442 escaped_help =
434 443 [ ('?', 'get_ipython().show_usage()'),
435 444 ('?x1', 'get_ipython().magic(u"pinfo x1")'),
436 445 ('??x2', 'get_ipython().magic(u"pinfo2 x2")'),
437 446 ('?a.*s', 'get_ipython().magic(u"psearch a.*s")'),
438 447 ('?%hist', 'get_ipython().magic(u"pinfo %hist")'),
439 448 ('?abc = qwe', 'get_ipython().magic(u"pinfo abc")'),
440 449 ],
441 450
442 451 end_help =
443 452 [ ('x3?', 'get_ipython().magic(u"pinfo x3")'),
444 453 ('x4??', 'get_ipython().magic(u"pinfo2 x4")'),
445 454 ('%hist?', 'get_ipython().magic(u"pinfo %hist")'),
446 455 ('f*?', 'get_ipython().magic(u"psearch f*")'),
447 456 ('ax.*aspe*?', 'get_ipython().magic(u"psearch ax.*aspe*")'),
448 ('a = abc?', 'get_ipython().magic(u"pinfo abc")'),
449 ('a = abc.qe??', 'get_ipython().magic(u"pinfo2 abc.qe")'),
450 ('a = *.items?', 'get_ipython().magic(u"psearch *.items")'),
457 ('a = abc?', 'get_ipython().magic(u"pinfo abc"); get_ipython().set_next_input(u"a = abc")'),
458 ('a = abc.qe??', 'get_ipython().magic(u"pinfo2 abc.qe"); get_ipython().set_next_input(u"a = abc.qe")'),
459 ('a = *.items?', 'get_ipython().magic(u"psearch *.items"); get_ipython().set_next_input(u"a = *.items")'),
460 ('a*2 #comment?', 'a*2 #comment?'),
451 461 ],
452 462
453 463 # Explicit magic calls
454 464 escaped_magic =
455 465 [ ('%cd', 'get_ipython().magic(u"cd")'),
456 466 ('%cd /home', 'get_ipython().magic(u"cd /home")'),
457 467 (' %magic', ' get_ipython().magic(u"magic")'),
458 468 ],
459 469
460 470 # Quoting with separate arguments
461 471 escaped_quote =
462 472 [ (',f', 'f("")'),
463 473 (',f x', 'f("x")'),
464 474 (' ,f y', ' f("y")'),
465 475 (',f a b', 'f("a", "b")'),
466 476 ],
467 477
468 478 # Quoting with single argument
469 479 escaped_quote2 =
470 480 [ (';f', 'f("")'),
471 481 (';f x', 'f("x")'),
472 482 (' ;f y', ' f("y")'),
473 483 (';f a b', 'f("a b")'),
474 484 ],
475 485
476 486 # Simply apply parens
477 487 escaped_paren =
478 488 [ ('/f', 'f()'),
479 489 ('/f x', 'f(x)'),
480 490 (' /f y', ' f(y)'),
481 491 ('/f a b', 'f(a, b)'),
482 492 ],
483 493
484 494 # Check that we transform prompts before other transforms
485 495 mixed =
486 496 [ ('In [1]: %lsmagic', 'get_ipython().magic(u"lsmagic")'),
487 497 ('>>> %lsmagic', 'get_ipython().magic(u"lsmagic")'),
488 498 ('In [2]: !ls', 'get_ipython().system(u"ls")'),
489 499 ('In [3]: abs?', 'get_ipython().magic(u"pinfo abs")'),
490 500 ('In [4]: b = %who', 'b = get_ipython().magic(u"who")'),
491 501 ],
492 502 )
493 503
494 504 # multiline syntax examples. Each of these should be a list of lists, with
495 505 # each entry itself having pairs of raw/transformed input. The union (with
496 506 # '\n'.join() of the transformed inputs is what the splitter should produce
497 507 # when fed the raw lines one at a time via push.
498 508 syntax_ml = \
499 509 dict(classic_prompt =
500 510 [ [('>>> for i in range(10):','for i in range(10):'),
501 511 ('... print i',' print i'),
502 512 ('... ', ''),
503 513 ],
504 514 ],
505 515
506 516 ipy_prompt =
507 517 [ [('In [24]: for i in range(10):','for i in range(10):'),
508 518 (' ....: print i',' print i'),
509 519 (' ....: ', ''),
510 520 ],
511 521 ],
512 522 )
513 523
514 524
515 525 def test_assign_system():
516 transform_checker(syntax['assign_system'], isp.transform_assign_system)
526 tt.check_pairs(isp.transform_assign_system, syntax['assign_system'])
517 527
518 528
519 529 def test_assign_magic():
520 transform_checker(syntax['assign_magic'], isp.transform_assign_magic)
530 tt.check_pairs(isp.transform_assign_magic, syntax['assign_magic'])
521 531
522 532
523 533 def test_classic_prompt():
524 534 transform_checker(syntax['classic_prompt'], isp.transform_classic_prompt)
525 535 for example in syntax_ml['classic_prompt']:
526 536 transform_checker(example, isp.transform_classic_prompt)
527 537
528 538
529 539 def test_ipy_prompt():
530 540 transform_checker(syntax['ipy_prompt'], isp.transform_ipy_prompt)
531 541 for example in syntax_ml['ipy_prompt']:
532 542 transform_checker(example, isp.transform_ipy_prompt)
533 543
534 544 def test_end_help():
535 transform_checker(syntax['end_help'], isp.transform_help_end)
545 tt.check_pairs(isp.transform_help_end, syntax['end_help'])
536 546
537 547 def test_escaped_noesc():
538 transform_checker(syntax['escaped_noesc'], isp.transform_escaped)
548 tt.check_pairs(isp.transform_escaped, syntax['escaped_noesc'])
539 549
540 550
541 551 def test_escaped_shell():
542 transform_checker(syntax['escaped_shell'], isp.transform_escaped)
552 tt.check_pairs(isp.transform_escaped, syntax['escaped_shell'])
543 553
544 554
545 555 def test_escaped_help():
546 transform_checker(syntax['escaped_help'], isp.transform_escaped)
556 tt.check_pairs(isp.transform_escaped, syntax['escaped_help'])
547 557
548 558
549 559 def test_escaped_magic():
550 transform_checker(syntax['escaped_magic'], isp.transform_escaped)
560 tt.check_pairs(isp.transform_escaped, syntax['escaped_magic'])
551 561
552 562
553 563 def test_escaped_quote():
554 transform_checker(syntax['escaped_quote'], isp.transform_escaped)
564 tt.check_pairs(isp.transform_escaped, syntax['escaped_quote'])
555 565
556 566
557 567 def test_escaped_quote2():
558 transform_checker(syntax['escaped_quote2'], isp.transform_escaped)
568 tt.check_pairs(isp.transform_escaped, syntax['escaped_quote2'])
559 569
560 570
561 571 def test_escaped_paren():
562 transform_checker(syntax['escaped_paren'], isp.transform_escaped)
572 tt.check_pairs(isp.transform_escaped, syntax['escaped_paren'])
563 573
564 574
565 575 class IPythonInputTestCase(InputSplitterTestCase):
566 576 """By just creating a new class whose .isp is a different instance, we
567 577 re-run the same test battery on the new input splitter.
568 578
569 579 In addition, this runs the tests over the syntax and syntax_ml dicts that
570 580 were tested by individual functions, as part of the OO interface.
571 581
572 582 It also makes some checks on the raw buffer storage.
573 583 """
574 584
575 585 def setUp(self):
576 586 self.isp = isp.IPythonInputSplitter(input_mode='line')
577 587
578 588 def test_syntax(self):
579 589 """Call all single-line syntax tests from the main object"""
580 590 isp = self.isp
581 591 for example in syntax.itervalues():
582 592 for raw, out_t in example:
583 593 if raw.startswith(' '):
584 594 continue
585 595
586 596 isp.push(raw)
587 597 out, out_raw = isp.source_raw_reset()
588 598 self.assertEqual(out.rstrip(), out_t)
589 599 self.assertEqual(out_raw.rstrip(), raw.rstrip())
590 600
591 601 def test_syntax_multiline(self):
592 602 isp = self.isp
593 603 for example in syntax_ml.itervalues():
594 604 out_t_parts = []
595 605 raw_parts = []
596 606 for line_pairs in example:
597 607 for lraw, out_t_part in line_pairs:
598 608 isp.push(lraw)
599 609 out_t_parts.append(out_t_part)
600 610 raw_parts.append(lraw)
601 611
602 612 out, out_raw = isp.source_raw_reset()
603 613 out_t = '\n'.join(out_t_parts).rstrip()
604 614 raw = '\n'.join(raw_parts).rstrip()
605 615 self.assertEqual(out.rstrip(), out_t)
606 616 self.assertEqual(out_raw.rstrip(), raw)
607 617
608 618
609 619 class BlockIPythonInputTestCase(IPythonInputTestCase):
610 620
611 621 # Deactivate tests that don't make sense for the block mode
612 622 test_push3 = test_split = lambda s: None
613 623
614 624 def setUp(self):
615 625 self.isp = isp.IPythonInputSplitter(input_mode='cell')
616 626
617 627 def test_syntax_multiline(self):
618 628 isp = self.isp
619 629 for example in syntax_ml.itervalues():
620 630 raw_parts = []
621 631 out_t_parts = []
622 632 for line_pairs in example:
623 633 for raw, out_t_part in line_pairs:
624 634 raw_parts.append(raw)
625 635 out_t_parts.append(out_t_part)
626 636
627 637 raw = '\n'.join(raw_parts)
628 638 out_t = '\n'.join(out_t_parts)
629 639
630 640 isp.push(raw)
631 641 out, out_raw = isp.source_raw_reset()
632 642 # Match ignoring trailing whitespace
633 643 self.assertEqual(out.rstrip(), out_t.rstrip())
634 644 self.assertEqual(out_raw.rstrip(), raw.rstrip())
635 645
636 646
637 647 #-----------------------------------------------------------------------------
638 648 # Main - use as a script, mostly for developer experiments
639 649 #-----------------------------------------------------------------------------
640 650
641 651 if __name__ == '__main__':
642 652 # A simple demo for interactive experimentation. This code will not get
643 653 # picked up by any test suite.
644 654 from IPython.core.inputsplitter import InputSplitter, IPythonInputSplitter
645 655
646 656 # configure here the syntax to use, prompt and whether to autoindent
647 657 #isp, start_prompt = InputSplitter(), '>>> '
648 658 isp, start_prompt = IPythonInputSplitter(), 'In> '
649 659
650 660 autoindent = True
651 661 #autoindent = False
652 662
653 663 try:
654 664 while True:
655 665 prompt = start_prompt
656 666 while isp.push_accepts_more():
657 667 indent = ' '*isp.indent_spaces
658 668 if autoindent:
659 669 line = indent + raw_input(prompt+indent)
660 670 else:
661 671 line = raw_input(prompt)
662 672 isp.push(line)
663 673 prompt = '... '
664 674
665 675 # Here we just return input so we can use it in a test suite, but a
666 676 # real interpreter would instead send it for execution somewhere.
667 677 #src = isp.source; raise EOFError # dbg
668 678 src, raw = isp.source_raw_reset()
669 679 print 'Input source was:\n', src
670 680 print 'Raw source was:\n', raw
671 681 except EOFError:
672 682 print 'Bye'
General Comments 0
You need to be logged in to leave comments. Login now