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