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