Show More
@@ -10,9 +10,30 b' with full support for the extended IPython syntax (magics, system calls, etc).' | |||||
10 |
|
10 | |||
11 | For more details, see the class docstring below. |
|
11 | For more details, see the class docstring below. | |
12 |
|
12 | |||
|
13 | Syntax Transformations | |||
|
14 | ---------------------- | |||
|
15 | ||||
|
16 | One of the main jobs of the code in this file is to apply all syntax | |||
|
17 | transformations that make up 'the IPython language', i.e. magics, shell | |||
|
18 | escapes, etc. All transformations should be implemented as *fully stateless* | |||
|
19 | entities, that simply take one line as their input and return a line. | |||
|
20 | Internally for implementation purposes they may be a normal function or a | |||
|
21 | callable object, but the only input they receive will be a single line and they | |||
|
22 | should only return a line, without holding any data-dependent state between | |||
|
23 | calls. | |||
|
24 | ||||
|
25 | As an example, the EscapedTransformer is a class so we can more clearly group | |||
|
26 | together the functionality of dispatching to individual functions based on the | |||
|
27 | starting escape character, but the only method for public use is its call | |||
|
28 | method. | |||
|
29 | ||||
|
30 | ||||
13 | ToDo |
|
31 | ToDo | |
14 | ---- |
|
32 | ---- | |
15 |
|
33 | |||
|
34 | - Should we make push() actually raise an exception once push_accepts_more() | |||
|
35 | returns False? | |||
|
36 | ||||
16 | - Naming cleanups. The tr_* names aren't the most elegant, though now they are |
|
37 | - Naming cleanups. The tr_* names aren't the most elegant, though now they are | |
17 | at least just attributes of a class so not really very exposed. |
|
38 | at least just attributes of a class so not really very exposed. | |
18 |
|
39 | |||
@@ -670,34 +691,34 b' class EscapedTransformer(object):' | |||||
670 | """Class to transform lines that are explicitly escaped out.""" |
|
691 | """Class to transform lines that are explicitly escaped out.""" | |
671 |
|
692 | |||
672 | def __init__(self): |
|
693 | def __init__(self): | |
673 | tr = { ESC_SHELL : self.tr_system, |
|
694 | tr = { ESC_SHELL : self._tr_system, | |
674 | ESC_SH_CAP : self.tr_system2, |
|
695 | ESC_SH_CAP : self._tr_system2, | |
675 | ESC_HELP : self.tr_help, |
|
696 | ESC_HELP : self._tr_help, | |
676 | ESC_HELP2 : self.tr_help, |
|
697 | ESC_HELP2 : self._tr_help, | |
677 | ESC_MAGIC : self.tr_magic, |
|
698 | ESC_MAGIC : self._tr_magic, | |
678 | ESC_QUOTE : self.tr_quote, |
|
699 | ESC_QUOTE : self._tr_quote, | |
679 | ESC_QUOTE2 : self.tr_quote2, |
|
700 | ESC_QUOTE2 : self._tr_quote2, | |
680 | ESC_PAREN : self.tr_paren } |
|
701 | ESC_PAREN : self._tr_paren } | |
681 | self.tr = tr |
|
702 | self.tr = tr | |
682 |
|
703 | |||
683 | # Support for syntax transformations that use explicit escapes typed by the |
|
704 | # Support for syntax transformations that use explicit escapes typed by the | |
684 | # user at the beginning of a line |
|
705 | # user at the beginning of a line | |
685 | @staticmethod |
|
706 | @staticmethod | |
686 | def tr_system(line_info): |
|
707 | def _tr_system(line_info): | |
687 | "Translate lines escaped with: !" |
|
708 | "Translate lines escaped with: !" | |
688 | cmd = line_info.line.lstrip().lstrip(ESC_SHELL) |
|
709 | cmd = line_info.line.lstrip().lstrip(ESC_SHELL) | |
689 | return '%sget_ipython().system(%s)' % (line_info.lspace, |
|
710 | return '%sget_ipython().system(%s)' % (line_info.lspace, | |
690 | make_quoted_expr(cmd)) |
|
711 | make_quoted_expr(cmd)) | |
691 |
|
712 | |||
692 | @staticmethod |
|
713 | @staticmethod | |
693 | def tr_system2(line_info): |
|
714 | def _tr_system2(line_info): | |
694 | "Translate lines escaped with: !!" |
|
715 | "Translate lines escaped with: !!" | |
695 | cmd = line_info.line.lstrip()[2:] |
|
716 | cmd = line_info.line.lstrip()[2:] | |
696 | return '%sget_ipython().getoutput(%s)' % (line_info.lspace, |
|
717 | return '%sget_ipython().getoutput(%s)' % (line_info.lspace, | |
697 | make_quoted_expr(cmd)) |
|
718 | make_quoted_expr(cmd)) | |
698 |
|
719 | |||
699 | @staticmethod |
|
720 | @staticmethod | |
700 | def tr_help(line_info): |
|
721 | def _tr_help(line_info): | |
701 | "Translate lines escaped with: ?/??" |
|
722 | "Translate lines escaped with: ?/??" | |
702 | # A naked help line should just fire the intro help screen |
|
723 | # A naked help line should just fire the intro help screen | |
703 | if not line_info.line[1:]: |
|
724 | if not line_info.line[1:]: | |
@@ -723,7 +744,7 b' class EscapedTransformer(object):' | |||||
723 | ' '.join([line_info.fpart, line_info.rest]).strip()) |
|
744 | ' '.join([line_info.fpart, line_info.rest]).strip()) | |
724 |
|
745 | |||
725 | @staticmethod |
|
746 | @staticmethod | |
726 | def tr_magic(line_info): |
|
747 | def _tr_magic(line_info): | |
727 | "Translate lines escaped with: %" |
|
748 | "Translate lines escaped with: %" | |
728 | tpl = '%sget_ipython().magic(%s)' |
|
749 | tpl = '%sget_ipython().magic(%s)' | |
729 | cmd = make_quoted_expr(' '.join([line_info.fpart, |
|
750 | cmd = make_quoted_expr(' '.join([line_info.fpart, | |
@@ -731,19 +752,19 b' class EscapedTransformer(object):' | |||||
731 | return tpl % (line_info.lspace, cmd) |
|
752 | return tpl % (line_info.lspace, cmd) | |
732 |
|
753 | |||
733 | @staticmethod |
|
754 | @staticmethod | |
734 | def tr_quote(line_info): |
|
755 | def _tr_quote(line_info): | |
735 | "Translate lines escaped with: ," |
|
756 | "Translate lines escaped with: ," | |
736 | return '%s%s("%s")' % (line_info.lspace, line_info.fpart, |
|
757 | return '%s%s("%s")' % (line_info.lspace, line_info.fpart, | |
737 | '", "'.join(line_info.rest.split()) ) |
|
758 | '", "'.join(line_info.rest.split()) ) | |
738 |
|
759 | |||
739 | @staticmethod |
|
760 | @staticmethod | |
740 | def tr_quote2(line_info): |
|
761 | def _tr_quote2(line_info): | |
741 | "Translate lines escaped with: ;" |
|
762 | "Translate lines escaped with: ;" | |
742 | return '%s%s("%s")' % (line_info.lspace, line_info.fpart, |
|
763 | return '%s%s("%s")' % (line_info.lspace, line_info.fpart, | |
743 | line_info.rest) |
|
764 | line_info.rest) | |
744 |
|
765 | |||
745 | @staticmethod |
|
766 | @staticmethod | |
746 | def tr_paren(line_info): |
|
767 | def _tr_paren(line_info): | |
747 | "Translate lines escaped with: /" |
|
768 | "Translate lines escaped with: /" | |
748 | return '%s%s(%s)' % (line_info.lspace, line_info.fpart, |
|
769 | return '%s%s(%s)' % (line_info.lspace, line_info.fpart, | |
749 | ", ".join(line_info.rest.split())) |
|
770 | ", ".join(line_info.rest.split())) | |
@@ -751,7 +772,7 b' class EscapedTransformer(object):' | |||||
751 | def __call__(self, line): |
|
772 | def __call__(self, line): | |
752 | """Class to transform lines that are explicitly escaped out. |
|
773 | """Class to transform lines that are explicitly escaped out. | |
753 |
|
774 | |||
754 | This calls the above tr_* static methods for the actual line |
|
775 | This calls the above _tr_* static methods for the actual line | |
755 | translations.""" |
|
776 | translations.""" | |
756 |
|
777 | |||
757 | # Empty lines just get returned unmodified |
|
778 | # Empty lines just get returned unmodified | |
@@ -765,13 +786,14 b' class EscapedTransformer(object):' | |||||
765 | # All other escapes are only valid at the start |
|
786 | # All other escapes are only valid at the start | |
766 | if not line_info.esc in self.tr: |
|
787 | if not line_info.esc in self.tr: | |
767 | if line.endswith(ESC_HELP): |
|
788 | if line.endswith(ESC_HELP): | |
768 | return self.tr_help(line_info) |
|
789 | return self._tr_help(line_info) | |
769 | else: |
|
790 | else: | |
770 | # If we don't recognize the escape, don't modify the line |
|
791 | # If we don't recognize the escape, don't modify the line | |
771 | return line |
|
792 | return line | |
772 |
|
793 | |||
773 | return self.tr[line_info.esc](line_info) |
|
794 | return self.tr[line_info.esc](line_info) | |
774 |
|
795 | |||
|
796 | ||||
775 | # A function-looking object to be used by the rest of the code. The purpose of |
|
797 | # A function-looking object to be used by the rest of the code. The purpose of | |
776 | # the class in this case is to organize related functionality, more than to |
|
798 | # the class in this case is to organize related functionality, more than to | |
777 | # manage state. |
|
799 | # manage state. |
@@ -583,7 +583,7 b' class IPythonInputTestCase(InputSplitterTestCase):' | |||||
583 | out_t = '\n'.join(out_t_parts).rstrip() |
|
583 | out_t = '\n'.join(out_t_parts).rstrip() | |
584 | self.assertEqual(out, out_t) |
|
584 | self.assertEqual(out, out_t) | |
585 |
|
585 | |||
586 |
|
586 | |||
587 | #----------------------------------------------------------------------------- |
|
587 | #----------------------------------------------------------------------------- | |
588 | # Main - use as a script |
|
588 | # Main - use as a script | |
589 | #----------------------------------------------------------------------------- |
|
589 | #----------------------------------------------------------------------------- | |
@@ -615,6 +615,7 b" if __name__ == '__main__':" | |||||
615 |
|
615 | |||
616 | # Here we just return input so we can use it in a test suite, but a |
|
616 | # Here we just return input so we can use it in a test suite, but a | |
617 | # real interpreter would instead send it for execution somewhere. |
|
617 | # real interpreter would instead send it for execution somewhere. | |
|
618 | #src = isp.source; raise EOFError # dbg | |||
618 | src = isp.source_reset() |
|
619 | src = isp.source_reset() | |
619 | print 'Input source was:\n', src |
|
620 | print 'Input source was:\n', src | |
620 | except EOFError: |
|
621 | except EOFError: |
General Comments 0
You need to be logged in to leave comments.
Login now