##// END OF EJS Templates
Add tests for new method.
Fernando Perez -
Show More
@@ -1,798 +1,809 b''
1 1 # -*- coding: utf-8 -*-
2 2 """Tests for the inputsplitter module.
3 3
4 4 Authors
5 5 -------
6 6 * Fernando Perez
7 7 * Robert Kern
8 8 """
9 9 #-----------------------------------------------------------------------------
10 10 # Copyright (C) 2010-2011 The IPython Development Team
11 11 #
12 12 # Distributed under the terms of the BSD License. The full license is in
13 13 # the file COPYING, distributed as part of this software.
14 14 #-----------------------------------------------------------------------------
15 15
16 16 #-----------------------------------------------------------------------------
17 17 # Imports
18 18 #-----------------------------------------------------------------------------
19 19 # stdlib
20 20 import unittest
21 21 import sys
22 22
23 23 # Third party
24 24 import nose.tools as nt
25 25
26 26 # Our own
27 27 from IPython.core import inputsplitter as isp
28 28 from IPython.testing import tools as tt
29 29 from IPython.utils import py3compat
30 30
31 31 #-----------------------------------------------------------------------------
32 32 # Semi-complete examples (also used as tests)
33 33 #-----------------------------------------------------------------------------
34 34
35 35 # Note: at the bottom, there's a slightly more complete version of this that
36 36 # can be useful during development of code here.
37 37
38 38 def mini_interactive_loop(input_func):
39 39 """Minimal example of the logic of an interactive interpreter loop.
40 40
41 41 This serves as an example, and it is used by the test system with a fake
42 42 raw_input that simulates interactive input."""
43 43
44 44 from IPython.core.inputsplitter import InputSplitter
45 45
46 46 isp = InputSplitter()
47 47 # In practice, this input loop would be wrapped in an outside loop to read
48 48 # input indefinitely, until some exit/quit command was issued. Here we
49 49 # only illustrate the basic inner loop.
50 50 while isp.push_accepts_more():
51 51 indent = ' '*isp.indent_spaces
52 52 prompt = '>>> ' + indent
53 53 line = indent + input_func(prompt)
54 54 isp.push(line)
55 55
56 56 # Here we just return input so we can use it in a test suite, but a real
57 57 # interpreter would instead send it for execution somewhere.
58 58 src = isp.source_reset()
59 59 #print 'Input source was:\n', src # dbg
60 60 return src
61 61
62 62 #-----------------------------------------------------------------------------
63 63 # Test utilities, just for local use
64 64 #-----------------------------------------------------------------------------
65 65
66 66 def assemble(block):
67 67 """Assemble a block into multi-line sub-blocks."""
68 68 return ['\n'.join(sub_block)+'\n' for sub_block in block]
69 69
70 70
71 71 def pseudo_input(lines):
72 72 """Return a function that acts like raw_input but feeds the input list."""
73 73 ilines = iter(lines)
74 74 def raw_in(prompt):
75 75 try:
76 76 return next(ilines)
77 77 except StopIteration:
78 78 return ''
79 79 return raw_in
80 80
81 81 #-----------------------------------------------------------------------------
82 82 # Tests
83 83 #-----------------------------------------------------------------------------
84 84 def test_spaces():
85 85 tests = [('', 0),
86 86 (' ', 1),
87 87 ('\n', 0),
88 88 (' \n', 1),
89 89 ('x', 0),
90 90 (' x', 1),
91 91 (' x',2),
92 92 (' x',4),
93 93 # Note: tabs are counted as a single whitespace!
94 94 ('\tx', 1),
95 95 ('\t x', 2),
96 96 ]
97 97 tt.check_pairs(isp.num_ini_spaces, tests)
98 98
99 99
100 100 def test_remove_comments():
101 101 tests = [('text', 'text'),
102 102 ('text # comment', 'text '),
103 103 ('text # comment\n', 'text \n'),
104 104 ('text # comment \n', 'text \n'),
105 105 ('line # c \nline\n','line \nline\n'),
106 106 ('line # c \nline#c2 \nline\nline #c\n\n',
107 107 'line \nline\nline\nline \n\n'),
108 108 ]
109 109 tt.check_pairs(isp.remove_comments, tests)
110 110
111 111 def test_has_comment():
112 112 tests = [('text', False),
113 113 ('text #comment', True),
114 114 ('text #comment\n', True),
115 115 ('#comment', True),
116 116 ('#comment\n', True),
117 117 ('a = "#string"', False),
118 118 ('a = "#string" # comment', True),
119 119 ('a #comment not "string"', True),
120 120 ]
121 121 tt.check_pairs(isp.has_comment, tests)
122 122
123 123
124 124 def test_get_input_encoding():
125 125 encoding = isp.get_input_encoding()
126 126 nt.assert_true(isinstance(encoding, basestring))
127 127 # simple-minded check that at least encoding a simple string works with the
128 128 # encoding we got.
129 129 nt.assert_equal(u'test'.encode(encoding), b'test')
130 130
131 131
132 132 class NoInputEncodingTestCase(unittest.TestCase):
133 133 def setUp(self):
134 134 self.old_stdin = sys.stdin
135 135 class X: pass
136 136 fake_stdin = X()
137 137 sys.stdin = fake_stdin
138 138
139 139 def test(self):
140 140 # Verify that if sys.stdin has no 'encoding' attribute we do the right
141 141 # thing
142 142 enc = isp.get_input_encoding()
143 143 self.assertEqual(enc, 'ascii')
144 144
145 145 def tearDown(self):
146 146 sys.stdin = self.old_stdin
147 147
148 148
149 149 class InputSplitterTestCase(unittest.TestCase):
150 150 def setUp(self):
151 151 self.isp = isp.InputSplitter()
152 152
153 153 def test_reset(self):
154 154 isp = self.isp
155 155 isp.push('x=1')
156 156 isp.reset()
157 157 self.assertEqual(isp._buffer, [])
158 158 self.assertEqual(isp.indent_spaces, 0)
159 159 self.assertEqual(isp.source, '')
160 160 self.assertEqual(isp.code, None)
161 161 self.assertEqual(isp._is_complete, False)
162 162
163 163 def test_source(self):
164 164 self.isp._store('1')
165 165 self.isp._store('2')
166 166 self.assertEqual(self.isp.source, '1\n2\n')
167 167 self.assertTrue(len(self.isp._buffer)>0)
168 168 self.assertEqual(self.isp.source_reset(), '1\n2\n')
169 169 self.assertEqual(self.isp._buffer, [])
170 170 self.assertEqual(self.isp.source, '')
171 171
172 172 def test_indent(self):
173 173 isp = self.isp # shorthand
174 174 isp.push('x=1')
175 175 self.assertEqual(isp.indent_spaces, 0)
176 176 isp.push('if 1:\n x=1')
177 177 self.assertEqual(isp.indent_spaces, 4)
178 178 isp.push('y=2\n')
179 179 self.assertEqual(isp.indent_spaces, 0)
180 180
181 181 def test_indent2(self):
182 182 # In cell mode, inputs must be fed in whole blocks, so skip this test
183 183 if self.isp.input_mode == 'cell': return
184 184
185 185 isp = self.isp
186 186 isp.push('if 1:')
187 187 self.assertEqual(isp.indent_spaces, 4)
188 188 isp.push(' x=1')
189 189 self.assertEqual(isp.indent_spaces, 4)
190 190 # Blank lines shouldn't change the indent level
191 191 isp.push(' '*2)
192 192 self.assertEqual(isp.indent_spaces, 4)
193 193
194 194 def test_indent3(self):
195 195 # In cell mode, inputs must be fed in whole blocks, so skip this test
196 196 if self.isp.input_mode == 'cell': return
197 197
198 198 isp = self.isp
199 199 # When a multiline statement contains parens or multiline strings, we
200 200 # shouldn't get confused.
201 201 isp.push("if 1:")
202 202 isp.push(" x = (1+\n 2)")
203 203 self.assertEqual(isp.indent_spaces, 4)
204 204
205 205 def test_indent4(self):
206 206 # In cell mode, inputs must be fed in whole blocks, so skip this test
207 207 if self.isp.input_mode == 'cell': return
208 208
209 209 isp = self.isp
210 210 # whitespace after ':' should not screw up indent level
211 211 isp.push('if 1: \n x=1')
212 212 self.assertEqual(isp.indent_spaces, 4)
213 213 isp.push('y=2\n')
214 214 self.assertEqual(isp.indent_spaces, 0)
215 215 isp.push('if 1:\t\n x=1')
216 216 self.assertEqual(isp.indent_spaces, 4)
217 217 isp.push('y=2\n')
218 218 self.assertEqual(isp.indent_spaces, 0)
219 219
220 220 def test_dedent_pass(self):
221 221 isp = self.isp # shorthand
222 222 # should NOT cause dedent
223 223 isp.push('if 1:\n passes = 5')
224 224 self.assertEqual(isp.indent_spaces, 4)
225 225 isp.push('if 1:\n pass')
226 226 self.assertEqual(isp.indent_spaces, 0)
227 227 isp.push('if 1:\n pass ')
228 228 self.assertEqual(isp.indent_spaces, 0)
229 229
230 230 def test_dedent_raise(self):
231 231 isp = self.isp # shorthand
232 232 # should NOT cause dedent
233 233 isp.push('if 1:\n raised = 4')
234 234 self.assertEqual(isp.indent_spaces, 4)
235 235 isp.push('if 1:\n raise TypeError()')
236 236 self.assertEqual(isp.indent_spaces, 0)
237 237 isp.push('if 1:\n raise')
238 238 self.assertEqual(isp.indent_spaces, 0)
239 239 isp.push('if 1:\n raise ')
240 240 self.assertEqual(isp.indent_spaces, 0)
241 241
242 242 def test_dedent_return(self):
243 243 isp = self.isp # shorthand
244 244 # should NOT cause dedent
245 245 isp.push('if 1:\n returning = 4')
246 246 self.assertEqual(isp.indent_spaces, 4)
247 247 isp.push('if 1:\n return 5 + 493')
248 248 self.assertEqual(isp.indent_spaces, 0)
249 249 isp.push('if 1:\n return')
250 250 self.assertEqual(isp.indent_spaces, 0)
251 251 isp.push('if 1:\n return ')
252 252 self.assertEqual(isp.indent_spaces, 0)
253 253 isp.push('if 1:\n return(0)')
254 254 self.assertEqual(isp.indent_spaces, 0)
255 255
256 256 def test_push(self):
257 257 isp = self.isp
258 258 self.assertTrue(isp.push('x=1'))
259 259
260 260 def test_push2(self):
261 261 isp = self.isp
262 262 self.assertFalse(isp.push('if 1:'))
263 263 for line in [' x=1', '# a comment', ' y=2']:
264 264 self.assertTrue(isp.push(line))
265 265
266 266 def test_push3(self):
267 267 isp = self.isp
268 268 isp.push('if True:')
269 269 isp.push(' a = 1')
270 270 self.assertFalse(isp.push('b = [1,'))
271 271
272 272 def test_replace_mode(self):
273 273 isp = self.isp
274 274 isp.input_mode = 'cell'
275 275 isp.push('x=1')
276 276 self.assertEqual(isp.source, 'x=1\n')
277 277 isp.push('x=2')
278 278 self.assertEqual(isp.source, 'x=2\n')
279 279
280 280 def test_push_accepts_more(self):
281 281 isp = self.isp
282 282 isp.push('x=1')
283 283 self.assertFalse(isp.push_accepts_more())
284 284
285 285 def test_push_accepts_more2(self):
286 286 # In cell mode, inputs must be fed in whole blocks, so skip this test
287 287 if self.isp.input_mode == 'cell': return
288 288
289 289 isp = self.isp
290 290 isp.push('if 1:')
291 291 self.assertTrue(isp.push_accepts_more())
292 292 isp.push(' x=1')
293 293 self.assertTrue(isp.push_accepts_more())
294 294 isp.push('')
295 295 self.assertFalse(isp.push_accepts_more())
296 296
297 297 def test_push_accepts_more3(self):
298 298 isp = self.isp
299 299 isp.push("x = (2+\n3)")
300 300 self.assertFalse(isp.push_accepts_more())
301 301
302 302 def test_push_accepts_more4(self):
303 303 # In cell mode, inputs must be fed in whole blocks, so skip this test
304 304 if self.isp.input_mode == 'cell': return
305 305
306 306 isp = self.isp
307 307 # When a multiline statement contains parens or multiline strings, we
308 308 # shouldn't get confused.
309 309 # FIXME: we should be able to better handle de-dents in statements like
310 310 # multiline strings and multiline expressions (continued with \ or
311 311 # parens). Right now we aren't handling the indentation tracking quite
312 312 # correctly with this, though in practice it may not be too much of a
313 313 # problem. We'll need to see.
314 314 isp.push("if 1:")
315 315 isp.push(" x = (2+")
316 316 isp.push(" 3)")
317 317 self.assertTrue(isp.push_accepts_more())
318 318 isp.push(" y = 3")
319 319 self.assertTrue(isp.push_accepts_more())
320 320 isp.push('')
321 321 self.assertFalse(isp.push_accepts_more())
322 322
323 323 def test_push_accepts_more5(self):
324 324 # In cell mode, inputs must be fed in whole blocks, so skip this test
325 325 if self.isp.input_mode == 'cell': return
326 326
327 327 isp = self.isp
328 328 isp.push('try:')
329 329 isp.push(' a = 5')
330 330 isp.push('except:')
331 331 isp.push(' raise')
332 332 self.assertTrue(isp.push_accepts_more())
333 333
334 334 def test_continuation(self):
335 335 isp = self.isp
336 336 isp.push("import os, \\")
337 337 self.assertTrue(isp.push_accepts_more())
338 338 isp.push("sys")
339 339 self.assertFalse(isp.push_accepts_more())
340 340
341 341 def test_syntax_error(self):
342 342 isp = self.isp
343 343 # Syntax errors immediately produce a 'ready' block, so the invalid
344 344 # Python can be sent to the kernel for evaluation with possible ipython
345 345 # special-syntax conversion.
346 346 isp.push('run foo')
347 347 self.assertFalse(isp.push_accepts_more())
348 348
349 349 def test_unicode(self):
350 350 self.isp.push(u"PΓ©rez")
351 351 self.isp.push(u'\xc3\xa9')
352 352 self.isp.push(u"u'\xc3\xa9'")
353 353
354 354 class InteractiveLoopTestCase(unittest.TestCase):
355 355 """Tests for an interactive loop like a python shell.
356 356 """
357 357 def check_ns(self, lines, ns):
358 358 """Validate that the given input lines produce the resulting namespace.
359 359
360 360 Note: the input lines are given exactly as they would be typed in an
361 361 auto-indenting environment, as mini_interactive_loop above already does
362 362 auto-indenting and prepends spaces to the input.
363 363 """
364 364 src = mini_interactive_loop(pseudo_input(lines))
365 365 test_ns = {}
366 366 exec src in test_ns
367 367 # We can't check that the provided ns is identical to the test_ns,
368 368 # because Python fills test_ns with extra keys (copyright, etc). But
369 369 # we can check that the given dict is *contained* in test_ns
370 370 for k,v in ns.iteritems():
371 371 self.assertEqual(test_ns[k], v)
372 372
373 373 def test_simple(self):
374 374 self.check_ns(['x=1'], dict(x=1))
375 375
376 376 def test_simple2(self):
377 377 self.check_ns(['if 1:', 'x=2'], dict(x=2))
378 378
379 379 def test_xy(self):
380 380 self.check_ns(['x=1; y=2'], dict(x=1, y=2))
381 381
382 382 def test_abc(self):
383 383 self.check_ns(['if 1:','a=1','b=2','c=3'], dict(a=1, b=2, c=3))
384 384
385 385 def test_multi(self):
386 386 self.check_ns(['x =(1+','1+','2)'], dict(x=4))
387 387
388 388
389 389 def test_LineInfo():
390 390 """Simple test for LineInfo construction and str()"""
391 391 linfo = isp.LineInfo(' %cd /home')
392 392 nt.assert_equals(str(linfo), 'LineInfo [ |%|cd|/home]')
393 393
394 394 # Transformer tests
395 395 def transform_checker(tests, func):
396 396 """Utility to loop over test inputs"""
397 397 for inp, tr in tests:
398 398 nt.assert_equals(func(inp), tr)
399 399
400 400 # Data for all the syntax tests in the form of lists of pairs of
401 401 # raw/transformed input. We store it here as a global dict so that we can use
402 402 # it both within single-function tests and also to validate the behavior of the
403 403 # larger objects
404 404
405 405 syntax = \
406 406 dict(assign_system =
407 407 [(i,py3compat.u_format(o)) for i,o in \
408 408 [(u'a =! ls', "a = get_ipython().getoutput({u}'ls')"),
409 409 (u'b = !ls', "b = get_ipython().getoutput({u}'ls')"),
410 410 ('x=1', 'x=1'), # normal input is unmodified
411 411 (' ',' '), # blank lines are kept intact
412 412 ]],
413 413
414 414 assign_magic =
415 415 [(i,py3compat.u_format(o)) for i,o in \
416 416 [(u'a =% who', "a = get_ipython().magic({u}'who')"),
417 417 (u'b = %who', "b = get_ipython().magic({u}'who')"),
418 418 ('x=1', 'x=1'), # normal input is unmodified
419 419 (' ',' '), # blank lines are kept intact
420 420 ]],
421 421
422 422 classic_prompt =
423 423 [('>>> x=1', 'x=1'),
424 424 ('x=1', 'x=1'), # normal input is unmodified
425 425 (' ', ' '), # blank lines are kept intact
426 426 ('... ', ''), # continuation prompts
427 427 ],
428 428
429 429 ipy_prompt =
430 430 [('In [1]: x=1', 'x=1'),
431 431 ('x=1', 'x=1'), # normal input is unmodified
432 432 (' ',' '), # blank lines are kept intact
433 433 (' ....: ', ''), # continuation prompts
434 434 ],
435 435
436 436 # Tests for the escape transformer to leave normal code alone
437 437 escaped_noesc =
438 438 [ (' ', ' '),
439 439 ('x=1', 'x=1'),
440 440 ],
441 441
442 442 # System calls
443 443 escaped_shell =
444 444 [(i,py3compat.u_format(o)) for i,o in \
445 445 [ (u'!ls', "get_ipython().system({u}'ls')"),
446 446 # Double-escape shell, this means to capture the output of the
447 447 # subprocess and return it
448 448 (u'!!ls', "get_ipython().getoutput({u}'ls')"),
449 449 ]],
450 450
451 451 # Help/object info
452 452 escaped_help =
453 453 [(i,py3compat.u_format(o)) for i,o in \
454 454 [ (u'?', 'get_ipython().show_usage()'),
455 455 (u'?x1', "get_ipython().magic({u}'pinfo x1')"),
456 456 (u'??x2', "get_ipython().magic({u}'pinfo2 x2')"),
457 457 (u'?a.*s', "get_ipython().magic({u}'psearch a.*s')"),
458 458 (u'?%hist1', "get_ipython().magic({u}'pinfo %hist1')"),
459 459 (u'?%%hist2', "get_ipython().magic({u}'pinfo %%hist2')"),
460 460 (u'?abc = qwe', "get_ipython().magic({u}'pinfo abc')"),
461 461 ]],
462 462
463 463 end_help =
464 464 [(i,py3compat.u_format(o)) for i,o in \
465 465 [ (u'x3?', "get_ipython().magic({u}'pinfo x3')"),
466 466 (u'x4??', "get_ipython().magic({u}'pinfo2 x4')"),
467 467 (u'%hist1?', "get_ipython().magic({u}'pinfo %hist1')"),
468 468 (u'%hist2??', "get_ipython().magic({u}'pinfo2 %hist2')"),
469 469 (u'%%hist3?', "get_ipython().magic({u}'pinfo %%hist3')"),
470 470 (u'%%hist4??', "get_ipython().magic({u}'pinfo2 %%hist4')"),
471 471 (u'f*?', "get_ipython().magic({u}'psearch f*')"),
472 472 (u'ax.*aspe*?', "get_ipython().magic({u}'psearch ax.*aspe*')"),
473 473 (u'a = abc?', "get_ipython().set_next_input({u}'a = abc');"
474 474 "get_ipython().magic({u}'pinfo abc')"),
475 475 (u'a = abc.qe??', "get_ipython().set_next_input({u}'a = abc.qe');"
476 476 "get_ipython().magic({u}'pinfo2 abc.qe')"),
477 477 (u'a = *.items?', "get_ipython().set_next_input({u}'a = *.items');"
478 478 "get_ipython().magic({u}'psearch *.items')"),
479 479 (u'plot(a?', "get_ipython().set_next_input({u}'plot(a');"
480 480 "get_ipython().magic({u}'pinfo a')"),
481 481 (u'a*2 #comment?', 'a*2 #comment?'),
482 482 ]],
483 483
484 484 # Explicit magic calls
485 485 escaped_magic =
486 486 [(i,py3compat.u_format(o)) for i,o in \
487 487 [ (u'%cd', "get_ipython().magic({u}'cd')"),
488 488 (u'%cd /home', "get_ipython().magic({u}'cd /home')"),
489 489 # Backslashes need to be escaped.
490 490 (u'%cd C:\\User', "get_ipython().magic({u}'cd C:\\\\User')"),
491 491 (u' %magic', " get_ipython().magic({u}'magic')"),
492 492 ]],
493 493
494 494 # Quoting with separate arguments
495 495 escaped_quote =
496 496 [ (',f', 'f("")'),
497 497 (',f x', 'f("x")'),
498 498 (' ,f y', ' f("y")'),
499 499 (',f a b', 'f("a", "b")'),
500 500 ],
501 501
502 502 # Quoting with single argument
503 503 escaped_quote2 =
504 504 [ (';f', 'f("")'),
505 505 (';f x', 'f("x")'),
506 506 (' ;f y', ' f("y")'),
507 507 (';f a b', 'f("a b")'),
508 508 ],
509 509
510 510 # Simply apply parens
511 511 escaped_paren =
512 512 [ ('/f', 'f()'),
513 513 ('/f x', 'f(x)'),
514 514 (' /f y', ' f(y)'),
515 515 ('/f a b', 'f(a, b)'),
516 516 ],
517 517
518 518 # Check that we transform prompts before other transforms
519 519 mixed =
520 520 [(i,py3compat.u_format(o)) for i,o in \
521 521 [ (u'In [1]: %lsmagic', "get_ipython().magic({u}'lsmagic')"),
522 522 (u'>>> %lsmagic', "get_ipython().magic({u}'lsmagic')"),
523 523 (u'In [2]: !ls', "get_ipython().system({u}'ls')"),
524 524 (u'In [3]: abs?', "get_ipython().magic({u}'pinfo abs')"),
525 525 (u'In [4]: b = %who', "b = get_ipython().magic({u}'who')"),
526 526 ]],
527 527 )
528 528
529 529 # multiline syntax examples. Each of these should be a list of lists, with
530 530 # each entry itself having pairs of raw/transformed input. The union (with
531 531 # '\n'.join() of the transformed inputs is what the splitter should produce
532 532 # when fed the raw lines one at a time via push.
533 533 syntax_ml = \
534 534 dict(classic_prompt =
535 535 [ [('>>> for i in range(10):','for i in range(10):'),
536 536 ('... print i',' print i'),
537 537 ('... ', ''),
538 538 ],
539 539 ],
540 540
541 541 ipy_prompt =
542 542 [ [('In [24]: for i in range(10):','for i in range(10):'),
543 543 (' ....: print i',' print i'),
544 544 (' ....: ', ''),
545 545 ],
546 546 ],
547 547
548 548 multiline_datastructure =
549 549 [ [('>>> a = [1,','a = [1,'),
550 550 ('... 2]','2]'),
551 551 ],
552 552 ],
553 553 )
554 554
555 555
556 556 def test_assign_system():
557 557 tt.check_pairs(isp.transform_assign_system, syntax['assign_system'])
558 558
559 559
560 560 def test_assign_magic():
561 561 tt.check_pairs(isp.transform_assign_magic, syntax['assign_magic'])
562 562
563 563
564 564 def test_classic_prompt():
565 565 transform_checker(syntax['classic_prompt'], isp.transform_classic_prompt)
566 566 for example in syntax_ml['classic_prompt']:
567 567 transform_checker(example, isp.transform_classic_prompt)
568 568
569 569
570 570 def test_ipy_prompt():
571 571 transform_checker(syntax['ipy_prompt'], isp.transform_ipy_prompt)
572 572 for example in syntax_ml['ipy_prompt']:
573 573 transform_checker(example, isp.transform_ipy_prompt)
574 574
575 575 def test_end_help():
576 576 tt.check_pairs(isp.transform_help_end, syntax['end_help'])
577 577
578 578 def test_escaped_noesc():
579 579 tt.check_pairs(isp.transform_escaped, syntax['escaped_noesc'])
580 580
581 581
582 582 def test_escaped_shell():
583 583 tt.check_pairs(isp.transform_escaped, syntax['escaped_shell'])
584 584
585 585
586 586 def test_escaped_help():
587 587 tt.check_pairs(isp.transform_escaped, syntax['escaped_help'])
588 588
589 589
590 590 def test_escaped_magic():
591 591 tt.check_pairs(isp.transform_escaped, syntax['escaped_magic'])
592 592
593 593
594 594 def test_escaped_quote():
595 595 tt.check_pairs(isp.transform_escaped, syntax['escaped_quote'])
596 596
597 597
598 598 def test_escaped_quote2():
599 599 tt.check_pairs(isp.transform_escaped, syntax['escaped_quote2'])
600 600
601 601
602 602 def test_escaped_paren():
603 603 tt.check_pairs(isp.transform_escaped, syntax['escaped_paren'])
604 604
605 605
606 606 class IPythonInputTestCase(InputSplitterTestCase):
607 607 """By just creating a new class whose .isp is a different instance, we
608 608 re-run the same test battery on the new input splitter.
609 609
610 610 In addition, this runs the tests over the syntax and syntax_ml dicts that
611 611 were tested by individual functions, as part of the OO interface.
612 612
613 613 It also makes some checks on the raw buffer storage.
614 614 """
615 615
616 616 def setUp(self):
617 617 self.isp = isp.IPythonInputSplitter(input_mode='line')
618 618
619 619 def test_syntax(self):
620 620 """Call all single-line syntax tests from the main object"""
621 621 isp = self.isp
622 622 for example in syntax.itervalues():
623 623 for raw, out_t in example:
624 624 if raw.startswith(' '):
625 625 continue
626 626
627 627 isp.push(raw+'\n')
628 628 out, out_raw = isp.source_raw_reset()
629 629 self.assertEqual(out.rstrip(), out_t,
630 630 tt.pair_fail_msg.format("inputsplitter",raw, out_t, out))
631 631 self.assertEqual(out_raw.rstrip(), raw.rstrip())
632 632
633 633 def test_syntax_multiline(self):
634 634 isp = self.isp
635 635 for example in syntax_ml.itervalues():
636 636 out_t_parts = []
637 637 raw_parts = []
638 638 for line_pairs in example:
639 639 for lraw, out_t_part in line_pairs:
640 640 isp.push(lraw)
641 641 out_t_parts.append(out_t_part)
642 642 raw_parts.append(lraw)
643 643
644 644 out, out_raw = isp.source_raw_reset()
645 645 out_t = '\n'.join(out_t_parts).rstrip()
646 646 raw = '\n'.join(raw_parts).rstrip()
647 647 self.assertEqual(out.rstrip(), out_t)
648 648 self.assertEqual(out_raw.rstrip(), raw)
649 649
650 650
651 651 class BlockIPythonInputTestCase(IPythonInputTestCase):
652 652
653 653 # Deactivate tests that don't make sense for the block mode
654 654 test_push3 = test_split = lambda s: None
655 655
656 656 def setUp(self):
657 657 self.isp = isp.IPythonInputSplitter(input_mode='cell')
658 658
659 659 def test_syntax_multiline(self):
660 660 isp = self.isp
661 661 for example in syntax_ml.itervalues():
662 662 raw_parts = []
663 663 out_t_parts = []
664 664 for line_pairs in example:
665 665 for raw, out_t_part in line_pairs:
666 666 raw_parts.append(raw)
667 667 out_t_parts.append(out_t_part)
668 668
669 669 raw = '\n'.join(raw_parts)
670 670 out_t = '\n'.join(out_t_parts)
671 671
672 672 isp.push(raw)
673 673 out, out_raw = isp.source_raw_reset()
674 674 # Match ignoring trailing whitespace
675 675 self.assertEqual(out.rstrip(), out_t.rstrip())
676 676 self.assertEqual(out_raw.rstrip(), raw.rstrip())
677 677
678 def test_syntax_multiline_cell(self):
679 isp = self.isp
680 for example in syntax_ml.itervalues():
681
682 out_t_parts = []
683 for line_pairs in example:
684 raw = '\n'.join(r for r, _ in line_pairs)
685 out_t = '\n'.join(t for _,t in line_pairs)
686 out = isp.transform_cell(raw)
687 # Match ignoring trailing whitespace
688 self.assertEqual(out.rstrip(), out_t.rstrip())
678 689
679 690 #-----------------------------------------------------------------------------
680 691 # Main - use as a script, mostly for developer experiments
681 692 #-----------------------------------------------------------------------------
682 693
683 694 if __name__ == '__main__':
684 695 # A simple demo for interactive experimentation. This code will not get
685 696 # picked up by any test suite.
686 697 from IPython.core.inputsplitter import InputSplitter, IPythonInputSplitter
687 698
688 699 # configure here the syntax to use, prompt and whether to autoindent
689 700 #isp, start_prompt = InputSplitter(), '>>> '
690 701 isp, start_prompt = IPythonInputSplitter(), 'In> '
691 702
692 703 autoindent = True
693 704 #autoindent = False
694 705
695 706 try:
696 707 while True:
697 708 prompt = start_prompt
698 709 while isp.push_accepts_more():
699 710 indent = ' '*isp.indent_spaces
700 711 if autoindent:
701 712 line = indent + raw_input(prompt+indent)
702 713 else:
703 714 line = raw_input(prompt)
704 715 isp.push(line)
705 716 prompt = '... '
706 717
707 718 # Here we just return input so we can use it in a test suite, but a
708 719 # real interpreter would instead send it for execution somewhere.
709 720 #src = isp.source; raise EOFError # dbg
710 721 src, raw = isp.source_raw_reset()
711 722 print 'Input source was:\n', src
712 723 print 'Raw source was:\n', raw
713 724 except EOFError:
714 725 print 'Bye'
715 726
716 727 # Tests for cell magics support
717 728
718 729 def test_last_blank():
719 730 nt.assert_false(isp.last_blank(''))
720 731 nt.assert_false(isp.last_blank('abc'))
721 732 nt.assert_false(isp.last_blank('abc\n'))
722 733 nt.assert_false(isp.last_blank('abc\na'))
723 734
724 735 nt.assert_true(isp.last_blank('\n'))
725 736 nt.assert_true(isp.last_blank('\n '))
726 737 nt.assert_true(isp.last_blank('abc\n '))
727 738 nt.assert_true(isp.last_blank('abc\n\n'))
728 739 nt.assert_true(isp.last_blank('abc\nd\n\n'))
729 740 nt.assert_true(isp.last_blank('abc\nd\ne\n\n'))
730 741 nt.assert_true(isp.last_blank('abc \n \n \n\n'))
731 742
732 743
733 744 def test_last_two_blanks():
734 745 nt.assert_false(isp.last_two_blanks(''))
735 746 nt.assert_false(isp.last_two_blanks('abc'))
736 747 nt.assert_false(isp.last_two_blanks('abc\n'))
737 748 nt.assert_false(isp.last_two_blanks('abc\n\na'))
738 749 nt.assert_false(isp.last_two_blanks('abc\n \n'))
739 750 nt.assert_false(isp.last_two_blanks('abc\n\n'))
740 751
741 752 nt.assert_true(isp.last_two_blanks('\n\n'))
742 753 nt.assert_true(isp.last_two_blanks('\n\n '))
743 754 nt.assert_true(isp.last_two_blanks('\n \n'))
744 755 nt.assert_true(isp.last_two_blanks('abc\n\n '))
745 756 nt.assert_true(isp.last_two_blanks('abc\n\n\n'))
746 757 nt.assert_true(isp.last_two_blanks('abc\n\n \n'))
747 758 nt.assert_true(isp.last_two_blanks('abc\n\n \n '))
748 759 nt.assert_true(isp.last_two_blanks('abc\n\n \n \n'))
749 760 nt.assert_true(isp.last_two_blanks('abc\nd\n\n\n'))
750 761 nt.assert_true(isp.last_two_blanks('abc\nd\ne\nf\n\n\n'))
751 762
752 763
753 764 class CellMagicsCommon(object):
754 765
755 766 def test_whole_cell(self):
756 767 src = "%%cellm line\nbody\n"
757 768 sp = self.sp
758 769 sp.push(src)
759 770 nt.assert_equal(sp.cell_magic_parts, ['body\n'])
760 771 out = sp.source
761 772 ref = u"get_ipython()._run_cached_cell_magic({u}'cellm', {u}'line')\n"
762 773 nt.assert_equal(out, py3compat.u_format(ref))
763 774
764 775 def tearDown(self):
765 776 self.sp.reset()
766 777
767 778
768 779 class CellModeCellMagics(CellMagicsCommon, unittest.TestCase):
769 780 sp = isp.IPythonInputSplitter(input_mode='cell')
770 781
771 782 def test_incremental(self):
772 783 sp = self.sp
773 784 src = '%%cellm line2\n'
774 785 sp.push(src)
775 786 nt.assert_true(sp.push_accepts_more()) #1
776 787 src += '\n'
777 788 sp.push(src)
778 789 # Note: if we ever change the logic to allow full blank lines (see
779 790 # _handle_cell_magic), then the following test should change to true
780 791 nt.assert_false(sp.push_accepts_more()) #2
781 792 # By now, even with full blanks allowed, a second blank should signal
782 793 # the end. For now this test is only a redundancy safety, but don't
783 794 # delete it in case we change our mind and the previous one goes to
784 795 # true.
785 796 src += '\n'
786 797 sp.push(src)
787 798 nt.assert_false(sp.push_accepts_more()) #3
788 799
789 800
790 801 class LineModeCellMagics(CellMagicsCommon, unittest.TestCase):
791 802 sp = isp.IPythonInputSplitter(input_mode='line')
792 803
793 804 def test_incremental(self):
794 805 sp = self.sp
795 806 sp.push('%%cellm line2\n')
796 807 nt.assert_true(sp.push_accepts_more()) #1
797 808 sp.push('\n')
798 809 nt.assert_false(sp.push_accepts_more()) #2
General Comments 0
You need to be logged in to leave comments. Login now