##// END OF EJS Templates
First go at new input transformation system
Thomas Kluyver -
Show More
@@ -0,0 +1,112 b''
1 import abc
2 import re
3
4 from IPython.core.splitinput import split_user_input, LineInfo
5 from IPython.core.inputsplitter import (ESC_SHELL, ESC_SH_CAP, ESC_HELP,
6 ESC_HELP2, ESC_MAGIC, ESC_MAGIC2,
7 ESC_QUOTE, ESC_QUOTE2, ESC_PAREN)
8 from IPython.core.inputsplitter import EscapedTransformer, _make_help_call, has_comment
9
10 class InputTransformer(object):
11 __metaclass__ = abc.ABCMeta
12
13 @abc.abstractmethod
14 def push(self, line):
15 pass
16
17 @abc.abstractmethod
18 def reset(self):
19 pass
20
21 class StatelessInputTransformer(InputTransformer):
22 """Decorator for a stateless input transformer implemented as a function."""
23 def __init__(self, func):
24 self.func = func
25
26 def push(self, line):
27 return self.func(line)
28
29 def reset(self):
30 pass
31
32 class CoroutineInputTransformer(InputTransformer):
33 """Decorator for an input transformer implemented as a coroutine."""
34 def __init__(self, coro):
35 # Prime it
36 self.coro = coro()
37 next(self.coro)
38
39 def push(self, line):
40 return self.coro.send(line)
41
42 def reset(self):
43 self.coro.send(None)
44
45 @CoroutineInputTransformer
46 def escaped_transformer():
47 et = EscapedTransformer()
48 line = ''
49 while True:
50 line = (yield line)
51 if not line or line.isspace():
52 continue
53 lineinf = LineInfo(line)
54 if lineinf.esc not in et.tr:
55 continue
56
57 parts = []
58 while line is not None:
59 parts.append(line.rstrip('\\'))
60 if not line.endswith('\\'):
61 break
62 line = (yield None)
63
64 # Output
65 lineinf = LineInfo(' '.join(parts))
66 line = et.tr[lineinf.esc](lineinf)
67
68 _initial_space_re = re.compile(r'\s*')
69
70 _help_end_re = re.compile(r"""(%{0,2}
71 [a-zA-Z_*][\w*]* # Variable name
72 (\.[a-zA-Z_*][\w*]*)* # .etc.etc
73 )
74 (\?\??)$ # ? or ??""",
75 re.VERBOSE)
76
77 @StatelessInputTransformer
78 def transform_help_end(line):
79 """Translate lines with ?/?? at the end"""
80 m = _help_end_re.search(line)
81 if m is None or has_comment(line):
82 return line
83 target = m.group(1)
84 esc = m.group(3)
85 lspace = _initial_space_re.match(line).group(0)
86
87 # If we're mid-command, put it back on the next prompt for the user.
88 next_input = line.rstrip('?') if line.strip() != m.group(0) else None
89
90 return _make_help_call(target, esc, lspace, next_input)
91
92
93 @CoroutineInputTransformer
94 def cellmagic():
95 tpl = 'get_ipython().run_cell_magic(%r, %r, %r)'
96 line = ''
97 while True:
98 line = (yield line)
99 if not line.startswith(ESC_MAGIC2):
100 continue
101
102 first = line
103 body = []
104 line = (yield None)
105 while (line is not None) and (line.strip() != ''):
106 body.append(line)
107 line = (yield None)
108
109 # Output
110 magic_name, _, first = first.partition(' ')
111 magic_name = magic_name.lstrip(ESC_MAGIC2)
112 line = tpl % (magic_name, first, '\n'.join(body))
@@ -0,0 +1,37 b''
1 import unittest
2 import nose.tools as nt
3
4 from IPython.testing import tools as tt
5 from IPython.utils import py3compat
6
7 from IPython.core import inputtransformer
8 from IPython.core.tests.test_inputsplitter import syntax
9
10 def wrap_transform(transformer):
11 def transform(inp):
12 for line in inp:
13 res = transformer.push(line)
14 if res is not None:
15 return res
16 return transformer.push(None)
17
18 return transform
19
20 cellmagic_tests = [
21 (['%%foo a'], "get_ipython().run_cell_magic('foo', 'a', '')"),
22 (['%%bar 123', 'hello', ''], "get_ipython().run_cell_magic('bar', '123', 'hello')"),
23 ]
24
25 def test_transform_cellmagic():
26 tt.check_pairs(wrap_transform(inputtransformer.cellmagic), cellmagic_tests)
27
28 esctransform_tests = [(i, py3compat.u_format(o)) for i,o in [
29 (['%pdef zip'], "get_ipython().magic({u}'pdef zip')"),
30 (['%abc def \\', 'ghi'], "get_ipython().magic({u}'abc def ghi')"),
31 ]]
32
33 def test_transform_escaped():
34 tt.check_pairs(wrap_transform(inputtransformer.escaped_transformer), esctransform_tests)
35
36 def endhelp_test():
37 tt.check_pairs(inputtransformer.transform_help_end.push, syntax['end_help'])
General Comments 0
You need to be logged in to leave comments. Login now