##// END OF EJS Templates
First working version of cell magics in inputsplitter in line mode....
Fernando Perez -
Show More
@@ -142,6 +142,21 b' def num_ini_spaces(s):'
142 return 0
142 return 0
143
143
144
144
145 def last_blank(src):
146 """Determine if the input source ends in a blank.
147
148 A blank is either a newline or a line consisting of whitespace.
149
150 Parameters
151 ----------
152 src : string
153 A single or multiline string.
154 """
155 if not src: return False
156 ll = src.splitlines()[-1]
157 return (ll == '') or ll.isspace()
158
159
145 def remove_comments(src):
160 def remove_comments(src):
146 """Remove all comments from input source.
161 """Remove all comments from input source.
147
162
@@ -685,23 +700,27 b' class IPythonInputSplitter(InputSplitter):'
685 # String with raw, untransformed input.
700 # String with raw, untransformed input.
686 source_raw = ''
701 source_raw = ''
687
702
688 cell_magic_body = None
703 cell_magic_parts = []
704
705 cell_magic_mode = False
689
706
690 # Private attributes
707 # Private attributes
691
708
692 # List with lines of raw input accumulated so far.
709 # List with lines of raw input accumulated so far.
693 _buffer_raw = None
710 _buffer_raw = None
694
711
695 def __init__(self, input_mode=None):
712 def __init__(self, input_mode=None):
696 super(IPythonInputSplitter, self).__init__(input_mode)
713 super(IPythonInputSplitter, self).__init__(input_mode)
697 self._buffer_raw = []
714 self._buffer_raw = []
715 self._validate = True
698
716
699 def reset(self):
717 def reset(self):
700 """Reset the input buffer and associated state."""
718 """Reset the input buffer and associated state."""
701 super(IPythonInputSplitter, self).reset()
719 super(IPythonInputSplitter, self).reset()
702 self._buffer_raw[:] = []
720 self._buffer_raw[:] = []
703 self.source_raw = ''
721 self.source_raw = ''
704 self.cell_magic_body = None
722 self.cell_magic_parts = []
723 self.cell_magic_mode = False
705
724
706 def source_raw_reset(self):
725 def source_raw_reset(self):
707 """Return input and raw source and perform a full reset.
726 """Return input and raw source and perform a full reset.
@@ -711,6 +730,96 b' class IPythonInputSplitter(InputSplitter):'
711 self.reset()
730 self.reset()
712 return out, out_r
731 return out, out_r
713
732
733 def push_accepts_more(self):
734 if self.cell_magic_mode:
735 return not self._is_complete
736 else:
737 return super(IPythonInputSplitter, self).push_accepts_more()
738
739 def _push_line_mode(self, lines):
740 """Push in line mode.
741
742 This means that we only get individual 'lines' with each call, though
743 in practice each input may be multiline. But this is in contrast to
744 cell mode, which feeds the entirety of the cell from the start with
745 each call.
746 """
747 # cell magic support
748 #print('#'*10)
749 #print(lines+'\n---') # dbg
750 #print (repr(lines)+'\n+++')
751 #print('raw', self._buffer_raw, 'validate', self.cell_magic_mode)
752 # Only trigger this block if we're at a 'fresh' pumping start.
753 if lines.startswith('%%') and (not self.cell_magic_mode) and \
754 not self._buffer_raw:
755 # Cell magics bypass all further transformations
756 self.cell_magic_mode = True
757 first, _, body = lines.partition('\n')
758 magic_name, _, line = first.partition(' ')
759 magic_name = magic_name.lstrip(ESC_MAGIC)
760 # We store the body of the cell and create a call to a method that
761 # will use this stored value. This is ugly, but it's a first cut to
762 # get it all working, as right now changing the return API of our
763 # methods would require major refactoring.
764 self.cell_magic_parts = [body]
765 tpl = 'get_ipython()._cell_magic(%r, %r)'
766 tlines = tpl % (magic_name, line)
767 self._store(tlines)
768 self._store(lines, self._buffer_raw, 'source_raw')
769 self._is_complete = False
770 return False
771
772 if self.cell_magic_mode:
773 # Find out if the last stored block has a whitespace line as its
774 # last line and also this line is whitespace, case in which we're
775 # done (two contiguous blank lines signal termination). Note that
776 # the storage logic *enforces* that every stored block is
777 # newline-terminated, so we grab everything but the last character
778 # so we can have the body of the block alone.
779 last_block = self.cell_magic_parts[-1]
780 self._is_complete = last_blank(last_block) and lines.isspace()
781 # Only store the raw input. For lines beyond the first one, we
782 # only store them for history purposes, and for execution we want
783 # the caller to only receive the _cell_magic() call.
784 self._store(lines, self._buffer_raw, 'source_raw')
785 self.cell_magic_parts.append(lines)
786 return self._is_complete
787
788 lines_list = lines.splitlines()
789
790 transforms = [transform_ipy_prompt, transform_classic_prompt,
791 transform_help_end, transform_escaped,
792 transform_assign_system, transform_assign_magic]
793
794 # Transform logic
795 #
796 # We only apply the line transformers to the input if we have either no
797 # input yet, or complete input, or if the last line of the buffer ends
798 # with ':' (opening an indented block). This prevents the accidental
799 # transformation of escapes inside multiline expressions like
800 # triple-quoted strings or parenthesized expressions.
801 #
802 # The last heuristic, while ugly, ensures that the first line of an
803 # indented block is correctly transformed.
804 #
805 # FIXME: try to find a cleaner approach for this last bit.
806
807 # Store raw source before applying any transformations to it. Note
808 # that this must be done *after* the reset() call that would otherwise
809 # flush the buffer.
810 self._store(lines, self._buffer_raw, 'source_raw')
811
812 push = super(IPythonInputSplitter, self).push
813 buf = self._buffer
814 for line in lines_list:
815 if self._is_complete or not buf or \
816 (buf and buf[-1].rstrip().endswith((':', ','))):
817 for f in transforms:
818 line = f(line)
819
820 out = push(line)
821 return out
822
714 def push(self, lines):
823 def push(self, lines):
715 """Push one or more lines of IPython input.
824 """Push one or more lines of IPython input.
716
825
@@ -734,25 +843,19 b' class IPythonInputSplitter(InputSplitter):'
734 this value is also stored as a private attribute (_is_complete), so it
843 this value is also stored as a private attribute (_is_complete), so it
735 can be queried at any time.
844 can be queried at any time.
736 """
845 """
846 print('mode:', self.input_mode)
847 print('lines:',repr(lines))
737 if not lines:
848 if not lines:
738 return super(IPythonInputSplitter, self).push(lines)
849 return super(IPythonInputSplitter, self).push(lines)
739
850
740 # We must ensure all input is pure unicode
851 # We must ensure all input is pure unicode
741 lines = cast_unicode(lines, self.encoding)
852 lines = cast_unicode(lines, self.encoding)
742
853
743 # cell magic support
854 if self.input_mode == 'line':
744 #print('IM:', self.input_mode,'\n'+lines); print('---') # dbg
855 return self._push_line_mode(lines)
745 #if self.input_mode == 'cell' and lines.startswith('%%'):
856
746 if lines.startswith('%%'):
857 ## else:
747 # Cell magics bypass all further transformations
858 ## return self._push_cell_mode(lines)
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
859
757 lines_list = lines.splitlines()
860 lines_list = lines.splitlines()
758
861
@@ -796,8 +899,7 b' class IPythonInputSplitter(InputSplitter):'
796 buf = self._buffer
899 buf = self._buffer
797 for line in lines_list:
900 for line in lines_list:
798 if self._is_complete or not buf or \
901 if self._is_complete or not buf or \
799 (buf and (buf[-1].rstrip().endswith(':') or
902 (buf and buf[-1].rstrip().endswith((':', ','))):
800 buf[-1].rstrip().endswith(',')) ):
801 for f in transforms:
903 for f in transforms:
802 line = f(line)
904 line = f(line)
803
905
@@ -2027,7 +2027,12 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("Line magic function `%%%s` not found." % magic_name)
2030 em = "Line magic function `%%%s` not found" % magic_name
2031 cm = self.find_cell_magic(magic_name)
2032 if cm is not None:
2033 em += (' (Did you by chance mean the cell magic `%%%%%s` '
2034 'instead?).')
2035 error()
2031 else:
2036 else:
2032 # Note: this is the distance in the stack to the user's frame.
2037 # 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
2038 # This will need to be updated if the internal calling logic gets
@@ -2469,13 +2474,9 b' class InteractiveShell(SingletonConfigurable):'
2469 self.showtraceback()
2474 self.showtraceback()
2470 warn('Unknown failure executing module: <%s>' % mod_name)
2475 warn('Unknown failure executing module: <%s>' % mod_name)
2471
2476
2472 def call_cell_magic(self, raw_cell, store_history=False):
2473 line, _, cell = raw_cell.partition(os.linesep)
2474 magic_name, _, line = line.partition(' ')
2475 magic_name = magic_name.lstrip(prefilter.ESC_MAGIC)
2476 return self.cell_magic(magic_name, line, cell)
2477
2478 def _cell_magic(self, magic_name, line):
2477 def _cell_magic(self, magic_name, line):
2478 """Special method to call a cell magic with the data stored in self.
2479 """
2479 cell = self._current_cell_magic_body
2480 cell = self._current_cell_magic_body
2480 self._current_cell_magic_body = None
2481 self._current_cell_magic_body = None
2481 return self.cell_magic(magic_name, line, cell)
2482 return self.cell_magic(magic_name, line, cell)
@@ -2507,8 +2508,9 b' class InteractiveShell(SingletonConfigurable):'
2507 # ugly, we need to do something cleaner later... Now the logic is
2508 # 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 # simply that the input_splitter remembers if there was a cell magic,
2509 # and in that case we grab the cell body.
2510 # and in that case we grab the cell body.
2510 if self.input_splitter.cell_magic_body is not None:
2511 if self.input_splitter.cell_magic_parts:
2511 self._current_cell_magic_body = self.input_splitter.cell_magic_body
2512 self._current_cell_magic_body = \
2513 ''.join(self.input_splitter.cell_magic_parts)
2512 cell = self.input_splitter.source_reset()
2514 cell = self.input_splitter.source_reset()
2513
2515
2514 with self.builtin_trap:
2516 with self.builtin_trap:
@@ -599,6 +599,41 b' def test_escaped_paren():'
599 tt.check_pairs(isp.transform_escaped, syntax['escaped_paren'])
599 tt.check_pairs(isp.transform_escaped, syntax['escaped_paren'])
600
600
601
601
602 def test_last_blank():
603 nt.assert_false(isp.last_blank(''))
604 nt.assert_false(isp.last_blank('abc'))
605 nt.assert_false(isp.last_blank('abc\n'))
606 nt.assert_false(isp.last_blank('abc\na'))
607 nt.assert_true(isp.last_blank('\n'))
608 nt.assert_true(isp.last_blank('\n '))
609 nt.assert_true(isp.last_blank('abc\n '))
610 nt.assert_true(isp.last_blank('abc\n\n'))
611
612
613 def test_cell_magics():
614 from IPython.core import magic
615
616 cell = """\
617 %%cellm line
618 body
619 """
620 sp = isp.IPythonInputSplitter(input_mode='line')
621 sp.push(cell)
622 nt.assert_equal(sp.cell_magic_parts, ['body\n'])
623 out = sp.source
624 ref = u"get_ipython()._cell_magic(u'cellm', u'line')\n"
625 nt.assert_equal(out, ref)
626
627 sp.reset()
628
629 sp.push('%%cellm line2\n')
630 nt.assert_true(sp.push_accepts_more()) #1
631 sp.push('\n')
632 nt.assert_true(sp.push_accepts_more()) #2
633 sp.push('\n')
634 nt.assert_false(sp.push_accepts_more()) #3
635
636
602 class IPythonInputTestCase(InputSplitterTestCase):
637 class IPythonInputTestCase(InputSplitterTestCase):
603 """By just creating a new class whose .isp is a different instance, we
638 """By just creating a new class whose .isp is a different instance, we
604 re-run the same test battery on the new input splitter.
639 re-run the same test battery on the new input splitter.
General Comments 0
You need to be logged in to leave comments. Login now