##// END OF EJS Templates
Merge pull request #2110 from asmeurer/inputsplitter...
Fernando Perez -
r7827:c7401c9b merge
parent child Browse files
Show More
@@ -115,7 +115,9 b" dedent_re = re.compile('|'.join(["
115 r'^\s+raise\([^\)]*\).*$', # wacky raise with immediate open paren
115 r'^\s+raise\([^\)]*\).*$', # wacky raise with immediate open paren
116 r'^\s+return(\s.*)?$', # normal return (+ space + other stuff, maybe)
116 r'^\s+return(\s.*)?$', # normal return (+ space + other stuff, maybe)
117 r'^\s+return\([^\)]*\).*$', # wacky return with immediate open paren
117 r'^\s+return\([^\)]*\).*$', # wacky return with immediate open paren
118 r'^\s+pass\s*$' # pass (optionally followed by trailing spaces)
118 r'^\s+pass\s*$', # pass (optionally followed by trailing spaces)
119 r'^\s+break\s*$', # break (optionally followed by trailing spaces)
120 r'^\s+continue\s*$', # continue (optionally followed by trailing spaces)
119 ]))
121 ]))
120 ini_spaces_re = re.compile(r'^([ \t\r\f\v]+)')
122 ini_spaces_re = re.compile(r'^([ \t\r\f\v]+)')
121
123
@@ -202,17 +204,17 b' def remove_comments(src):'
202 """
204 """
203
205
204 return re.sub('#.*', '', src)
206 return re.sub('#.*', '', src)
205
207
206 def has_comment(src):
208 def has_comment(src):
207 """Indicate whether an input line has (i.e. ends in, or is) a comment.
209 """Indicate whether an input line has (i.e. ends in, or is) a comment.
208
210
209 This uses tokenize, so it can distinguish comments from # inside strings.
211 This uses tokenize, so it can distinguish comments from # inside strings.
210
212
211 Parameters
213 Parameters
212 ----------
214 ----------
213 src : string
215 src : string
214 A single line input string.
216 A single line input string.
215
217
216 Returns
218 Returns
217 -------
219 -------
218 Boolean: True if source has a comment.
220 Boolean: True if source has a comment.
@@ -280,9 +282,9 b' class InputSplitter(object):'
280 code = None
282 code = None
281 # Input mode
283 # Input mode
282 input_mode = 'line'
284 input_mode = 'line'
283
285
284 # Private attributes
286 # Private attributes
285
287
286 # List with lines of input accumulated so far
288 # List with lines of input accumulated so far
287 _buffer = None
289 _buffer = None
288 # Command compiler
290 # Command compiler
@@ -291,7 +293,7 b' class InputSplitter(object):'
291 _full_dedent = False
293 _full_dedent = False
292 # Boolean indicating whether the current block is complete
294 # Boolean indicating whether the current block is complete
293 _is_complete = None
295 _is_complete = None
294
296
295 def __init__(self, input_mode=None):
297 def __init__(self, input_mode=None):
296 """Create a new InputSplitter instance.
298 """Create a new InputSplitter instance.
297
299
@@ -348,7 +350,7 b' class InputSplitter(object):'
348 ----------
350 ----------
349 lines : string
351 lines : string
350 One or more lines of Python input.
352 One or more lines of Python input.
351
353
352 Returns
354 Returns
353 -------
355 -------
354 is_complete : boolean
356 is_complete : boolean
@@ -359,7 +361,7 b' class InputSplitter(object):'
359 """
361 """
360 if self.input_mode == 'cell':
362 if self.input_mode == 'cell':
361 self.reset()
363 self.reset()
362
364
363 self._store(lines)
365 self._store(lines)
364 source = self.source
366 source = self.source
365
367
@@ -369,7 +371,7 b' class InputSplitter(object):'
369 self.code, self._is_complete = None, None
371 self.code, self._is_complete = None, None
370
372
371 # Honor termination lines properly
373 # Honor termination lines properly
372 if source.rstrip().endswith('\\'):
374 if source.endswith('\\\n'):
373 return False
375 return False
374
376
375 self._update_indent(lines)
377 self._update_indent(lines)
@@ -400,11 +402,11 b' class InputSplitter(object):'
400 SyntaxError is raised, or *all* of the following are true:
402 SyntaxError is raised, or *all* of the following are true:
401
403
402 1. The input compiles to a complete statement.
404 1. The input compiles to a complete statement.
403
405
404 2. The indentation level is flush-left (because if we are indented,
406 2. The indentation level is flush-left (because if we are indented,
405 like inside a function definition or for loop, we need to keep
407 like inside a function definition or for loop, we need to keep
406 reading new input).
408 reading new input).
407
409
408 3. There is one extra line consisting only of whitespace.
410 3. There is one extra line consisting only of whitespace.
409
411
410 Because of condition #3, this method should be used only by
412 Because of condition #3, this method should be used only by
@@ -464,7 +466,7 b' class InputSplitter(object):'
464 ----------
466 ----------
465 line : str
467 line : str
466 A single new line of non-whitespace, non-comment Python input.
468 A single new line of non-whitespace, non-comment Python input.
467
469
468 Returns
470 Returns
469 -------
471 -------
470 indent_spaces : int
472 indent_spaces : int
@@ -476,7 +478,7 b' class InputSplitter(object):'
476 """
478 """
477 indent_spaces = self.indent_spaces
479 indent_spaces = self.indent_spaces
478 full_dedent = self._full_dedent
480 full_dedent = self._full_dedent
479
481
480 inisp = num_ini_spaces(line)
482 inisp = num_ini_spaces(line)
481 if inisp < indent_spaces:
483 if inisp < indent_spaces:
482 indent_spaces = inisp
484 indent_spaces = inisp
@@ -495,9 +497,9 b' class InputSplitter(object):'
495 if indent_spaces < 0:
497 if indent_spaces < 0:
496 indent_spaces = 0
498 indent_spaces = 0
497 #print 'safety' # dbg
499 #print 'safety' # dbg
498
500
499 return indent_spaces, full_dedent
501 return indent_spaces, full_dedent
500
502
501 def _update_indent(self, lines):
503 def _update_indent(self, lines):
502 for line in remove_comments(lines).splitlines():
504 for line in remove_comments(lines).splitlines():
503 if line and not line.isspace():
505 if line and not line.isspace():
@@ -508,10 +510,10 b' class InputSplitter(object):'
508
510
509 If input lines are not newline-terminated, a newline is automatically
511 If input lines are not newline-terminated, a newline is automatically
510 appended."""
512 appended."""
511
513
512 if buffer is None:
514 if buffer is None:
513 buffer = self._buffer
515 buffer = self._buffer
514
516
515 if lines.endswith('\n'):
517 if lines.endswith('\n'):
516 buffer.append(lines)
518 buffer.append(lines)
517 else:
519 else:
@@ -627,10 +629,10 b' def transform_help_end(line):'
627 target = m.group(1)
629 target = m.group(1)
628 esc = m.group(3)
630 esc = m.group(3)
629 lspace = _initial_space_re.match(line).group(0)
631 lspace = _initial_space_re.match(line).group(0)
630
632
631 # If we're mid-command, put it back on the next prompt for the user.
633 # If we're mid-command, put it back on the next prompt for the user.
632 next_input = line.rstrip('?') if line.strip() != m.group(0) else None
634 next_input = line.rstrip('?') if line.strip() != m.group(0) else None
633
635
634 return _make_help_call(target, esc, lspace, next_input)
636 return _make_help_call(target, esc, lspace, next_input)
635
637
636
638
@@ -647,7 +649,7 b' class EscapedTransformer(object):'
647 ESC_QUOTE2 : self._tr_quote2,
649 ESC_QUOTE2 : self._tr_quote2,
648 ESC_PAREN : self._tr_paren }
650 ESC_PAREN : self._tr_paren }
649 self.tr = tr
651 self.tr = tr
650
652
651 # Support for syntax transformations that use explicit escapes typed by the
653 # Support for syntax transformations that use explicit escapes typed by the
652 # user at the beginning of a line
654 # user at the beginning of a line
653 @staticmethod
655 @staticmethod
@@ -668,7 +670,7 b' class EscapedTransformer(object):'
668 # A naked help line should just fire the intro help screen
670 # A naked help line should just fire the intro help screen
669 if not line_info.line[1:]:
671 if not line_info.line[1:]:
670 return 'get_ipython().show_usage()'
672 return 'get_ipython().show_usage()'
671
673
672 return _make_help_call(line_info.ifun, line_info.esc, line_info.pre)
674 return _make_help_call(line_info.ifun, line_info.esc, line_info.pre)
673
675
674 @staticmethod
676 @staticmethod
@@ -745,7 +747,7 b' class IPythonInputSplitter(InputSplitter):'
745 super(IPythonInputSplitter, self).__init__(input_mode)
747 super(IPythonInputSplitter, self).__init__(input_mode)
746 self._buffer_raw = []
748 self._buffer_raw = []
747 self._validate = True
749 self._validate = True
748
750
749 def reset(self):
751 def reset(self):
750 """Reset the input buffer and associated state."""
752 """Reset the input buffer and associated state."""
751 super(IPythonInputSplitter, self).reset()
753 super(IPythonInputSplitter, self).reset()
@@ -897,7 +899,7 b' class IPythonInputSplitter(InputSplitter):'
897 # that this must be done *after* the reset() call that would otherwise
899 # that this must be done *after* the reset() call that would otherwise
898 # flush the buffer.
900 # flush the buffer.
899 self._store(lines, self._buffer_raw, 'source_raw')
901 self._store(lines, self._buffer_raw, 'source_raw')
900
902
901 try:
903 try:
902 push = super(IPythonInputSplitter, self).push
904 push = super(IPythonInputSplitter, self).push
903 buf = self._buffer
905 buf = self._buffer
@@ -227,6 +227,26 b' class InputSplitterTestCase(unittest.TestCase):'
227 isp.push('if 1:\n pass ')
227 isp.push('if 1:\n pass ')
228 self.assertEqual(isp.indent_spaces, 0)
228 self.assertEqual(isp.indent_spaces, 0)
229
229
230 def test_dedent_break(self):
231 isp = self.isp # shorthand
232 # should NOT cause dedent
233 isp.push('while 1:\n breaks = 5')
234 self.assertEqual(isp.indent_spaces, 4)
235 isp.push('while 1:\n break')
236 self.assertEqual(isp.indent_spaces, 0)
237 isp.push('while 1:\n break ')
238 self.assertEqual(isp.indent_spaces, 0)
239
240 def test_dedent_continue(self):
241 isp = self.isp # shorthand
242 # should NOT cause dedent
243 isp.push('while 1:\n continues = 5')
244 self.assertEqual(isp.indent_spaces, 4)
245 isp.push('while 1:\n continue')
246 self.assertEqual(isp.indent_spaces, 0)
247 isp.push('while 1:\n continue ')
248 self.assertEqual(isp.indent_spaces, 0)
249
230 def test_dedent_raise(self):
250 def test_dedent_raise(self):
231 isp = self.isp # shorthand
251 isp = self.isp # shorthand
232 # should NOT cause dedent
252 # should NOT cause dedent
@@ -351,6 +371,22 b' class InputSplitterTestCase(unittest.TestCase):'
351 self.isp.push(u'\xc3\xa9')
371 self.isp.push(u'\xc3\xa9')
352 self.isp.push(u"u'\xc3\xa9'")
372 self.isp.push(u"u'\xc3\xa9'")
353
373
374 def test_line_continuation(self):
375 """ Test issue #2108."""
376 isp = self.isp
377 # A blank line after a line continuation should not accept more
378 isp.push("1 \\\n\n")
379 self.assertFalse(isp.push_accepts_more())
380 # Whitespace after a \ is a SyntaxError. The only way to test that
381 # here is to test that push doesn't accept more (as with
382 # test_syntax_error() above).
383 isp.push(r"1 \ ")
384 self.assertFalse(isp.push_accepts_more())
385 # Even if the line is continuable (c.f. the regular Python
386 # interpreter)
387 isp.push(r"(1 \ ")
388 self.assertFalse(isp.push_accepts_more())
389
354 class InteractiveLoopTestCase(unittest.TestCase):
390 class InteractiveLoopTestCase(unittest.TestCase):
355 """Tests for an interactive loop like a python shell.
391 """Tests for an interactive loop like a python shell.
356 """
392 """
@@ -678,7 +714,7 b' class BlockIPythonInputTestCase(IPythonInputTestCase):'
678 def test_syntax_multiline_cell(self):
714 def test_syntax_multiline_cell(self):
679 isp = self.isp
715 isp = self.isp
680 for example in syntax_ml.itervalues():
716 for example in syntax_ml.itervalues():
681
717
682 out_t_parts = []
718 out_t_parts = []
683 for line_pairs in example:
719 for line_pairs in example:
684 raw = '\n'.join(r for r, _ in line_pairs)
720 raw = '\n'.join(r for r, _ in line_pairs)
@@ -762,7 +798,7 b' def test_last_two_blanks():'
762
798
763
799
764 class CellMagicsCommon(object):
800 class CellMagicsCommon(object):
765
801
766 def test_whole_cell(self):
802 def test_whole_cell(self):
767 src = "%%cellm line\nbody\n"
803 src = "%%cellm line\nbody\n"
768 sp = self.sp
804 sp = self.sp
@@ -9,7 +9,7 b' Welcome to IPython. Our full documentation is available on `our website'
9 <http://ipython.org/documentation.html>`_; if you downloaded a built source
9 <http://ipython.org/documentation.html>`_; if you downloaded a built source
10 distribution the ``docs/source`` directory contains the plaintext version of
10 distribution the ``docs/source`` directory contains the plaintext version of
11 these manuals. If you have Sphinx installed, you can build them by typing
11 these manuals. If you have Sphinx installed, you can build them by typing
12 ``make html`` for local browsing.
12 ``cd docs; make html`` for local browsing.
13
13
14
14
15 Dependencies and supported Python versions
15 Dependencies and supported Python versions
@@ -21,7 +21,7 b' functionality requires extra packages.'
21
21
22 Officially, IPython requires Python version 2.6, 2.7, or 3.1 and above.
22 Officially, IPython requires Python version 2.6, 2.7, or 3.1 and above.
23
23
24
24
25 Instant running
25 Instant running
26 ===============
26 ===============
27
27
General Comments 0
You need to be logged in to leave comments. Login now