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. |
|
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