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