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