From ae1c8be45db4b51ea487931a90d1704f5807ab48 2010-07-22 00:08:27 From: Fernando Perez Date: 2010-07-22 00:08:27 Subject: [PATCH] Add support for append/replace mode after discussion with Evan. Also increase test coverage. --- diff --git a/IPython/core/blockbreaker.py b/IPython/core/blockbreaker.py index f755063..6483b90 100644 --- a/IPython/core/blockbreaker.py +++ b/IPython/core/blockbreaker.py @@ -91,16 +91,35 @@ class BlockBreaker(object): code = None # Boolean indicating whether the current block is complete is_complete = None - + # Input mode + input_mode = 'append' + # Private attributes # List _buffer = None - def __init__(self): + def __init__(self, input_mode=None): + """Create a new BlockBreaker instance. + + Parameters + ---------- + input_mode : str + + One of 'append', 'replace', default is 'append'. This controls how + new inputs are used: in 'append' mode, they are appended to the + existing buffer and the whole buffer is compiled; in 'replace' mode, + each new input completely replaces all prior inputs. Replace mode is + thus equivalent to prepending a full reset() to every push() call. + + In practice, line-oriented clients likely want to use 'append' mode + while block-oriented ones will want to use 'replace'. + """ self._buffer = [] self.compile = codeop.CommandCompiler() self.encoding = get_input_encoding() + self.input_mode = BlockBreaker.input_mode if input_mode is None \ + else input_mode def reset(self): """Reset the input buffer and associated state.""" @@ -143,6 +162,9 @@ class BlockBreaker(object): this value is also stored as an attribute so it can be queried at any time. """ + if self.input_mode == 'replace': + self.reset() + # If the source code has leading blanks, add 'if 1:\n' to it # this allows execution of indented pasted code. It is tempting # to add '\n' at the end of source to run commands like ' a=1' diff --git a/IPython/core/tests/test_blockbreaker.py b/IPython/core/tests/test_blockbreaker.py index 6bf642d..94c9f52 100644 --- a/IPython/core/tests/test_blockbreaker.py +++ b/IPython/core/tests/test_blockbreaker.py @@ -137,6 +137,14 @@ class BlockBreakerTestCase(unittest.TestCase): bb.push(' y=2') self.assertEqual(bb.source, 'if 1:\n x=1\n y=2\n') + def test_replace_mode(self): + bb = self.bb + bb.input_mode = 'replace' + bb.push('x=1') + self.assertEqual(bb.source, 'x=1\n') + bb.push('x=2') + self.assertEqual(bb.source, 'x=2\n') + def test_interactive_block_ready(self): bb = self.bb bb.push('x=1') @@ -144,7 +152,9 @@ class BlockBreakerTestCase(unittest.TestCase): def test_interactive_block_ready2(self): bb = self.bb - bb.push('if 1:\n x=1') + bb.push('if 1:') + self.assertFalse(bb.interactive_block_ready()) + bb.push(' x=1') self.assertFalse(bb.interactive_block_ready()) bb.push('') self.assertTrue(bb.interactive_block_ready())