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