##// END OF EJS Templates
Merge pull request #10024 from srinivasreddy/assert...
Matthias Bussonnier -
r22973:17c5957c merge
parent child Browse files
Show More
@@ -1,615 +1,615 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2 """Tests for the inputsplitter module."""
2 """Tests for the inputsplitter module."""
3
3
4 from __future__ import print_function
4 from __future__ import print_function
5
5
6 # Copyright (c) IPython Development Team.
6 # Copyright (c) IPython Development Team.
7 # Distributed under the terms of the Modified BSD License.
7 # Distributed under the terms of the Modified BSD License.
8
8
9 import unittest
9 import unittest
10 import sys
10 import sys
11
11
12 import nose.tools as nt
12 import nose.tools as nt
13
13
14 from IPython.core import inputsplitter as isp
14 from IPython.core import inputsplitter as isp
15 from IPython.core.inputtransformer import InputTransformer
15 from IPython.core.inputtransformer import InputTransformer
16 from IPython.core.tests.test_inputtransformer import syntax, syntax_ml
16 from IPython.core.tests.test_inputtransformer import syntax, syntax_ml
17 from IPython.testing import tools as tt
17 from IPython.testing import tools as tt
18 from IPython.utils import py3compat
18 from IPython.utils import py3compat
19 from IPython.utils.py3compat import string_types, input
19 from IPython.utils.py3compat import string_types, input
20
20
21 #-----------------------------------------------------------------------------
21 #-----------------------------------------------------------------------------
22 # Semi-complete examples (also used as tests)
22 # Semi-complete examples (also used as tests)
23 #-----------------------------------------------------------------------------
23 #-----------------------------------------------------------------------------
24
24
25 # Note: at the bottom, there's a slightly more complete version of this that
25 # Note: at the bottom, there's a slightly more complete version of this that
26 # can be useful during development of code here.
26 # can be useful during development of code here.
27
27
28 def mini_interactive_loop(input_func):
28 def mini_interactive_loop(input_func):
29 """Minimal example of the logic of an interactive interpreter loop.
29 """Minimal example of the logic of an interactive interpreter loop.
30
30
31 This serves as an example, and it is used by the test system with a fake
31 This serves as an example, and it is used by the test system with a fake
32 raw_input that simulates interactive input."""
32 raw_input that simulates interactive input."""
33
33
34 from IPython.core.inputsplitter import InputSplitter
34 from IPython.core.inputsplitter import InputSplitter
35
35
36 isp = InputSplitter()
36 isp = InputSplitter()
37 # In practice, this input loop would be wrapped in an outside loop to read
37 # In practice, this input loop would be wrapped in an outside loop to read
38 # input indefinitely, until some exit/quit command was issued. Here we
38 # input indefinitely, until some exit/quit command was issued. Here we
39 # only illustrate the basic inner loop.
39 # only illustrate the basic inner loop.
40 while isp.push_accepts_more():
40 while isp.push_accepts_more():
41 indent = ' '*isp.indent_spaces
41 indent = ' '*isp.indent_spaces
42 prompt = '>>> ' + indent
42 prompt = '>>> ' + indent
43 line = indent + input_func(prompt)
43 line = indent + input_func(prompt)
44 isp.push(line)
44 isp.push(line)
45
45
46 # Here we just return input so we can use it in a test suite, but a real
46 # Here we just return input so we can use it in a test suite, but a real
47 # interpreter would instead send it for execution somewhere.
47 # interpreter would instead send it for execution somewhere.
48 src = isp.source_reset()
48 src = isp.source_reset()
49 #print 'Input source was:\n', src # dbg
49 #print 'Input source was:\n', src # dbg
50 return src
50 return src
51
51
52 #-----------------------------------------------------------------------------
52 #-----------------------------------------------------------------------------
53 # Test utilities, just for local use
53 # Test utilities, just for local use
54 #-----------------------------------------------------------------------------
54 #-----------------------------------------------------------------------------
55
55
56 def assemble(block):
56 def assemble(block):
57 """Assemble a block into multi-line sub-blocks."""
57 """Assemble a block into multi-line sub-blocks."""
58 return ['\n'.join(sub_block)+'\n' for sub_block in block]
58 return ['\n'.join(sub_block)+'\n' for sub_block in block]
59
59
60
60
61 def pseudo_input(lines):
61 def pseudo_input(lines):
62 """Return a function that acts like raw_input but feeds the input list."""
62 """Return a function that acts like raw_input but feeds the input list."""
63 ilines = iter(lines)
63 ilines = iter(lines)
64 def raw_in(prompt):
64 def raw_in(prompt):
65 try:
65 try:
66 return next(ilines)
66 return next(ilines)
67 except StopIteration:
67 except StopIteration:
68 return ''
68 return ''
69 return raw_in
69 return raw_in
70
70
71 #-----------------------------------------------------------------------------
71 #-----------------------------------------------------------------------------
72 # Tests
72 # Tests
73 #-----------------------------------------------------------------------------
73 #-----------------------------------------------------------------------------
74 def test_spaces():
74 def test_spaces():
75 tests = [('', 0),
75 tests = [('', 0),
76 (' ', 1),
76 (' ', 1),
77 ('\n', 0),
77 ('\n', 0),
78 (' \n', 1),
78 (' \n', 1),
79 ('x', 0),
79 ('x', 0),
80 (' x', 1),
80 (' x', 1),
81 (' x',2),
81 (' x',2),
82 (' x',4),
82 (' x',4),
83 # Note: tabs are counted as a single whitespace!
83 # Note: tabs are counted as a single whitespace!
84 ('\tx', 1),
84 ('\tx', 1),
85 ('\t x', 2),
85 ('\t x', 2),
86 ]
86 ]
87 tt.check_pairs(isp.num_ini_spaces, tests)
87 tt.check_pairs(isp.num_ini_spaces, tests)
88
88
89
89
90 def test_remove_comments():
90 def test_remove_comments():
91 tests = [('text', 'text'),
91 tests = [('text', 'text'),
92 ('text # comment', 'text '),
92 ('text # comment', 'text '),
93 ('text # comment\n', 'text \n'),
93 ('text # comment\n', 'text \n'),
94 ('text # comment \n', 'text \n'),
94 ('text # comment \n', 'text \n'),
95 ('line # c \nline\n','line \nline\n'),
95 ('line # c \nline\n','line \nline\n'),
96 ('line # c \nline#c2 \nline\nline #c\n\n',
96 ('line # c \nline#c2 \nline\nline #c\n\n',
97 'line \nline\nline\nline \n\n'),
97 'line \nline\nline\nline \n\n'),
98 ]
98 ]
99 tt.check_pairs(isp.remove_comments, tests)
99 tt.check_pairs(isp.remove_comments, tests)
100
100
101
101
102 def test_get_input_encoding():
102 def test_get_input_encoding():
103 encoding = isp.get_input_encoding()
103 encoding = isp.get_input_encoding()
104 nt.assert_true(isinstance(encoding, string_types))
104 nt.assert_true(isinstance(encoding, string_types))
105 # simple-minded check that at least encoding a simple string works with the
105 # simple-minded check that at least encoding a simple string works with the
106 # encoding we got.
106 # encoding we got.
107 nt.assert_equal(u'test'.encode(encoding), b'test')
107 nt.assert_equal(u'test'.encode(encoding), b'test')
108
108
109
109
110 class NoInputEncodingTestCase(unittest.TestCase):
110 class NoInputEncodingTestCase(unittest.TestCase):
111 def setUp(self):
111 def setUp(self):
112 self.old_stdin = sys.stdin
112 self.old_stdin = sys.stdin
113 class X: pass
113 class X: pass
114 fake_stdin = X()
114 fake_stdin = X()
115 sys.stdin = fake_stdin
115 sys.stdin = fake_stdin
116
116
117 def test(self):
117 def test(self):
118 # Verify that if sys.stdin has no 'encoding' attribute we do the right
118 # Verify that if sys.stdin has no 'encoding' attribute we do the right
119 # thing
119 # thing
120 enc = isp.get_input_encoding()
120 enc = isp.get_input_encoding()
121 self.assertEqual(enc, 'ascii')
121 self.assertEqual(enc, 'ascii')
122
122
123 def tearDown(self):
123 def tearDown(self):
124 sys.stdin = self.old_stdin
124 sys.stdin = self.old_stdin
125
125
126
126
127 class InputSplitterTestCase(unittest.TestCase):
127 class InputSplitterTestCase(unittest.TestCase):
128 def setUp(self):
128 def setUp(self):
129 self.isp = isp.InputSplitter()
129 self.isp = isp.InputSplitter()
130
130
131 def test_reset(self):
131 def test_reset(self):
132 isp = self.isp
132 isp = self.isp
133 isp.push('x=1')
133 isp.push('x=1')
134 isp.reset()
134 isp.reset()
135 self.assertEqual(isp._buffer, [])
135 self.assertEqual(isp._buffer, [])
136 self.assertEqual(isp.indent_spaces, 0)
136 self.assertEqual(isp.indent_spaces, 0)
137 self.assertEqual(isp.source, '')
137 self.assertEqual(isp.source, '')
138 self.assertEqual(isp.code, None)
138 self.assertEqual(isp.code, None)
139 self.assertEqual(isp._is_complete, False)
139 self.assertEqual(isp._is_complete, False)
140
140
141 def test_source(self):
141 def test_source(self):
142 self.isp._store('1')
142 self.isp._store('1')
143 self.isp._store('2')
143 self.isp._store('2')
144 self.assertEqual(self.isp.source, '1\n2\n')
144 self.assertEqual(self.isp.source, '1\n2\n')
145 self.assertTrue(len(self.isp._buffer)>0)
145 self.assertEqual(len(self.isp._buffer)>0, True)
146 self.assertEqual(self.isp.source_reset(), '1\n2\n')
146 self.assertEqual(self.isp.source_reset(), '1\n2\n')
147 self.assertEqual(self.isp._buffer, [])
147 self.assertEqual(self.isp._buffer, [])
148 self.assertEqual(self.isp.source, '')
148 self.assertEqual(self.isp.source, '')
149
149
150 def test_indent(self):
150 def test_indent(self):
151 isp = self.isp # shorthand
151 isp = self.isp # shorthand
152 isp.push('x=1')
152 isp.push('x=1')
153 self.assertEqual(isp.indent_spaces, 0)
153 self.assertEqual(isp.indent_spaces, 0)
154 isp.push('if 1:\n x=1')
154 isp.push('if 1:\n x=1')
155 self.assertEqual(isp.indent_spaces, 4)
155 self.assertEqual(isp.indent_spaces, 4)
156 isp.push('y=2\n')
156 isp.push('y=2\n')
157 self.assertEqual(isp.indent_spaces, 0)
157 self.assertEqual(isp.indent_spaces, 0)
158
158
159 def test_indent2(self):
159 def test_indent2(self):
160 isp = self.isp
160 isp = self.isp
161 isp.push('if 1:')
161 isp.push('if 1:')
162 self.assertEqual(isp.indent_spaces, 4)
162 self.assertEqual(isp.indent_spaces, 4)
163 isp.push(' x=1')
163 isp.push(' x=1')
164 self.assertEqual(isp.indent_spaces, 4)
164 self.assertEqual(isp.indent_spaces, 4)
165 # Blank lines shouldn't change the indent level
165 # Blank lines shouldn't change the indent level
166 isp.push(' '*2)
166 isp.push(' '*2)
167 self.assertEqual(isp.indent_spaces, 4)
167 self.assertEqual(isp.indent_spaces, 4)
168
168
169 def test_indent3(self):
169 def test_indent3(self):
170 isp = self.isp
170 isp = self.isp
171 # When a multiline statement contains parens or multiline strings, we
171 # When a multiline statement contains parens or multiline strings, we
172 # shouldn't get confused.
172 # shouldn't get confused.
173 isp.push("if 1:")
173 isp.push("if 1:")
174 isp.push(" x = (1+\n 2)")
174 isp.push(" x = (1+\n 2)")
175 self.assertEqual(isp.indent_spaces, 4)
175 self.assertEqual(isp.indent_spaces, 4)
176
176
177 def test_indent4(self):
177 def test_indent4(self):
178 isp = self.isp
178 isp = self.isp
179 # whitespace after ':' should not screw up indent level
179 # whitespace after ':' should not screw up indent level
180 isp.push('if 1: \n x=1')
180 isp.push('if 1: \n x=1')
181 self.assertEqual(isp.indent_spaces, 4)
181 self.assertEqual(isp.indent_spaces, 4)
182 isp.push('y=2\n')
182 isp.push('y=2\n')
183 self.assertEqual(isp.indent_spaces, 0)
183 self.assertEqual(isp.indent_spaces, 0)
184 isp.push('if 1:\t\n x=1')
184 isp.push('if 1:\t\n x=1')
185 self.assertEqual(isp.indent_spaces, 4)
185 self.assertEqual(isp.indent_spaces, 4)
186 isp.push('y=2\n')
186 isp.push('y=2\n')
187 self.assertEqual(isp.indent_spaces, 0)
187 self.assertEqual(isp.indent_spaces, 0)
188
188
189 def test_dedent_pass(self):
189 def test_dedent_pass(self):
190 isp = self.isp # shorthand
190 isp = self.isp # shorthand
191 # should NOT cause dedent
191 # should NOT cause dedent
192 isp.push('if 1:\n passes = 5')
192 isp.push('if 1:\n passes = 5')
193 self.assertEqual(isp.indent_spaces, 4)
193 self.assertEqual(isp.indent_spaces, 4)
194 isp.push('if 1:\n pass')
194 isp.push('if 1:\n pass')
195 self.assertEqual(isp.indent_spaces, 0)
195 self.assertEqual(isp.indent_spaces, 0)
196 isp.push('if 1:\n pass ')
196 isp.push('if 1:\n pass ')
197 self.assertEqual(isp.indent_spaces, 0)
197 self.assertEqual(isp.indent_spaces, 0)
198
198
199 def test_dedent_break(self):
199 def test_dedent_break(self):
200 isp = self.isp # shorthand
200 isp = self.isp # shorthand
201 # should NOT cause dedent
201 # should NOT cause dedent
202 isp.push('while 1:\n breaks = 5')
202 isp.push('while 1:\n breaks = 5')
203 self.assertEqual(isp.indent_spaces, 4)
203 self.assertEqual(isp.indent_spaces, 4)
204 isp.push('while 1:\n break')
204 isp.push('while 1:\n break')
205 self.assertEqual(isp.indent_spaces, 0)
205 self.assertEqual(isp.indent_spaces, 0)
206 isp.push('while 1:\n break ')
206 isp.push('while 1:\n break ')
207 self.assertEqual(isp.indent_spaces, 0)
207 self.assertEqual(isp.indent_spaces, 0)
208
208
209 def test_dedent_continue(self):
209 def test_dedent_continue(self):
210 isp = self.isp # shorthand
210 isp = self.isp # shorthand
211 # should NOT cause dedent
211 # should NOT cause dedent
212 isp.push('while 1:\n continues = 5')
212 isp.push('while 1:\n continues = 5')
213 self.assertEqual(isp.indent_spaces, 4)
213 self.assertEqual(isp.indent_spaces, 4)
214 isp.push('while 1:\n continue')
214 isp.push('while 1:\n continue')
215 self.assertEqual(isp.indent_spaces, 0)
215 self.assertEqual(isp.indent_spaces, 0)
216 isp.push('while 1:\n continue ')
216 isp.push('while 1:\n continue ')
217 self.assertEqual(isp.indent_spaces, 0)
217 self.assertEqual(isp.indent_spaces, 0)
218
218
219 def test_dedent_raise(self):
219 def test_dedent_raise(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 raised = 4')
222 isp.push('if 1:\n raised = 4')
223 self.assertEqual(isp.indent_spaces, 4)
223 self.assertEqual(isp.indent_spaces, 4)
224 isp.push('if 1:\n raise TypeError()')
224 isp.push('if 1:\n raise TypeError()')
225 self.assertEqual(isp.indent_spaces, 0)
225 self.assertEqual(isp.indent_spaces, 0)
226 isp.push('if 1:\n raise')
226 isp.push('if 1:\n raise')
227 self.assertEqual(isp.indent_spaces, 0)
227 self.assertEqual(isp.indent_spaces, 0)
228 isp.push('if 1:\n raise ')
228 isp.push('if 1:\n raise ')
229 self.assertEqual(isp.indent_spaces, 0)
229 self.assertEqual(isp.indent_spaces, 0)
230
230
231 def test_dedent_return(self):
231 def test_dedent_return(self):
232 isp = self.isp # shorthand
232 isp = self.isp # shorthand
233 # should NOT cause dedent
233 # should NOT cause dedent
234 isp.push('if 1:\n returning = 4')
234 isp.push('if 1:\n returning = 4')
235 self.assertEqual(isp.indent_spaces, 4)
235 self.assertEqual(isp.indent_spaces, 4)
236 isp.push('if 1:\n return 5 + 493')
236 isp.push('if 1:\n return 5 + 493')
237 self.assertEqual(isp.indent_spaces, 0)
237 self.assertEqual(isp.indent_spaces, 0)
238 isp.push('if 1:\n return')
238 isp.push('if 1:\n return')
239 self.assertEqual(isp.indent_spaces, 0)
239 self.assertEqual(isp.indent_spaces, 0)
240 isp.push('if 1:\n return ')
240 isp.push('if 1:\n return ')
241 self.assertEqual(isp.indent_spaces, 0)
241 self.assertEqual(isp.indent_spaces, 0)
242 isp.push('if 1:\n return(0)')
242 isp.push('if 1:\n return(0)')
243 self.assertEqual(isp.indent_spaces, 0)
243 self.assertEqual(isp.indent_spaces, 0)
244
244
245 def test_push(self):
245 def test_push(self):
246 isp = self.isp
246 isp = self.isp
247 self.assertTrue(isp.push('x=1'))
247 self.assertEqual(isp.push('x=1'), True)
248
248
249 def test_push2(self):
249 def test_push2(self):
250 isp = self.isp
250 isp = self.isp
251 self.assertFalse(isp.push('if 1:'))
251 self.assertEqual(isp.push('if 1:'), False)
252 for line in [' x=1', '# a comment', ' y=2']:
252 for line in [' x=1', '# a comment', ' y=2']:
253 print(line)
253 print(line)
254 self.assertTrue(isp.push(line))
254 self.assertEqual(isp.push(line), True)
255
255
256 def test_push3(self):
256 def test_push3(self):
257 isp = self.isp
257 isp = self.isp
258 isp.push('if True:')
258 isp.push('if True:')
259 isp.push(' a = 1')
259 isp.push(' a = 1')
260 self.assertFalse(isp.push('b = [1,'))
260 self.assertEqual(isp.push('b = [1,'), False)
261
261
262 def test_push_accepts_more(self):
262 def test_push_accepts_more(self):
263 isp = self.isp
263 isp = self.isp
264 isp.push('x=1')
264 isp.push('x=1')
265 self.assertFalse(isp.push_accepts_more())
265 self.assertEqual(isp.push_accepts_more(), False)
266
266
267 def test_push_accepts_more2(self):
267 def test_push_accepts_more2(self):
268 isp = self.isp
268 isp = self.isp
269 isp.push('if 1:')
269 isp.push('if 1:')
270 self.assertTrue(isp.push_accepts_more())
270 self.assertEqual(isp.push_accepts_more(), True)
271 isp.push(' x=1')
271 isp.push(' x=1')
272 self.assertTrue(isp.push_accepts_more())
272 self.assertEqual(isp.push_accepts_more(), True)
273 isp.push('')
273 isp.push('')
274 self.assertFalse(isp.push_accepts_more())
274 self.assertEqual(isp.push_accepts_more(), False)
275
275
276 def test_push_accepts_more3(self):
276 def test_push_accepts_more3(self):
277 isp = self.isp
277 isp = self.isp
278 isp.push("x = (2+\n3)")
278 isp.push("x = (2+\n3)")
279 self.assertFalse(isp.push_accepts_more())
279 self.assertEqual(isp.push_accepts_more(), False)
280
280
281 def test_push_accepts_more4(self):
281 def test_push_accepts_more4(self):
282 isp = self.isp
282 isp = self.isp
283 # When a multiline statement contains parens or multiline strings, we
283 # When a multiline statement contains parens or multiline strings, we
284 # shouldn't get confused.
284 # shouldn't get confused.
285 # FIXME: we should be able to better handle de-dents in statements like
285 # FIXME: we should be able to better handle de-dents in statements like
286 # multiline strings and multiline expressions (continued with \ or
286 # multiline strings and multiline expressions (continued with \ or
287 # parens). Right now we aren't handling the indentation tracking quite
287 # parens). Right now we aren't handling the indentation tracking quite
288 # correctly with this, though in practice it may not be too much of a
288 # correctly with this, though in practice it may not be too much of a
289 # problem. We'll need to see.
289 # problem. We'll need to see.
290 isp.push("if 1:")
290 isp.push("if 1:")
291 isp.push(" x = (2+")
291 isp.push(" x = (2+")
292 isp.push(" 3)")
292 isp.push(" 3)")
293 self.assertTrue(isp.push_accepts_more())
293 self.assertEqual(isp.push_accepts_more(), True)
294 isp.push(" y = 3")
294 isp.push(" y = 3")
295 self.assertTrue(isp.push_accepts_more())
295 self.assertEqual(isp.push_accepts_more(), True)
296 isp.push('')
296 isp.push('')
297 self.assertFalse(isp.push_accepts_more())
297 self.assertEqual(isp.push_accepts_more(), False)
298
298
299 def test_push_accepts_more5(self):
299 def test_push_accepts_more5(self):
300 isp = self.isp
300 isp = self.isp
301 isp.push('try:')
301 isp.push('try:')
302 isp.push(' a = 5')
302 isp.push(' a = 5')
303 isp.push('except:')
303 isp.push('except:')
304 isp.push(' raise')
304 isp.push(' raise')
305 # We want to be able to add an else: block at this point, so it should
305 # We want to be able to add an else: block at this point, so it should
306 # wait for a blank line.
306 # wait for a blank line.
307 self.assertTrue(isp.push_accepts_more())
307 self.assertEqual(isp.push_accepts_more(), True)
308
308
309 def test_continuation(self):
309 def test_continuation(self):
310 isp = self.isp
310 isp = self.isp
311 isp.push("import os, \\")
311 isp.push("import os, \\")
312 self.assertTrue(isp.push_accepts_more())
312 self.assertEqual(isp.push_accepts_more(), True)
313 isp.push("sys")
313 isp.push("sys")
314 self.assertFalse(isp.push_accepts_more())
314 self.assertEqual(isp.push_accepts_more(), False)
315
315
316 def test_syntax_error(self):
316 def test_syntax_error(self):
317 isp = self.isp
317 isp = self.isp
318 # Syntax errors immediately produce a 'ready' block, so the invalid
318 # Syntax errors immediately produce a 'ready' block, so the invalid
319 # Python can be sent to the kernel for evaluation with possible ipython
319 # Python can be sent to the kernel for evaluation with possible ipython
320 # special-syntax conversion.
320 # special-syntax conversion.
321 isp.push('run foo')
321 isp.push('run foo')
322 self.assertFalse(isp.push_accepts_more())
322 self.assertEqual(isp.push_accepts_more(), False)
323
323
324 def test_unicode(self):
324 def test_unicode(self):
325 self.isp.push(u"Pérez")
325 self.isp.push(u"Pérez")
326 self.isp.push(u'\xc3\xa9')
326 self.isp.push(u'\xc3\xa9')
327 self.isp.push(u"u'\xc3\xa9'")
327 self.isp.push(u"u'\xc3\xa9'")
328
328
329 def test_line_continuation(self):
329 def test_line_continuation(self):
330 """ Test issue #2108."""
330 """ Test issue #2108."""
331 isp = self.isp
331 isp = self.isp
332 # A blank line after a line continuation should not accept more
332 # A blank line after a line continuation should not accept more
333 isp.push("1 \\\n\n")
333 isp.push("1 \\\n\n")
334 self.assertFalse(isp.push_accepts_more())
334 self.assertEqual(isp.push_accepts_more(), False)
335 # Whitespace after a \ is a SyntaxError. The only way to test that
335 # Whitespace after a \ is a SyntaxError. The only way to test that
336 # here is to test that push doesn't accept more (as with
336 # here is to test that push doesn't accept more (as with
337 # test_syntax_error() above).
337 # test_syntax_error() above).
338 isp.push(r"1 \ ")
338 isp.push(r"1 \ ")
339 self.assertFalse(isp.push_accepts_more())
339 self.assertEqual(isp.push_accepts_more(), False)
340 # Even if the line is continuable (c.f. the regular Python
340 # Even if the line is continuable (c.f. the regular Python
341 # interpreter)
341 # interpreter)
342 isp.push(r"(1 \ ")
342 isp.push(r"(1 \ ")
343 self.assertFalse(isp.push_accepts_more())
343 self.assertEqual(isp.push_accepts_more(), False)
344
344
345 def test_check_complete(self):
345 def test_check_complete(self):
346 isp = self.isp
346 isp = self.isp
347 self.assertEqual(isp.check_complete("a = 1"), ('complete', None))
347 self.assertEqual(isp.check_complete("a = 1"), ('complete', None))
348 self.assertEqual(isp.check_complete("for a in range(5):"), ('incomplete', 4))
348 self.assertEqual(isp.check_complete("for a in range(5):"), ('incomplete', 4))
349 self.assertEqual(isp.check_complete("raise = 2"), ('invalid', None))
349 self.assertEqual(isp.check_complete("raise = 2"), ('invalid', None))
350 self.assertEqual(isp.check_complete("a = [1,\n2,"), ('incomplete', 0))
350 self.assertEqual(isp.check_complete("a = [1,\n2,"), ('incomplete', 0))
351 self.assertEqual(isp.check_complete("def a():\n x=1\n global x"), ('invalid', None))
351 self.assertEqual(isp.check_complete("def a():\n x=1\n global x"), ('invalid', None))
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, test_ns)
365 exec(src, 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.items():
369 for k,v in ns.items():
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 class IPythonInputTestCase(InputSplitterTestCase):
388 class IPythonInputTestCase(InputSplitterTestCase):
389 """By just creating a new class whose .isp is a different instance, we
389 """By just creating a new class whose .isp is a different instance, we
390 re-run the same test battery on the new input splitter.
390 re-run the same test battery on the new input splitter.
391
391
392 In addition, this runs the tests over the syntax and syntax_ml dicts that
392 In addition, this runs the tests over the syntax and syntax_ml dicts that
393 were tested by individual functions, as part of the OO interface.
393 were tested by individual functions, as part of the OO interface.
394
394
395 It also makes some checks on the raw buffer storage.
395 It also makes some checks on the raw buffer storage.
396 """
396 """
397
397
398 def setUp(self):
398 def setUp(self):
399 self.isp = isp.IPythonInputSplitter()
399 self.isp = isp.IPythonInputSplitter()
400
400
401 def test_syntax(self):
401 def test_syntax(self):
402 """Call all single-line syntax tests from the main object"""
402 """Call all single-line syntax tests from the main object"""
403 isp = self.isp
403 isp = self.isp
404 for example in syntax.values():
404 for example in syntax.values():
405 for raw, out_t in example:
405 for raw, out_t in example:
406 if raw.startswith(' '):
406 if raw.startswith(' '):
407 continue
407 continue
408
408
409 isp.push(raw+'\n')
409 isp.push(raw+'\n')
410 out_raw = isp.source_raw
410 out_raw = isp.source_raw
411 out = isp.source_reset()
411 out = isp.source_reset()
412 self.assertEqual(out.rstrip(), out_t,
412 self.assertEqual(out.rstrip(), out_t,
413 tt.pair_fail_msg.format("inputsplitter",raw, out_t, out))
413 tt.pair_fail_msg.format("inputsplitter",raw, out_t, out))
414 self.assertEqual(out_raw.rstrip(), raw.rstrip())
414 self.assertEqual(out_raw.rstrip(), raw.rstrip())
415
415
416 def test_syntax_multiline(self):
416 def test_syntax_multiline(self):
417 isp = self.isp
417 isp = self.isp
418 for example in syntax_ml.values():
418 for example in syntax_ml.values():
419 for line_pairs in example:
419 for line_pairs in example:
420 out_t_parts = []
420 out_t_parts = []
421 raw_parts = []
421 raw_parts = []
422 for lraw, out_t_part in line_pairs:
422 for lraw, out_t_part in line_pairs:
423 if out_t_part is not None:
423 if out_t_part is not None:
424 out_t_parts.append(out_t_part)
424 out_t_parts.append(out_t_part)
425
425
426 if lraw is not None:
426 if lraw is not None:
427 isp.push(lraw)
427 isp.push(lraw)
428 raw_parts.append(lraw)
428 raw_parts.append(lraw)
429
429
430 out_raw = isp.source_raw
430 out_raw = isp.source_raw
431 out = isp.source_reset()
431 out = isp.source_reset()
432 out_t = '\n'.join(out_t_parts).rstrip()
432 out_t = '\n'.join(out_t_parts).rstrip()
433 raw = '\n'.join(raw_parts).rstrip()
433 raw = '\n'.join(raw_parts).rstrip()
434 self.assertEqual(out.rstrip(), out_t)
434 self.assertEqual(out.rstrip(), out_t)
435 self.assertEqual(out_raw.rstrip(), raw)
435 self.assertEqual(out_raw.rstrip(), raw)
436
436
437 def test_syntax_multiline_cell(self):
437 def test_syntax_multiline_cell(self):
438 isp = self.isp
438 isp = self.isp
439 for example in syntax_ml.values():
439 for example in syntax_ml.values():
440
440
441 out_t_parts = []
441 out_t_parts = []
442 for line_pairs in example:
442 for line_pairs in example:
443 raw = '\n'.join(r for r, _ in line_pairs if r is not None)
443 raw = '\n'.join(r for r, _ in line_pairs if r is not None)
444 out_t = '\n'.join(t for _,t in line_pairs if t is not None)
444 out_t = '\n'.join(t for _,t in line_pairs if t is not None)
445 out = isp.transform_cell(raw)
445 out = isp.transform_cell(raw)
446 # Match ignoring trailing whitespace
446 # Match ignoring trailing whitespace
447 self.assertEqual(out.rstrip(), out_t.rstrip())
447 self.assertEqual(out.rstrip(), out_t.rstrip())
448
448
449 def test_cellmagic_preempt(self):
449 def test_cellmagic_preempt(self):
450 isp = self.isp
450 isp = self.isp
451 for raw, name, line, cell in [
451 for raw, name, line, cell in [
452 ("%%cellm a\nIn[1]:", u'cellm', u'a', u'In[1]:'),
452 ("%%cellm a\nIn[1]:", u'cellm', u'a', u'In[1]:'),
453 ("%%cellm \nline\n>>> hi", u'cellm', u'', u'line\n>>> hi'),
453 ("%%cellm \nline\n>>> hi", u'cellm', u'', u'line\n>>> hi'),
454 (">>> %%cellm \nline\n>>> hi", u'cellm', u'', u'line\nhi'),
454 (">>> %%cellm \nline\n>>> hi", u'cellm', u'', u'line\nhi'),
455 ("%%cellm \n>>> hi", u'cellm', u'', u'>>> hi'),
455 ("%%cellm \n>>> hi", u'cellm', u'', u'>>> hi'),
456 ("%%cellm \nline1\nline2", u'cellm', u'', u'line1\nline2'),
456 ("%%cellm \nline1\nline2", u'cellm', u'', u'line1\nline2'),
457 ("%%cellm \nline1\\\\\nline2", u'cellm', u'', u'line1\\\\\nline2'),
457 ("%%cellm \nline1\\\\\nline2", u'cellm', u'', u'line1\\\\\nline2'),
458 ]:
458 ]:
459 expected = "get_ipython().run_cell_magic(%r, %r, %r)" % (
459 expected = "get_ipython().run_cell_magic(%r, %r, %r)" % (
460 name, line, cell
460 name, line, cell
461 )
461 )
462 out = isp.transform_cell(raw)
462 out = isp.transform_cell(raw)
463 self.assertEqual(out.rstrip(), expected.rstrip())
463 self.assertEqual(out.rstrip(), expected.rstrip())
464
464
465 def test_multiline_passthrough(self):
465 def test_multiline_passthrough(self):
466 isp = self.isp
466 isp = self.isp
467 class CommentTransformer(InputTransformer):
467 class CommentTransformer(InputTransformer):
468 def __init__(self):
468 def __init__(self):
469 self._lines = []
469 self._lines = []
470
470
471 def push(self, line):
471 def push(self, line):
472 self._lines.append(line + '#')
472 self._lines.append(line + '#')
473
473
474 def reset(self):
474 def reset(self):
475 text = '\n'.join(self._lines)
475 text = '\n'.join(self._lines)
476 self._lines = []
476 self._lines = []
477 return text
477 return text
478
478
479 isp.physical_line_transforms.insert(0, CommentTransformer())
479 isp.physical_line_transforms.insert(0, CommentTransformer())
480
480
481 for raw, expected in [
481 for raw, expected in [
482 ("a=5", "a=5#"),
482 ("a=5", "a=5#"),
483 ("%ls foo", "get_ipython().magic(%r)" % u'ls foo#'),
483 ("%ls foo", "get_ipython().magic(%r)" % u'ls foo#'),
484 ("!ls foo\n%ls bar", "get_ipython().system(%r)\nget_ipython().magic(%r)" % (
484 ("!ls foo\n%ls bar", "get_ipython().system(%r)\nget_ipython().magic(%r)" % (
485 u'ls foo#', u'ls bar#'
485 u'ls foo#', u'ls bar#'
486 )),
486 )),
487 ("1\n2\n3\n%ls foo\n4\n5", "1#\n2#\n3#\nget_ipython().magic(%r)\n4#\n5#" % u'ls foo#'),
487 ("1\n2\n3\n%ls foo\n4\n5", "1#\n2#\n3#\nget_ipython().magic(%r)\n4#\n5#" % u'ls foo#'),
488 ]:
488 ]:
489 out = isp.transform_cell(raw)
489 out = isp.transform_cell(raw)
490 self.assertEqual(out.rstrip(), expected.rstrip())
490 self.assertEqual(out.rstrip(), expected.rstrip())
491
491
492 #-----------------------------------------------------------------------------
492 #-----------------------------------------------------------------------------
493 # Main - use as a script, mostly for developer experiments
493 # Main - use as a script, mostly for developer experiments
494 #-----------------------------------------------------------------------------
494 #-----------------------------------------------------------------------------
495
495
496 if __name__ == '__main__':
496 if __name__ == '__main__':
497 # A simple demo for interactive experimentation. This code will not get
497 # A simple demo for interactive experimentation. This code will not get
498 # picked up by any test suite.
498 # picked up by any test suite.
499 from IPython.core.inputsplitter import IPythonInputSplitter
499 from IPython.core.inputsplitter import IPythonInputSplitter
500
500
501 # configure here the syntax to use, prompt and whether to autoindent
501 # configure here the syntax to use, prompt and whether to autoindent
502 #isp, start_prompt = InputSplitter(), '>>> '
502 #isp, start_prompt = InputSplitter(), '>>> '
503 isp, start_prompt = IPythonInputSplitter(), 'In> '
503 isp, start_prompt = IPythonInputSplitter(), 'In> '
504
504
505 autoindent = True
505 autoindent = True
506 #autoindent = False
506 #autoindent = False
507
507
508 try:
508 try:
509 while True:
509 while True:
510 prompt = start_prompt
510 prompt = start_prompt
511 while isp.push_accepts_more():
511 while isp.push_accepts_more():
512 indent = ' '*isp.indent_spaces
512 indent = ' '*isp.indent_spaces
513 if autoindent:
513 if autoindent:
514 line = indent + input(prompt+indent)
514 line = indent + input(prompt+indent)
515 else:
515 else:
516 line = input(prompt)
516 line = input(prompt)
517 isp.push(line)
517 isp.push(line)
518 prompt = '... '
518 prompt = '... '
519
519
520 # Here we just return input so we can use it in a test suite, but a
520 # Here we just return input so we can use it in a test suite, but a
521 # real interpreter would instead send it for execution somewhere.
521 # real interpreter would instead send it for execution somewhere.
522 #src = isp.source; raise EOFError # dbg
522 #src = isp.source; raise EOFError # dbg
523 raw = isp.source_raw
523 raw = isp.source_raw
524 src = isp.source_reset()
524 src = isp.source_reset()
525 print('Input source was:\n', src)
525 print('Input source was:\n', src)
526 print('Raw source was:\n', raw)
526 print('Raw source was:\n', raw)
527 except EOFError:
527 except EOFError:
528 print('Bye')
528 print('Bye')
529
529
530 # Tests for cell magics support
530 # Tests for cell magics support
531
531
532 def test_last_blank():
532 def test_last_blank():
533 nt.assert_false(isp.last_blank(''))
533 nt.assert_false(isp.last_blank(''))
534 nt.assert_false(isp.last_blank('abc'))
534 nt.assert_false(isp.last_blank('abc'))
535 nt.assert_false(isp.last_blank('abc\n'))
535 nt.assert_false(isp.last_blank('abc\n'))
536 nt.assert_false(isp.last_blank('abc\na'))
536 nt.assert_false(isp.last_blank('abc\na'))
537
537
538 nt.assert_true(isp.last_blank('\n'))
538 nt.assert_true(isp.last_blank('\n'))
539 nt.assert_true(isp.last_blank('\n '))
539 nt.assert_true(isp.last_blank('\n '))
540 nt.assert_true(isp.last_blank('abc\n '))
540 nt.assert_true(isp.last_blank('abc\n '))
541 nt.assert_true(isp.last_blank('abc\n\n'))
541 nt.assert_true(isp.last_blank('abc\n\n'))
542 nt.assert_true(isp.last_blank('abc\nd\n\n'))
542 nt.assert_true(isp.last_blank('abc\nd\n\n'))
543 nt.assert_true(isp.last_blank('abc\nd\ne\n\n'))
543 nt.assert_true(isp.last_blank('abc\nd\ne\n\n'))
544 nt.assert_true(isp.last_blank('abc \n \n \n\n'))
544 nt.assert_true(isp.last_blank('abc \n \n \n\n'))
545
545
546
546
547 def test_last_two_blanks():
547 def test_last_two_blanks():
548 nt.assert_false(isp.last_two_blanks(''))
548 nt.assert_false(isp.last_two_blanks(''))
549 nt.assert_false(isp.last_two_blanks('abc'))
549 nt.assert_false(isp.last_two_blanks('abc'))
550 nt.assert_false(isp.last_two_blanks('abc\n'))
550 nt.assert_false(isp.last_two_blanks('abc\n'))
551 nt.assert_false(isp.last_two_blanks('abc\n\na'))
551 nt.assert_false(isp.last_two_blanks('abc\n\na'))
552 nt.assert_false(isp.last_two_blanks('abc\n \n'))
552 nt.assert_false(isp.last_two_blanks('abc\n \n'))
553 nt.assert_false(isp.last_two_blanks('abc\n\n'))
553 nt.assert_false(isp.last_two_blanks('abc\n\n'))
554
554
555 nt.assert_true(isp.last_two_blanks('\n\n'))
555 nt.assert_true(isp.last_two_blanks('\n\n'))
556 nt.assert_true(isp.last_two_blanks('\n\n '))
556 nt.assert_true(isp.last_two_blanks('\n\n '))
557 nt.assert_true(isp.last_two_blanks('\n \n'))
557 nt.assert_true(isp.last_two_blanks('\n \n'))
558 nt.assert_true(isp.last_two_blanks('abc\n\n '))
558 nt.assert_true(isp.last_two_blanks('abc\n\n '))
559 nt.assert_true(isp.last_two_blanks('abc\n\n\n'))
559 nt.assert_true(isp.last_two_blanks('abc\n\n\n'))
560 nt.assert_true(isp.last_two_blanks('abc\n\n \n'))
560 nt.assert_true(isp.last_two_blanks('abc\n\n \n'))
561 nt.assert_true(isp.last_two_blanks('abc\n\n \n '))
561 nt.assert_true(isp.last_two_blanks('abc\n\n \n '))
562 nt.assert_true(isp.last_two_blanks('abc\n\n \n \n'))
562 nt.assert_true(isp.last_two_blanks('abc\n\n \n \n'))
563 nt.assert_true(isp.last_two_blanks('abc\nd\n\n\n'))
563 nt.assert_true(isp.last_two_blanks('abc\nd\n\n\n'))
564 nt.assert_true(isp.last_two_blanks('abc\nd\ne\nf\n\n\n'))
564 nt.assert_true(isp.last_two_blanks('abc\nd\ne\nf\n\n\n'))
565
565
566
566
567 class CellMagicsCommon(object):
567 class CellMagicsCommon(object):
568
568
569 def test_whole_cell(self):
569 def test_whole_cell(self):
570 src = "%%cellm line\nbody\n"
570 src = "%%cellm line\nbody\n"
571 out = self.sp.transform_cell(src)
571 out = self.sp.transform_cell(src)
572 ref = u"get_ipython().run_cell_magic({u}'cellm', {u}'line', {u}'body')\n"
572 ref = u"get_ipython().run_cell_magic({u}'cellm', {u}'line', {u}'body')\n"
573 nt.assert_equal(out, py3compat.u_format(ref))
573 nt.assert_equal(out, py3compat.u_format(ref))
574
574
575 def test_cellmagic_help(self):
575 def test_cellmagic_help(self):
576 self.sp.push('%%cellm?')
576 self.sp.push('%%cellm?')
577 nt.assert_false(self.sp.push_accepts_more())
577 nt.assert_false(self.sp.push_accepts_more())
578
578
579 def tearDown(self):
579 def tearDown(self):
580 self.sp.reset()
580 self.sp.reset()
581
581
582
582
583 class CellModeCellMagics(CellMagicsCommon, unittest.TestCase):
583 class CellModeCellMagics(CellMagicsCommon, unittest.TestCase):
584 sp = isp.IPythonInputSplitter(line_input_checker=False)
584 sp = isp.IPythonInputSplitter(line_input_checker=False)
585
585
586 def test_incremental(self):
586 def test_incremental(self):
587 sp = self.sp
587 sp = self.sp
588 sp.push('%%cellm firstline\n')
588 sp.push('%%cellm firstline\n')
589 nt.assert_true(sp.push_accepts_more()) #1
589 nt.assert_true(sp.push_accepts_more()) #1
590 sp.push('line2\n')
590 sp.push('line2\n')
591 nt.assert_true(sp.push_accepts_more()) #2
591 nt.assert_true(sp.push_accepts_more()) #2
592 sp.push('\n')
592 sp.push('\n')
593 # This should accept a blank line and carry on until the cell is reset
593 # This should accept a blank line and carry on until the cell is reset
594 nt.assert_true(sp.push_accepts_more()) #3
594 nt.assert_true(sp.push_accepts_more()) #3
595
595
596 def test_no_strip_coding(self):
596 def test_no_strip_coding(self):
597 src = '\n'.join([
597 src = '\n'.join([
598 '%%writefile foo.py',
598 '%%writefile foo.py',
599 '# coding: utf-8',
599 '# coding: utf-8',
600 'print(u"üñîçø∂é")',
600 'print(u"üñîçø∂é")',
601 ])
601 ])
602 out = self.sp.transform_cell(src)
602 out = self.sp.transform_cell(src)
603 nt.assert_in('# coding: utf-8', out)
603 nt.assert_in('# coding: utf-8', out)
604
604
605
605
606 class LineModeCellMagics(CellMagicsCommon, unittest.TestCase):
606 class LineModeCellMagics(CellMagicsCommon, unittest.TestCase):
607 sp = isp.IPythonInputSplitter(line_input_checker=True)
607 sp = isp.IPythonInputSplitter(line_input_checker=True)
608
608
609 def test_incremental(self):
609 def test_incremental(self):
610 sp = self.sp
610 sp = self.sp
611 sp.push('%%cellm line2\n')
611 sp.push('%%cellm line2\n')
612 nt.assert_true(sp.push_accepts_more()) #1
612 nt.assert_true(sp.push_accepts_more()) #1
613 sp.push('\n')
613 sp.push('\n')
614 # In this case, a blank line should end the cell magic
614 # In this case, a blank line should end the cell magic
615 nt.assert_false(sp.push_accepts_more()) #2
615 nt.assert_false(sp.push_accepts_more()) #2
General Comments 0
You need to be logged in to leave comments. Login now