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