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