Show More
@@ -55,7 +55,7 b' Authors' | |||
|
55 | 55 | * Brian Granger |
|
56 | 56 | """ |
|
57 | 57 | #----------------------------------------------------------------------------- |
|
58 |
# Copyright (C) 2010 |
|
|
58 | # Copyright (C) 2010 The IPython Development Team | |
|
59 | 59 | # |
|
60 | 60 | # Distributed under the terms of the BSD License. The full license is in |
|
61 | 61 | # the file COPYING, distributed as part of this software. |
@@ -685,20 +685,23 b' class IPythonInputSplitter(InputSplitter):' | |||
|
685 | 685 | # String with raw, untransformed input. |
|
686 | 686 | source_raw = '' |
|
687 | 687 | |
|
688 | cell_magic_body = None | |
|
689 | ||
|
688 | 690 | # Private attributes |
|
689 | 691 | |
|
690 | 692 | # List with lines of raw input accumulated so far. |
|
691 | 693 | _buffer_raw = None |
|
692 | 694 | |
|
693 | 695 | def __init__(self, input_mode=None): |
|
694 |
InputSplitter.__init__( |
|
|
696 | super(IPythonInputSplitter, self).__init__(input_mode) | |
|
695 | 697 | self._buffer_raw = [] |
|
696 | 698 | |
|
697 | 699 | def reset(self): |
|
698 | 700 | """Reset the input buffer and associated state.""" |
|
699 |
InputSplitter.reset( |
|
|
701 | super(IPythonInputSplitter, self).reset() | |
|
700 | 702 | self._buffer_raw[:] = [] |
|
701 | 703 | self.source_raw = '' |
|
704 | self.cell_magic_body = None | |
|
702 | 705 | |
|
703 | 706 | def source_raw_reset(self): |
|
704 | 707 | """Return input and raw source and perform a full reset. |
@@ -710,6 +713,26 b' class IPythonInputSplitter(InputSplitter):' | |||
|
710 | 713 | |
|
711 | 714 | def push(self, lines): |
|
712 | 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 | 737 | if not lines: |
|
715 | 738 | return super(IPythonInputSplitter, self).push(lines) |
@@ -717,6 +740,20 b' class IPythonInputSplitter(InputSplitter):' | |||
|
717 | 740 | # We must ensure all input is pure unicode |
|
718 | 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 | 757 | lines_list = lines.splitlines() |
|
721 | 758 | |
|
722 | 759 | transforms = [transform_ipy_prompt, transform_classic_prompt, |
@@ -2027,7 +2027,7 b' class InteractiveShell(SingletonConfigurable):' | |||
|
2027 | 2027 | """ |
|
2028 | 2028 | fn = self.find_line_magic(magic_name) |
|
2029 | 2029 | if fn is None: |
|
2030 |
error(" |
|
|
2030 | error("Line magic function `%%%s` not found." % magic_name) | |
|
2031 | 2031 | else: |
|
2032 | 2032 | # Note: this is the distance in the stack to the user's frame. |
|
2033 | 2033 | # This will need to be updated if the internal calling logic gets |
@@ -2048,7 +2048,7 b' class InteractiveShell(SingletonConfigurable):' | |||
|
2048 | 2048 | """ |
|
2049 | 2049 | fn = self.find_cell_magic(magic_name) |
|
2050 | 2050 | if fn is None: |
|
2051 |
error(" |
|
|
2051 | error("Cell magic function `%%%%%s` not found." % magic_name) | |
|
2052 | 2052 | else: |
|
2053 | 2053 | # Note: this is the distance in the stack to the user's frame. |
|
2054 | 2054 | # This will need to be updated if the internal calling logic gets |
@@ -2475,6 +2475,11 b' class InteractiveShell(SingletonConfigurable):' | |||
|
2475 | 2475 | magic_name = magic_name.lstrip(prefilter.ESC_MAGIC) |
|
2476 | 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 | 2483 | def run_cell(self, raw_cell, store_history=False, silent=False): |
|
2479 | 2484 | """Run a complete IPython cell. |
|
2480 | 2485 | |
@@ -2496,11 +2501,14 b' class InteractiveShell(SingletonConfigurable):' | |||
|
2496 | 2501 | if silent: |
|
2497 | 2502 | store_history = False |
|
2498 | 2503 | |
|
2499 | if raw_cell.startswith('%%'): | |
|
2500 | return self.call_cell_magic(raw_cell, store_history) | |
|
2504 | self.input_splitter.push(raw_cell) | |
|
2501 | 2505 | |
|
2502 | for line in raw_cell.splitlines(): | |
|
2503 | self.input_splitter.push(line) | |
|
2506 | # Check for cell magics, which leave state behind. This interface is | |
|
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 | 2512 | cell = self.input_splitter.source_reset() |
|
2505 | 2513 | |
|
2506 | 2514 | with self.builtin_trap: |
@@ -495,10 +495,12 b' def test_env():' | |||
|
495 | 495 | class CellMagicTestCase(TestCase): |
|
496 | 496 | |
|
497 | 497 | def check_ident(self, magic): |
|
498 | # Manually called, we get the result | |
|
498 | 499 | out = _ip.cell_magic(magic, 'a', 'b') |
|
499 | 500 | nt.assert_equals(out, ('a','b')) |
|
500 | out = _ip.run_cell('%%' + magic +' a\nb') | |
|
501 | nt.assert_equals(out, ('a','b')) | |
|
501 | # Via run_cell, it goes into the user's namespace via displayhook | |
|
502 | _ip.run_cell('%%' + magic +' c\nd') | |
|
503 | nt.assert_equals(_ip.user_ns['_'], ('c','d')) | |
|
502 | 504 | |
|
503 | 505 | def test_cell_magic_func_deco(self): |
|
504 | 506 | "Cell magic using simple decorator" |
@@ -525,12 +527,19 b' class CellMagicTestCase(TestCase):' | |||
|
525 | 527 | def cellm3(self, line, cell): |
|
526 | 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 | 538 | @cell_magic('cellm4') |
|
529 | 539 | def cellm33(self, line, cell): |
|
530 | 540 | return line, cell |
|
531 | ||
|
532 | _ip.register_magics(MyMagics) | |
|
533 | self.check_ident('cellm3') | |
|
541 | ||
|
542 | _ip.register_magics(MyMagics2) | |
|
534 | 543 | self.check_ident('cellm4') |
|
535 | 544 | # Check that nothing is registered as 'cellm33' |
|
536 | 545 | c33 = _ip.find_cell_magic('cellm33') |
General Comments 0
You need to be logged in to leave comments.
Login now