##// END OF EJS Templates
First implementation of cell magics that goes via inputsplitter....
Fernando Perez -
Show More
@@ -55,7 +55,7 b' Authors'
55 * Brian Granger
55 * Brian Granger
56 """
56 """
57 #-----------------------------------------------------------------------------
57 #-----------------------------------------------------------------------------
58 # Copyright (C) 2010-2011 The IPython Development Team
58 # Copyright (C) 2010 The IPython Development Team
59 #
59 #
60 # Distributed under the terms of the BSD License. The full license is in
60 # Distributed under the terms of the BSD License. The full license is in
61 # the file COPYING, distributed as part of this software.
61 # the file COPYING, distributed as part of this software.
@@ -685,20 +685,23 b' class IPythonInputSplitter(InputSplitter):'
685 # String with raw, untransformed input.
685 # String with raw, untransformed input.
686 source_raw = ''
686 source_raw = ''
687
687
688 cell_magic_body = None
689
688 # Private attributes
690 # Private attributes
689
691
690 # List with lines of raw input accumulated so far.
692 # List with lines of raw input accumulated so far.
691 _buffer_raw = None
693 _buffer_raw = None
692
694
693 def __init__(self, input_mode=None):
695 def __init__(self, input_mode=None):
694 InputSplitter.__init__(self, input_mode)
696 super(IPythonInputSplitter, self).__init__(input_mode)
695 self._buffer_raw = []
697 self._buffer_raw = []
696
698
697 def reset(self):
699 def reset(self):
698 """Reset the input buffer and associated state."""
700 """Reset the input buffer and associated state."""
699 InputSplitter.reset(self)
701 super(IPythonInputSplitter, self).reset()
700 self._buffer_raw[:] = []
702 self._buffer_raw[:] = []
701 self.source_raw = ''
703 self.source_raw = ''
704 self.cell_magic_body = None
702
705
703 def source_raw_reset(self):
706 def source_raw_reset(self):
704 """Return input and raw source and perform a full reset.
707 """Return input and raw source and perform a full reset.
@@ -710,6 +713,26 b' class IPythonInputSplitter(InputSplitter):'
710
713
711 def push(self, lines):
714 def push(self, lines):
712 """Push one or more lines of IPython input.
715 """Push one or more lines of IPython input.
716
717 This stores the given lines and returns a status code indicating
718 whether the code forms a complete Python block or not, after processing
719 all input lines for special IPython syntax.
720
721 Any exceptions generated in compilation are swallowed, but if an
722 exception was produced, the method returns True.
723
724 Parameters
725 ----------
726 lines : string
727 One or more lines of Python input.
728
729 Returns
730 -------
731 is_complete : boolean
732 True if the current input source (the result of the current input
733 plus prior inputs) forms a complete Python execution block. Note that
734 this value is also stored as a private attribute (_is_complete), so it
735 can be queried at any time.
713 """
736 """
714 if not lines:
737 if not lines:
715 return super(IPythonInputSplitter, self).push(lines)
738 return super(IPythonInputSplitter, self).push(lines)
@@ -717,6 +740,20 b' class IPythonInputSplitter(InputSplitter):'
717 # We must ensure all input is pure unicode
740 # We must ensure all input is pure unicode
718 lines = cast_unicode(lines, self.encoding)
741 lines = cast_unicode(lines, self.encoding)
719
742
743 # cell magic support
744 #print('IM:', self.input_mode,'\n'+lines); print('---') # dbg
745 #if self.input_mode == 'cell' and lines.startswith('%%'):
746 if lines.startswith('%%'):
747 # Cell magics bypass all further transformations
748 self.reset()
749 self._is_complete = is_complete = True
750 first, _, body = lines.partition('\n')
751 magic_name, _, line = first.partition(' ')
752 magic_name = magic_name.lstrip(ESC_MAGIC)
753 self.cell_magic_body = body
754 tpl = 'get_ipython()._cell_magic(%r, %r)'
755 lines = tpl % (magic_name, line)
756
720 lines_list = lines.splitlines()
757 lines_list = lines.splitlines()
721
758
722 transforms = [transform_ipy_prompt, transform_classic_prompt,
759 transforms = [transform_ipy_prompt, transform_classic_prompt,
@@ -2027,7 +2027,7 b' class InteractiveShell(SingletonConfigurable):'
2027 """
2027 """
2028 fn = self.find_line_magic(magic_name)
2028 fn = self.find_line_magic(magic_name)
2029 if fn is None:
2029 if fn is None:
2030 error("Magic function `%s` not found." % magic_name)
2030 error("Line magic function `%%%s` not found." % magic_name)
2031 else:
2031 else:
2032 # Note: this is the distance in the stack to the user's frame.
2032 # Note: this is the distance in the stack to the user's frame.
2033 # This will need to be updated if the internal calling logic gets
2033 # This will need to be updated if the internal calling logic gets
@@ -2048,7 +2048,7 b' class InteractiveShell(SingletonConfigurable):'
2048 """
2048 """
2049 fn = self.find_cell_magic(magic_name)
2049 fn = self.find_cell_magic(magic_name)
2050 if fn is None:
2050 if fn is None:
2051 error("Magic function `%s` not found." % magic_name)
2051 error("Cell magic function `%%%%%s` not found." % magic_name)
2052 else:
2052 else:
2053 # Note: this is the distance in the stack to the user's frame.
2053 # Note: this is the distance in the stack to the user's frame.
2054 # This will need to be updated if the internal calling logic gets
2054 # This will need to be updated if the internal calling logic gets
@@ -2475,6 +2475,11 b' class InteractiveShell(SingletonConfigurable):'
2475 magic_name = magic_name.lstrip(prefilter.ESC_MAGIC)
2475 magic_name = magic_name.lstrip(prefilter.ESC_MAGIC)
2476 return self.cell_magic(magic_name, line, cell)
2476 return self.cell_magic(magic_name, line, cell)
2477
2477
2478 def _cell_magic(self, magic_name, line):
2479 cell = self._current_cell_magic_body
2480 self._current_cell_magic_body = None
2481 return self.cell_magic(magic_name, line, cell)
2482
2478 def run_cell(self, raw_cell, store_history=False, silent=False):
2483 def run_cell(self, raw_cell, store_history=False, silent=False):
2479 """Run a complete IPython cell.
2484 """Run a complete IPython cell.
2480
2485
@@ -2496,11 +2501,14 b' class InteractiveShell(SingletonConfigurable):'
2496 if silent:
2501 if silent:
2497 store_history = False
2502 store_history = False
2498
2503
2499 if raw_cell.startswith('%%'):
2504 self.input_splitter.push(raw_cell)
2500 return self.call_cell_magic(raw_cell, store_history)
2501
2505
2502 for line in raw_cell.splitlines():
2506 # Check for cell magics, which leave state behind. This interface is
2503 self.input_splitter.push(line)
2507 # ugly, we need to do something cleaner later... Now the logic is
2508 # simply that the input_splitter remembers if there was a cell magic,
2509 # and in that case we grab the cell body.
2510 if self.input_splitter.cell_magic_body is not None:
2511 self._current_cell_magic_body = self.input_splitter.cell_magic_body
2504 cell = self.input_splitter.source_reset()
2512 cell = self.input_splitter.source_reset()
2505
2513
2506 with self.builtin_trap:
2514 with self.builtin_trap:
@@ -495,10 +495,12 b' def test_env():'
495 class CellMagicTestCase(TestCase):
495 class CellMagicTestCase(TestCase):
496
496
497 def check_ident(self, magic):
497 def check_ident(self, magic):
498 # Manually called, we get the result
498 out = _ip.cell_magic(magic, 'a', 'b')
499 out = _ip.cell_magic(magic, 'a', 'b')
499 nt.assert_equals(out, ('a','b'))
500 nt.assert_equals(out, ('a','b'))
500 out = _ip.run_cell('%%' + magic +' a\nb')
501 # Via run_cell, it goes into the user's namespace via displayhook
501 nt.assert_equals(out, ('a','b'))
502 _ip.run_cell('%%' + magic +' c\nd')
503 nt.assert_equals(_ip.user_ns['_'], ('c','d'))
502
504
503 def test_cell_magic_func_deco(self):
505 def test_cell_magic_func_deco(self):
504 "Cell magic using simple decorator"
506 "Cell magic using simple decorator"
@@ -525,12 +527,19 b' class CellMagicTestCase(TestCase):'
525 def cellm3(self, line, cell):
527 def cellm3(self, line, cell):
526 return line, cell
528 return line, cell
527
529
530 _ip.register_magics(MyMagics)
531 self.check_ident('cellm3')
532
533 def test_cell_magic_class2(self):
534 "Cell magics declared via a class, #2"
535 @magics_class
536 class MyMagics2(Magics):
537
528 @cell_magic('cellm4')
538 @cell_magic('cellm4')
529 def cellm33(self, line, cell):
539 def cellm33(self, line, cell):
530 return line, cell
540 return line, cell
531
541
532 _ip.register_magics(MyMagics)
542 _ip.register_magics(MyMagics2)
533 self.check_ident('cellm3')
534 self.check_ident('cellm4')
543 self.check_ident('cellm4')
535 # Check that nothing is registered as 'cellm33'
544 # Check that nothing is registered as 'cellm33'
536 c33 = _ip.find_cell_magic('cellm33')
545 c33 = _ip.find_cell_magic('cellm33')
General Comments 0
You need to be logged in to leave comments. Login now