##// END OF EJS Templates
Fix bug with IPythonInputSplitter in block input mode.
Fernando Perez -
Show More
@@ -71,7 +71,6 b' import sys'
71
71
72 # IPython modules
72 # IPython modules
73 from IPython.utils.text import make_quoted_expr
73 from IPython.utils.text import make_quoted_expr
74
75 #-----------------------------------------------------------------------------
74 #-----------------------------------------------------------------------------
76 # Globals
75 # Globals
77 #-----------------------------------------------------------------------------
76 #-----------------------------------------------------------------------------
@@ -223,7 +222,7 b' class InputSplitter(object):'
223 ----------
222 ----------
224 input_mode : str
223 input_mode : str
225
224
226 One of 'append', 'replace', default is 'append'. This controls how
225 One of ['append', 'replace']; default is 'append'. This controls how
227 new inputs are used: in 'append' mode, they are appended to the
226 new inputs are used: in 'append' mode, they are appended to the
228 existing buffer and the whole buffer is compiled; in 'replace' mode,
227 existing buffer and the whole buffer is compiled; in 'replace' mode,
229 each new input completely replaces all prior inputs. Replace mode is
228 each new input completely replaces all prior inputs. Replace mode is
@@ -680,8 +679,10 b' def transform_ipy_prompt(line):'
680
679
681 if not line or line.isspace():
680 if not line or line.isspace():
682 return line
681 return line
682 #print 'LINE: %r' % line # dbg
683 m = _ipy_prompt_re.match(line)
683 m = _ipy_prompt_re.match(line)
684 if m:
684 if m:
685 #print 'MATCH! %r -> %r' % (line, line[len(m.group(0)):]) # dbg
685 return line[len(m.group(0)):]
686 return line[len(m.group(0)):]
686 else:
687 else:
687 return line
688 return line
@@ -828,12 +829,30 b' class IPythonInputSplitter(InputSplitter):'
828 #
829 #
829 # FIXME: try to find a cleaner approach for this last bit.
830 # FIXME: try to find a cleaner approach for this last bit.
830
831
831 for line in lines_list:
832 # If we were in 'replace' mode, since we're going to pump the parent
832 if self._is_complete or not self._buffer or \
833 # class by hand line by line, we need to temporarily switch out to
833 (self._buffer and self._buffer[-1].rstrip().endswith(':')):
834 # 'append' mode, do a single manual reset and then feed the lines one
834 for f in transforms:
835 # by one. Note that this only matters if the input has more than one
835 line = f(line)
836 # line.
836
837 changed_input_mode = False
837 out = super(IPythonInputSplitter, self).push(line)
838
839 if len(lines_list)>1 and self.input_mode == 'replace':
840 self.reset()
841 changed_input_mode = True
842 saved_input_mode = 'replace'
843 self.input_mode = 'append'
838
844
845 try:
846 push = super(IPythonInputSplitter, self).push
847 for line in lines_list:
848 if self._is_complete or not self._buffer or \
849 (self._buffer and self._buffer[-1].rstrip().endswith(':')):
850 for f in transforms:
851 line = f(line)
852
853 out = push(line)
854 finally:
855 if changed_input_mode:
856 self.input_mode = saved_input_mode
857
839 return out
858 return out
@@ -411,13 +411,15 b' syntax = \\'
411 classic_prompt =
411 classic_prompt =
412 [('>>> x=1', 'x=1'),
412 [('>>> x=1', 'x=1'),
413 ('x=1', 'x=1'), # normal input is unmodified
413 ('x=1', 'x=1'), # normal input is unmodified
414 (' ',' '), # blank lines are kept intact
414 (' ', ' '), # blank lines are kept intact
415 ('... ', ''), # continuation prompts
415 ],
416 ],
416
417
417 ipy_prompt =
418 ipy_prompt =
418 [('In [1]: x=1', 'x=1'),
419 [('In [1]: x=1', 'x=1'),
419 ('x=1', 'x=1'), # normal input is unmodified
420 ('x=1', 'x=1'), # normal input is unmodified
420 (' ',' '), # blank lines are kept intact
421 (' ',' '), # blank lines are kept intact
422 (' ....: ', ''), # continuation prompts
421 ],
423 ],
422
424
423 # Tests for the escape transformer to leave normal code alone
425 # Tests for the escape transformer to leave normal code alone
@@ -474,9 +476,6 b' syntax = \\'
474 ('/f a b', 'f(a, b)'),
476 ('/f a b', 'f(a, b)'),
475 ],
477 ],
476
478
477 # More complex multiline tests
478 ## escaped_multiline =
479 ## [()],
480 )
479 )
481
480
482 # multiline syntax examples. Each of these should be a list of lists, with
481 # multiline syntax examples. Each of these should be a list of lists, with
@@ -555,8 +554,9 b' class IPythonInputTestCase(InputSplitterTestCase):'
555 In addition, this runs the tests over the syntax and syntax_ml dicts that
554 In addition, this runs the tests over the syntax and syntax_ml dicts that
556 were tested by individual functions, as part of the OO interface.
555 were tested by individual functions, as part of the OO interface.
557 """
556 """
557
558 def setUp(self):
558 def setUp(self):
559 self.isp = isp.IPythonInputSplitter()
559 self.isp = isp.IPythonInputSplitter(input_mode='append')
560
560
561 def test_syntax(self):
561 def test_syntax(self):
562 """Call all single-line syntax tests from the main object"""
562 """Call all single-line syntax tests from the main object"""
@@ -569,7 +569,7 b' class IPythonInputTestCase(InputSplitterTestCase):'
569 isp.push(raw)
569 isp.push(raw)
570 out = isp.source_reset().rstrip()
570 out = isp.source_reset().rstrip()
571 self.assertEqual(out, out_t)
571 self.assertEqual(out, out_t)
572
572
573 def test_syntax_multiline(self):
573 def test_syntax_multiline(self):
574 isp = self.isp
574 isp = self.isp
575 for example in syntax_ml.itervalues():
575 for example in syntax_ml.itervalues():
@@ -583,15 +583,41 b' class IPythonInputTestCase(InputSplitterTestCase):'
583 out_t = '\n'.join(out_t_parts).rstrip()
583 out_t = '\n'.join(out_t_parts).rstrip()
584 self.assertEqual(out, out_t)
584 self.assertEqual(out, out_t)
585
585
586
586
587 class BlockIPythonInputTestCase(IPythonInputTestCase):
588
589 # Deactivate tests that don't make sense for the block mode
590 test_push3 = test_split = lambda s: None
591
592 def setUp(self):
593 self.isp = isp.IPythonInputSplitter(input_mode='replace')
594
595 def test_syntax_multiline(self):
596 isp = self.isp
597 for example in syntax_ml.itervalues():
598 raw_parts = []
599 out_t_parts = []
600 for line_pairs in example:
601 for raw, out_t_part in line_pairs:
602 raw_parts.append(raw)
603 out_t_parts.append(out_t_part)
604
605 raw = '\n'.join(raw_parts)
606 out_t = '\n'.join(out_t_parts)
607
608 isp.push(raw)
609 out = isp.source_reset()
610 # Match ignoring trailing whitespace
611 self.assertEqual(out.rstrip(), out_t.rstrip())
612
613
587 #-----------------------------------------------------------------------------
614 #-----------------------------------------------------------------------------
588 # Main - use as a script
615 # Main - use as a script, mostly for developer experiments
589 #-----------------------------------------------------------------------------
616 #-----------------------------------------------------------------------------
590
617
591 if __name__ == '__main__':
618 if __name__ == '__main__':
592 # A simple demo for interactive experimentation. This code will not get
619 # A simple demo for interactive experimentation. This code will not get
593 # picked up by any test suite. Useful mostly for illustration and during
620 # picked up by any test suite.
594 # development.
595 from IPython.core.inputsplitter import InputSplitter, IPythonInputSplitter
621 from IPython.core.inputsplitter import InputSplitter, IPythonInputSplitter
596
622
597 # configure here the syntax to use, prompt and whether to autoindent
623 # configure here the syntax to use, prompt and whether to autoindent
@@ -60,7 +60,7 b' class IPythonWidget(FrontendWidget):'
60 out_prompt = 'Out[<span class="out-prompt-number">%i</span>]: '
60 out_prompt = 'Out[<span class="out-prompt-number">%i</span>]: '
61
61
62 # FrontendWidget protected class variables.
62 # FrontendWidget protected class variables.
63 #_input_splitter_class = IPythonInputSplitter
63 _input_splitter_class = IPythonInputSplitter
64
64
65 # IPythonWidget protected class variables.
65 # IPythonWidget protected class variables.
66 _payload_source_edit = 'IPython.zmq.zmqshell.ZMQInteractiveShell.edit_magic'
66 _payload_source_edit = 'IPython.zmq.zmqshell.ZMQInteractiveShell.edit_magic'
General Comments 0
You need to be logged in to leave comments. Login now