##// END OF EJS Templates
Add failing tests for tuple unpacking assignments from system cmds
Thomas Kluyver -
Show More
@@ -1,475 +1,479 b''
1 1 import tokenize
2 2 import nose.tools as nt
3 3
4 4 from IPython.testing import tools as tt
5 5 from IPython.utils import py3compat
6 6 u_fmt = py3compat.u_format
7 7
8 8 from IPython.core import inputtransformer as ipt
9 9
10 10 def transform_and_reset(transformer):
11 11 transformer = transformer()
12 12 def transform(inp):
13 13 try:
14 14 return transformer.push(inp)
15 15 finally:
16 16 transformer.reset()
17 17
18 18 return transform
19 19
20 20 # Transformer tests
21 21 def transform_checker(tests, transformer, **kwargs):
22 22 """Utility to loop over test inputs"""
23 23 transformer = transformer(**kwargs)
24 24 try:
25 25 for inp, tr in tests:
26 26 if inp is None:
27 27 out = transformer.reset()
28 28 else:
29 29 out = transformer.push(inp)
30 30 nt.assert_equal(out, tr)
31 31 finally:
32 32 transformer.reset()
33 33
34 34 # Data for all the syntax tests in the form of lists of pairs of
35 35 # raw/transformed input. We store it here as a global dict so that we can use
36 36 # it both within single-function tests and also to validate the behavior of the
37 37 # larger objects
38 38
39 39 syntax = \
40 40 dict(assign_system =
41 41 [(i,py3compat.u_format(o)) for i,o in \
42 42 [(u'a =! ls', "a = get_ipython().getoutput({u}'ls')"),
43 43 (u'b = !ls', "b = get_ipython().getoutput({u}'ls')"),
44 44 ('x=1', 'x=1'), # normal input is unmodified
45 45 (' ',' '), # blank lines are kept intact
46 # Tuple unpacking
47 (u"a, b = !echo 'a\\nb'", u"a, b = get_ipython().getoutput({u}\"echo 'a\\\\nb'\")"),
48 (u"a,= !echo 'a'", u"a, = get_ipython().getoutput({u}\"echo 'a'\")"),
49 (u"a, *bc = !echo 'a\\nb\\nc'", u"a, *bc = get_ipython().getoutput({u}\"echo 'a\\\\nb\\\\nc'\")"),
46 50 ]],
47 51
48 52 assign_magic =
49 53 [(i,py3compat.u_format(o)) for i,o in \
50 54 [(u'a =% who', "a = get_ipython().magic({u}'who')"),
51 55 (u'b = %who', "b = get_ipython().magic({u}'who')"),
52 56 ('x=1', 'x=1'), # normal input is unmodified
53 57 (' ',' '), # blank lines are kept intact
54 58 ]],
55 59
56 60 classic_prompt =
57 61 [('>>> x=1', 'x=1'),
58 62 ('x=1', 'x=1'), # normal input is unmodified
59 63 (' ', ' '), # blank lines are kept intact
60 64 ],
61 65
62 66 ipy_prompt =
63 67 [('In [1]: x=1', 'x=1'),
64 68 ('x=1', 'x=1'), # normal input is unmodified
65 69 (' ',' '), # blank lines are kept intact
66 70 ],
67 71
68 72 strip_encoding_cookie =
69 73 [
70 74 ('# -*- encoding: utf-8 -*-', ''),
71 75 ('# coding: latin-1', ''),
72 76 ],
73 77
74 78
75 79 # Tests for the escape transformer to leave normal code alone
76 80 escaped_noesc =
77 81 [ (' ', ' '),
78 82 ('x=1', 'x=1'),
79 83 ],
80 84
81 85 # System calls
82 86 escaped_shell =
83 87 [(i,py3compat.u_format(o)) for i,o in \
84 88 [ (u'!ls', "get_ipython().system({u}'ls')"),
85 89 # Double-escape shell, this means to capture the output of the
86 90 # subprocess and return it
87 91 (u'!!ls', "get_ipython().getoutput({u}'ls')"),
88 92 ]],
89 93
90 94 # Help/object info
91 95 escaped_help =
92 96 [(i,py3compat.u_format(o)) for i,o in \
93 97 [ (u'?', 'get_ipython().show_usage()'),
94 98 (u'?x1', "get_ipython().magic({u}'pinfo x1')"),
95 99 (u'??x2', "get_ipython().magic({u}'pinfo2 x2')"),
96 100 (u'?a.*s', "get_ipython().magic({u}'psearch a.*s')"),
97 101 (u'?%hist1', "get_ipython().magic({u}'pinfo %hist1')"),
98 102 (u'?%%hist2', "get_ipython().magic({u}'pinfo %%hist2')"),
99 103 (u'?abc = qwe', "get_ipython().magic({u}'pinfo abc')"),
100 104 ]],
101 105
102 106 end_help =
103 107 [(i,py3compat.u_format(o)) for i,o in \
104 108 [ (u'x3?', "get_ipython().magic({u}'pinfo x3')"),
105 109 (u'x4??', "get_ipython().magic({u}'pinfo2 x4')"),
106 110 (u'%hist1?', "get_ipython().magic({u}'pinfo %hist1')"),
107 111 (u'%hist2??', "get_ipython().magic({u}'pinfo2 %hist2')"),
108 112 (u'%%hist3?', "get_ipython().magic({u}'pinfo %%hist3')"),
109 113 (u'%%hist4??', "get_ipython().magic({u}'pinfo2 %%hist4')"),
110 114 (u'f*?', "get_ipython().magic({u}'psearch f*')"),
111 115 (u'ax.*aspe*?', "get_ipython().magic({u}'psearch ax.*aspe*')"),
112 116 (u'a = abc?', "get_ipython().set_next_input({u}'a = abc');"
113 117 "get_ipython().magic({u}'pinfo abc')"),
114 118 (u'a = abc.qe??', "get_ipython().set_next_input({u}'a = abc.qe');"
115 119 "get_ipython().magic({u}'pinfo2 abc.qe')"),
116 120 (u'a = *.items?', "get_ipython().set_next_input({u}'a = *.items');"
117 121 "get_ipython().magic({u}'psearch *.items')"),
118 122 (u'plot(a?', "get_ipython().set_next_input({u}'plot(a');"
119 123 "get_ipython().magic({u}'pinfo a')"),
120 124 (u'a*2 #comment?', 'a*2 #comment?'),
121 125 ]],
122 126
123 127 # Explicit magic calls
124 128 escaped_magic =
125 129 [(i,py3compat.u_format(o)) for i,o in \
126 130 [ (u'%cd', "get_ipython().magic({u}'cd')"),
127 131 (u'%cd /home', "get_ipython().magic({u}'cd /home')"),
128 132 # Backslashes need to be escaped.
129 133 (u'%cd C:\\User', "get_ipython().magic({u}'cd C:\\\\User')"),
130 134 (u' %magic', " get_ipython().magic({u}'magic')"),
131 135 ]],
132 136
133 137 # Quoting with separate arguments
134 138 escaped_quote =
135 139 [ (',f', 'f("")'),
136 140 (',f x', 'f("x")'),
137 141 (' ,f y', ' f("y")'),
138 142 (',f a b', 'f("a", "b")'),
139 143 ],
140 144
141 145 # Quoting with single argument
142 146 escaped_quote2 =
143 147 [ (';f', 'f("")'),
144 148 (';f x', 'f("x")'),
145 149 (' ;f y', ' f("y")'),
146 150 (';f a b', 'f("a b")'),
147 151 ],
148 152
149 153 # Simply apply parens
150 154 escaped_paren =
151 155 [ ('/f', 'f()'),
152 156 ('/f x', 'f(x)'),
153 157 (' /f y', ' f(y)'),
154 158 ('/f a b', 'f(a, b)'),
155 159 ],
156 160
157 161 # Check that we transform prompts before other transforms
158 162 mixed =
159 163 [(i,py3compat.u_format(o)) for i,o in \
160 164 [ (u'In [1]: %lsmagic', "get_ipython().magic({u}'lsmagic')"),
161 165 (u'>>> %lsmagic', "get_ipython().magic({u}'lsmagic')"),
162 166 (u'In [2]: !ls', "get_ipython().system({u}'ls')"),
163 167 (u'In [3]: abs?', "get_ipython().magic({u}'pinfo abs')"),
164 168 (u'In [4]: b = %who', "b = get_ipython().magic({u}'who')"),
165 169 ]],
166 170 )
167 171
168 172 # multiline syntax examples. Each of these should be a list of lists, with
169 173 # each entry itself having pairs of raw/transformed input. The union (with
170 174 # '\n'.join() of the transformed inputs is what the splitter should produce
171 175 # when fed the raw lines one at a time via push.
172 176 syntax_ml = \
173 177 dict(classic_prompt =
174 178 [ [('>>> for i in range(10):','for i in range(10):'),
175 179 ('... print i',' print i'),
176 180 ('... ', ''),
177 181 ],
178 182 [('>>> a="""','a="""'),
179 183 ('... 123"""','123"""'),
180 184 ],
181 185 [('a="""','a="""'),
182 186 ('... 123','123'),
183 187 ('... 456"""','456"""'),
184 188 ],
185 189 [('a="""','a="""'),
186 190 ('>>> 123','123'),
187 191 ('... 456"""','456"""'),
188 192 ],
189 193 [('a="""','a="""'),
190 194 ('123','123'),
191 195 ('... 456"""','... 456"""'),
192 196 ],
193 197 [('....__class__','....__class__'),
194 198 ],
195 199 [('a=5', 'a=5'),
196 200 ('...', ''),
197 201 ],
198 202 [('>>> def f(x):', 'def f(x):'),
199 203 ('...', ''),
200 204 ('... return x', ' return x'),
201 205 ],
202 206 ],
203 207
204 208 ipy_prompt =
205 209 [ [('In [24]: for i in range(10):','for i in range(10):'),
206 210 (' ....: print i',' print i'),
207 211 (' ....: ', ''),
208 212 ],
209 213 [('In [24]: for i in range(10):','for i in range(10):'),
210 214 # Qt console prompts expand with spaces, not dots
211 215 (' ...: print i',' print i'),
212 216 (' ...: ', ''),
213 217 ],
214 218 [('In [2]: a="""','a="""'),
215 219 (' ...: 123"""','123"""'),
216 220 ],
217 221 [('a="""','a="""'),
218 222 (' ...: 123','123'),
219 223 (' ...: 456"""','456"""'),
220 224 ],
221 225 [('a="""','a="""'),
222 226 ('In [1]: 123','123'),
223 227 (' ...: 456"""','456"""'),
224 228 ],
225 229 [('a="""','a="""'),
226 230 ('123','123'),
227 231 (' ...: 456"""',' ...: 456"""'),
228 232 ],
229 233 ],
230 234
231 235 strip_encoding_cookie =
232 236 [
233 237 [
234 238 ('# -*- coding: utf-8 -*-', ''),
235 239 ('foo', 'foo'),
236 240 ],
237 241 [
238 242 ('#!/usr/bin/env python', '#!/usr/bin/env python'),
239 243 ('# -*- coding: latin-1 -*-', ''),
240 244 # only the first-two lines
241 245 ('# -*- coding: latin-1 -*-', '# -*- coding: latin-1 -*-'),
242 246 ],
243 247 ],
244 248
245 249 multiline_datastructure_prompt =
246 250 [ [('>>> a = [1,','a = [1,'),
247 251 ('... 2]','2]'),
248 252 ],
249 253 ],
250 254
251 255 multiline_datastructure =
252 256 [ [('b = ("%s"', None),
253 257 ('# comment', None),
254 258 ('%foo )', 'b = ("%s"\n# comment\n%foo )'),
255 259 ],
256 260 ],
257 261
258 262 multiline_string =
259 263 [ [("'''foo?", None),
260 264 ("bar'''", "'''foo?\nbar'''"),
261 265 ],
262 266 ],
263 267
264 268 leading_indent =
265 269 [ [(' print "hi"','print "hi"'),
266 270 ],
267 271 [(' for a in range(5):','for a in range(5):'),
268 272 (' a*2',' a*2'),
269 273 ],
270 274 [(' a="""','a="""'),
271 275 (' 123"""','123"""'),
272 276 ],
273 277 [('a="""','a="""'),
274 278 (' 123"""',' 123"""'),
275 279 ],
276 280 ],
277 281
278 282 cellmagic =
279 283 [ [(u'%%foo a', None),
280 284 (None, u_fmt("get_ipython().run_cell_magic({u}'foo', {u}'a', {u}'')")),
281 285 ],
282 286 [(u'%%bar 123', None),
283 287 (u'hello', None),
284 288 (None , u_fmt("get_ipython().run_cell_magic({u}'bar', {u}'123', {u}'hello')")),
285 289 ],
286 290 [(u'a=5', 'a=5'),
287 291 (u'%%cellmagic', '%%cellmagic'),
288 292 ],
289 293 ],
290 294
291 295 escaped =
292 296 [ [('%abc def \\', None),
293 297 ('ghi', u_fmt("get_ipython().magic({u}'abc def ghi')")),
294 298 ],
295 299 [('%abc def \\', None),
296 300 ('ghi\\', None),
297 301 (None, u_fmt("get_ipython().magic({u}'abc def ghi')")),
298 302 ],
299 303 ],
300 304
301 305 assign_magic =
302 306 [ [(u'a = %bc de \\', None),
303 307 (u'fg', u_fmt("a = get_ipython().magic({u}'bc de fg')")),
304 308 ],
305 309 [(u'a = %bc de \\', None),
306 310 (u'fg\\', None),
307 311 (None, u_fmt("a = get_ipython().magic({u}'bc de fg')")),
308 312 ],
309 313 ],
310 314
311 315 assign_system =
312 316 [ [(u'a = !bc de \\', None),
313 317 (u'fg', u_fmt("a = get_ipython().getoutput({u}'bc de fg')")),
314 318 ],
315 319 [(u'a = !bc de \\', None),
316 320 (u'fg\\', None),
317 321 (None, u_fmt("a = get_ipython().getoutput({u}'bc de fg')")),
318 322 ],
319 323 ],
320 324 )
321 325
322 326
323 327 def test_assign_system():
324 328 tt.check_pairs(transform_and_reset(ipt.assign_from_system), syntax['assign_system'])
325 329
326 330 def test_assign_magic():
327 331 tt.check_pairs(transform_and_reset(ipt.assign_from_magic), syntax['assign_magic'])
328 332
329 333 def test_classic_prompt():
330 334 tt.check_pairs(transform_and_reset(ipt.classic_prompt), syntax['classic_prompt'])
331 335 for example in syntax_ml['classic_prompt']:
332 336 transform_checker(example, ipt.classic_prompt)
333 337 for example in syntax_ml['multiline_datastructure_prompt']:
334 338 transform_checker(example, ipt.classic_prompt)
335 339
336 340
337 341 def test_ipy_prompt():
338 342 tt.check_pairs(transform_and_reset(ipt.ipy_prompt), syntax['ipy_prompt'])
339 343 for example in syntax_ml['ipy_prompt']:
340 344 transform_checker(example, ipt.ipy_prompt)
341 345
342 346 def test_coding_cookie():
343 347 tt.check_pairs(transform_and_reset(ipt.strip_encoding_cookie), syntax['strip_encoding_cookie'])
344 348 for example in syntax_ml['strip_encoding_cookie']:
345 349 transform_checker(example, ipt.strip_encoding_cookie)
346 350
347 351 def test_assemble_logical_lines():
348 352 tests = \
349 353 [ [(u"a = \\", None),
350 354 (u"123", u"a = 123"),
351 355 ],
352 356 [(u"a = \\", None), # Test resetting when within a multi-line string
353 357 (u"12 *\\", None),
354 358 (None, u"a = 12 *"),
355 359 ],
356 360 [(u"# foo\\", u"# foo\\"), # Comments can't be continued like this
357 361 ],
358 362 ]
359 363 for example in tests:
360 364 transform_checker(example, ipt.assemble_logical_lines)
361 365
362 366 def test_assemble_python_lines():
363 367 tests = \
364 368 [ [(u"a = '''", None),
365 369 (u"abc'''", u"a = '''\nabc'''"),
366 370 ],
367 371 [(u"a = '''", None), # Test resetting when within a multi-line string
368 372 (u"def", None),
369 373 (None, u"a = '''\ndef"),
370 374 ],
371 375 [(u"a = [1,", None),
372 376 (u"2]", u"a = [1,\n2]"),
373 377 ],
374 378 [(u"a = [1,", None), # Test resetting when within a multi-line string
375 379 (u"2,", None),
376 380 (None, u"a = [1,\n2,"),
377 381 ],
378 382 ] + syntax_ml['multiline_datastructure']
379 383 for example in tests:
380 384 transform_checker(example, ipt.assemble_python_lines)
381 385
382 386
383 387 def test_help_end():
384 388 tt.check_pairs(transform_and_reset(ipt.help_end), syntax['end_help'])
385 389
386 390 def test_escaped_noesc():
387 391 tt.check_pairs(transform_and_reset(ipt.escaped_commands), syntax['escaped_noesc'])
388 392
389 393
390 394 def test_escaped_shell():
391 395 tt.check_pairs(transform_and_reset(ipt.escaped_commands), syntax['escaped_shell'])
392 396
393 397
394 398 def test_escaped_help():
395 399 tt.check_pairs(transform_and_reset(ipt.escaped_commands), syntax['escaped_help'])
396 400
397 401
398 402 def test_escaped_magic():
399 403 tt.check_pairs(transform_and_reset(ipt.escaped_commands), syntax['escaped_magic'])
400 404
401 405
402 406 def test_escaped_quote():
403 407 tt.check_pairs(transform_and_reset(ipt.escaped_commands), syntax['escaped_quote'])
404 408
405 409
406 410 def test_escaped_quote2():
407 411 tt.check_pairs(transform_and_reset(ipt.escaped_commands), syntax['escaped_quote2'])
408 412
409 413
410 414 def test_escaped_paren():
411 415 tt.check_pairs(transform_and_reset(ipt.escaped_commands), syntax['escaped_paren'])
412 416
413 417
414 418 def test_cellmagic():
415 419 for example in syntax_ml['cellmagic']:
416 420 transform_checker(example, ipt.cellmagic)
417 421
418 422 line_example = [(u'%%bar 123', None),
419 423 (u'hello', None),
420 424 (u'' , u_fmt("get_ipython().run_cell_magic({u}'bar', {u}'123', {u}'hello')")),
421 425 ]
422 426 transform_checker(line_example, ipt.cellmagic, end_on_blank_line=True)
423 427
424 428 def test_has_comment():
425 429 tests = [('text', False),
426 430 ('text #comment', True),
427 431 ('text #comment\n', True),
428 432 ('#comment', True),
429 433 ('#comment\n', True),
430 434 ('a = "#string"', False),
431 435 ('a = "#string" # comment', True),
432 436 ('a #comment not "string"', True),
433 437 ]
434 438 tt.check_pairs(ipt.has_comment, tests)
435 439
436 440 @ipt.TokenInputTransformer.wrap
437 441 def decistmt(tokens):
438 442 """Substitute Decimals for floats in a string of statements.
439 443
440 444 Based on an example from the tokenize module docs.
441 445 """
442 446 result = []
443 447 for toknum, tokval, _, _, _ in tokens:
444 448 if toknum == tokenize.NUMBER and '.' in tokval: # replace NUMBER tokens
445 449 for newtok in [
446 450 (tokenize.NAME, 'Decimal'),
447 451 (tokenize.OP, '('),
448 452 (tokenize.STRING, repr(tokval)),
449 453 (tokenize.OP, ')')
450 454 ]:
451 455 yield newtok
452 456 else:
453 457 yield (toknum, tokval)
454 458
455 459
456 460
457 461 def test_token_input_transformer():
458 462 tests = [(u'1.2', u_fmt(u"Decimal ({u}'1.2')")),
459 463 (u'"1.2"', u'"1.2"'),
460 464 ]
461 465 tt.check_pairs(transform_and_reset(decistmt), tests)
462 466 ml_tests = \
463 467 [ [(u"a = 1.2; b = '''x", None),
464 468 (u"y'''", u_fmt(u"a =Decimal ({u}'1.2');b ='''x\ny'''")),
465 469 ],
466 470 [(u"a = [1.2,", None),
467 471 (u"3]", u_fmt(u"a =[Decimal ({u}'1.2'),\n3 ]")),
468 472 ],
469 473 [(u"a = '''foo", None), # Test resetting when within a multi-line string
470 474 (u"bar", None),
471 475 (None, u"a = '''foo\nbar"),
472 476 ],
473 477 ]
474 478 for example in ml_tests:
475 479 transform_checker(example, decistmt)
General Comments 0
You need to be logged in to leave comments. Login now