##// END OF EJS Templates
Update split_user_input unicode test.
Thomas Kluyver -
Show More
@@ -1,698 +1,690 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2 """Tests for the inputsplitter module.
2 """Tests for the inputsplitter module.
3
3
4 Authors
4 Authors
5 -------
5 -------
6 * Fernando Perez
6 * Fernando Perez
7 * Robert Kern
7 * Robert Kern
8 """
8 """
9 #-----------------------------------------------------------------------------
9 #-----------------------------------------------------------------------------
10 # Copyright (C) 2010 The IPython Development Team
10 # Copyright (C) 2010 The IPython Development Team
11 #
11 #
12 # Distributed under the terms of the BSD License. The full license is in
12 # Distributed under the terms of the BSD License. The full license is in
13 # the file COPYING, distributed as part of this software.
13 # the file COPYING, distributed as part of this software.
14 #-----------------------------------------------------------------------------
14 #-----------------------------------------------------------------------------
15
15
16 #-----------------------------------------------------------------------------
16 #-----------------------------------------------------------------------------
17 # Imports
17 # Imports
18 #-----------------------------------------------------------------------------
18 #-----------------------------------------------------------------------------
19 # stdlib
19 # stdlib
20 import unittest
20 import unittest
21 import sys
21 import sys
22
22
23 # Third party
23 # Third party
24 import nose.tools as nt
24 import nose.tools as nt
25
25
26 # Our own
26 # Our own
27 from IPython.core import inputsplitter as isp
27 from IPython.core import inputsplitter as isp
28 from IPython.testing import tools as tt
28 from IPython.testing import tools as tt
29
29
30 #-----------------------------------------------------------------------------
30 #-----------------------------------------------------------------------------
31 # Semi-complete examples (also used as tests)
31 # Semi-complete examples (also used as tests)
32 #-----------------------------------------------------------------------------
32 #-----------------------------------------------------------------------------
33
33
34 # Note: at the bottom, there's a slightly more complete version of this that
34 # Note: at the bottom, there's a slightly more complete version of this that
35 # can be useful during development of code here.
35 # can be useful during development of code here.
36
36
37 def mini_interactive_loop(input_func):
37 def mini_interactive_loop(input_func):
38 """Minimal example of the logic of an interactive interpreter loop.
38 """Minimal example of the logic of an interactive interpreter loop.
39
39
40 This serves as an example, and it is used by the test system with a fake
40 This serves as an example, and it is used by the test system with a fake
41 raw_input that simulates interactive input."""
41 raw_input that simulates interactive input."""
42
42
43 from IPython.core.inputsplitter import InputSplitter
43 from IPython.core.inputsplitter import InputSplitter
44
44
45 isp = InputSplitter()
45 isp = InputSplitter()
46 # In practice, this input loop would be wrapped in an outside loop to read
46 # In practice, this input loop would be wrapped in an outside loop to read
47 # input indefinitely, until some exit/quit command was issued. Here we
47 # input indefinitely, until some exit/quit command was issued. Here we
48 # only illustrate the basic inner loop.
48 # only illustrate the basic inner loop.
49 while isp.push_accepts_more():
49 while isp.push_accepts_more():
50 indent = ' '*isp.indent_spaces
50 indent = ' '*isp.indent_spaces
51 prompt = '>>> ' + indent
51 prompt = '>>> ' + indent
52 line = indent + input_func(prompt)
52 line = indent + input_func(prompt)
53 isp.push(line)
53 isp.push(line)
54
54
55 # Here we just return input so we can use it in a test suite, but a real
55 # Here we just return input so we can use it in a test suite, but a real
56 # interpreter would instead send it for execution somewhere.
56 # interpreter would instead send it for execution somewhere.
57 src = isp.source_reset()
57 src = isp.source_reset()
58 #print 'Input source was:\n', src # dbg
58 #print 'Input source was:\n', src # dbg
59 return src
59 return src
60
60
61 #-----------------------------------------------------------------------------
61 #-----------------------------------------------------------------------------
62 # Test utilities, just for local use
62 # Test utilities, just for local use
63 #-----------------------------------------------------------------------------
63 #-----------------------------------------------------------------------------
64
64
65 def assemble(block):
65 def assemble(block):
66 """Assemble a block into multi-line sub-blocks."""
66 """Assemble a block into multi-line sub-blocks."""
67 return ['\n'.join(sub_block)+'\n' for sub_block in block]
67 return ['\n'.join(sub_block)+'\n' for sub_block in block]
68
68
69
69
70 def pseudo_input(lines):
70 def pseudo_input(lines):
71 """Return a function that acts like raw_input but feeds the input list."""
71 """Return a function that acts like raw_input but feeds the input list."""
72 ilines = iter(lines)
72 ilines = iter(lines)
73 def raw_in(prompt):
73 def raw_in(prompt):
74 try:
74 try:
75 return next(ilines)
75 return next(ilines)
76 except StopIteration:
76 except StopIteration:
77 return ''
77 return ''
78 return raw_in
78 return raw_in
79
79
80 #-----------------------------------------------------------------------------
80 #-----------------------------------------------------------------------------
81 # Tests
81 # Tests
82 #-----------------------------------------------------------------------------
82 #-----------------------------------------------------------------------------
83 def test_spaces():
83 def test_spaces():
84 tests = [('', 0),
84 tests = [('', 0),
85 (' ', 1),
85 (' ', 1),
86 ('\n', 0),
86 ('\n', 0),
87 (' \n', 1),
87 (' \n', 1),
88 ('x', 0),
88 ('x', 0),
89 (' x', 1),
89 (' x', 1),
90 (' x',2),
90 (' x',2),
91 (' x',4),
91 (' x',4),
92 # Note: tabs are counted as a single whitespace!
92 # Note: tabs are counted as a single whitespace!
93 ('\tx', 1),
93 ('\tx', 1),
94 ('\t x', 2),
94 ('\t x', 2),
95 ]
95 ]
96 tt.check_pairs(isp.num_ini_spaces, tests)
96 tt.check_pairs(isp.num_ini_spaces, tests)
97
97
98
98
99 def test_remove_comments():
99 def test_remove_comments():
100 tests = [('text', 'text'),
100 tests = [('text', 'text'),
101 ('text # comment', 'text '),
101 ('text # comment', 'text '),
102 ('text # comment\n', 'text \n'),
102 ('text # comment\n', 'text \n'),
103 ('text # comment \n', 'text \n'),
103 ('text # comment \n', 'text \n'),
104 ('line # c \nline\n','line \nline\n'),
104 ('line # c \nline\n','line \nline\n'),
105 ('line # c \nline#c2 \nline\nline #c\n\n',
105 ('line # c \nline#c2 \nline\nline #c\n\n',
106 'line \nline\nline\nline \n\n'),
106 'line \nline\nline\nline \n\n'),
107 ]
107 ]
108 tt.check_pairs(isp.remove_comments, tests)
108 tt.check_pairs(isp.remove_comments, tests)
109
109
110 def test_has_comment():
110 def test_has_comment():
111 tests = [('text', False),
111 tests = [('text', False),
112 ('text #comment', True),
112 ('text #comment', True),
113 ('text #comment\n', True),
113 ('text #comment\n', True),
114 ('#comment', True),
114 ('#comment', True),
115 ('#comment\n', True),
115 ('#comment\n', True),
116 ('a = "#string"', False),
116 ('a = "#string"', False),
117 ('a = "#string" # comment', True),
117 ('a = "#string" # comment', True),
118 ('a #comment not "string"', True),
118 ('a #comment not "string"', True),
119 ]
119 ]
120 tt.check_pairs(isp.has_comment, tests)
120 tt.check_pairs(isp.has_comment, tests)
121
121
122
122
123 def test_get_input_encoding():
123 def test_get_input_encoding():
124 encoding = isp.get_input_encoding()
124 encoding = isp.get_input_encoding()
125 nt.assert_true(isinstance(encoding, basestring))
125 nt.assert_true(isinstance(encoding, basestring))
126 # simple-minded check that at least encoding a simple string works with the
126 # simple-minded check that at least encoding a simple string works with the
127 # encoding we got.
127 # encoding we got.
128 nt.assert_equal(u'test'.encode(encoding), b'test')
128 nt.assert_equal(u'test'.encode(encoding), b'test')
129
129
130
130
131 class NoInputEncodingTestCase(unittest.TestCase):
131 class NoInputEncodingTestCase(unittest.TestCase):
132 def setUp(self):
132 def setUp(self):
133 self.old_stdin = sys.stdin
133 self.old_stdin = sys.stdin
134 class X: pass
134 class X: pass
135 fake_stdin = X()
135 fake_stdin = X()
136 sys.stdin = fake_stdin
136 sys.stdin = fake_stdin
137
137
138 def test(self):
138 def test(self):
139 # Verify that if sys.stdin has no 'encoding' attribute we do the right
139 # Verify that if sys.stdin has no 'encoding' attribute we do the right
140 # thing
140 # thing
141 enc = isp.get_input_encoding()
141 enc = isp.get_input_encoding()
142 self.assertEqual(enc, 'ascii')
142 self.assertEqual(enc, 'ascii')
143
143
144 def tearDown(self):
144 def tearDown(self):
145 sys.stdin = self.old_stdin
145 sys.stdin = self.old_stdin
146
146
147
147
148 class InputSplitterTestCase(unittest.TestCase):
148 class InputSplitterTestCase(unittest.TestCase):
149 def setUp(self):
149 def setUp(self):
150 self.isp = isp.InputSplitter()
150 self.isp = isp.InputSplitter()
151
151
152 def test_reset(self):
152 def test_reset(self):
153 isp = self.isp
153 isp = self.isp
154 isp.push('x=1')
154 isp.push('x=1')
155 isp.reset()
155 isp.reset()
156 self.assertEqual(isp._buffer, [])
156 self.assertEqual(isp._buffer, [])
157 self.assertEqual(isp.indent_spaces, 0)
157 self.assertEqual(isp.indent_spaces, 0)
158 self.assertEqual(isp.source, '')
158 self.assertEqual(isp.source, '')
159 self.assertEqual(isp.code, None)
159 self.assertEqual(isp.code, None)
160 self.assertEqual(isp._is_complete, False)
160 self.assertEqual(isp._is_complete, False)
161
161
162 def test_source(self):
162 def test_source(self):
163 self.isp._store('1')
163 self.isp._store('1')
164 self.isp._store('2')
164 self.isp._store('2')
165 self.assertEqual(self.isp.source, '1\n2\n')
165 self.assertEqual(self.isp.source, '1\n2\n')
166 self.assertTrue(len(self.isp._buffer)>0)
166 self.assertTrue(len(self.isp._buffer)>0)
167 self.assertEqual(self.isp.source_reset(), '1\n2\n')
167 self.assertEqual(self.isp.source_reset(), '1\n2\n')
168 self.assertEqual(self.isp._buffer, [])
168 self.assertEqual(self.isp._buffer, [])
169 self.assertEqual(self.isp.source, '')
169 self.assertEqual(self.isp.source, '')
170
170
171 def test_indent(self):
171 def test_indent(self):
172 isp = self.isp # shorthand
172 isp = self.isp # shorthand
173 isp.push('x=1')
173 isp.push('x=1')
174 self.assertEqual(isp.indent_spaces, 0)
174 self.assertEqual(isp.indent_spaces, 0)
175 isp.push('if 1:\n x=1')
175 isp.push('if 1:\n x=1')
176 self.assertEqual(isp.indent_spaces, 4)
176 self.assertEqual(isp.indent_spaces, 4)
177 isp.push('y=2\n')
177 isp.push('y=2\n')
178 self.assertEqual(isp.indent_spaces, 0)
178 self.assertEqual(isp.indent_spaces, 0)
179
179
180 def test_indent2(self):
180 def test_indent2(self):
181 # In cell mode, inputs must be fed in whole blocks, so skip this test
181 # In cell mode, inputs must be fed in whole blocks, so skip this test
182 if self.isp.input_mode == 'cell': return
182 if self.isp.input_mode == 'cell': return
183
183
184 isp = self.isp
184 isp = self.isp
185 isp.push('if 1:')
185 isp.push('if 1:')
186 self.assertEqual(isp.indent_spaces, 4)
186 self.assertEqual(isp.indent_spaces, 4)
187 isp.push(' x=1')
187 isp.push(' x=1')
188 self.assertEqual(isp.indent_spaces, 4)
188 self.assertEqual(isp.indent_spaces, 4)
189 # Blank lines shouldn't change the indent level
189 # Blank lines shouldn't change the indent level
190 isp.push(' '*2)
190 isp.push(' '*2)
191 self.assertEqual(isp.indent_spaces, 4)
191 self.assertEqual(isp.indent_spaces, 4)
192
192
193 def test_indent3(self):
193 def test_indent3(self):
194 # In cell mode, inputs must be fed in whole blocks, so skip this test
194 # In cell mode, inputs must be fed in whole blocks, so skip this test
195 if self.isp.input_mode == 'cell': return
195 if self.isp.input_mode == 'cell': return
196
196
197 isp = self.isp
197 isp = self.isp
198 # When a multiline statement contains parens or multiline strings, we
198 # When a multiline statement contains parens or multiline strings, we
199 # shouldn't get confused.
199 # shouldn't get confused.
200 isp.push("if 1:")
200 isp.push("if 1:")
201 isp.push(" x = (1+\n 2)")
201 isp.push(" x = (1+\n 2)")
202 self.assertEqual(isp.indent_spaces, 4)
202 self.assertEqual(isp.indent_spaces, 4)
203
203
204 def test_indent4(self):
204 def test_indent4(self):
205 # In cell mode, inputs must be fed in whole blocks, so skip this test
205 # In cell mode, inputs must be fed in whole blocks, so skip this test
206 if self.isp.input_mode == 'cell': return
206 if self.isp.input_mode == 'cell': return
207
207
208 isp = self.isp
208 isp = self.isp
209 # whitespace after ':' should not screw up indent level
209 # whitespace after ':' should not screw up indent level
210 isp.push('if 1: \n x=1')
210 isp.push('if 1: \n x=1')
211 self.assertEqual(isp.indent_spaces, 4)
211 self.assertEqual(isp.indent_spaces, 4)
212 isp.push('y=2\n')
212 isp.push('y=2\n')
213 self.assertEqual(isp.indent_spaces, 0)
213 self.assertEqual(isp.indent_spaces, 0)
214 isp.push('if 1:\t\n x=1')
214 isp.push('if 1:\t\n x=1')
215 self.assertEqual(isp.indent_spaces, 4)
215 self.assertEqual(isp.indent_spaces, 4)
216 isp.push('y=2\n')
216 isp.push('y=2\n')
217 self.assertEqual(isp.indent_spaces, 0)
217 self.assertEqual(isp.indent_spaces, 0)
218
218
219 def test_dedent_pass(self):
219 def test_dedent_pass(self):
220 isp = self.isp # shorthand
220 isp = self.isp # shorthand
221 # should NOT cause dedent
221 # should NOT cause dedent
222 isp.push('if 1:\n passes = 5')
222 isp.push('if 1:\n passes = 5')
223 self.assertEqual(isp.indent_spaces, 4)
223 self.assertEqual(isp.indent_spaces, 4)
224 isp.push('if 1:\n pass')
224 isp.push('if 1:\n pass')
225 self.assertEqual(isp.indent_spaces, 0)
225 self.assertEqual(isp.indent_spaces, 0)
226 isp.push('if 1:\n pass ')
226 isp.push('if 1:\n pass ')
227 self.assertEqual(isp.indent_spaces, 0)
227 self.assertEqual(isp.indent_spaces, 0)
228
228
229 def test_dedent_raise(self):
229 def test_dedent_raise(self):
230 isp = self.isp # shorthand
230 isp = self.isp # shorthand
231 # should NOT cause dedent
231 # should NOT cause dedent
232 isp.push('if 1:\n raised = 4')
232 isp.push('if 1:\n raised = 4')
233 self.assertEqual(isp.indent_spaces, 4)
233 self.assertEqual(isp.indent_spaces, 4)
234 isp.push('if 1:\n raise TypeError()')
234 isp.push('if 1:\n raise TypeError()')
235 self.assertEqual(isp.indent_spaces, 0)
235 self.assertEqual(isp.indent_spaces, 0)
236 isp.push('if 1:\n raise')
236 isp.push('if 1:\n raise')
237 self.assertEqual(isp.indent_spaces, 0)
237 self.assertEqual(isp.indent_spaces, 0)
238 isp.push('if 1:\n raise ')
238 isp.push('if 1:\n raise ')
239 self.assertEqual(isp.indent_spaces, 0)
239 self.assertEqual(isp.indent_spaces, 0)
240
240
241 def test_dedent_return(self):
241 def test_dedent_return(self):
242 isp = self.isp # shorthand
242 isp = self.isp # shorthand
243 # should NOT cause dedent
243 # should NOT cause dedent
244 isp.push('if 1:\n returning = 4')
244 isp.push('if 1:\n returning = 4')
245 self.assertEqual(isp.indent_spaces, 4)
245 self.assertEqual(isp.indent_spaces, 4)
246 isp.push('if 1:\n return 5 + 493')
246 isp.push('if 1:\n return 5 + 493')
247 self.assertEqual(isp.indent_spaces, 0)
247 self.assertEqual(isp.indent_spaces, 0)
248 isp.push('if 1:\n return')
248 isp.push('if 1:\n return')
249 self.assertEqual(isp.indent_spaces, 0)
249 self.assertEqual(isp.indent_spaces, 0)
250 isp.push('if 1:\n return ')
250 isp.push('if 1:\n return ')
251 self.assertEqual(isp.indent_spaces, 0)
251 self.assertEqual(isp.indent_spaces, 0)
252 isp.push('if 1:\n return(0)')
252 isp.push('if 1:\n return(0)')
253 self.assertEqual(isp.indent_spaces, 0)
253 self.assertEqual(isp.indent_spaces, 0)
254
254
255 def test_push(self):
255 def test_push(self):
256 isp = self.isp
256 isp = self.isp
257 self.assertTrue(isp.push('x=1'))
257 self.assertTrue(isp.push('x=1'))
258
258
259 def test_push2(self):
259 def test_push2(self):
260 isp = self.isp
260 isp = self.isp
261 self.assertFalse(isp.push('if 1:'))
261 self.assertFalse(isp.push('if 1:'))
262 for line in [' x=1', '# a comment', ' y=2']:
262 for line in [' x=1', '# a comment', ' y=2']:
263 self.assertTrue(isp.push(line))
263 self.assertTrue(isp.push(line))
264
264
265 def test_push3(self):
265 def test_push3(self):
266 isp = self.isp
266 isp = self.isp
267 isp.push('if True:')
267 isp.push('if True:')
268 isp.push(' a = 1')
268 isp.push(' a = 1')
269 self.assertFalse(isp.push('b = [1,'))
269 self.assertFalse(isp.push('b = [1,'))
270
270
271 def test_replace_mode(self):
271 def test_replace_mode(self):
272 isp = self.isp
272 isp = self.isp
273 isp.input_mode = 'cell'
273 isp.input_mode = 'cell'
274 isp.push('x=1')
274 isp.push('x=1')
275 self.assertEqual(isp.source, 'x=1\n')
275 self.assertEqual(isp.source, 'x=1\n')
276 isp.push('x=2')
276 isp.push('x=2')
277 self.assertEqual(isp.source, 'x=2\n')
277 self.assertEqual(isp.source, 'x=2\n')
278
278
279 def test_push_accepts_more(self):
279 def test_push_accepts_more(self):
280 isp = self.isp
280 isp = self.isp
281 isp.push('x=1')
281 isp.push('x=1')
282 self.assertFalse(isp.push_accepts_more())
282 self.assertFalse(isp.push_accepts_more())
283
283
284 def test_push_accepts_more2(self):
284 def test_push_accepts_more2(self):
285 # In cell mode, inputs must be fed in whole blocks, so skip this test
285 # In cell mode, inputs must be fed in whole blocks, so skip this test
286 if self.isp.input_mode == 'cell': return
286 if self.isp.input_mode == 'cell': return
287
287
288 isp = self.isp
288 isp = self.isp
289 isp.push('if 1:')
289 isp.push('if 1:')
290 self.assertTrue(isp.push_accepts_more())
290 self.assertTrue(isp.push_accepts_more())
291 isp.push(' x=1')
291 isp.push(' x=1')
292 self.assertTrue(isp.push_accepts_more())
292 self.assertTrue(isp.push_accepts_more())
293 isp.push('')
293 isp.push('')
294 self.assertFalse(isp.push_accepts_more())
294 self.assertFalse(isp.push_accepts_more())
295
295
296 def test_push_accepts_more3(self):
296 def test_push_accepts_more3(self):
297 isp = self.isp
297 isp = self.isp
298 isp.push("x = (2+\n3)")
298 isp.push("x = (2+\n3)")
299 self.assertFalse(isp.push_accepts_more())
299 self.assertFalse(isp.push_accepts_more())
300
300
301 def test_push_accepts_more4(self):
301 def test_push_accepts_more4(self):
302 # In cell mode, inputs must be fed in whole blocks, so skip this test
302 # In cell mode, inputs must be fed in whole blocks, so skip this test
303 if self.isp.input_mode == 'cell': return
303 if self.isp.input_mode == 'cell': return
304
304
305 isp = self.isp
305 isp = self.isp
306 # When a multiline statement contains parens or multiline strings, we
306 # When a multiline statement contains parens or multiline strings, we
307 # shouldn't get confused.
307 # shouldn't get confused.
308 # FIXME: we should be able to better handle de-dents in statements like
308 # FIXME: we should be able to better handle de-dents in statements like
309 # multiline strings and multiline expressions (continued with \ or
309 # multiline strings and multiline expressions (continued with \ or
310 # parens). Right now we aren't handling the indentation tracking quite
310 # parens). Right now we aren't handling the indentation tracking quite
311 # correctly with this, though in practice it may not be too much of a
311 # correctly with this, though in practice it may not be too much of a
312 # problem. We'll need to see.
312 # problem. We'll need to see.
313 isp.push("if 1:")
313 isp.push("if 1:")
314 isp.push(" x = (2+")
314 isp.push(" x = (2+")
315 isp.push(" 3)")
315 isp.push(" 3)")
316 self.assertTrue(isp.push_accepts_more())
316 self.assertTrue(isp.push_accepts_more())
317 isp.push(" y = 3")
317 isp.push(" y = 3")
318 self.assertTrue(isp.push_accepts_more())
318 self.assertTrue(isp.push_accepts_more())
319 isp.push('')
319 isp.push('')
320 self.assertFalse(isp.push_accepts_more())
320 self.assertFalse(isp.push_accepts_more())
321
321
322 def test_push_accepts_more5(self):
322 def test_push_accepts_more5(self):
323 # In cell mode, inputs must be fed in whole blocks, so skip this test
323 # In cell mode, inputs must be fed in whole blocks, so skip this test
324 if self.isp.input_mode == 'cell': return
324 if self.isp.input_mode == 'cell': return
325
325
326 isp = self.isp
326 isp = self.isp
327 isp.push('try:')
327 isp.push('try:')
328 isp.push(' a = 5')
328 isp.push(' a = 5')
329 isp.push('except:')
329 isp.push('except:')
330 isp.push(' raise')
330 isp.push(' raise')
331 self.assertTrue(isp.push_accepts_more())
331 self.assertTrue(isp.push_accepts_more())
332
332
333 def test_continuation(self):
333 def test_continuation(self):
334 isp = self.isp
334 isp = self.isp
335 isp.push("import os, \\")
335 isp.push("import os, \\")
336 self.assertTrue(isp.push_accepts_more())
336 self.assertTrue(isp.push_accepts_more())
337 isp.push("sys")
337 isp.push("sys")
338 self.assertFalse(isp.push_accepts_more())
338 self.assertFalse(isp.push_accepts_more())
339
339
340 def test_syntax_error(self):
340 def test_syntax_error(self):
341 isp = self.isp
341 isp = self.isp
342 # Syntax errors immediately produce a 'ready' block, so the invalid
342 # Syntax errors immediately produce a 'ready' block, so the invalid
343 # Python can be sent to the kernel for evaluation with possible ipython
343 # Python can be sent to the kernel for evaluation with possible ipython
344 # special-syntax conversion.
344 # special-syntax conversion.
345 isp.push('run foo')
345 isp.push('run foo')
346 self.assertFalse(isp.push_accepts_more())
346 self.assertFalse(isp.push_accepts_more())
347
347
348 def test_unicode(self):
348 def test_unicode(self):
349 self.isp.push(u"Pérez")
349 self.isp.push(u"Pérez")
350 self.isp.push(u'\xc3\xa9')
350 self.isp.push(u'\xc3\xa9')
351 self.isp.push(u"u'\xc3\xa9'")
351 self.isp.push(u"u'\xc3\xa9'")
352
352
353 class InteractiveLoopTestCase(unittest.TestCase):
353 class InteractiveLoopTestCase(unittest.TestCase):
354 """Tests for an interactive loop like a python shell.
354 """Tests for an interactive loop like a python shell.
355 """
355 """
356 def check_ns(self, lines, ns):
356 def check_ns(self, lines, ns):
357 """Validate that the given input lines produce the resulting namespace.
357 """Validate that the given input lines produce the resulting namespace.
358
358
359 Note: the input lines are given exactly as they would be typed in an
359 Note: the input lines are given exactly as they would be typed in an
360 auto-indenting environment, as mini_interactive_loop above already does
360 auto-indenting environment, as mini_interactive_loop above already does
361 auto-indenting and prepends spaces to the input.
361 auto-indenting and prepends spaces to the input.
362 """
362 """
363 src = mini_interactive_loop(pseudo_input(lines))
363 src = mini_interactive_loop(pseudo_input(lines))
364 test_ns = {}
364 test_ns = {}
365 exec src in test_ns
365 exec src in test_ns
366 # We can't check that the provided ns is identical to the test_ns,
366 # We can't check that the provided ns is identical to the test_ns,
367 # because Python fills test_ns with extra keys (copyright, etc). But
367 # because Python fills test_ns with extra keys (copyright, etc). But
368 # we can check that the given dict is *contained* in test_ns
368 # we can check that the given dict is *contained* in test_ns
369 for k,v in ns.iteritems():
369 for k,v in ns.iteritems():
370 self.assertEqual(test_ns[k], v)
370 self.assertEqual(test_ns[k], v)
371
371
372 def test_simple(self):
372 def test_simple(self):
373 self.check_ns(['x=1'], dict(x=1))
373 self.check_ns(['x=1'], dict(x=1))
374
374
375 def test_simple2(self):
375 def test_simple2(self):
376 self.check_ns(['if 1:', 'x=2'], dict(x=2))
376 self.check_ns(['if 1:', 'x=2'], dict(x=2))
377
377
378 def test_xy(self):
378 def test_xy(self):
379 self.check_ns(['x=1; y=2'], dict(x=1, y=2))
379 self.check_ns(['x=1; y=2'], dict(x=1, y=2))
380
380
381 def test_abc(self):
381 def test_abc(self):
382 self.check_ns(['if 1:','a=1','b=2','c=3'], dict(a=1, b=2, c=3))
382 self.check_ns(['if 1:','a=1','b=2','c=3'], dict(a=1, b=2, c=3))
383
383
384 def test_multi(self):
384 def test_multi(self):
385 self.check_ns(['x =(1+','1+','2)'], dict(x=4))
385 self.check_ns(['x =(1+','1+','2)'], dict(x=4))
386
386
387
387
388 def test_LineInfo():
388 def test_LineInfo():
389 """Simple test for LineInfo construction and str()"""
389 """Simple test for LineInfo construction and str()"""
390 linfo = isp.LineInfo(' %cd /home')
390 linfo = isp.LineInfo(' %cd /home')
391 nt.assert_equals(str(linfo), 'LineInfo [ |%|cd|/home]')
391 nt.assert_equals(str(linfo), 'LineInfo [ |%|cd|/home]')
392
392
393
394 def test_split_user_input():
395 """Unicode test - split_user_input already has good doctests"""
396 line = u"Pérez Fernando"
397 parts_expected = (u'', u'', u'', line)
398 tt.check_pairs(isp.split_user_input, [(line, parts_expected),])
399
400
401 # Transformer tests
393 # Transformer tests
402 def transform_checker(tests, func):
394 def transform_checker(tests, func):
403 """Utility to loop over test inputs"""
395 """Utility to loop over test inputs"""
404 for inp, tr in tests:
396 for inp, tr in tests:
405 nt.assert_equals(func(inp), tr)
397 nt.assert_equals(func(inp), tr)
406
398
407 # Data for all the syntax tests in the form of lists of pairs of
399 # Data for all the syntax tests in the form of lists of pairs of
408 # raw/transformed input. We store it here as a global dict so that we can use
400 # raw/transformed input. We store it here as a global dict so that we can use
409 # it both within single-function tests and also to validate the behavior of the
401 # it both within single-function tests and also to validate the behavior of the
410 # larger objects
402 # larger objects
411
403
412 syntax = \
404 syntax = \
413 dict(assign_system =
405 dict(assign_system =
414 [('a =! ls', 'a = get_ipython().getoutput(u"ls")'),
406 [('a =! ls', 'a = get_ipython().getoutput(u"ls")'),
415 ('b = !ls', 'b = get_ipython().getoutput(u"ls")'),
407 ('b = !ls', 'b = get_ipython().getoutput(u"ls")'),
416 ('x=1', 'x=1'), # normal input is unmodified
408 ('x=1', 'x=1'), # normal input is unmodified
417 (' ',' '), # blank lines are kept intact
409 (' ',' '), # blank lines are kept intact
418 ],
410 ],
419
411
420 assign_magic =
412 assign_magic =
421 [('a =% who', 'a = get_ipython().magic(u"who")'),
413 [('a =% who', 'a = get_ipython().magic(u"who")'),
422 ('b = %who', 'b = get_ipython().magic(u"who")'),
414 ('b = %who', 'b = get_ipython().magic(u"who")'),
423 ('x=1', 'x=1'), # normal input is unmodified
415 ('x=1', 'x=1'), # normal input is unmodified
424 (' ',' '), # blank lines are kept intact
416 (' ',' '), # blank lines are kept intact
425 ],
417 ],
426
418
427 classic_prompt =
419 classic_prompt =
428 [('>>> x=1', 'x=1'),
420 [('>>> x=1', 'x=1'),
429 ('x=1', 'x=1'), # normal input is unmodified
421 ('x=1', 'x=1'), # normal input is unmodified
430 (' ', ' '), # blank lines are kept intact
422 (' ', ' '), # blank lines are kept intact
431 ('... ', ''), # continuation prompts
423 ('... ', ''), # continuation prompts
432 ],
424 ],
433
425
434 ipy_prompt =
426 ipy_prompt =
435 [('In [1]: x=1', 'x=1'),
427 [('In [1]: x=1', 'x=1'),
436 ('x=1', 'x=1'), # normal input is unmodified
428 ('x=1', 'x=1'), # normal input is unmodified
437 (' ',' '), # blank lines are kept intact
429 (' ',' '), # blank lines are kept intact
438 (' ....: ', ''), # continuation prompts
430 (' ....: ', ''), # continuation prompts
439 ],
431 ],
440
432
441 # Tests for the escape transformer to leave normal code alone
433 # Tests for the escape transformer to leave normal code alone
442 escaped_noesc =
434 escaped_noesc =
443 [ (' ', ' '),
435 [ (' ', ' '),
444 ('x=1', 'x=1'),
436 ('x=1', 'x=1'),
445 ],
437 ],
446
438
447 # System calls
439 # System calls
448 escaped_shell =
440 escaped_shell =
449 [ ('!ls', 'get_ipython().system(u"ls")'),
441 [ ('!ls', 'get_ipython().system(u"ls")'),
450 # Double-escape shell, this means to capture the output of the
442 # Double-escape shell, this means to capture the output of the
451 # subprocess and return it
443 # subprocess and return it
452 ('!!ls', 'get_ipython().getoutput(u"ls")'),
444 ('!!ls', 'get_ipython().getoutput(u"ls")'),
453 ],
445 ],
454
446
455 # Help/object info
447 # Help/object info
456 escaped_help =
448 escaped_help =
457 [ ('?', 'get_ipython().show_usage()'),
449 [ ('?', 'get_ipython().show_usage()'),
458 ('?x1', 'get_ipython().magic(u"pinfo x1")'),
450 ('?x1', 'get_ipython().magic(u"pinfo x1")'),
459 ('??x2', 'get_ipython().magic(u"pinfo2 x2")'),
451 ('??x2', 'get_ipython().magic(u"pinfo2 x2")'),
460 ('?a.*s', 'get_ipython().magic(u"psearch a.*s")'),
452 ('?a.*s', 'get_ipython().magic(u"psearch a.*s")'),
461 ('?%hist', 'get_ipython().magic(u"pinfo %hist")'),
453 ('?%hist', 'get_ipython().magic(u"pinfo %hist")'),
462 ('?abc = qwe', 'get_ipython().magic(u"pinfo abc")'),
454 ('?abc = qwe', 'get_ipython().magic(u"pinfo abc")'),
463 ],
455 ],
464
456
465 end_help =
457 end_help =
466 [ ('x3?', 'get_ipython().magic(u"pinfo x3")'),
458 [ ('x3?', 'get_ipython().magic(u"pinfo x3")'),
467 ('x4??', 'get_ipython().magic(u"pinfo2 x4")'),
459 ('x4??', 'get_ipython().magic(u"pinfo2 x4")'),
468 ('%hist?', 'get_ipython().magic(u"pinfo %hist")'),
460 ('%hist?', 'get_ipython().magic(u"pinfo %hist")'),
469 ('f*?', 'get_ipython().magic(u"psearch f*")'),
461 ('f*?', 'get_ipython().magic(u"psearch f*")'),
470 ('ax.*aspe*?', 'get_ipython().magic(u"psearch ax.*aspe*")'),
462 ('ax.*aspe*?', 'get_ipython().magic(u"psearch ax.*aspe*")'),
471 ('a = abc?', 'get_ipython().magic(u"pinfo abc", next_input=u"a = abc")'),
463 ('a = abc?', 'get_ipython().magic(u"pinfo abc", next_input=u"a = abc")'),
472 ('a = abc.qe??', 'get_ipython().magic(u"pinfo2 abc.qe", next_input=u"a = abc.qe")'),
464 ('a = abc.qe??', 'get_ipython().magic(u"pinfo2 abc.qe", next_input=u"a = abc.qe")'),
473 ('a = *.items?', 'get_ipython().magic(u"psearch *.items", next_input=u"a = *.items")'),
465 ('a = *.items?', 'get_ipython().magic(u"psearch *.items", next_input=u"a = *.items")'),
474 ('plot(a?', 'get_ipython().magic(u"pinfo a", next_input=u"plot(a")'),
466 ('plot(a?', 'get_ipython().magic(u"pinfo a", next_input=u"plot(a")'),
475 ('a*2 #comment?', 'a*2 #comment?'),
467 ('a*2 #comment?', 'a*2 #comment?'),
476 ],
468 ],
477
469
478 # Explicit magic calls
470 # Explicit magic calls
479 escaped_magic =
471 escaped_magic =
480 [ ('%cd', 'get_ipython().magic(u"cd")'),
472 [ ('%cd', 'get_ipython().magic(u"cd")'),
481 ('%cd /home', 'get_ipython().magic(u"cd /home")'),
473 ('%cd /home', 'get_ipython().magic(u"cd /home")'),
482 (' %magic', ' get_ipython().magic(u"magic")'),
474 (' %magic', ' get_ipython().magic(u"magic")'),
483 ],
475 ],
484
476
485 # Quoting with separate arguments
477 # Quoting with separate arguments
486 escaped_quote =
478 escaped_quote =
487 [ (',f', 'f("")'),
479 [ (',f', 'f("")'),
488 (',f x', 'f("x")'),
480 (',f x', 'f("x")'),
489 (' ,f y', ' f("y")'),
481 (' ,f y', ' f("y")'),
490 (',f a b', 'f("a", "b")'),
482 (',f a b', 'f("a", "b")'),
491 ],
483 ],
492
484
493 # Quoting with single argument
485 # Quoting with single argument
494 escaped_quote2 =
486 escaped_quote2 =
495 [ (';f', 'f("")'),
487 [ (';f', 'f("")'),
496 (';f x', 'f("x")'),
488 (';f x', 'f("x")'),
497 (' ;f y', ' f("y")'),
489 (' ;f y', ' f("y")'),
498 (';f a b', 'f("a b")'),
490 (';f a b', 'f("a b")'),
499 ],
491 ],
500
492
501 # Simply apply parens
493 # Simply apply parens
502 escaped_paren =
494 escaped_paren =
503 [ ('/f', 'f()'),
495 [ ('/f', 'f()'),
504 ('/f x', 'f(x)'),
496 ('/f x', 'f(x)'),
505 (' /f y', ' f(y)'),
497 (' /f y', ' f(y)'),
506 ('/f a b', 'f(a, b)'),
498 ('/f a b', 'f(a, b)'),
507 ],
499 ],
508
500
509 # Check that we transform prompts before other transforms
501 # Check that we transform prompts before other transforms
510 mixed =
502 mixed =
511 [ ('In [1]: %lsmagic', 'get_ipython().magic(u"lsmagic")'),
503 [ ('In [1]: %lsmagic', 'get_ipython().magic(u"lsmagic")'),
512 ('>>> %lsmagic', 'get_ipython().magic(u"lsmagic")'),
504 ('>>> %lsmagic', 'get_ipython().magic(u"lsmagic")'),
513 ('In [2]: !ls', 'get_ipython().system(u"ls")'),
505 ('In [2]: !ls', 'get_ipython().system(u"ls")'),
514 ('In [3]: abs?', 'get_ipython().magic(u"pinfo abs")'),
506 ('In [3]: abs?', 'get_ipython().magic(u"pinfo abs")'),
515 ('In [4]: b = %who', 'b = get_ipython().magic(u"who")'),
507 ('In [4]: b = %who', 'b = get_ipython().magic(u"who")'),
516 ],
508 ],
517 )
509 )
518
510
519 # multiline syntax examples. Each of these should be a list of lists, with
511 # multiline syntax examples. Each of these should be a list of lists, with
520 # each entry itself having pairs of raw/transformed input. The union (with
512 # each entry itself having pairs of raw/transformed input. The union (with
521 # '\n'.join() of the transformed inputs is what the splitter should produce
513 # '\n'.join() of the transformed inputs is what the splitter should produce
522 # when fed the raw lines one at a time via push.
514 # when fed the raw lines one at a time via push.
523 syntax_ml = \
515 syntax_ml = \
524 dict(classic_prompt =
516 dict(classic_prompt =
525 [ [('>>> for i in range(10):','for i in range(10):'),
517 [ [('>>> for i in range(10):','for i in range(10):'),
526 ('... print i',' print i'),
518 ('... print i',' print i'),
527 ('... ', ''),
519 ('... ', ''),
528 ],
520 ],
529 ],
521 ],
530
522
531 ipy_prompt =
523 ipy_prompt =
532 [ [('In [24]: for i in range(10):','for i in range(10):'),
524 [ [('In [24]: for i in range(10):','for i in range(10):'),
533 (' ....: print i',' print i'),
525 (' ....: print i',' print i'),
534 (' ....: ', ''),
526 (' ....: ', ''),
535 ],
527 ],
536 ],
528 ],
537 )
529 )
538
530
539
531
540 def test_assign_system():
532 def test_assign_system():
541 tt.check_pairs(isp.transform_assign_system, syntax['assign_system'])
533 tt.check_pairs(isp.transform_assign_system, syntax['assign_system'])
542
534
543
535
544 def test_assign_magic():
536 def test_assign_magic():
545 tt.check_pairs(isp.transform_assign_magic, syntax['assign_magic'])
537 tt.check_pairs(isp.transform_assign_magic, syntax['assign_magic'])
546
538
547
539
548 def test_classic_prompt():
540 def test_classic_prompt():
549 transform_checker(syntax['classic_prompt'], isp.transform_classic_prompt)
541 transform_checker(syntax['classic_prompt'], isp.transform_classic_prompt)
550 for example in syntax_ml['classic_prompt']:
542 for example in syntax_ml['classic_prompt']:
551 transform_checker(example, isp.transform_classic_prompt)
543 transform_checker(example, isp.transform_classic_prompt)
552
544
553
545
554 def test_ipy_prompt():
546 def test_ipy_prompt():
555 transform_checker(syntax['ipy_prompt'], isp.transform_ipy_prompt)
547 transform_checker(syntax['ipy_prompt'], isp.transform_ipy_prompt)
556 for example in syntax_ml['ipy_prompt']:
548 for example in syntax_ml['ipy_prompt']:
557 transform_checker(example, isp.transform_ipy_prompt)
549 transform_checker(example, isp.transform_ipy_prompt)
558
550
559 def test_end_help():
551 def test_end_help():
560 tt.check_pairs(isp.transform_help_end, syntax['end_help'])
552 tt.check_pairs(isp.transform_help_end, syntax['end_help'])
561
553
562 def test_escaped_noesc():
554 def test_escaped_noesc():
563 tt.check_pairs(isp.transform_escaped, syntax['escaped_noesc'])
555 tt.check_pairs(isp.transform_escaped, syntax['escaped_noesc'])
564
556
565
557
566 def test_escaped_shell():
558 def test_escaped_shell():
567 tt.check_pairs(isp.transform_escaped, syntax['escaped_shell'])
559 tt.check_pairs(isp.transform_escaped, syntax['escaped_shell'])
568
560
569
561
570 def test_escaped_help():
562 def test_escaped_help():
571 tt.check_pairs(isp.transform_escaped, syntax['escaped_help'])
563 tt.check_pairs(isp.transform_escaped, syntax['escaped_help'])
572
564
573
565
574 def test_escaped_magic():
566 def test_escaped_magic():
575 tt.check_pairs(isp.transform_escaped, syntax['escaped_magic'])
567 tt.check_pairs(isp.transform_escaped, syntax['escaped_magic'])
576
568
577
569
578 def test_escaped_quote():
570 def test_escaped_quote():
579 tt.check_pairs(isp.transform_escaped, syntax['escaped_quote'])
571 tt.check_pairs(isp.transform_escaped, syntax['escaped_quote'])
580
572
581
573
582 def test_escaped_quote2():
574 def test_escaped_quote2():
583 tt.check_pairs(isp.transform_escaped, syntax['escaped_quote2'])
575 tt.check_pairs(isp.transform_escaped, syntax['escaped_quote2'])
584
576
585
577
586 def test_escaped_paren():
578 def test_escaped_paren():
587 tt.check_pairs(isp.transform_escaped, syntax['escaped_paren'])
579 tt.check_pairs(isp.transform_escaped, syntax['escaped_paren'])
588
580
589
581
590 class IPythonInputTestCase(InputSplitterTestCase):
582 class IPythonInputTestCase(InputSplitterTestCase):
591 """By just creating a new class whose .isp is a different instance, we
583 """By just creating a new class whose .isp is a different instance, we
592 re-run the same test battery on the new input splitter.
584 re-run the same test battery on the new input splitter.
593
585
594 In addition, this runs the tests over the syntax and syntax_ml dicts that
586 In addition, this runs the tests over the syntax and syntax_ml dicts that
595 were tested by individual functions, as part of the OO interface.
587 were tested by individual functions, as part of the OO interface.
596
588
597 It also makes some checks on the raw buffer storage.
589 It also makes some checks on the raw buffer storage.
598 """
590 """
599
591
600 def setUp(self):
592 def setUp(self):
601 self.isp = isp.IPythonInputSplitter(input_mode='line')
593 self.isp = isp.IPythonInputSplitter(input_mode='line')
602
594
603 def test_syntax(self):
595 def test_syntax(self):
604 """Call all single-line syntax tests from the main object"""
596 """Call all single-line syntax tests from the main object"""
605 isp = self.isp
597 isp = self.isp
606 for example in syntax.itervalues():
598 for example in syntax.itervalues():
607 for raw, out_t in example:
599 for raw, out_t in example:
608 if raw.startswith(' '):
600 if raw.startswith(' '):
609 continue
601 continue
610
602
611 isp.push(raw)
603 isp.push(raw)
612 out, out_raw = isp.source_raw_reset()
604 out, out_raw = isp.source_raw_reset()
613 self.assertEqual(out.rstrip(), out_t,
605 self.assertEqual(out.rstrip(), out_t,
614 tt.pair_fail_msg.format("inputsplitter",raw, out_t, out))
606 tt.pair_fail_msg.format("inputsplitter",raw, out_t, out))
615 self.assertEqual(out_raw.rstrip(), raw.rstrip())
607 self.assertEqual(out_raw.rstrip(), raw.rstrip())
616
608
617 def test_syntax_multiline(self):
609 def test_syntax_multiline(self):
618 isp = self.isp
610 isp = self.isp
619 for example in syntax_ml.itervalues():
611 for example in syntax_ml.itervalues():
620 out_t_parts = []
612 out_t_parts = []
621 raw_parts = []
613 raw_parts = []
622 for line_pairs in example:
614 for line_pairs in example:
623 for lraw, out_t_part in line_pairs:
615 for lraw, out_t_part in line_pairs:
624 isp.push(lraw)
616 isp.push(lraw)
625 out_t_parts.append(out_t_part)
617 out_t_parts.append(out_t_part)
626 raw_parts.append(lraw)
618 raw_parts.append(lraw)
627
619
628 out, out_raw = isp.source_raw_reset()
620 out, out_raw = isp.source_raw_reset()
629 out_t = '\n'.join(out_t_parts).rstrip()
621 out_t = '\n'.join(out_t_parts).rstrip()
630 raw = '\n'.join(raw_parts).rstrip()
622 raw = '\n'.join(raw_parts).rstrip()
631 self.assertEqual(out.rstrip(), out_t)
623 self.assertEqual(out.rstrip(), out_t)
632 self.assertEqual(out_raw.rstrip(), raw)
624 self.assertEqual(out_raw.rstrip(), raw)
633
625
634
626
635 class BlockIPythonInputTestCase(IPythonInputTestCase):
627 class BlockIPythonInputTestCase(IPythonInputTestCase):
636
628
637 # Deactivate tests that don't make sense for the block mode
629 # Deactivate tests that don't make sense for the block mode
638 test_push3 = test_split = lambda s: None
630 test_push3 = test_split = lambda s: None
639
631
640 def setUp(self):
632 def setUp(self):
641 self.isp = isp.IPythonInputSplitter(input_mode='cell')
633 self.isp = isp.IPythonInputSplitter(input_mode='cell')
642
634
643 def test_syntax_multiline(self):
635 def test_syntax_multiline(self):
644 isp = self.isp
636 isp = self.isp
645 for example in syntax_ml.itervalues():
637 for example in syntax_ml.itervalues():
646 raw_parts = []
638 raw_parts = []
647 out_t_parts = []
639 out_t_parts = []
648 for line_pairs in example:
640 for line_pairs in example:
649 for raw, out_t_part in line_pairs:
641 for raw, out_t_part in line_pairs:
650 raw_parts.append(raw)
642 raw_parts.append(raw)
651 out_t_parts.append(out_t_part)
643 out_t_parts.append(out_t_part)
652
644
653 raw = '\n'.join(raw_parts)
645 raw = '\n'.join(raw_parts)
654 out_t = '\n'.join(out_t_parts)
646 out_t = '\n'.join(out_t_parts)
655
647
656 isp.push(raw)
648 isp.push(raw)
657 out, out_raw = isp.source_raw_reset()
649 out, out_raw = isp.source_raw_reset()
658 # Match ignoring trailing whitespace
650 # Match ignoring trailing whitespace
659 self.assertEqual(out.rstrip(), out_t.rstrip())
651 self.assertEqual(out.rstrip(), out_t.rstrip())
660 self.assertEqual(out_raw.rstrip(), raw.rstrip())
652 self.assertEqual(out_raw.rstrip(), raw.rstrip())
661
653
662
654
663 #-----------------------------------------------------------------------------
655 #-----------------------------------------------------------------------------
664 # Main - use as a script, mostly for developer experiments
656 # Main - use as a script, mostly for developer experiments
665 #-----------------------------------------------------------------------------
657 #-----------------------------------------------------------------------------
666
658
667 if __name__ == '__main__':
659 if __name__ == '__main__':
668 # A simple demo for interactive experimentation. This code will not get
660 # A simple demo for interactive experimentation. This code will not get
669 # picked up by any test suite.
661 # picked up by any test suite.
670 from IPython.core.inputsplitter import InputSplitter, IPythonInputSplitter
662 from IPython.core.inputsplitter import InputSplitter, IPythonInputSplitter
671
663
672 # configure here the syntax to use, prompt and whether to autoindent
664 # configure here the syntax to use, prompt and whether to autoindent
673 #isp, start_prompt = InputSplitter(), '>>> '
665 #isp, start_prompt = InputSplitter(), '>>> '
674 isp, start_prompt = IPythonInputSplitter(), 'In> '
666 isp, start_prompt = IPythonInputSplitter(), 'In> '
675
667
676 autoindent = True
668 autoindent = True
677 #autoindent = False
669 #autoindent = False
678
670
679 try:
671 try:
680 while True:
672 while True:
681 prompt = start_prompt
673 prompt = start_prompt
682 while isp.push_accepts_more():
674 while isp.push_accepts_more():
683 indent = ' '*isp.indent_spaces
675 indent = ' '*isp.indent_spaces
684 if autoindent:
676 if autoindent:
685 line = indent + raw_input(prompt+indent)
677 line = indent + raw_input(prompt+indent)
686 else:
678 else:
687 line = raw_input(prompt)
679 line = raw_input(prompt)
688 isp.push(line)
680 isp.push(line)
689 prompt = '... '
681 prompt = '... '
690
682
691 # Here we just return input so we can use it in a test suite, but a
683 # Here we just return input so we can use it in a test suite, but a
692 # real interpreter would instead send it for execution somewhere.
684 # real interpreter would instead send it for execution somewhere.
693 #src = isp.source; raise EOFError # dbg
685 #src = isp.source; raise EOFError # dbg
694 src, raw = isp.source_raw_reset()
686 src, raw = isp.source_raw_reset()
695 print 'Input source was:\n', src
687 print 'Input source was:\n', src
696 print 'Raw source was:\n', raw
688 print 'Raw source was:\n', raw
697 except EOFError:
689 except EOFError:
698 print 'Bye'
690 print 'Bye'
@@ -1,26 +1,32 b''
1 # coding: utf-8
1 from IPython.core.splitinput import split_user_input
2 from IPython.core.splitinput import split_user_input
2 from IPython.testing import tools as tt
3 from IPython.testing import tools as tt
4 from IPython.utils import py3compat
3
5
4 tests = [
6 tests = [
5 ('x=1', ('', '', 'x', '=1')),
7 ('x=1', ('', '', 'x', '=1')),
6 ('?', ('', '?', '', '')),
8 ('?', ('', '?', '', '')),
7 ('??', ('', '??', '', '')),
9 ('??', ('', '??', '', '')),
8 (' ?', (' ', '?', '', '')),
10 (' ?', (' ', '?', '', '')),
9 (' ??', (' ', '??', '', '')),
11 (' ??', (' ', '??', '', '')),
10 ('??x', ('', '??', 'x', '')),
12 ('??x', ('', '??', 'x', '')),
11 ('?x=1', ('', '?', 'x', '=1')),
13 ('?x=1', ('', '?', 'x', '=1')),
12 ('!ls', ('', '!', 'ls', '')),
14 ('!ls', ('', '!', 'ls', '')),
13 (' !ls', (' ', '!', 'ls', '')),
15 (' !ls', (' ', '!', 'ls', '')),
14 ('!!ls', ('', '!!', 'ls', '')),
16 ('!!ls', ('', '!!', 'ls', '')),
15 (' !!ls', (' ', '!!', 'ls', '')),
17 (' !!ls', (' ', '!!', 'ls', '')),
16 (',ls', ('', ',', 'ls', '')),
18 (',ls', ('', ',', 'ls', '')),
17 (';ls', ('', ';', 'ls', '')),
19 (';ls', ('', ';', 'ls', '')),
18 (' ;ls', (' ', ';', 'ls', '')),
20 (' ;ls', (' ', ';', 'ls', '')),
19 ('f.g(x)', ('', '', 'f.g', '(x)')),
21 ('f.g(x)', ('', '', 'f.g', '(x)')),
20 ('f.g (x)', ('', '', 'f.g', '(x)')),
22 ('f.g (x)', ('', '', 'f.g', '(x)')),
21 ('?%hist', ('', '?', '%hist', '')),
23 ('?%hist', ('', '?', '%hist', '')),
22 ('?x*', ('', '?', 'x*', '')),
24 ('?x*', ('', '?', 'x*', '')),
23 ]
25 ]
26 if py3compat.PY3:
27 tests.append((u"Pérez Fernando", (u'', u'', u'Pérez', u'Fernando')))
28 else:
29 tests.append((u"Pérez Fernando", (u'', u'', u'P', u'érez Fernando')))
24
30
25 def test_split_user_input():
31 def test_split_user_input():
26 return tt.check_pairs(split_user_input, tests)
32 return tt.check_pairs(split_user_input, tests)
General Comments 0
You need to be logged in to leave comments. Login now