##// END OF EJS Templates
Line continuations now terminate after one blank line (#2108)...
Aaron Meurer -
Show More
@@ -202,17 +202,17 b' def remove_comments(src):'
202 """
202 """
203
203
204 return re.sub('#.*', '', src)
204 return re.sub('#.*', '', src)
205
205
206 def has_comment(src):
206 def has_comment(src):
207 """Indicate whether an input line has (i.e. ends in, or is) a comment.
207 """Indicate whether an input line has (i.e. ends in, or is) a comment.
208
208
209 This uses tokenize, so it can distinguish comments from # inside strings.
209 This uses tokenize, so it can distinguish comments from # inside strings.
210
210
211 Parameters
211 Parameters
212 ----------
212 ----------
213 src : string
213 src : string
214 A single line input string.
214 A single line input string.
215
215
216 Returns
216 Returns
217 -------
217 -------
218 Boolean: True if source has a comment.
218 Boolean: True if source has a comment.
@@ -280,9 +280,9 b' class InputSplitter(object):'
280 code = None
280 code = None
281 # Input mode
281 # Input mode
282 input_mode = 'line'
282 input_mode = 'line'
283
283
284 # Private attributes
284 # Private attributes
285
285
286 # List with lines of input accumulated so far
286 # List with lines of input accumulated so far
287 _buffer = None
287 _buffer = None
288 # Command compiler
288 # Command compiler
@@ -291,7 +291,7 b' class InputSplitter(object):'
291 _full_dedent = False
291 _full_dedent = False
292 # Boolean indicating whether the current block is complete
292 # Boolean indicating whether the current block is complete
293 _is_complete = None
293 _is_complete = None
294
294
295 def __init__(self, input_mode=None):
295 def __init__(self, input_mode=None):
296 """Create a new InputSplitter instance.
296 """Create a new InputSplitter instance.
297
297
@@ -348,7 +348,7 b' class InputSplitter(object):'
348 ----------
348 ----------
349 lines : string
349 lines : string
350 One or more lines of Python input.
350 One or more lines of Python input.
351
351
352 Returns
352 Returns
353 -------
353 -------
354 is_complete : boolean
354 is_complete : boolean
@@ -359,7 +359,7 b' class InputSplitter(object):'
359 """
359 """
360 if self.input_mode == 'cell':
360 if self.input_mode == 'cell':
361 self.reset()
361 self.reset()
362
362
363 self._store(lines)
363 self._store(lines)
364 source = self.source
364 source = self.source
365
365
@@ -369,7 +369,7 b' class InputSplitter(object):'
369 self.code, self._is_complete = None, None
369 self.code, self._is_complete = None, None
370
370
371 # Honor termination lines properly
371 # Honor termination lines properly
372 if source.rstrip().endswith('\\'):
372 if source.endswith('\\\n'):
373 return False
373 return False
374
374
375 self._update_indent(lines)
375 self._update_indent(lines)
@@ -400,11 +400,11 b' class InputSplitter(object):'
400 SyntaxError is raised, or *all* of the following are true:
400 SyntaxError is raised, or *all* of the following are true:
401
401
402 1. The input compiles to a complete statement.
402 1. The input compiles to a complete statement.
403
403
404 2. The indentation level is flush-left (because if we are indented,
404 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
405 like inside a function definition or for loop, we need to keep
406 reading new input).
406 reading new input).
407
407
408 3. There is one extra line consisting only of whitespace.
408 3. There is one extra line consisting only of whitespace.
409
409
410 Because of condition #3, this method should be used only by
410 Because of condition #3, this method should be used only by
@@ -464,7 +464,7 b' class InputSplitter(object):'
464 ----------
464 ----------
465 line : str
465 line : str
466 A single new line of non-whitespace, non-comment Python input.
466 A single new line of non-whitespace, non-comment Python input.
467
467
468 Returns
468 Returns
469 -------
469 -------
470 indent_spaces : int
470 indent_spaces : int
@@ -476,7 +476,7 b' class InputSplitter(object):'
476 """
476 """
477 indent_spaces = self.indent_spaces
477 indent_spaces = self.indent_spaces
478 full_dedent = self._full_dedent
478 full_dedent = self._full_dedent
479
479
480 inisp = num_ini_spaces(line)
480 inisp = num_ini_spaces(line)
481 if inisp < indent_spaces:
481 if inisp < indent_spaces:
482 indent_spaces = inisp
482 indent_spaces = inisp
@@ -495,9 +495,9 b' class InputSplitter(object):'
495 if indent_spaces < 0:
495 if indent_spaces < 0:
496 indent_spaces = 0
496 indent_spaces = 0
497 #print 'safety' # dbg
497 #print 'safety' # dbg
498
498
499 return indent_spaces, full_dedent
499 return indent_spaces, full_dedent
500
500
501 def _update_indent(self, lines):
501 def _update_indent(self, lines):
502 for line in remove_comments(lines).splitlines():
502 for line in remove_comments(lines).splitlines():
503 if line and not line.isspace():
503 if line and not line.isspace():
@@ -508,10 +508,10 b' class InputSplitter(object):'
508
508
509 If input lines are not newline-terminated, a newline is automatically
509 If input lines are not newline-terminated, a newline is automatically
510 appended."""
510 appended."""
511
511
512 if buffer is None:
512 if buffer is None:
513 buffer = self._buffer
513 buffer = self._buffer
514
514
515 if lines.endswith('\n'):
515 if lines.endswith('\n'):
516 buffer.append(lines)
516 buffer.append(lines)
517 else:
517 else:
@@ -627,10 +627,10 b' def transform_help_end(line):'
627 target = m.group(1)
627 target = m.group(1)
628 esc = m.group(3)
628 esc = m.group(3)
629 lspace = _initial_space_re.match(line).group(0)
629 lspace = _initial_space_re.match(line).group(0)
630
630
631 # If we're mid-command, put it back on the next prompt for the user.
631 # 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
632 next_input = line.rstrip('?') if line.strip() != m.group(0) else None
633
633
634 return _make_help_call(target, esc, lspace, next_input)
634 return _make_help_call(target, esc, lspace, next_input)
635
635
636
636
@@ -647,7 +647,7 b' class EscapedTransformer(object):'
647 ESC_QUOTE2 : self._tr_quote2,
647 ESC_QUOTE2 : self._tr_quote2,
648 ESC_PAREN : self._tr_paren }
648 ESC_PAREN : self._tr_paren }
649 self.tr = tr
649 self.tr = tr
650
650
651 # Support for syntax transformations that use explicit escapes typed by the
651 # Support for syntax transformations that use explicit escapes typed by the
652 # user at the beginning of a line
652 # user at the beginning of a line
653 @staticmethod
653 @staticmethod
@@ -668,7 +668,7 b' class EscapedTransformer(object):'
668 # A naked help line should just fire the intro help screen
668 # A naked help line should just fire the intro help screen
669 if not line_info.line[1:]:
669 if not line_info.line[1:]:
670 return 'get_ipython().show_usage()'
670 return 'get_ipython().show_usage()'
671
671
672 return _make_help_call(line_info.ifun, line_info.esc, line_info.pre)
672 return _make_help_call(line_info.ifun, line_info.esc, line_info.pre)
673
673
674 @staticmethod
674 @staticmethod
@@ -745,7 +745,7 b' class IPythonInputSplitter(InputSplitter):'
745 super(IPythonInputSplitter, self).__init__(input_mode)
745 super(IPythonInputSplitter, self).__init__(input_mode)
746 self._buffer_raw = []
746 self._buffer_raw = []
747 self._validate = True
747 self._validate = True
748
748
749 def reset(self):
749 def reset(self):
750 """Reset the input buffer and associated state."""
750 """Reset the input buffer and associated state."""
751 super(IPythonInputSplitter, self).reset()
751 super(IPythonInputSplitter, self).reset()
@@ -897,7 +897,7 b' class IPythonInputSplitter(InputSplitter):'
897 # that this must be done *after* the reset() call that would otherwise
897 # that this must be done *after* the reset() call that would otherwise
898 # flush the buffer.
898 # flush the buffer.
899 self._store(lines, self._buffer_raw, 'source_raw')
899 self._store(lines, self._buffer_raw, 'source_raw')
900
900
901 try:
901 try:
902 push = super(IPythonInputSplitter, self).push
902 push = super(IPythonInputSplitter, self).push
903 buf = self._buffer
903 buf = self._buffer
@@ -351,6 +351,22 b' class InputSplitterTestCase(unittest.TestCase):'
351 self.isp.push(u'\xc3\xa9')
351 self.isp.push(u'\xc3\xa9')
352 self.isp.push(u"u'\xc3\xa9'")
352 self.isp.push(u"u'\xc3\xa9'")
353
353
354 def test_line_continuation(self):
355 """ Test issue #2108."""
356 isp = self.isp
357 # A blank line after a line continuation should not accept more
358 isp.push("1 \\\n\n")
359 self.assertFalse(isp.push_accepts_more())
360 # Whitespace after a \ is a SyntaxError. The only way to test that
361 # here is to test that push doesn't accept more (as with
362 # test_syntax_error() above).
363 isp.push(r"1 \ ")
364 self.assertFalse(isp.push_accepts_more())
365 # Even if the line is continuable (c.f. the regular Python
366 # interpreter)
367 isp.push(r"(1 \ ")
368 self.assertFalse(isp.push_accepts_more())
369
354 class InteractiveLoopTestCase(unittest.TestCase):
370 class InteractiveLoopTestCase(unittest.TestCase):
355 """Tests for an interactive loop like a python shell.
371 """Tests for an interactive loop like a python shell.
356 """
372 """
@@ -678,7 +694,7 b' class BlockIPythonInputTestCase(IPythonInputTestCase):'
678 def test_syntax_multiline_cell(self):
694 def test_syntax_multiline_cell(self):
679 isp = self.isp
695 isp = self.isp
680 for example in syntax_ml.itervalues():
696 for example in syntax_ml.itervalues():
681
697
682 out_t_parts = []
698 out_t_parts = []
683 for line_pairs in example:
699 for line_pairs in example:
684 raw = '\n'.join(r for r, _ in line_pairs)
700 raw = '\n'.join(r for r, _ in line_pairs)
@@ -762,7 +778,7 b' def test_last_two_blanks():'
762
778
763
779
764 class CellMagicsCommon(object):
780 class CellMagicsCommon(object):
765
781
766 def test_whole_cell(self):
782 def test_whole_cell(self):
767 src = "%%cellm line\nbody\n"
783 src = "%%cellm line\nbody\n"
768 sp = self.sp
784 sp = self.sp
General Comments 0
You need to be logged in to leave comments. Login now