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