##// END OF EJS Templates
Merge pull request #3203 from takluyver/cell-magics-wholecell...
Min RK -
r10256:410df964 merge
parent child Browse files
Show More
@@ -247,8 +247,6 b' class InputSplitter(object):'
247 # synced to the source, so it can be queried at any time to obtain the code
247 # synced to the source, so it can be queried at any time to obtain the code
248 # object; it will be None if the source doesn't compile to valid Python.
248 # object; it will be None if the source doesn't compile to valid Python.
249 code = None
249 code = None
250 # Input mode
251 input_mode = 'line'
252
250
253 # Private attributes
251 # Private attributes
254
252
@@ -261,32 +259,12 b' class InputSplitter(object):'
261 # Boolean indicating whether the current block is complete
259 # Boolean indicating whether the current block is complete
262 _is_complete = None
260 _is_complete = None
263
261
264 def __init__(self, input_mode=None):
262 def __init__(self):
265 """Create a new InputSplitter instance.
263 """Create a new InputSplitter instance.
266
267 Parameters
268 ----------
269 input_mode : str
270
271 One of ['line', 'cell']; default is 'line'.
272
273 The input_mode parameter controls how new inputs are used when fed via
274 the :meth:`push` method:
275
276 - 'line': meant for line-oriented clients, inputs are appended one at a
277 time to the internal buffer and the whole buffer is compiled.
278
279 - 'cell': meant for clients that can edit multi-line 'cells' of text at
280 a time. A cell can contain one or more blocks that can be compile in
281 'single' mode by Python. In this mode, each new input new input
282 completely replaces all prior inputs. Cell mode is thus equivalent
283 to prepending a full reset() to every push() call.
284 """
264 """
285 self._buffer = []
265 self._buffer = []
286 self._compile = codeop.CommandCompiler()
266 self._compile = codeop.CommandCompiler()
287 self.encoding = get_input_encoding()
267 self.encoding = get_input_encoding()
288 self.input_mode = InputSplitter.input_mode if input_mode is None \
289 else input_mode
290
268
291 def reset(self):
269 def reset(self):
292 """Reset the input buffer and associated state."""
270 """Reset the input buffer and associated state."""
@@ -326,9 +304,6 b' class InputSplitter(object):'
326 this value is also stored as a private attribute (``_is_complete``), so it
304 this value is also stored as a private attribute (``_is_complete``), so it
327 can be queried at any time.
305 can be queried at any time.
328 """
306 """
329 if self.input_mode == 'cell':
330 self.reset()
331
332 self._store(lines)
307 self._store(lines)
333 source = self.source
308 source = self.source
334
309
@@ -365,20 +340,14 b' class InputSplitter(object):'
365 This method is meant to be used by line-oriented frontends, who need to
340 This method is meant to be used by line-oriented frontends, who need to
366 guess whether a block is complete or not based solely on prior and
341 guess whether a block is complete or not based solely on prior and
367 current input lines. The InputSplitter considers it has a complete
342 current input lines. The InputSplitter considers it has a complete
368 interactive block and will not accept more input only when either a
343 interactive block and will not accept more input when either:
369 SyntaxError is raised, or *all* of the following are true:
344
370
345 * A SyntaxError is raised
371 1. The input compiles to a complete statement.
372
373 2. The indentation level is flush-left (because if we are indented,
374 like inside a function definition or for loop, we need to keep
375 reading new input).
376
346
377 3. There is one extra line consisting only of whitespace.
347 * The code is complete and consists of a single line or a single
348 non-compound statement
378
349
379 Because of condition #3, this method should be used only by
350 * The code is complete and has a blank line at the end
380 *line-oriented* frontends, since it means that intermediate blank lines
381 are not allowed in function definitions (or any other indented block).
382
351
383 If the current input produces a syntax error, this method immediately
352 If the current input produces a syntax error, this method immediately
384 returns False but does *not* raise the syntax error exception, as
353 returns False but does *not* raise the syntax error exception, as
@@ -388,39 +357,37 b' class InputSplitter(object):'
388 """
357 """
389
358
390 # With incomplete input, unconditionally accept more
359 # With incomplete input, unconditionally accept more
360 # A syntax error also sets _is_complete to True - see push()
391 if not self._is_complete:
361 if not self._is_complete:
362 #print("Not complete") # debug
392 return True
363 return True
393
364
394 # If we already have complete input and we're flush left, the answer
365 # The user can make any (complete) input execute by leaving a blank line
395 # depends. In line mode, if there hasn't been any indentation,
366 last_line = self.source.splitlines()[-1]
396 # that's it. If we've come back from some indentation, we need
367 if (not last_line) or last_line.isspace():
397 # the blank final line to finish.
368 #print("Blank line") # debug
398 # In cell mode, we need to check how many blocks the input so far
369 return False
399 # compiles into, because if there's already more than one full
370
400 # independent block of input, then the client has entered full
371 # If there's just a single line or AST node, and we're flush left, as is
401 # 'cell' mode and is feeding lines that each is complete. In this
372 # the case after a simple statement such as 'a=1', we want to execute it
402 # case we should then keep accepting. The Qt terminal-like console
373 # straight away.
403 # does precisely this, to provide the convenience of terminal-like
404 # input of single expressions, but allowing the user (with a
405 # separate keystroke) to switch to 'cell' mode and type multiple
406 # expressions in one shot.
407 if self.indent_spaces==0:
374 if self.indent_spaces==0:
408 if self.input_mode=='line':
375 if len(self.source.splitlines()) <= 1:
409 if not self._full_dedent:
376 return False
410 return False
377
378 try:
379 code_ast = ast.parse(u''.join(self._buffer))
380 except Exception:
381 #print("Can't parse AST") # debug
382 return False
411 else:
383 else:
412 try:
384 if len(code_ast.body) == 1 and \
413 code_ast = ast.parse(u''.join(self._buffer))
385 not hasattr(code_ast.body[0], 'body'):
414 except Exception:
386 #print("Simple statement") # debug
415 return False
387 return False
416 else:
417 if len(code_ast.body) == 1:
418 return False
419
388
420 # When input is complete, then termination is marked by an extra blank
389 # General fallback - accept more code
421 # line at the end.
390 return True
422 last_line = self.source.splitlines()[-1]
423 return bool(last_line and not last_line.isspace())
424
391
425 #------------------------------------------------------------------------
392 #------------------------------------------------------------------------
426 # Private interface
393 # Private interface
@@ -510,9 +477,9 b' class IPythonInputSplitter(InputSplitter):'
510 # List with lines of raw input accumulated so far.
477 # List with lines of raw input accumulated so far.
511 _buffer_raw = None
478 _buffer_raw = None
512
479
513 def __init__(self, input_mode=None, physical_line_transforms=None,
480 def __init__(self, line_input_checker=False, physical_line_transforms=None,
514 logical_line_transforms=None, python_line_transforms=None):
481 logical_line_transforms=None, python_line_transforms=None):
515 super(IPythonInputSplitter, self).__init__(input_mode)
482 super(IPythonInputSplitter, self).__init__()
516 self._buffer_raw = []
483 self._buffer_raw = []
517 self._validate = True
484 self._validate = True
518
485
@@ -528,7 +495,7 b' class IPythonInputSplitter(InputSplitter):'
528 if logical_line_transforms is not None:
495 if logical_line_transforms is not None:
529 self.logical_line_transforms = logical_line_transforms
496 self.logical_line_transforms = logical_line_transforms
530 else:
497 else:
531 self.logical_line_transforms = [cellmagic(),
498 self.logical_line_transforms = [cellmagic(end_on_blank_line=line_input_checker),
532 help_end(),
499 help_end(),
533 escaped_commands(),
500 escaped_commands(),
534 assign_from_magic(),
501 assign_from_magic(),
@@ -641,44 +608,14 b' class IPythonInputSplitter(InputSplitter):'
641 if not lines_list:
608 if not lines_list:
642 lines_list = ['']
609 lines_list = ['']
643
610
644 # Transform logic
645 #
646 # We only apply the line transformers to the input if we have either no
647 # input yet, or complete input, or if the last line of the buffer ends
648 # with ':' (opening an indented block). This prevents the accidental
649 # transformation of escapes inside multiline expressions like
650 # triple-quoted strings or parenthesized expressions.
651 #
652 # The last heuristic, while ugly, ensures that the first line of an
653 # indented block is correctly transformed.
654 #
655 # FIXME: try to find a cleaner approach for this last bit.
656
657 # If we were in 'block' mode, since we're going to pump the parent
658 # class by hand line by line, we need to temporarily switch out to
659 # 'line' mode, do a single manual reset and then feed the lines one
660 # by one. Note that this only matters if the input has more than one
661 # line.
662 changed_input_mode = False
663
664 if self.input_mode == 'cell':
665 self.reset()
666 changed_input_mode = True
667 saved_input_mode = 'cell'
668 self.input_mode = 'line'
669
670 # Store raw source before applying any transformations to it. Note
611 # Store raw source before applying any transformations to it. Note
671 # that this must be done *after* the reset() call that would otherwise
612 # that this must be done *after* the reset() call that would otherwise
672 # flush the buffer.
613 # flush the buffer.
673 self._store(lines, self._buffer_raw, 'source_raw')
614 self._store(lines, self._buffer_raw, 'source_raw')
674
615
675 try:
616 for line in lines_list:
676 for line in lines_list:
617 out = self.push_line(line)
677 out = self.push_line(line)
618
678 finally:
679 if changed_input_mode:
680 self.input_mode = saved_input_mode
681
682 return out
619 return out
683
620
684 def push_line(self, line):
621 def push_line(self, line):
@@ -60,8 +60,8 b' class InputTransformer(object):'
60 will allow instantiation with the decorated object.
60 will allow instantiation with the decorated object.
61 """
61 """
62 @functools.wraps(func)
62 @functools.wraps(func)
63 def transformer_factory():
63 def transformer_factory(**kwargs):
64 return cls(func)
64 return cls(func, **kwargs)
65
65
66 return transformer_factory
66 return transformer_factory
67
67
@@ -84,9 +84,9 b' class StatelessInputTransformer(InputTransformer):'
84
84
85 class CoroutineInputTransformer(InputTransformer):
85 class CoroutineInputTransformer(InputTransformer):
86 """Wrapper for an input transformer implemented as a coroutine."""
86 """Wrapper for an input transformer implemented as a coroutine."""
87 def __init__(self, coro):
87 def __init__(self, coro, **kwargs):
88 # Prime it
88 # Prime it
89 self.coro = coro()
89 self.coro = coro(**kwargs)
90 next(self.coro)
90 next(self.coro)
91
91
92 def __repr__(self):
92 def __repr__(self):
@@ -316,7 +316,7 b' def help_end(line):'
316
316
317
317
318 @CoroutineInputTransformer.wrap
318 @CoroutineInputTransformer.wrap
319 def cellmagic():
319 def cellmagic(end_on_blank_line=False):
320 """Captures & transforms cell magics.
320 """Captures & transforms cell magics.
321
321
322 After a cell magic is started, this stores up any lines it gets until it is
322 After a cell magic is started, this stores up any lines it gets until it is
@@ -337,7 +337,8 b' def cellmagic():'
337 first = line
337 first = line
338 body = []
338 body = []
339 line = (yield None)
339 line = (yield None)
340 while (line is not None) and (line.strip() != ''):
340 while (line is not None) and \
341 ((line.strip() != '') or not end_on_blank_line):
341 body.append(line)
342 body.append(line)
342 line = (yield None)
343 line = (yield None)
343
344
@@ -283,10 +283,16 b' class InteractiveShell(SingletonConfigurable):'
283 filename = Unicode("<ipython console>")
283 filename = Unicode("<ipython console>")
284 ipython_dir= Unicode('', config=True) # Set to get_ipython_dir() in __init__
284 ipython_dir= Unicode('', config=True) # Set to get_ipython_dir() in __init__
285
285
286 # Input splitter, to split entire cells of input into either individual
286 # Input splitter, to transform input line by line and detect when a block
287 # interactive statements or whole blocks.
287 # is ready to be executed.
288 input_splitter = Instance('IPython.core.inputsplitter.IPythonInputSplitter',
288 input_splitter = Instance('IPython.core.inputsplitter.IPythonInputSplitter',
289 (), {})
289 (), {'line_input_checker': True})
290
291 # This InputSplitter instance is used to transform completed cells before
292 # running them. It allows cell magics to contain blank lines.
293 input_transformer_manager = Instance('IPython.core.inputsplitter.IPythonInputSplitter',
294 (), {'line_input_checker': False})
295
290 logstart = CBool(False, config=True, help=
296 logstart = CBool(False, config=True, help=
291 """
297 """
292 Start logging to the default log file.
298 Start logging to the default log file.
@@ -2581,10 +2587,9 b' class InteractiveShell(SingletonConfigurable):'
2581 if silent:
2587 if silent:
2582 store_history = False
2588 store_history = False
2583
2589
2584 self.input_splitter.push(raw_cell)
2590 self.input_transformer_manager.push(raw_cell)
2591 cell = self.input_transformer_manager.source_reset()
2585
2592
2586 cell = self.input_splitter.source_reset()
2587
2588 # Our own compiler remembers the __future__ environment. If we want to
2593 # Our own compiler remembers the __future__ environment. If we want to
2589 # run code with a separate __future__ environment, use the default
2594 # run code with a separate __future__ environment, use the default
2590 # compiler
2595 # compiler
@@ -168,9 +168,6 b' class InputSplitterTestCase(unittest.TestCase):'
168 self.assertEqual(isp.indent_spaces, 0)
168 self.assertEqual(isp.indent_spaces, 0)
169
169
170 def test_indent2(self):
170 def test_indent2(self):
171 # In cell mode, inputs must be fed in whole blocks, so skip this test
172 if self.isp.input_mode == 'cell': return
173
174 isp = self.isp
171 isp = self.isp
175 isp.push('if 1:')
172 isp.push('if 1:')
176 self.assertEqual(isp.indent_spaces, 4)
173 self.assertEqual(isp.indent_spaces, 4)
@@ -181,9 +178,6 b' class InputSplitterTestCase(unittest.TestCase):'
181 self.assertEqual(isp.indent_spaces, 4)
178 self.assertEqual(isp.indent_spaces, 4)
182
179
183 def test_indent3(self):
180 def test_indent3(self):
184 # In cell mode, inputs must be fed in whole blocks, so skip this test
185 if self.isp.input_mode == 'cell': return
186
187 isp = self.isp
181 isp = self.isp
188 # When a multiline statement contains parens or multiline strings, we
182 # When a multiline statement contains parens or multiline strings, we
189 # shouldn't get confused.
183 # shouldn't get confused.
@@ -192,9 +186,6 b' class InputSplitterTestCase(unittest.TestCase):'
192 self.assertEqual(isp.indent_spaces, 4)
186 self.assertEqual(isp.indent_spaces, 4)
193
187
194 def test_indent4(self):
188 def test_indent4(self):
195 # In cell mode, inputs must be fed in whole blocks, so skip this test
196 if self.isp.input_mode == 'cell': return
197
198 isp = self.isp
189 isp = self.isp
199 # whitespace after ':' should not screw up indent level
190 # whitespace after ':' should not screw up indent level
200 isp.push('if 1: \n x=1')
191 isp.push('if 1: \n x=1')
@@ -279,23 +270,12 b' class InputSplitterTestCase(unittest.TestCase):'
279 isp.push(' a = 1')
270 isp.push(' a = 1')
280 self.assertFalse(isp.push('b = [1,'))
271 self.assertFalse(isp.push('b = [1,'))
281
272
282 def test_replace_mode(self):
283 isp = self.isp
284 isp.input_mode = 'cell'
285 isp.push('x=1')
286 self.assertEqual(isp.source, 'x=1\n')
287 isp.push('x=2')
288 self.assertEqual(isp.source, 'x=2\n')
289
290 def test_push_accepts_more(self):
273 def test_push_accepts_more(self):
291 isp = self.isp
274 isp = self.isp
292 isp.push('x=1')
275 isp.push('x=1')
293 self.assertFalse(isp.push_accepts_more())
276 self.assertFalse(isp.push_accepts_more())
294
277
295 def test_push_accepts_more2(self):
278 def test_push_accepts_more2(self):
296 # In cell mode, inputs must be fed in whole blocks, so skip this test
297 if self.isp.input_mode == 'cell': return
298
299 isp = self.isp
279 isp = self.isp
300 isp.push('if 1:')
280 isp.push('if 1:')
301 self.assertTrue(isp.push_accepts_more())
281 self.assertTrue(isp.push_accepts_more())
@@ -310,9 +290,6 b' class InputSplitterTestCase(unittest.TestCase):'
310 self.assertFalse(isp.push_accepts_more())
290 self.assertFalse(isp.push_accepts_more())
311
291
312 def test_push_accepts_more4(self):
292 def test_push_accepts_more4(self):
313 # In cell mode, inputs must be fed in whole blocks, so skip this test
314 if self.isp.input_mode == 'cell': return
315
316 isp = self.isp
293 isp = self.isp
317 # When a multiline statement contains parens or multiline strings, we
294 # When a multiline statement contains parens or multiline strings, we
318 # shouldn't get confused.
295 # shouldn't get confused.
@@ -331,14 +308,13 b' class InputSplitterTestCase(unittest.TestCase):'
331 self.assertFalse(isp.push_accepts_more())
308 self.assertFalse(isp.push_accepts_more())
332
309
333 def test_push_accepts_more5(self):
310 def test_push_accepts_more5(self):
334 # In cell mode, inputs must be fed in whole blocks, so skip this test
335 if self.isp.input_mode == 'cell': return
336
337 isp = self.isp
311 isp = self.isp
338 isp.push('try:')
312 isp.push('try:')
339 isp.push(' a = 5')
313 isp.push(' a = 5')
340 isp.push('except:')
314 isp.push('except:')
341 isp.push(' raise')
315 isp.push(' raise')
316 # We want to be able to add an else: block at this point, so it should
317 # wait for a blank line.
342 self.assertTrue(isp.push_accepts_more())
318 self.assertTrue(isp.push_accepts_more())
343
319
344 def test_continuation(self):
320 def test_continuation(self):
@@ -431,7 +407,7 b' class IPythonInputTestCase(InputSplitterTestCase):'
431 """
407 """
432
408
433 def setUp(self):
409 def setUp(self):
434 self.isp = isp.IPythonInputSplitter(input_mode='line')
410 self.isp = isp.IPythonInputSplitter()
435
411
436 def test_syntax(self):
412 def test_syntax(self):
437 """Call all single-line syntax tests from the main object"""
413 """Call all single-line syntax tests from the main object"""
@@ -467,32 +443,6 b' class IPythonInputTestCase(InputSplitterTestCase):'
467 self.assertEqual(out.rstrip(), out_t)
443 self.assertEqual(out.rstrip(), out_t)
468 self.assertEqual(out_raw.rstrip(), raw)
444 self.assertEqual(out_raw.rstrip(), raw)
469
445
470
471 class BlockIPythonInputTestCase(IPythonInputTestCase):
472
473 # Deactivate tests that don't make sense for the block mode
474 test_push3 = test_split = lambda s: None
475
476 def setUp(self):
477 self.isp = isp.IPythonInputSplitter(input_mode='cell')
478
479 def test_syntax_multiline(self):
480 isp = self.isp
481 for example in syntax_ml.itervalues():
482 raw_parts = []
483 out_t_parts = []
484 for line_pairs in example:
485 raw_parts, out_t_parts = zip(*line_pairs)
486
487 raw = '\n'.join(r for r in raw_parts if r is not None)
488 out_t = '\n'.join(o for o in out_t_parts if o is not None)
489
490 isp.push(raw)
491 out, out_raw = isp.source_raw_reset()
492 # Match ignoring trailing whitespace
493 self.assertEqual(out.rstrip(), out_t.rstrip())
494 self.assertEqual(out_raw.rstrip(), raw.rstrip())
495
496 def test_syntax_multiline_cell(self):
446 def test_syntax_multiline_cell(self):
497 isp = self.isp
447 isp = self.isp
498 for example in syntax_ml.itervalues():
448 for example in syntax_ml.itervalues():
@@ -588,39 +538,35 b' class CellMagicsCommon(object):'
588 out = sp.source_reset()
538 out = sp.source_reset()
589 ref = u"get_ipython().run_cell_magic({u}'cellm', {u}'line', {u}'body')\n"
539 ref = u"get_ipython().run_cell_magic({u}'cellm', {u}'line', {u}'body')\n"
590 nt.assert_equal(out, py3compat.u_format(ref))
540 nt.assert_equal(out, py3compat.u_format(ref))
541
542 def test_cellmagic_help(self):
543 self.sp.push('%%cellm?')
544 nt.assert_false(self.sp.push_accepts_more())
591
545
592 def tearDown(self):
546 def tearDown(self):
593 self.sp.reset()
547 self.sp.reset()
594
548
595
549
596 class CellModeCellMagics(CellMagicsCommon, unittest.TestCase):
550 class CellModeCellMagics(CellMagicsCommon, unittest.TestCase):
597 sp = isp.IPythonInputSplitter(input_mode='cell')
551 sp = isp.IPythonInputSplitter(line_input_checker=False)
598
552
599 def test_incremental(self):
553 def test_incremental(self):
600 sp = self.sp
554 sp = self.sp
601 src = '%%cellm line2\n'
555 sp.push('%%cellm firstline\n')
602 sp.push(src)
603 nt.assert_true(sp.push_accepts_more()) #1
556 nt.assert_true(sp.push_accepts_more()) #1
604 src += '\n'
557 sp.push('line2\n')
605 sp.push(src)
558 nt.assert_true(sp.push_accepts_more()) #2
606 # Note: if we ever change the logic to allow full blank lines (see
559 sp.push('\n')
607 # _handle_cell_magic), then the following test should change to true
560 # This should accept a blank line and carry on until the cell is reset
608 nt.assert_false(sp.push_accepts_more()) #2
561 nt.assert_true(sp.push_accepts_more()) #3
609 # By now, even with full blanks allowed, a second blank should signal
610 # the end. For now this test is only a redundancy safety, but don't
611 # delete it in case we change our mind and the previous one goes to
612 # true.
613 src += '\n'
614 sp.push(src)
615 nt.assert_false(sp.push_accepts_more()) #3
616
617
562
618 class LineModeCellMagics(CellMagicsCommon, unittest.TestCase):
563 class LineModeCellMagics(CellMagicsCommon, unittest.TestCase):
619 sp = isp.IPythonInputSplitter(input_mode='line')
564 sp = isp.IPythonInputSplitter(line_input_checker=True)
620
565
621 def test_incremental(self):
566 def test_incremental(self):
622 sp = self.sp
567 sp = self.sp
623 sp.push('%%cellm line2\n')
568 sp.push('%%cellm line2\n')
624 nt.assert_true(sp.push_accepts_more()) #1
569 nt.assert_true(sp.push_accepts_more()) #1
625 sp.push('\n')
570 sp.push('\n')
571 # In this case, a blank line should end the cell magic
626 nt.assert_false(sp.push_accepts_more()) #2
572 nt.assert_false(sp.push_accepts_more()) #2
@@ -19,9 +19,9 b' def transform_and_reset(transformer):'
19 return transform
19 return transform
20
20
21 # Transformer tests
21 # Transformer tests
22 def transform_checker(tests, transformer):
22 def transform_checker(tests, transformer, **kwargs):
23 """Utility to loop over test inputs"""
23 """Utility to loop over test inputs"""
24 transformer = transformer()
24 transformer = transformer(**kwargs)
25 try:
25 try:
26 for inp, tr in tests:
26 for inp, tr in tests:
27 if inp is None:
27 if inp is None:
@@ -223,7 +223,7 b' syntax_ml = \\'
223 ],
223 ],
224 [(u'%%bar 123', None),
224 [(u'%%bar 123', None),
225 (u'hello', None),
225 (u'hello', None),
226 (u'', u_fmt("get_ipython().run_cell_magic({u}'bar', {u}'123', {u}'hello')")),
226 (None , u_fmt("get_ipython().run_cell_magic({u}'bar', {u}'123', {u}'hello')")),
227 ],
227 ],
228 ],
228 ],
229
229
@@ -348,6 +348,12 b' def test_escaped_paren():'
348 def test_cellmagic():
348 def test_cellmagic():
349 for example in syntax_ml['cellmagic']:
349 for example in syntax_ml['cellmagic']:
350 transform_checker(example, ipt.cellmagic)
350 transform_checker(example, ipt.cellmagic)
351
352 line_example = [(u'%%bar 123', None),
353 (u'hello', None),
354 (u'' , u_fmt("get_ipython().run_cell_magic({u}'bar', {u}'123', {u}'hello')")),
355 ]
356 transform_checker(line_example, ipt.cellmagic, end_on_blank_line=True)
351
357
352 def test_has_comment():
358 def test_has_comment():
353 tests = [('text', False),
359 tests = [('text', False),
@@ -146,7 +146,7 b' class FrontendWidget(HistoryConsoleWidget, BaseFrontendMixin):'
146 self._copy_raw_action = QtGui.QAction('Copy (Raw Text)', None)
146 self._copy_raw_action = QtGui.QAction('Copy (Raw Text)', None)
147 self._hidden = False
147 self._hidden = False
148 self._highlighter = FrontendHighlighter(self)
148 self._highlighter = FrontendHighlighter(self)
149 self._input_splitter = self._input_splitter_class(input_mode='cell')
149 self._input_splitter = self._input_splitter_class()
150 self._kernel_manager = None
150 self._kernel_manager = None
151 self._request_info = {}
151 self._request_info = {}
152 self._request_info['execute'] = {};
152 self._request_info['execute'] = {};
@@ -204,6 +204,7 b' class FrontendWidget(HistoryConsoleWidget, BaseFrontendMixin):'
204 prompt created. When triggered by an Enter/Return key press,
204 prompt created. When triggered by an Enter/Return key press,
205 'interactive' is True; otherwise, it is False.
205 'interactive' is True; otherwise, it is False.
206 """
206 """
207 self._input_splitter.reset()
207 complete = self._input_splitter.push(source)
208 complete = self._input_splitter.push(source)
208 if interactive:
209 if interactive:
209 complete = not self._input_splitter.push_accepts_more()
210 complete = not self._input_splitter.push_accepts_more()
@@ -82,7 +82,7 b' def get_pasted_lines(sentinel, l_input=py3compat.input):'
82 class TerminalMagics(Magics):
82 class TerminalMagics(Magics):
83 def __init__(self, shell):
83 def __init__(self, shell):
84 super(TerminalMagics, self).__init__(shell)
84 super(TerminalMagics, self).__init__(shell)
85 self.input_splitter = IPythonInputSplitter(input_mode='line')
85 self.input_splitter = IPythonInputSplitter()
86
86
87 def cleanup_input(self, block):
87 def cleanup_input(self, block):
88 """Apply all possible IPython cleanups to an input block.
88 """Apply all possible IPython cleanups to an input block.
@@ -35,6 +35,14 b' in attributes of :class:`~IPython.core.inputsplitter.IPythonInputSplitter`:'
35 passed to these, but note that function and class *definitions* are still a
35 passed to these, but note that function and class *definitions* are still a
36 series of separate statements. IPython does not use any of these by default.
36 series of separate statements. IPython does not use any of these by default.
37
37
38 An InteractiveShell instance actually has two
39 :class:`~IPython.core.inputsplitter.IPythonInputSplitter` instances, as the
40 attributes :attr:`~IPython.core.interactiveshell.InteractiveShell.input_splitter`,
41 to tell when a block of input is complete, and
42 :attr:`~IPython.core.interactiveshell.InteractiveShell.input_transformer_manager`,
43 to transform complete cells. If you add a transformer, you should make sure that
44 it gets added to both.
45
38 Stateless transformations
46 Stateless transformations
39 -------------------------
47 -------------------------
40
48
General Comments 0
You need to be logged in to leave comments. Login now