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