##// END OF EJS Templates
Rewrite bunch of `raise AssertionError` and `assert False` tests
Nikita Kniazev -
Show More
@@ -1,73 +1,71 b''
1 1 # coding: utf-8
2 2 """Tests for the compilerop module.
3 3 """
4 4 #-----------------------------------------------------------------------------
5 5 # Copyright (C) 2010-2011 The IPython Development Team.
6 6 #
7 7 # Distributed under the terms of the BSD License.
8 8 #
9 9 # The full license is in the file COPYING.txt, distributed with this software.
10 10 #-----------------------------------------------------------------------------
11 11
12 12 #-----------------------------------------------------------------------------
13 13 # Imports
14 14 #-----------------------------------------------------------------------------
15 15
16 16 # Stdlib imports
17 17 import linecache
18 18 import sys
19 19
20 20 # Third-party imports
21 21 import pytest
22 22
23 23 # Our own imports
24 24 from IPython.core import compilerop
25 25
26 26 #-----------------------------------------------------------------------------
27 27 # Test functions
28 28 #-----------------------------------------------------------------------------
29 29
30 30 def test_code_name():
31 31 code = 'x=1'
32 32 name = compilerop.code_name(code)
33 33 assert name.startswith("<ipython-input-0")
34 34
35 35
36 36 def test_code_name2():
37 37 code = 'x=1'
38 38 name = compilerop.code_name(code, 9)
39 39 assert name.startswith("<ipython-input-9")
40 40
41 41
42 42 def test_cache():
43 43 """Test the compiler correctly compiles and caches inputs
44 44 """
45 45 cp = compilerop.CachingCompiler()
46 46 ncache = len(linecache.cache)
47 47 cp.cache('x=1')
48 48 assert len(linecache.cache) > ncache
49 49
50 50 def test_proper_default_encoding():
51 51 # Check we're in a proper Python 2 environment (some imports, such
52 52 # as GTK, can change the default encoding, which can hide bugs.)
53 53 assert sys.getdefaultencoding() == "utf-8"
54 54
55 55 def test_cache_unicode():
56 56 cp = compilerop.CachingCompiler()
57 57 ncache = len(linecache.cache)
58 58 cp.cache(u"t = 'žćčőđ'")
59 59 assert len(linecache.cache) > ncache
60 60
61 61 def test_compiler_check_cache():
62 62 """Test the compiler properly manages the cache.
63 63 """
64 64 # Rather simple-minded tests that just exercise the API
65 65 cp = compilerop.CachingCompiler()
66 66 cp.cache('x=1', 99)
67 67 # Ensure now that after clearing the cache, our entries survive
68 68 linecache.checkcache()
69 for k in linecache.cache:
70 if k.startswith('<ipython-input-99'):
71 break
72 else:
73 raise AssertionError('Entry for input-99 missing from linecache')
69 assert any(
70 k.startswith("<ipython-input-99") for k in linecache.cache
71 ), "Entry for input-99 missing from linecache"
@@ -1,580 +1,578 b''
1 1 """Tests for debugging machinery.
2 2 """
3 3
4 4 # Copyright (c) IPython Development Team.
5 5 # Distributed under the terms of the Modified BSD License.
6 6
7 7 import bdb
8 8 import builtins
9 9 import os
10 10 import signal
11 11 import subprocess
12 12 import sys
13 13 import time
14 14 import warnings
15 15
16 16 from subprocess import PIPE, CalledProcessError, check_output
17 17 from tempfile import NamedTemporaryFile
18 18 from textwrap import dedent
19 19 from unittest.mock import patch
20 20
21 21 from IPython.core import debugger
22 22 from IPython.testing import IPYTHON_TESTING_TIMEOUT_SCALE
23 23 from IPython.testing.decorators import skip_win32
24 24
25 25 #-----------------------------------------------------------------------------
26 26 # Helper classes, from CPython's Pdb test suite
27 27 #-----------------------------------------------------------------------------
28 28
29 29 class _FakeInput(object):
30 30 """
31 31 A fake input stream for pdb's interactive debugger. Whenever a
32 32 line is read, print it (to simulate the user typing it), and then
33 33 return it. The set of lines to return is specified in the
34 34 constructor; they should not have trailing newlines.
35 35 """
36 36 def __init__(self, lines):
37 37 self.lines = iter(lines)
38 38
39 39 def readline(self):
40 40 line = next(self.lines)
41 41 print(line)
42 42 return line+'\n'
43 43
44 44 class PdbTestInput(object):
45 45 """Context manager that makes testing Pdb in doctests easier."""
46 46
47 47 def __init__(self, input):
48 48 self.input = input
49 49
50 50 def __enter__(self):
51 51 self.real_stdin = sys.stdin
52 52 sys.stdin = _FakeInput(self.input)
53 53
54 54 def __exit__(self, *exc):
55 55 sys.stdin = self.real_stdin
56 56
57 57 #-----------------------------------------------------------------------------
58 58 # Tests
59 59 #-----------------------------------------------------------------------------
60 60
61 61 def test_longer_repr():
62 62 from reprlib import repr as trepr
63 63
64 64 a = '1234567890'* 7
65 65 ar = "'1234567890123456789012345678901234567890123456789012345678901234567890'"
66 66 a_trunc = "'123456789012...8901234567890'"
67 67 assert trepr(a) == a_trunc
68 68 # The creation of our tracer modifies the repr module's repr function
69 69 # in-place, since that global is used directly by the stdlib's pdb module.
70 70 with warnings.catch_warnings():
71 71 warnings.simplefilter('ignore', DeprecationWarning)
72 72 debugger.Tracer()
73 73 assert trepr(a) == ar
74 74
75 75 def test_ipdb_magics():
76 76 '''Test calling some IPython magics from ipdb.
77 77
78 78 First, set up some test functions and classes which we can inspect.
79 79
80 80 >>> class ExampleClass(object):
81 81 ... """Docstring for ExampleClass."""
82 82 ... def __init__(self):
83 83 ... """Docstring for ExampleClass.__init__"""
84 84 ... pass
85 85 ... def __str__(self):
86 86 ... return "ExampleClass()"
87 87
88 88 >>> def example_function(x, y, z="hello"):
89 89 ... """Docstring for example_function."""
90 90 ... pass
91 91
92 92 >>> old_trace = sys.gettrace()
93 93
94 94 Create a function which triggers ipdb.
95 95
96 96 >>> def trigger_ipdb():
97 97 ... a = ExampleClass()
98 98 ... debugger.Pdb().set_trace()
99 99
100 100 >>> with PdbTestInput([
101 101 ... 'pdef example_function',
102 102 ... 'pdoc ExampleClass',
103 103 ... 'up',
104 104 ... 'down',
105 105 ... 'list',
106 106 ... 'pinfo a',
107 107 ... 'll',
108 108 ... 'continue',
109 109 ... ]):
110 110 ... trigger_ipdb()
111 111 --Return--
112 112 None
113 113 > <doctest ...>(3)trigger_ipdb()
114 114 1 def trigger_ipdb():
115 115 2 a = ExampleClass()
116 116 ----> 3 debugger.Pdb().set_trace()
117 117 <BLANKLINE>
118 118 ipdb> pdef example_function
119 119 example_function(x, y, z='hello')
120 120 ipdb> pdoc ExampleClass
121 121 Class docstring:
122 122 Docstring for ExampleClass.
123 123 Init docstring:
124 124 Docstring for ExampleClass.__init__
125 125 ipdb> up
126 126 > <doctest ...>(11)<module>()
127 127 7 'pinfo a',
128 128 8 'll',
129 129 9 'continue',
130 130 10 ]):
131 131 ---> 11 trigger_ipdb()
132 132 <BLANKLINE>
133 133 ipdb> down
134 134 None
135 135 > <doctest ...>(3)trigger_ipdb()
136 136 1 def trigger_ipdb():
137 137 2 a = ExampleClass()
138 138 ----> 3 debugger.Pdb().set_trace()
139 139 <BLANKLINE>
140 140 ipdb> list
141 141 1 def trigger_ipdb():
142 142 2 a = ExampleClass()
143 143 ----> 3 debugger.Pdb().set_trace()
144 144 <BLANKLINE>
145 145 ipdb> pinfo a
146 146 Type: ExampleClass
147 147 String form: ExampleClass()
148 148 Namespace: Local...
149 149 Docstring: Docstring for ExampleClass.
150 150 Init docstring: Docstring for ExampleClass.__init__
151 151 ipdb> ll
152 152 1 def trigger_ipdb():
153 153 2 a = ExampleClass()
154 154 ----> 3 debugger.Pdb().set_trace()
155 155 <BLANKLINE>
156 156 ipdb> continue
157 157
158 158 Restore previous trace function, e.g. for coverage.py
159 159
160 160 >>> sys.settrace(old_trace)
161 161 '''
162 162
163 163 def test_ipdb_magics2():
164 164 '''Test ipdb with a very short function.
165 165
166 166 >>> old_trace = sys.gettrace()
167 167
168 168 >>> def bar():
169 169 ... pass
170 170
171 171 Run ipdb.
172 172
173 173 >>> with PdbTestInput([
174 174 ... 'continue',
175 175 ... ]):
176 176 ... debugger.Pdb().runcall(bar)
177 177 > <doctest ...>(2)bar()
178 178 1 def bar():
179 179 ----> 2 pass
180 180 <BLANKLINE>
181 181 ipdb> continue
182 182
183 183 Restore previous trace function, e.g. for coverage.py
184 184
185 185 >>> sys.settrace(old_trace)
186 186 '''
187 187
188 188 def can_quit():
189 189 '''Test that quit work in ipydb
190 190
191 191 >>> old_trace = sys.gettrace()
192 192
193 193 >>> def bar():
194 194 ... pass
195 195
196 196 >>> with PdbTestInput([
197 197 ... 'quit',
198 198 ... ]):
199 199 ... debugger.Pdb().runcall(bar)
200 200 > <doctest ...>(2)bar()
201 201 1 def bar():
202 202 ----> 2 pass
203 203 <BLANKLINE>
204 204 ipdb> quit
205 205
206 206 Restore previous trace function, e.g. for coverage.py
207 207
208 208 >>> sys.settrace(old_trace)
209 209 '''
210 210
211 211
212 212 def can_exit():
213 213 '''Test that quit work in ipydb
214 214
215 215 >>> old_trace = sys.gettrace()
216 216
217 217 >>> def bar():
218 218 ... pass
219 219
220 220 >>> with PdbTestInput([
221 221 ... 'exit',
222 222 ... ]):
223 223 ... debugger.Pdb().runcall(bar)
224 224 > <doctest ...>(2)bar()
225 225 1 def bar():
226 226 ----> 2 pass
227 227 <BLANKLINE>
228 228 ipdb> exit
229 229
230 230 Restore previous trace function, e.g. for coverage.py
231 231
232 232 >>> sys.settrace(old_trace)
233 233 '''
234 234
235 235
236 236 def test_interruptible_core_debugger():
237 237 """The debugger can be interrupted.
238 238
239 239 The presumption is there is some mechanism that causes a KeyboardInterrupt
240 240 (this is implemented in ipykernel). We want to ensure the
241 241 KeyboardInterrupt cause debugging to cease.
242 242 """
243 243 def raising_input(msg="", called=[0]):
244 244 called[0] += 1
245 if called[0] == 1:
246 raise KeyboardInterrupt()
247 else:
248 raise AssertionError("input() should only be called once!")
245 assert called[0] == 1, "input() should only be called once!"
246 raise KeyboardInterrupt()
249 247
250 248 tracer_orig = sys.gettrace()
251 249 try:
252 250 with patch.object(builtins, "input", raising_input):
253 251 debugger.InterruptiblePdb().set_trace()
254 252 # The way this test will fail is by set_trace() never exiting,
255 253 # resulting in a timeout by the test runner. The alternative
256 254 # implementation would involve a subprocess, but that adds issues
257 255 # with interrupting subprocesses that are rather complex, so it's
258 256 # simpler just to do it this way.
259 257 finally:
260 258 # restore the original trace function
261 259 sys.settrace(tracer_orig)
262 260
263 261
264 262 @skip_win32
265 263 def test_xmode_skip():
266 264 """that xmode skip frames
267 265
268 266 Not as a doctest as pytest does not run doctests.
269 267 """
270 268 import pexpect
271 269 env = os.environ.copy()
272 270 env["IPY_TEST_SIMPLE_PROMPT"] = "1"
273 271
274 272 child = pexpect.spawn(
275 273 sys.executable, ["-m", "IPython", "--colors=nocolor"], env=env
276 274 )
277 275 child.timeout = 15 * IPYTHON_TESTING_TIMEOUT_SCALE
278 276
279 277 child.expect("IPython")
280 278 child.expect("\n")
281 279 child.expect_exact("In [1]")
282 280
283 281 block = dedent(
284 282 """
285 283 def f():
286 284 __tracebackhide__ = True
287 285 g()
288 286
289 287 def g():
290 288 raise ValueError
291 289
292 290 f()
293 291 """
294 292 )
295 293
296 294 for line in block.splitlines():
297 295 child.sendline(line)
298 296 child.expect_exact(line)
299 297 child.expect_exact("skipping")
300 298
301 299 block = dedent(
302 300 """
303 301 def f():
304 302 __tracebackhide__ = True
305 303 g()
306 304
307 305 def g():
308 306 from IPython.core.debugger import set_trace
309 307 set_trace()
310 308
311 309 f()
312 310 """
313 311 )
314 312
315 313 for line in block.splitlines():
316 314 child.sendline(line)
317 315 child.expect_exact(line)
318 316
319 317 child.expect("ipdb>")
320 318 child.sendline("w")
321 319 child.expect("hidden")
322 320 child.expect("ipdb>")
323 321 child.sendline("skip_hidden false")
324 322 child.sendline("w")
325 323 child.expect("__traceba")
326 324 child.expect("ipdb>")
327 325
328 326 child.close()
329 327
330 328
331 329 skip_decorators_blocks = (
332 330 """
333 331 def helpers_helper():
334 332 pass # should not stop here except breakpoint
335 333 """,
336 334 """
337 335 def helper_1():
338 336 helpers_helper() # should not stop here
339 337 """,
340 338 """
341 339 def helper_2():
342 340 pass # should not stop here
343 341 """,
344 342 """
345 343 def pdb_skipped_decorator2(function):
346 344 def wrapped_fn(*args, **kwargs):
347 345 __debuggerskip__ = True
348 346 helper_2()
349 347 __debuggerskip__ = False
350 348 result = function(*args, **kwargs)
351 349 __debuggerskip__ = True
352 350 helper_2()
353 351 return result
354 352 return wrapped_fn
355 353 """,
356 354 """
357 355 def pdb_skipped_decorator(function):
358 356 def wrapped_fn(*args, **kwargs):
359 357 __debuggerskip__ = True
360 358 helper_1()
361 359 __debuggerskip__ = False
362 360 result = function(*args, **kwargs)
363 361 __debuggerskip__ = True
364 362 helper_2()
365 363 return result
366 364 return wrapped_fn
367 365 """,
368 366 """
369 367 @pdb_skipped_decorator
370 368 @pdb_skipped_decorator2
371 369 def bar(x, y):
372 370 return x * y
373 371 """,
374 372 """import IPython.terminal.debugger as ipdb""",
375 373 """
376 374 def f():
377 375 ipdb.set_trace()
378 376 bar(3, 4)
379 377 """,
380 378 """
381 379 f()
382 380 """,
383 381 )
384 382
385 383
386 384 def _decorator_skip_setup():
387 385 import pexpect
388 386
389 387 env = os.environ.copy()
390 388 env["IPY_TEST_SIMPLE_PROMPT"] = "1"
391 389
392 390 child = pexpect.spawn(
393 391 sys.executable, ["-m", "IPython", "--colors=nocolor"], env=env
394 392 )
395 393 child.timeout = 5 * IPYTHON_TESTING_TIMEOUT_SCALE
396 394
397 395 child.expect("IPython")
398 396 child.expect("\n")
399 397
400 398 dedented_blocks = [dedent(b).strip() for b in skip_decorators_blocks]
401 399 in_prompt_number = 1
402 400 for cblock in dedented_blocks:
403 401 child.expect_exact(f"In [{in_prompt_number}]:")
404 402 in_prompt_number += 1
405 403 for line in cblock.splitlines():
406 404 child.sendline(line)
407 405 child.expect_exact(line)
408 406 child.sendline("")
409 407 return child
410 408
411 409
412 410 @skip_win32
413 411 def test_decorator_skip():
414 412 """test that decorator frames can be skipped."""
415 413
416 414 child = _decorator_skip_setup()
417 415
418 416 child.expect_exact("3 bar(3, 4)")
419 417 child.expect("ipdb>")
420 418
421 419 child.expect("ipdb>")
422 420 child.sendline("step")
423 421 child.expect_exact("step")
424 422
425 423 child.expect_exact("1 @pdb_skipped_decorator")
426 424
427 425 child.sendline("s")
428 426 child.expect_exact("return x * y")
429 427
430 428 child.close()
431 429
432 430
433 431 @skip_win32
434 432 def test_decorator_skip_disabled():
435 433 """test that decorator frame skipping can be disabled"""
436 434
437 435 child = _decorator_skip_setup()
438 436
439 437 child.expect_exact("3 bar(3, 4)")
440 438
441 439 for input_, expected in [
442 440 ("skip_predicates debuggerskip False", ""),
443 441 ("skip_predicates", "debuggerskip : False"),
444 442 ("step", "---> 2 def wrapped_fn"),
445 443 ("step", "----> 3 __debuggerskip__"),
446 444 ("step", "----> 4 helper_1()"),
447 445 ("step", "---> 1 def helper_1():"),
448 446 ("next", "----> 2 helpers_helper()"),
449 447 ("next", "--Return--"),
450 448 ("next", "----> 5 __debuggerskip__ = False"),
451 449 ]:
452 450 child.expect("ipdb>")
453 451 child.sendline(input_)
454 452 child.expect_exact(input_)
455 453 child.expect_exact(expected)
456 454
457 455 child.close()
458 456
459 457
460 458 @skip_win32
461 459 def test_decorator_skip_with_breakpoint():
462 460 """test that decorator frame skipping can be disabled"""
463 461
464 462 import pexpect
465 463
466 464 env = os.environ.copy()
467 465 env["IPY_TEST_SIMPLE_PROMPT"] = "1"
468 466
469 467 child = pexpect.spawn(
470 468 sys.executable, ["-m", "IPython", "--colors=nocolor"], env=env
471 469 )
472 470 child.timeout = 5 * IPYTHON_TESTING_TIMEOUT_SCALE
473 471
474 472 child.expect("IPython")
475 473 child.expect("\n")
476 474
477 475 ### we need a filename, so we need to exec the full block with a filename
478 476 with NamedTemporaryFile(suffix=".py", dir=".", delete=True) as tf:
479 477
480 478 name = tf.name[:-3].split("/")[-1]
481 479 tf.write("\n".join([dedent(x) for x in skip_decorators_blocks[:-1]]).encode())
482 480 tf.flush()
483 481 codeblock = f"from {name} import f"
484 482
485 483 dedented_blocks = [
486 484 codeblock,
487 485 "f()",
488 486 ]
489 487
490 488 in_prompt_number = 1
491 489 for cblock in dedented_blocks:
492 490 child.expect_exact(f"In [{in_prompt_number}]:")
493 491 in_prompt_number += 1
494 492 for line in cblock.splitlines():
495 493 child.sendline(line)
496 494 child.expect_exact(line)
497 495 child.sendline("")
498 496
499 497 # as the filename does not exists, we'll rely on the filename prompt
500 498 child.expect_exact("47 bar(3, 4)")
501 499
502 500 for input_, expected in [
503 501 (f"b {name}.py:3", ""),
504 502 ("step", "1---> 3 pass # should not stop here except"),
505 503 ("step", "---> 38 @pdb_skipped_decorator"),
506 504 ("continue", ""),
507 505 ]:
508 506 child.expect("ipdb>")
509 507 child.sendline(input_)
510 508 child.expect_exact(input_)
511 509 child.expect_exact(expected)
512 510
513 511 child.close()
514 512
515 513
516 514 @skip_win32
517 515 def test_where_erase_value():
518 516 """Test that `where` does not access f_locals and erase values."""
519 517 import pexpect
520 518
521 519 env = os.environ.copy()
522 520 env["IPY_TEST_SIMPLE_PROMPT"] = "1"
523 521
524 522 child = pexpect.spawn(
525 523 sys.executable, ["-m", "IPython", "--colors=nocolor"], env=env
526 524 )
527 525 child.timeout = 15 * IPYTHON_TESTING_TIMEOUT_SCALE
528 526
529 527 child.expect("IPython")
530 528 child.expect("\n")
531 529 child.expect_exact("In [1]")
532 530
533 531 block = dedent(
534 532 """
535 533 def simple_f():
536 534 myvar = 1
537 535 print(myvar)
538 536 1/0
539 537 print(myvar)
540 538 simple_f() """
541 539 )
542 540
543 541 for line in block.splitlines():
544 542 child.sendline(line)
545 543 child.expect_exact(line)
546 544 child.expect_exact("ZeroDivisionError")
547 545 child.expect_exact("In [2]:")
548 546
549 547 child.sendline("%debug")
550 548
551 549 ##
552 550 child.expect("ipdb>")
553 551
554 552 child.sendline("myvar")
555 553 child.expect("1")
556 554
557 555 ##
558 556 child.expect("ipdb>")
559 557
560 558 child.sendline("myvar = 2")
561 559
562 560 ##
563 561 child.expect_exact("ipdb>")
564 562
565 563 child.sendline("myvar")
566 564
567 565 child.expect_exact("2")
568 566
569 567 ##
570 568 child.expect("ipdb>")
571 569 child.sendline("where")
572 570
573 571 ##
574 572 child.expect("ipdb>")
575 573 child.sendline("myvar")
576 574
577 575 child.expect_exact("2")
578 576 child.expect("ipdb>")
579 577
580 578 child.close()
@@ -1,78 +1,76 b''
1 1 # -*- coding: utf-8 -*-
2 2 """Tests for CommandChainDispatcher."""
3 3
4 4
5 5 #-----------------------------------------------------------------------------
6 6 # Imports
7 7 #-----------------------------------------------------------------------------
8 8
9 import pytest
9 10 from IPython.core.error import TryNext
10 11 from IPython.core.hooks import CommandChainDispatcher
11 12
12 13 #-----------------------------------------------------------------------------
13 14 # Local utilities
14 15 #-----------------------------------------------------------------------------
15 16
16 17 # Define two classes, one which succeeds and one which raises TryNext. Each
17 18 # sets the attribute `called` to True when it is called.
18 19 class Okay(object):
19 20 def __init__(self, message):
20 21 self.message = message
21 22 self.called = False
22 23 def __call__(self):
23 24 self.called = True
24 25 return self.message
25 26
26 27 class Fail(object):
27 28 def __init__(self, message):
28 29 self.message = message
29 30 self.called = False
30 31 def __call__(self):
31 32 self.called = True
32 33 raise TryNext(self.message)
33 34
34 35 #-----------------------------------------------------------------------------
35 36 # Test functions
36 37 #-----------------------------------------------------------------------------
37 38
38 39 def test_command_chain_dispatcher_ff():
39 40 """Test two failing hooks"""
40 41 fail1 = Fail("fail1")
41 42 fail2 = Fail("fail2")
42 43 dp = CommandChainDispatcher([(0, fail1), (10, fail2)])
43 44
44 try:
45 with pytest.raises(TryNext) as e:
45 46 dp()
46 except TryNext as e:
47 assert str(e) == "fail2"
48 else:
49 assert False, "Expected exception was not raised."
47 assert str(e.value) == "fail2"
50 48
51 49 assert fail1.called is True
52 50 assert fail2.called is True
53 51
54 52 def test_command_chain_dispatcher_fofo():
55 53 """Test a mixture of failing and succeeding hooks."""
56 54 fail1 = Fail("fail1")
57 55 fail2 = Fail("fail2")
58 56 okay1 = Okay("okay1")
59 57 okay2 = Okay("okay2")
60 58
61 59 dp = CommandChainDispatcher([(0, fail1),
62 60 # (5, okay1), # add this later
63 61 (10, fail2),
64 62 (15, okay2)])
65 63 dp.add(okay1, 5)
66 64
67 65 assert dp() == "okay1"
68 66
69 67 assert fail1.called is True
70 68 assert okay1.called is True
71 69 assert fail2.called is False
72 70 assert okay2.called is False
73 71
74 72 def test_command_chain_dispatcher_eq_priority():
75 73 okay1 = Okay(u'okay1')
76 74 okay2 = Okay(u'okay2')
77 75 dp = CommandChainDispatcher([(1, okay1)])
78 76 dp.add(okay2, 1)
@@ -1,30 +1,26 b''
1 1 # -*- coding: utf-8 -*-
2 2 """Test IPython.core.logger"""
3 3
4 4 import os.path
5 5 import pytest
6 6
7 7 from IPython.utils.tempdir import TemporaryDirectory
8 8
9 9 def test_logstart_inaccessible_file():
10 try:
10 with pytest.raises(IOError):
11 11 _ip.logger.logstart(logfname="/") # Opening that filename will fail.
12 except IOError:
13 pass
14 else:
15 assert False # The try block should never pass.
16 12
17 13 try:
18 14 _ip.run_cell("a=1") # Check it doesn't try to log this
19 15 finally:
20 16 _ip.logger.log_active = False # If this fails, don't let later tests fail
21 17
22 18 def test_logstart_unicode():
23 19 with TemporaryDirectory() as tdir:
24 20 logfname = os.path.join(tdir, "test_unicode.log")
25 21 _ip.run_cell("'abc€'")
26 22 try:
27 23 _ip.magic("logstart -to %s" % logfname)
28 24 _ip.run_cell("'abc€'")
29 25 finally:
30 26 _ip.logger.logstop()
@@ -1,1363 +1,1360 b''
1 1 # -*- coding: utf-8 -*-
2 2 """Tests for various magic functions."""
3 3
4 4 import asyncio
5 5 import io
6 6 import os
7 7 import re
8 8 import shlex
9 9 import sys
10 10 import warnings
11 11 from importlib import invalidate_caches
12 12 from io import StringIO
13 13 from pathlib import Path
14 14 from textwrap import dedent
15 15 from unittest import TestCase, mock
16 16
17 17 import pytest
18 18
19 19 from IPython import get_ipython
20 20 from IPython.core import magic
21 21 from IPython.core.error import UsageError
22 22 from IPython.core.magic import (
23 23 Magics,
24 24 cell_magic,
25 25 line_magic,
26 26 magics_class,
27 27 register_cell_magic,
28 28 register_line_magic,
29 29 )
30 30 from IPython.core.magics import code, execution, logging, osm, script
31 31 from IPython.testing import decorators as dec
32 32 from IPython.testing import tools as tt
33 33 from IPython.utils.io import capture_output
34 34 from IPython.utils.process import find_cmd
35 35 from IPython.utils.tempdir import TemporaryDirectory, TemporaryWorkingDirectory
36 36
37 37 from .test_debugger import PdbTestInput
38 38
39 39
40 40 @magic.magics_class
41 41 class DummyMagics(magic.Magics): pass
42 42
43 43 def test_extract_code_ranges():
44 44 instr = "1 3 5-6 7-9 10:15 17: :10 10- -13 :"
45 45 expected = [
46 46 (0, 1),
47 47 (2, 3),
48 48 (4, 6),
49 49 (6, 9),
50 50 (9, 14),
51 51 (16, None),
52 52 (None, 9),
53 53 (9, None),
54 54 (None, 13),
55 55 (None, None),
56 56 ]
57 57 actual = list(code.extract_code_ranges(instr))
58 58 assert actual == expected
59 59
60 60 def test_extract_symbols():
61 61 source = """import foo\na = 10\ndef b():\n return 42\n\n\nclass A: pass\n\n\n"""
62 62 symbols_args = ["a", "b", "A", "A,b", "A,a", "z"]
63 63 expected = [([], ['a']),
64 64 (["def b():\n return 42\n"], []),
65 65 (["class A: pass\n"], []),
66 66 (["class A: pass\n", "def b():\n return 42\n"], []),
67 67 (["class A: pass\n"], ['a']),
68 68 ([], ['z'])]
69 69 for symbols, exp in zip(symbols_args, expected):
70 70 assert code.extract_symbols(source, symbols) == exp
71 71
72 72
73 73 def test_extract_symbols_raises_exception_with_non_python_code():
74 74 source = ("=begin A Ruby program :)=end\n"
75 75 "def hello\n"
76 76 "puts 'Hello world'\n"
77 77 "end")
78 78 with pytest.raises(SyntaxError):
79 79 code.extract_symbols(source, "hello")
80 80
81 81
82 82 def test_magic_not_found():
83 83 # magic not found raises UsageError
84 84 with pytest.raises(UsageError):
85 85 _ip.magic('doesntexist')
86 86
87 87 # ensure result isn't success when a magic isn't found
88 88 result = _ip.run_cell('%doesntexist')
89 89 assert isinstance(result.error_in_exec, UsageError)
90 90
91 91
92 92 def test_cell_magic_not_found():
93 93 # magic not found raises UsageError
94 94 with pytest.raises(UsageError):
95 95 _ip.run_cell_magic('doesntexist', 'line', 'cell')
96 96
97 97 # ensure result isn't success when a magic isn't found
98 98 result = _ip.run_cell('%%doesntexist')
99 99 assert isinstance(result.error_in_exec, UsageError)
100 100
101 101
102 102 def test_magic_error_status():
103 103 def fail(shell):
104 104 1/0
105 105 _ip.register_magic_function(fail)
106 106 result = _ip.run_cell('%fail')
107 107 assert isinstance(result.error_in_exec, ZeroDivisionError)
108 108
109 109
110 110 def test_config():
111 111 """ test that config magic does not raise
112 112 can happen if Configurable init is moved too early into
113 113 Magics.__init__ as then a Config object will be registered as a
114 114 magic.
115 115 """
116 116 ## should not raise.
117 117 _ip.magic('config')
118 118
119 119 def test_config_available_configs():
120 120 """ test that config magic prints available configs in unique and
121 121 sorted order. """
122 122 with capture_output() as captured:
123 123 _ip.magic('config')
124 124
125 125 stdout = captured.stdout
126 126 config_classes = stdout.strip().split('\n')[1:]
127 127 assert config_classes == sorted(set(config_classes))
128 128
129 129 def test_config_print_class():
130 130 """ test that config with a classname prints the class's options. """
131 131 with capture_output() as captured:
132 132 _ip.magic('config TerminalInteractiveShell')
133 133
134 134 stdout = captured.stdout
135 if not re.match("TerminalInteractiveShell.* options", stdout.splitlines()[0]):
136 print(stdout)
137 raise AssertionError("1st line of stdout not like "
138 "'TerminalInteractiveShell.* options'")
135 assert re.match(
136 "TerminalInteractiveShell.* options", stdout.splitlines()[0]
137 ), f"{stdout}\n\n1st line of stdout not like 'TerminalInteractiveShell.* options'"
138
139 139
140 140 def test_rehashx():
141 141 # clear up everything
142 142 _ip.alias_manager.clear_aliases()
143 143 del _ip.db['syscmdlist']
144 144
145 145 _ip.magic('rehashx')
146 146 # Practically ALL ipython development systems will have more than 10 aliases
147 147
148 148 assert len(_ip.alias_manager.aliases) > 10
149 149 for name, cmd in _ip.alias_manager.aliases:
150 150 # we must strip dots from alias names
151 151 assert "." not in name
152 152
153 153 # rehashx must fill up syscmdlist
154 154 scoms = _ip.db['syscmdlist']
155 155 assert len(scoms) > 10
156 156
157 157
158 158 def test_magic_parse_options():
159 159 """Test that we don't mangle paths when parsing magic options."""
160 160 ip = get_ipython()
161 161 path = 'c:\\x'
162 162 m = DummyMagics(ip)
163 163 opts = m.parse_options('-f %s' % path,'f:')[0]
164 164 # argv splitting is os-dependent
165 165 if os.name == 'posix':
166 166 expected = 'c:x'
167 167 else:
168 168 expected = path
169 169 assert opts["f"] == expected
170 170
171 171
172 172 def test_magic_parse_long_options():
173 173 """Magic.parse_options can handle --foo=bar long options"""
174 174 ip = get_ipython()
175 175 m = DummyMagics(ip)
176 176 opts, _ = m.parse_options("--foo --bar=bubble", "a", "foo", "bar=")
177 177 assert "foo" in opts
178 178 assert "bar" in opts
179 179 assert opts["bar"] == "bubble"
180 180
181 181
182 182 def doctest_hist_f():
183 183 """Test %hist -f with temporary filename.
184 184
185 185 In [9]: import tempfile
186 186
187 187 In [10]: tfile = tempfile.mktemp('.py','tmp-ipython-')
188 188
189 189 In [11]: %hist -nl -f $tfile 3
190 190
191 191 In [13]: import os; os.unlink(tfile)
192 192 """
193 193
194 194
195 195 def doctest_hist_op():
196 196 """Test %hist -op
197 197
198 198 In [1]: class b(float):
199 199 ...: pass
200 200 ...:
201 201
202 202 In [2]: class s(object):
203 203 ...: def __str__(self):
204 204 ...: return 's'
205 205 ...:
206 206
207 207 In [3]:
208 208
209 209 In [4]: class r(b):
210 210 ...: def __repr__(self):
211 211 ...: return 'r'
212 212 ...:
213 213
214 214 In [5]: class sr(s,r): pass
215 215 ...:
216 216
217 217 In [6]:
218 218
219 219 In [7]: bb=b()
220 220
221 221 In [8]: ss=s()
222 222
223 223 In [9]: rr=r()
224 224
225 225 In [10]: ssrr=sr()
226 226
227 227 In [11]: 4.5
228 228 Out[11]: 4.5
229 229
230 230 In [12]: str(ss)
231 231 Out[12]: 's'
232 232
233 233 In [13]:
234 234
235 235 In [14]: %hist -op
236 236 >>> class b:
237 237 ... pass
238 238 ...
239 239 >>> class s(b):
240 240 ... def __str__(self):
241 241 ... return 's'
242 242 ...
243 243 >>>
244 244 >>> class r(b):
245 245 ... def __repr__(self):
246 246 ... return 'r'
247 247 ...
248 248 >>> class sr(s,r): pass
249 249 >>>
250 250 >>> bb=b()
251 251 >>> ss=s()
252 252 >>> rr=r()
253 253 >>> ssrr=sr()
254 254 >>> 4.5
255 255 4.5
256 256 >>> str(ss)
257 257 's'
258 258 >>>
259 259 """
260 260
261 261 def test_hist_pof():
262 262 ip = get_ipython()
263 263 ip.run_cell("1+2", store_history=True)
264 264 #raise Exception(ip.history_manager.session_number)
265 265 #raise Exception(list(ip.history_manager._get_range_session()))
266 266 with TemporaryDirectory() as td:
267 267 tf = os.path.join(td, 'hist.py')
268 268 ip.run_line_magic('history', '-pof %s' % tf)
269 269 assert os.path.isfile(tf)
270 270
271 271
272 272 def test_macro():
273 273 ip = get_ipython()
274 274 ip.history_manager.reset() # Clear any existing history.
275 275 cmds = ["a=1", "def b():\n return a**2", "print(a,b())"]
276 276 for i, cmd in enumerate(cmds, start=1):
277 277 ip.history_manager.store_inputs(i, cmd)
278 278 ip.magic("macro test 1-3")
279 279 assert ip.user_ns["test"].value == "\n".join(cmds) + "\n"
280 280
281 281 # List macros
282 282 assert "test" in ip.magic("macro")
283 283
284 284
285 285 def test_macro_run():
286 286 """Test that we can run a multi-line macro successfully."""
287 287 ip = get_ipython()
288 288 ip.history_manager.reset()
289 289 cmds = ["a=10", "a+=1", "print(a)", "%macro test 2-3"]
290 290 for cmd in cmds:
291 291 ip.run_cell(cmd, store_history=True)
292 292 assert ip.user_ns["test"].value == "a+=1\nprint(a)\n"
293 293 with tt.AssertPrints("12"):
294 294 ip.run_cell("test")
295 295 with tt.AssertPrints("13"):
296 296 ip.run_cell("test")
297 297
298 298
299 299 def test_magic_magic():
300 300 """Test %magic"""
301 301 ip = get_ipython()
302 302 with capture_output() as captured:
303 303 ip.magic("magic")
304 304
305 305 stdout = captured.stdout
306 306 assert "%magic" in stdout
307 307 assert "IPython" in stdout
308 308 assert "Available" in stdout
309 309
310 310
311 311 @dec.skipif_not_numpy
312 312 def test_numpy_reset_array_undec():
313 313 "Test '%reset array' functionality"
314 314 _ip.ex("import numpy as np")
315 315 _ip.ex("a = np.empty(2)")
316 316 assert "a" in _ip.user_ns
317 317 _ip.magic("reset -f array")
318 318 assert "a" not in _ip.user_ns
319 319
320 320
321 321 def test_reset_out():
322 322 "Test '%reset out' magic"
323 323 _ip.run_cell("parrot = 'dead'", store_history=True)
324 324 # test '%reset -f out', make an Out prompt
325 325 _ip.run_cell("parrot", store_history=True)
326 326 assert "dead" in [_ip.user_ns[x] for x in ("_", "__", "___")]
327 327 _ip.magic("reset -f out")
328 328 assert "dead" not in [_ip.user_ns[x] for x in ("_", "__", "___")]
329 329 assert len(_ip.user_ns["Out"]) == 0
330 330
331 331
332 332 def test_reset_in():
333 333 "Test '%reset in' magic"
334 334 # test '%reset -f in'
335 335 _ip.run_cell("parrot", store_history=True)
336 336 assert "parrot" in [_ip.user_ns[x] for x in ("_i", "_ii", "_iii")]
337 337 _ip.magic("%reset -f in")
338 338 assert "parrot" not in [_ip.user_ns[x] for x in ("_i", "_ii", "_iii")]
339 339 assert len(set(_ip.user_ns["In"])) == 1
340 340
341 341
342 342 def test_reset_dhist():
343 343 "Test '%reset dhist' magic"
344 344 _ip.run_cell("tmp = [d for d in _dh]") # copy before clearing
345 345 _ip.magic("cd " + os.path.dirname(pytest.__file__))
346 346 _ip.magic("cd -")
347 347 assert len(_ip.user_ns["_dh"]) > 0
348 348 _ip.magic("reset -f dhist")
349 349 assert len(_ip.user_ns["_dh"]) == 0
350 350 _ip.run_cell("_dh = [d for d in tmp]") # restore
351 351
352 352
353 353 def test_reset_in_length():
354 354 "Test that '%reset in' preserves In[] length"
355 355 _ip.run_cell("print 'foo'")
356 356 _ip.run_cell("reset -f in")
357 357 assert len(_ip.user_ns["In"]) == _ip.displayhook.prompt_count + 1
358 358
359 359
360 360 class TestResetErrors(TestCase):
361 361
362 362 def test_reset_redefine(self):
363 363
364 364 @magics_class
365 365 class KernelMagics(Magics):
366 366 @line_magic
367 367 def less(self, shell): pass
368 368
369 369 _ip.register_magics(KernelMagics)
370 370
371 371 with self.assertLogs() as cm:
372 372 # hack, we want to just capture logs, but assertLogs fails if not
373 373 # logs get produce.
374 374 # so log one things we ignore.
375 375 import logging as log_mod
376 376 log = log_mod.getLogger()
377 377 log.info('Nothing')
378 378 # end hack.
379 379 _ip.run_cell("reset -f")
380 380
381 381 assert len(cm.output) == 1
382 382 for out in cm.output:
383 383 assert "Invalid alias" not in out
384 384
385 385 def test_tb_syntaxerror():
386 386 """test %tb after a SyntaxError"""
387 387 ip = get_ipython()
388 388 ip.run_cell("for")
389 389
390 390 # trap and validate stdout
391 391 save_stdout = sys.stdout
392 392 try:
393 393 sys.stdout = StringIO()
394 394 ip.run_cell("%tb")
395 395 out = sys.stdout.getvalue()
396 396 finally:
397 397 sys.stdout = save_stdout
398 398 # trim output, and only check the last line
399 399 last_line = out.rstrip().splitlines()[-1].strip()
400 400 assert last_line == "SyntaxError: invalid syntax"
401 401
402 402
403 403 def test_time():
404 404 ip = get_ipython()
405 405
406 406 with tt.AssertPrints("Wall time: "):
407 407 ip.run_cell("%time None")
408 408
409 409 ip.run_cell("def f(kmjy):\n"
410 410 " %time print (2*kmjy)")
411 411
412 412 with tt.AssertPrints("Wall time: "):
413 413 with tt.AssertPrints("hihi", suppress=False):
414 414 ip.run_cell("f('hi')")
415 415
416 416 def test_time_last_not_expression():
417 417 ip.run_cell("%%time\n"
418 418 "var_1 = 1\n"
419 419 "var_2 = 2\n")
420 420 assert ip.user_ns['var_1'] == 1
421 421 del ip.user_ns['var_1']
422 422 assert ip.user_ns['var_2'] == 2
423 423 del ip.user_ns['var_2']
424 424
425 425
426 426 @dec.skip_win32
427 427 def test_time2():
428 428 ip = get_ipython()
429 429
430 430 with tt.AssertPrints("CPU times: user "):
431 431 ip.run_cell("%time None")
432 432
433 433 def test_time3():
434 434 """Erroneous magic function calls, issue gh-3334"""
435 435 ip = get_ipython()
436 436 ip.user_ns.pop('run', None)
437 437
438 438 with tt.AssertNotPrints("not found", channel='stderr'):
439 439 ip.run_cell("%%time\n"
440 440 "run = 0\n"
441 441 "run += 1")
442 442
443 443 def test_multiline_time():
444 444 """Make sure last statement from time return a value."""
445 445 ip = get_ipython()
446 446 ip.user_ns.pop('run', None)
447 447
448 448 ip.run_cell(dedent("""\
449 449 %%time
450 450 a = "ho"
451 451 b = "hey"
452 452 a+b
453 453 """
454 454 )
455 455 )
456 456 assert ip.user_ns_hidden["_"] == "hohey"
457 457
458 458
459 459 def test_time_local_ns():
460 460 """
461 461 Test that local_ns is actually global_ns when running a cell magic
462 462 """
463 463 ip = get_ipython()
464 464 ip.run_cell("%%time\n" "myvar = 1")
465 465 assert ip.user_ns["myvar"] == 1
466 466 del ip.user_ns["myvar"]
467 467
468 468
469 469 def test_doctest_mode():
470 470 "Toggle doctest_mode twice, it should be a no-op and run without error"
471 471 _ip.magic('doctest_mode')
472 472 _ip.magic('doctest_mode')
473 473
474 474
475 475 def test_parse_options():
476 476 """Tests for basic options parsing in magics."""
477 477 # These are only the most minimal of tests, more should be added later. At
478 478 # the very least we check that basic text/unicode calls work OK.
479 479 m = DummyMagics(_ip)
480 480 assert m.parse_options("foo", "")[1] == "foo"
481 481 assert m.parse_options("foo", "")[1] == "foo"
482 482
483 483
484 484 def test_parse_options_preserve_non_option_string():
485 485 """Test to assert preservation of non-option part of magic-block, while parsing magic options."""
486 486 m = DummyMagics(_ip)
487 487 opts, stmt = m.parse_options(
488 488 " -n1 -r 13 _ = 314 + foo", "n:r:", preserve_non_opts=True
489 489 )
490 490 assert opts == {"n": "1", "r": "13"}
491 491 assert stmt == "_ = 314 + foo"
492 492
493 493
494 494 def test_run_magic_preserve_code_block():
495 495 """Test to assert preservation of non-option part of magic-block, while running magic."""
496 496 _ip.user_ns["spaces"] = []
497 497 _ip.magic("timeit -n1 -r1 spaces.append([s.count(' ') for s in ['document']])")
498 498 assert _ip.user_ns["spaces"] == [[0]]
499 499
500 500
501 501 def test_dirops():
502 502 """Test various directory handling operations."""
503 503 # curpath = lambda :os.path.splitdrive(os.getcwd())[1].replace('\\','/')
504 504 curpath = os.getcwd
505 505 startdir = os.getcwd()
506 506 ipdir = os.path.realpath(_ip.ipython_dir)
507 507 try:
508 508 _ip.magic('cd "%s"' % ipdir)
509 509 assert curpath() == ipdir
510 510 _ip.magic('cd -')
511 511 assert curpath() == startdir
512 512 _ip.magic('pushd "%s"' % ipdir)
513 513 assert curpath() == ipdir
514 514 _ip.magic('popd')
515 515 assert curpath() == startdir
516 516 finally:
517 517 os.chdir(startdir)
518 518
519 519
520 520 def test_cd_force_quiet():
521 521 """Test OSMagics.cd_force_quiet option"""
522 522 _ip.config.OSMagics.cd_force_quiet = True
523 523 osmagics = osm.OSMagics(shell=_ip)
524 524
525 525 startdir = os.getcwd()
526 526 ipdir = os.path.realpath(_ip.ipython_dir)
527 527
528 528 try:
529 529 with tt.AssertNotPrints(ipdir):
530 530 osmagics.cd('"%s"' % ipdir)
531 531 with tt.AssertNotPrints(startdir):
532 532 osmagics.cd('-')
533 533 finally:
534 534 os.chdir(startdir)
535 535
536 536
537 537 def test_xmode():
538 538 # Calling xmode three times should be a no-op
539 539 xmode = _ip.InteractiveTB.mode
540 540 for i in range(4):
541 541 _ip.magic("xmode")
542 542 assert _ip.InteractiveTB.mode == xmode
543 543
544 544 def test_reset_hard():
545 545 monitor = []
546 546 class A(object):
547 547 def __del__(self):
548 548 monitor.append(1)
549 549 def __repr__(self):
550 550 return "<A instance>"
551 551
552 552 _ip.user_ns["a"] = A()
553 553 _ip.run_cell("a")
554 554
555 555 assert monitor == []
556 556 _ip.magic("reset -f")
557 557 assert monitor == [1]
558 558
559 559 class TestXdel(tt.TempFileMixin):
560 560 def test_xdel(self):
561 561 """Test that references from %run are cleared by xdel."""
562 562 src = ("class A(object):\n"
563 563 " monitor = []\n"
564 564 " def __del__(self):\n"
565 565 " self.monitor.append(1)\n"
566 566 "a = A()\n")
567 567 self.mktmp(src)
568 568 # %run creates some hidden references...
569 569 _ip.magic("run %s" % self.fname)
570 570 # ... as does the displayhook.
571 571 _ip.run_cell("a")
572 572
573 573 monitor = _ip.user_ns["A"].monitor
574 574 assert monitor == []
575 575
576 576 _ip.magic("xdel a")
577 577
578 578 # Check that a's __del__ method has been called.
579 579 assert monitor == [1]
580 580
581 581 def doctest_who():
582 582 """doctest for %who
583 583
584 584 In [1]: %reset -sf
585 585
586 586 In [2]: alpha = 123
587 587
588 588 In [3]: beta = 'beta'
589 589
590 590 In [4]: %who int
591 591 alpha
592 592
593 593 In [5]: %who str
594 594 beta
595 595
596 596 In [6]: %whos
597 597 Variable Type Data/Info
598 598 ----------------------------
599 599 alpha int 123
600 600 beta str beta
601 601
602 602 In [7]: %who_ls
603 603 Out[7]: ['alpha', 'beta']
604 604 """
605 605
606 606 def test_whos():
607 607 """Check that whos is protected against objects where repr() fails."""
608 608 class A(object):
609 609 def __repr__(self):
610 610 raise Exception()
611 611 _ip.user_ns['a'] = A()
612 612 _ip.magic("whos")
613 613
614 614 def doctest_precision():
615 615 """doctest for %precision
616 616
617 617 In [1]: f = get_ipython().display_formatter.formatters['text/plain']
618 618
619 619 In [2]: %precision 5
620 620 Out[2]: '%.5f'
621 621
622 622 In [3]: f.float_format
623 623 Out[3]: '%.5f'
624 624
625 625 In [4]: %precision %e
626 626 Out[4]: '%e'
627 627
628 628 In [5]: f(3.1415927)
629 629 Out[5]: '3.141593e+00'
630 630 """
631 631
632 632 def test_debug_magic():
633 633 """Test debugging a small code with %debug
634 634
635 635 In [1]: with PdbTestInput(['c']):
636 636 ...: %debug print("a b") #doctest: +ELLIPSIS
637 637 ...:
638 638 ...
639 639 ipdb> c
640 640 a b
641 641 In [2]:
642 642 """
643 643
644 644 def test_psearch():
645 645 with tt.AssertPrints("dict.fromkeys"):
646 646 _ip.run_cell("dict.fr*?")
647 647 with tt.AssertPrints("Ο€.is_integer"):
648 648 _ip.run_cell("Ο€ = 3.14;\nΟ€.is_integ*?")
649 649
650 650 def test_timeit_shlex():
651 651 """test shlex issues with timeit (#1109)"""
652 652 _ip.ex("def f(*a,**kw): pass")
653 653 _ip.magic('timeit -n1 "this is a bug".count(" ")')
654 654 _ip.magic('timeit -r1 -n1 f(" ", 1)')
655 655 _ip.magic('timeit -r1 -n1 f(" ", 1, " ", 2, " ")')
656 656 _ip.magic('timeit -r1 -n1 ("a " + "b")')
657 657 _ip.magic('timeit -r1 -n1 f("a " + "b")')
658 658 _ip.magic('timeit -r1 -n1 f("a " + "b ")')
659 659
660 660
661 661 def test_timeit_special_syntax():
662 662 "Test %%timeit with IPython special syntax"
663 663 @register_line_magic
664 664 def lmagic(line):
665 665 ip = get_ipython()
666 666 ip.user_ns['lmagic_out'] = line
667 667
668 668 # line mode test
669 669 _ip.run_line_magic("timeit", "-n1 -r1 %lmagic my line")
670 670 assert _ip.user_ns["lmagic_out"] == "my line"
671 671 # cell mode test
672 672 _ip.run_cell_magic("timeit", "-n1 -r1", "%lmagic my line2")
673 673 assert _ip.user_ns["lmagic_out"] == "my line2"
674 674
675 675
676 676 def test_timeit_return():
677 677 """
678 678 test whether timeit -o return object
679 679 """
680 680
681 681 res = _ip.run_line_magic('timeit','-n10 -r10 -o 1')
682 682 assert(res is not None)
683 683
684 684 def test_timeit_quiet():
685 685 """
686 686 test quiet option of timeit magic
687 687 """
688 688 with tt.AssertNotPrints("loops"):
689 689 _ip.run_cell("%timeit -n1 -r1 -q 1")
690 690
691 691 def test_timeit_return_quiet():
692 692 with tt.AssertNotPrints("loops"):
693 693 res = _ip.run_line_magic('timeit', '-n1 -r1 -q -o 1')
694 694 assert (res is not None)
695 695
696 696 def test_timeit_invalid_return():
697 697 with pytest.raises(SyntaxError):
698 698 _ip.run_line_magic('timeit', 'return')
699 699
700 700 @dec.skipif(execution.profile is None)
701 701 def test_prun_special_syntax():
702 702 "Test %%prun with IPython special syntax"
703 703 @register_line_magic
704 704 def lmagic(line):
705 705 ip = get_ipython()
706 706 ip.user_ns['lmagic_out'] = line
707 707
708 708 # line mode test
709 709 _ip.run_line_magic("prun", "-q %lmagic my line")
710 710 assert _ip.user_ns["lmagic_out"] == "my line"
711 711 # cell mode test
712 712 _ip.run_cell_magic("prun", "-q", "%lmagic my line2")
713 713 assert _ip.user_ns["lmagic_out"] == "my line2"
714 714
715 715
716 716 @dec.skipif(execution.profile is None)
717 717 def test_prun_quotes():
718 718 "Test that prun does not clobber string escapes (GH #1302)"
719 719 _ip.magic(r"prun -q x = '\t'")
720 720 assert _ip.user_ns["x"] == "\t"
721 721
722 722
723 723 def test_extension():
724 724 # Debugging information for failures of this test
725 725 print('sys.path:')
726 726 for p in sys.path:
727 727 print(' ', p)
728 728 print('CWD', os.getcwd())
729 729
730 730 pytest.raises(ImportError, _ip.magic, "load_ext daft_extension")
731 731 daft_path = os.path.join(os.path.dirname(__file__), "daft_extension")
732 732 sys.path.insert(0, daft_path)
733 733 try:
734 734 _ip.user_ns.pop('arq', None)
735 735 invalidate_caches() # Clear import caches
736 736 _ip.magic("load_ext daft_extension")
737 737 assert _ip.user_ns["arq"] == 185
738 738 _ip.magic("unload_ext daft_extension")
739 739 assert 'arq' not in _ip.user_ns
740 740 finally:
741 741 sys.path.remove(daft_path)
742 742
743 743
744 744 def test_notebook_export_json():
745 745 _ip = get_ipython()
746 746 _ip.history_manager.reset() # Clear any existing history.
747 747 cmds = ["a=1", "def b():\n return a**2", "print('noΓ«l, Γ©tΓ©', b())"]
748 748 for i, cmd in enumerate(cmds, start=1):
749 749 _ip.history_manager.store_inputs(i, cmd)
750 750 with TemporaryDirectory() as td:
751 751 outfile = os.path.join(td, "nb.ipynb")
752 752 _ip.magic("notebook -e %s" % outfile)
753 753
754 754
755 755 class TestEnv(TestCase):
756 756
757 757 def test_env(self):
758 758 env = _ip.magic("env")
759 759 self.assertTrue(isinstance(env, dict))
760 760
761 761 def test_env_secret(self):
762 762 env = _ip.magic("env")
763 763 hidden = "<hidden>"
764 764 with mock.patch.dict(
765 765 os.environ,
766 766 {
767 767 "API_KEY": "abc123",
768 768 "SECRET_THING": "ssshhh",
769 769 "JUPYTER_TOKEN": "",
770 770 "VAR": "abc"
771 771 }
772 772 ):
773 773 env = _ip.magic("env")
774 774 assert env["API_KEY"] == hidden
775 775 assert env["SECRET_THING"] == hidden
776 776 assert env["JUPYTER_TOKEN"] == hidden
777 777 assert env["VAR"] == "abc"
778 778
779 779 def test_env_get_set_simple(self):
780 780 env = _ip.magic("env var val1")
781 781 self.assertEqual(env, None)
782 782 self.assertEqual(os.environ['var'], 'val1')
783 783 self.assertEqual(_ip.magic("env var"), 'val1')
784 784 env = _ip.magic("env var=val2")
785 785 self.assertEqual(env, None)
786 786 self.assertEqual(os.environ['var'], 'val2')
787 787
788 788 def test_env_get_set_complex(self):
789 789 env = _ip.magic("env var 'val1 '' 'val2")
790 790 self.assertEqual(env, None)
791 791 self.assertEqual(os.environ['var'], "'val1 '' 'val2")
792 792 self.assertEqual(_ip.magic("env var"), "'val1 '' 'val2")
793 793 env = _ip.magic('env var=val2 val3="val4')
794 794 self.assertEqual(env, None)
795 795 self.assertEqual(os.environ['var'], 'val2 val3="val4')
796 796
797 797 def test_env_set_bad_input(self):
798 798 self.assertRaises(UsageError, lambda: _ip.magic("set_env var"))
799 799
800 800 def test_env_set_whitespace(self):
801 801 self.assertRaises(UsageError, lambda: _ip.magic("env var A=B"))
802 802
803 803
804 804 class CellMagicTestCase(TestCase):
805 805
806 806 def check_ident(self, magic):
807 807 # Manually called, we get the result
808 808 out = _ip.run_cell_magic(magic, "a", "b")
809 809 assert out == ("a", "b")
810 810 # Via run_cell, it goes into the user's namespace via displayhook
811 811 _ip.run_cell("%%" + magic + " c\nd\n")
812 812 assert _ip.user_ns["_"] == ("c", "d\n")
813 813
814 814 def test_cell_magic_func_deco(self):
815 815 "Cell magic using simple decorator"
816 816 @register_cell_magic
817 817 def cellm(line, cell):
818 818 return line, cell
819 819
820 820 self.check_ident('cellm')
821 821
822 822 def test_cell_magic_reg(self):
823 823 "Cell magic manually registered"
824 824 def cellm(line, cell):
825 825 return line, cell
826 826
827 827 _ip.register_magic_function(cellm, 'cell', 'cellm2')
828 828 self.check_ident('cellm2')
829 829
830 830 def test_cell_magic_class(self):
831 831 "Cell magics declared via a class"
832 832 @magics_class
833 833 class MyMagics(Magics):
834 834
835 835 @cell_magic
836 836 def cellm3(self, line, cell):
837 837 return line, cell
838 838
839 839 _ip.register_magics(MyMagics)
840 840 self.check_ident('cellm3')
841 841
842 842 def test_cell_magic_class2(self):
843 843 "Cell magics declared via a class, #2"
844 844 @magics_class
845 845 class MyMagics2(Magics):
846 846
847 847 @cell_magic('cellm4')
848 848 def cellm33(self, line, cell):
849 849 return line, cell
850 850
851 851 _ip.register_magics(MyMagics2)
852 852 self.check_ident('cellm4')
853 853 # Check that nothing is registered as 'cellm33'
854 854 c33 = _ip.find_cell_magic('cellm33')
855 855 assert c33 == None
856 856
857 857 def test_file():
858 858 """Basic %%writefile"""
859 859 ip = get_ipython()
860 860 with TemporaryDirectory() as td:
861 861 fname = os.path.join(td, 'file1')
862 862 ip.run_cell_magic("writefile", fname, u'\n'.join([
863 863 'line1',
864 864 'line2',
865 865 ]))
866 866 s = Path(fname).read_text()
867 867 assert "line1\n" in s
868 868 assert "line2" in s
869 869
870 870
871 871 @dec.skip_win32
872 872 def test_file_single_quote():
873 873 """Basic %%writefile with embedded single quotes"""
874 874 ip = get_ipython()
875 875 with TemporaryDirectory() as td:
876 876 fname = os.path.join(td, '\'file1\'')
877 877 ip.run_cell_magic("writefile", fname, u'\n'.join([
878 878 'line1',
879 879 'line2',
880 880 ]))
881 881 s = Path(fname).read_text()
882 882 assert "line1\n" in s
883 883 assert "line2" in s
884 884
885 885
886 886 @dec.skip_win32
887 887 def test_file_double_quote():
888 888 """Basic %%writefile with embedded double quotes"""
889 889 ip = get_ipython()
890 890 with TemporaryDirectory() as td:
891 891 fname = os.path.join(td, '"file1"')
892 892 ip.run_cell_magic("writefile", fname, u'\n'.join([
893 893 'line1',
894 894 'line2',
895 895 ]))
896 896 s = Path(fname).read_text()
897 897 assert "line1\n" in s
898 898 assert "line2" in s
899 899
900 900
901 901 def test_file_var_expand():
902 902 """%%writefile $filename"""
903 903 ip = get_ipython()
904 904 with TemporaryDirectory() as td:
905 905 fname = os.path.join(td, 'file1')
906 906 ip.user_ns['filename'] = fname
907 907 ip.run_cell_magic("writefile", '$filename', u'\n'.join([
908 908 'line1',
909 909 'line2',
910 910 ]))
911 911 s = Path(fname).read_text()
912 912 assert "line1\n" in s
913 913 assert "line2" in s
914 914
915 915
916 916 def test_file_unicode():
917 917 """%%writefile with unicode cell"""
918 918 ip = get_ipython()
919 919 with TemporaryDirectory() as td:
920 920 fname = os.path.join(td, 'file1')
921 921 ip.run_cell_magic("writefile", fname, u'\n'.join([
922 922 u'linΓ©1',
923 923 u'linΓ©2',
924 924 ]))
925 925 with io.open(fname, encoding='utf-8') as f:
926 926 s = f.read()
927 927 assert "linΓ©1\n" in s
928 928 assert "linΓ©2" in s
929 929
930 930
931 931 def test_file_amend():
932 932 """%%writefile -a amends files"""
933 933 ip = get_ipython()
934 934 with TemporaryDirectory() as td:
935 935 fname = os.path.join(td, 'file2')
936 936 ip.run_cell_magic("writefile", fname, u'\n'.join([
937 937 'line1',
938 938 'line2',
939 939 ]))
940 940 ip.run_cell_magic("writefile", "-a %s" % fname, u'\n'.join([
941 941 'line3',
942 942 'line4',
943 943 ]))
944 944 s = Path(fname).read_text()
945 945 assert "line1\n" in s
946 946 assert "line3\n" in s
947 947
948 948
949 949 def test_file_spaces():
950 950 """%%file with spaces in filename"""
951 951 ip = get_ipython()
952 952 with TemporaryWorkingDirectory() as td:
953 953 fname = "file name"
954 954 ip.run_cell_magic("file", '"%s"'%fname, u'\n'.join([
955 955 'line1',
956 956 'line2',
957 957 ]))
958 958 s = Path(fname).read_text()
959 959 assert "line1\n" in s
960 960 assert "line2" in s
961 961
962 962
963 963 def test_script_config():
964 964 ip = get_ipython()
965 965 ip.config.ScriptMagics.script_magics = ['whoda']
966 966 sm = script.ScriptMagics(shell=ip)
967 967 assert "whoda" in sm.magics["cell"]
968 968
969 969
970 970 @dec.skip_iptest_but_not_pytest
971 971 @dec.skip_win32
972 972 @pytest.mark.skipif(
973 973 sys.platform == "win32", reason="This test does not run under Windows"
974 974 )
975 975 def test_script_out():
976 976 assert asyncio.get_event_loop().is_running() is False
977 977
978 978 ip = get_ipython()
979 979 ip.run_cell_magic("script", "--out output sh", "echo 'hi'")
980 980 assert asyncio.get_event_loop().is_running() is False
981 981 assert ip.user_ns["output"] == "hi\n"
982 982
983 983
984 984 @dec.skip_iptest_but_not_pytest
985 985 @dec.skip_win32
986 986 @pytest.mark.skipif(
987 987 sys.platform == "win32", reason="This test does not run under Windows"
988 988 )
989 989 def test_script_err():
990 990 ip = get_ipython()
991 991 assert asyncio.get_event_loop().is_running() is False
992 992 ip.run_cell_magic("script", "--err error sh", "echo 'hello' >&2")
993 993 assert asyncio.get_event_loop().is_running() is False
994 994 assert ip.user_ns["error"] == "hello\n"
995 995
996 996
997 997 @dec.skip_iptest_but_not_pytest
998 998 @dec.skip_win32
999 999 @pytest.mark.skipif(
1000 1000 sys.platform == "win32", reason="This test does not run under Windows"
1001 1001 )
1002 1002 def test_script_out_err():
1003 1003
1004 1004 ip = get_ipython()
1005 1005 ip.run_cell_magic(
1006 1006 "script", "--out output --err error sh", "echo 'hi'\necho 'hello' >&2"
1007 1007 )
1008 1008 assert ip.user_ns["output"] == "hi\n"
1009 1009 assert ip.user_ns["error"] == "hello\n"
1010 1010
1011 1011
1012 1012 @dec.skip_iptest_but_not_pytest
1013 1013 @dec.skip_win32
1014 1014 @pytest.mark.skipif(
1015 1015 sys.platform == "win32", reason="This test does not run under Windows"
1016 1016 )
1017 1017 async def test_script_bg_out():
1018 1018 ip = get_ipython()
1019 1019 ip.run_cell_magic("script", "--bg --out output sh", "echo 'hi'")
1020 1020 assert (await ip.user_ns["output"].read()) == b"hi\n"
1021 1021 ip.user_ns["output"].close()
1022 1022 asyncio.get_event_loop().stop()
1023 1023
1024 1024
1025 1025 @dec.skip_iptest_but_not_pytest
1026 1026 @dec.skip_win32
1027 1027 @pytest.mark.skipif(
1028 1028 sys.platform == "win32", reason="This test does not run under Windows"
1029 1029 )
1030 1030 async def test_script_bg_err():
1031 1031 ip = get_ipython()
1032 1032 ip.run_cell_magic("script", "--bg --err error sh", "echo 'hello' >&2")
1033 1033 assert (await ip.user_ns["error"].read()) == b"hello\n"
1034 1034 ip.user_ns["error"].close()
1035 1035
1036 1036
1037 1037 @dec.skip_iptest_but_not_pytest
1038 1038 @dec.skip_win32
1039 1039 @pytest.mark.skipif(
1040 1040 sys.platform == "win32", reason="This test does not run under Windows"
1041 1041 )
1042 1042 async def test_script_bg_out_err():
1043 1043 ip = get_ipython()
1044 1044 ip.run_cell_magic(
1045 1045 "script", "--bg --out output --err error sh", "echo 'hi'\necho 'hello' >&2"
1046 1046 )
1047 1047 assert (await ip.user_ns["output"].read()) == b"hi\n"
1048 1048 assert (await ip.user_ns["error"].read()) == b"hello\n"
1049 1049 ip.user_ns["output"].close()
1050 1050 ip.user_ns["error"].close()
1051 1051
1052 1052
1053 1053 def test_script_defaults():
1054 1054 ip = get_ipython()
1055 1055 for cmd in ['sh', 'bash', 'perl', 'ruby']:
1056 1056 try:
1057 1057 find_cmd(cmd)
1058 1058 except Exception:
1059 1059 pass
1060 1060 else:
1061 1061 assert cmd in ip.magics_manager.magics["cell"]
1062 1062
1063 1063
1064 1064 @magics_class
1065 1065 class FooFoo(Magics):
1066 1066 """class with both %foo and %%foo magics"""
1067 1067 @line_magic('foo')
1068 1068 def line_foo(self, line):
1069 1069 "I am line foo"
1070 1070 pass
1071 1071
1072 1072 @cell_magic("foo")
1073 1073 def cell_foo(self, line, cell):
1074 1074 "I am cell foo, not line foo"
1075 1075 pass
1076 1076
1077 1077 def test_line_cell_info():
1078 1078 """%%foo and %foo magics are distinguishable to inspect"""
1079 1079 ip = get_ipython()
1080 1080 ip.magics_manager.register(FooFoo)
1081 1081 oinfo = ip.object_inspect("foo")
1082 1082 assert oinfo["found"] is True
1083 1083 assert oinfo["ismagic"] is True
1084 1084
1085 1085 oinfo = ip.object_inspect("%%foo")
1086 1086 assert oinfo["found"] is True
1087 1087 assert oinfo["ismagic"] is True
1088 1088 assert oinfo["docstring"] == FooFoo.cell_foo.__doc__
1089 1089
1090 1090 oinfo = ip.object_inspect("%foo")
1091 1091 assert oinfo["found"] is True
1092 1092 assert oinfo["ismagic"] is True
1093 1093 assert oinfo["docstring"] == FooFoo.line_foo.__doc__
1094 1094
1095 1095
1096 1096 def test_multiple_magics():
1097 1097 ip = get_ipython()
1098 1098 foo1 = FooFoo(ip)
1099 1099 foo2 = FooFoo(ip)
1100 1100 mm = ip.magics_manager
1101 1101 mm.register(foo1)
1102 1102 assert mm.magics["line"]["foo"].__self__ is foo1
1103 1103 mm.register(foo2)
1104 1104 assert mm.magics["line"]["foo"].__self__ is foo2
1105 1105
1106 1106
1107 1107 def test_alias_magic():
1108 1108 """Test %alias_magic."""
1109 1109 ip = get_ipython()
1110 1110 mm = ip.magics_manager
1111 1111
1112 1112 # Basic operation: both cell and line magics are created, if possible.
1113 1113 ip.run_line_magic("alias_magic", "timeit_alias timeit")
1114 1114 assert "timeit_alias" in mm.magics["line"]
1115 1115 assert "timeit_alias" in mm.magics["cell"]
1116 1116
1117 1117 # --cell is specified, line magic not created.
1118 1118 ip.run_line_magic("alias_magic", "--cell timeit_cell_alias timeit")
1119 1119 assert "timeit_cell_alias" not in mm.magics["line"]
1120 1120 assert "timeit_cell_alias" in mm.magics["cell"]
1121 1121
1122 1122 # Test that line alias is created successfully.
1123 1123 ip.run_line_magic("alias_magic", "--line env_alias env")
1124 1124 assert ip.run_line_magic("env", "") == ip.run_line_magic("env_alias", "")
1125 1125
1126 1126 # Test that line alias with parameters passed in is created successfully.
1127 1127 ip.run_line_magic(
1128 1128 "alias_magic", "--line history_alias history --params " + shlex.quote("3")
1129 1129 )
1130 1130 assert "history_alias" in mm.magics["line"]
1131 1131
1132 1132
1133 1133 def test_save():
1134 1134 """Test %save."""
1135 1135 ip = get_ipython()
1136 1136 ip.history_manager.reset() # Clear any existing history.
1137 1137 cmds = ["a=1", "def b():\n return a**2", "print(a, b())"]
1138 1138 for i, cmd in enumerate(cmds, start=1):
1139 1139 ip.history_manager.store_inputs(i, cmd)
1140 1140 with TemporaryDirectory() as tmpdir:
1141 1141 file = os.path.join(tmpdir, "testsave.py")
1142 1142 ip.run_line_magic("save", "%s 1-10" % file)
1143 1143 content = Path(file).read_text()
1144 1144 assert content.count(cmds[0]) == 1
1145 1145 assert "coding: utf-8" in content
1146 1146 ip.run_line_magic("save", "-a %s 1-10" % file)
1147 1147 content = Path(file).read_text()
1148 1148 assert content.count(cmds[0]) == 2
1149 1149 assert "coding: utf-8" in content
1150 1150
1151 1151
1152 1152 def test_save_with_no_args():
1153 1153 ip = get_ipython()
1154 1154 ip.history_manager.reset() # Clear any existing history.
1155 1155 cmds = ["a=1", "def b():\n return a**2", "print(a, b())", "%save"]
1156 1156 for i, cmd in enumerate(cmds, start=1):
1157 1157 ip.history_manager.store_inputs(i, cmd)
1158 1158
1159 1159 with TemporaryDirectory() as tmpdir:
1160 1160 path = os.path.join(tmpdir, "testsave.py")
1161 1161 ip.run_line_magic("save", path)
1162 1162 content = Path(path).read_text()
1163 1163 expected_content = dedent(
1164 1164 """\
1165 1165 # coding: utf-8
1166 1166 a=1
1167 1167 def b():
1168 1168 return a**2
1169 1169 print(a, b())
1170 1170 """
1171 1171 )
1172 1172 assert content == expected_content
1173 1173
1174 1174
1175 1175 def test_store():
1176 1176 """Test %store."""
1177 1177 ip = get_ipython()
1178 1178 ip.run_line_magic('load_ext', 'storemagic')
1179 1179
1180 1180 # make sure the storage is empty
1181 1181 ip.run_line_magic("store", "-z")
1182 1182 ip.user_ns["var"] = 42
1183 1183 ip.run_line_magic("store", "var")
1184 1184 ip.user_ns["var"] = 39
1185 1185 ip.run_line_magic("store", "-r")
1186 1186 assert ip.user_ns["var"] == 42
1187 1187
1188 1188 ip.run_line_magic("store", "-d var")
1189 1189 ip.user_ns["var"] = 39
1190 1190 ip.run_line_magic("store", "-r")
1191 1191 assert ip.user_ns["var"] == 39
1192 1192
1193 1193
1194 1194 def _run_edit_test(arg_s, exp_filename=None,
1195 1195 exp_lineno=-1,
1196 1196 exp_contents=None,
1197 1197 exp_is_temp=None):
1198 1198 ip = get_ipython()
1199 1199 M = code.CodeMagics(ip)
1200 1200 last_call = ['','']
1201 1201 opts,args = M.parse_options(arg_s,'prxn:')
1202 1202 filename, lineno, is_temp = M._find_edit_target(ip, args, opts, last_call)
1203 1203
1204 1204 if exp_filename is not None:
1205 1205 assert exp_filename == filename
1206 1206 if exp_contents is not None:
1207 1207 with io.open(filename, 'r', encoding='utf-8') as f:
1208 1208 contents = f.read()
1209 1209 assert exp_contents == contents
1210 1210 if exp_lineno != -1:
1211 1211 assert exp_lineno == lineno
1212 1212 if exp_is_temp is not None:
1213 1213 assert exp_is_temp == is_temp
1214 1214
1215 1215
1216 1216 def test_edit_interactive():
1217 1217 """%edit on interactively defined objects"""
1218 1218 ip = get_ipython()
1219 1219 n = ip.execution_count
1220 1220 ip.run_cell("def foo(): return 1", store_history=True)
1221 1221
1222 try:
1222 with pytest.raises(code.InteractivelyDefined) as e:
1223 1223 _run_edit_test("foo")
1224 except code.InteractivelyDefined as e:
1225 assert e.index == n
1226 else:
1227 raise AssertionError("Should have raised InteractivelyDefined")
1224 assert e.value.index == n
1228 1225
1229 1226
1230 1227 def test_edit_cell():
1231 1228 """%edit [cell id]"""
1232 1229 ip = get_ipython()
1233 1230
1234 1231 ip.run_cell("def foo(): return 1", store_history=True)
1235 1232
1236 1233 # test
1237 1234 _run_edit_test("1", exp_contents=ip.user_ns['In'][1], exp_is_temp=True)
1238 1235
1239 1236 def test_edit_fname():
1240 1237 """%edit file"""
1241 1238 # test
1242 1239 _run_edit_test("test file.py", exp_filename="test file.py")
1243 1240
1244 1241 def test_bookmark():
1245 1242 ip = get_ipython()
1246 1243 ip.run_line_magic('bookmark', 'bmname')
1247 1244 with tt.AssertPrints('bmname'):
1248 1245 ip.run_line_magic('bookmark', '-l')
1249 1246 ip.run_line_magic('bookmark', '-d bmname')
1250 1247
1251 1248 def test_ls_magic():
1252 1249 ip = get_ipython()
1253 1250 json_formatter = ip.display_formatter.formatters['application/json']
1254 1251 json_formatter.enabled = True
1255 1252 lsmagic = ip.magic('lsmagic')
1256 1253 with warnings.catch_warnings(record=True) as w:
1257 1254 j = json_formatter(lsmagic)
1258 1255 assert sorted(j) == ["cell", "line"]
1259 1256 assert w == [] # no warnings
1260 1257
1261 1258
1262 1259 def test_strip_initial_indent():
1263 1260 def sii(s):
1264 1261 lines = s.splitlines()
1265 1262 return '\n'.join(code.strip_initial_indent(lines))
1266 1263
1267 1264 assert sii(" a = 1\nb = 2") == "a = 1\nb = 2"
1268 1265 assert sii(" a\n b\nc") == "a\n b\nc"
1269 1266 assert sii("a\n b") == "a\n b"
1270 1267
1271 1268 def test_logging_magic_quiet_from_arg():
1272 1269 _ip.config.LoggingMagics.quiet = False
1273 1270 lm = logging.LoggingMagics(shell=_ip)
1274 1271 with TemporaryDirectory() as td:
1275 1272 try:
1276 1273 with tt.AssertNotPrints(re.compile("Activating.*")):
1277 1274 lm.logstart('-q {}'.format(
1278 1275 os.path.join(td, "quiet_from_arg.log")))
1279 1276 finally:
1280 1277 _ip.logger.logstop()
1281 1278
1282 1279 def test_logging_magic_quiet_from_config():
1283 1280 _ip.config.LoggingMagics.quiet = True
1284 1281 lm = logging.LoggingMagics(shell=_ip)
1285 1282 with TemporaryDirectory() as td:
1286 1283 try:
1287 1284 with tt.AssertNotPrints(re.compile("Activating.*")):
1288 1285 lm.logstart(os.path.join(td, "quiet_from_config.log"))
1289 1286 finally:
1290 1287 _ip.logger.logstop()
1291 1288
1292 1289
1293 1290 def test_logging_magic_not_quiet():
1294 1291 _ip.config.LoggingMagics.quiet = False
1295 1292 lm = logging.LoggingMagics(shell=_ip)
1296 1293 with TemporaryDirectory() as td:
1297 1294 try:
1298 1295 with tt.AssertPrints(re.compile("Activating.*")):
1299 1296 lm.logstart(os.path.join(td, "not_quiet.log"))
1300 1297 finally:
1301 1298 _ip.logger.logstop()
1302 1299
1303 1300
1304 1301 def test_time_no_var_expand():
1305 1302 _ip.user_ns['a'] = 5
1306 1303 _ip.user_ns['b'] = []
1307 1304 _ip.magic('time b.append("{a}")')
1308 1305 assert _ip.user_ns['b'] == ['{a}']
1309 1306
1310 1307
1311 1308 # this is slow, put at the end for local testing.
1312 1309 def test_timeit_arguments():
1313 1310 "Test valid timeit arguments, should not cause SyntaxError (GH #1269)"
1314 1311 if sys.version_info < (3,7):
1315 1312 _ip.magic("timeit -n1 -r1 ('#')")
1316 1313 else:
1317 1314 # 3.7 optimize no-op statement like above out, and complain there is
1318 1315 # nothing in the for loop.
1319 1316 _ip.magic("timeit -n1 -r1 a=('#')")
1320 1317
1321 1318
1322 1319 TEST_MODULE = """
1323 1320 print('Loaded my_tmp')
1324 1321 if __name__ == "__main__":
1325 1322 print('I just ran a script')
1326 1323 """
1327 1324
1328 1325
1329 1326 def test_run_module_from_import_hook():
1330 1327 "Test that a module can be loaded via an import hook"
1331 1328 with TemporaryDirectory() as tmpdir:
1332 1329 fullpath = os.path.join(tmpdir, 'my_tmp.py')
1333 1330 Path(fullpath).write_text(TEST_MODULE)
1334 1331
1335 1332 class MyTempImporter(object):
1336 1333 def __init__(self):
1337 1334 pass
1338 1335
1339 1336 def find_module(self, fullname, path=None):
1340 1337 if 'my_tmp' in fullname:
1341 1338 return self
1342 1339 return None
1343 1340
1344 1341 def load_module(self, name):
1345 1342 import imp
1346 1343 return imp.load_source('my_tmp', fullpath)
1347 1344
1348 1345 def get_code(self, fullname):
1349 1346 return compile(Path(fullpath).read_text(), "foo", "exec")
1350 1347
1351 1348 def is_package(self, __):
1352 1349 return False
1353 1350
1354 1351 sys.meta_path.insert(0, MyTempImporter())
1355 1352
1356 1353 with capture_output() as captured:
1357 1354 _ip.magic("run -m my_tmp")
1358 1355 _ip.run_cell("import my_tmp")
1359 1356
1360 1357 output = "Loaded my_tmp\nI just ran a script\nLoaded my_tmp\n"
1361 1358 assert output == captured.stdout
1362 1359
1363 1360 sys.meta_path.pop(0)
@@ -1,207 +1,210 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 import sys
19 19
20 20 from pathlib import Path
21 21
22 22 import pytest
23 23
24 24 from IPython.utils import text
25 25
26 26 #-----------------------------------------------------------------------------
27 27 # Globals
28 28 #-----------------------------------------------------------------------------
29 29
30 30 def test_columnize():
31 31 """Basic columnize tests."""
32 32 size = 5
33 33 items = [l*size for l in 'abcd']
34 34
35 35 out = text.columnize(items, displaywidth=80)
36 36 assert out == "aaaaa bbbbb ccccc ddddd\n"
37 37 out = text.columnize(items, displaywidth=25)
38 38 assert out == "aaaaa ccccc\nbbbbb ddddd\n"
39 39 out = text.columnize(items, displaywidth=12)
40 40 assert out == "aaaaa ccccc\nbbbbb ddddd\n"
41 41 out = text.columnize(items, displaywidth=10)
42 42 assert out == "aaaaa\nbbbbb\nccccc\nddddd\n"
43 43
44 44 out = text.columnize(items, row_first=True, displaywidth=80)
45 45 assert out == "aaaaa bbbbb ccccc ddddd\n"
46 46 out = text.columnize(items, row_first=True, displaywidth=25)
47 47 assert out == "aaaaa bbbbb\nccccc ddddd\n"
48 48 out = text.columnize(items, row_first=True, displaywidth=12)
49 49 assert out == "aaaaa bbbbb\nccccc ddddd\n"
50 50 out = text.columnize(items, row_first=True, displaywidth=10)
51 51 assert out == "aaaaa\nbbbbb\nccccc\nddddd\n"
52 52
53 53 out = text.columnize(items, displaywidth=40, spread=True)
54 54 assert out == "aaaaa bbbbb ccccc ddddd\n"
55 55 out = text.columnize(items, displaywidth=20, spread=True)
56 56 assert out == "aaaaa ccccc\nbbbbb ddddd\n"
57 57 out = text.columnize(items, displaywidth=12, spread=True)
58 58 assert out == "aaaaa ccccc\nbbbbb ddddd\n"
59 59 out = text.columnize(items, displaywidth=10, spread=True)
60 60 assert out == "aaaaa\nbbbbb\nccccc\nddddd\n"
61 61
62 62
63 63 def test_columnize_random():
64 64 """Test with random input to hopefully catch edge case """
65 65 for row_first in [True, False]:
66 66 for nitems in [random.randint(2,70) for i in range(2,20)]:
67 67 displaywidth = random.randint(20,200)
68 68 rand_len = [random.randint(2,displaywidth) for i in range(nitems)]
69 69 items = ['x'*l for l in rand_len]
70 70 out = text.columnize(items, row_first=row_first, displaywidth=displaywidth)
71 71 longer_line = max([len(x) for x in out.split('\n')])
72 72 longer_element = max(rand_len)
73 if longer_line > displaywidth:
74 print("Columnize displayed something lager than displaywidth : %s " % longer_line)
75 print("longer element : %s " % longer_element)
76 print("displaywidth : %s " % displaywidth)
77 print("number of element : %s " % nitems)
78 print("size of each element :\n %s" % rand_len)
79 assert False, "row_first={0}".format(row_first)
73 assert longer_line <= displaywidth, (
74 f"Columnize displayed something lager than displaywidth : {longer_line}\n"
75 f"longer element : {longer_element}\n"
76 f"displaywidth : {displaywidth}\n"
77 f"number of element : {nitems}\n"
78 f"size of each element : {rand_len}\n"
79 f"row_first={row_first}\n"
80 )
80 81
81 82
82 83 # TODO: pytest mark.parametrize once nose removed.
83 84 def test_columnize_medium():
84 85 """Test with inputs than shouldn't be wider than 80"""
85 86 size = 40
86 87 items = [l*size for l in 'abc']
87 88 for row_first in [True, False]:
88 89 out = text.columnize(items, row_first=row_first, displaywidth=80)
89 90 assert out == "\n".join(items + [""]), "row_first={0}".format(row_first)
90 91
91 92
92 93 # TODO: pytest mark.parametrize once nose removed.
93 94 def test_columnize_long():
94 95 """Test columnize with inputs longer than the display window"""
95 96 size = 11
96 97 items = [l*size for l in 'abc']
97 98 for row_first in [True, False]:
98 99 out = text.columnize(items, row_first=row_first, displaywidth=size - 1)
99 100 assert out == "\n".join(items + [""]), "row_first={0}".format(row_first)
100 101
101 102
102 103 def eval_formatter_check(f):
103 104 ns = dict(n=12, pi=math.pi, stuff='hello there', os=os, u=u"cafΓ©", b="cafΓ©")
104 105 s = f.format("{n} {n//4} {stuff.split()[0]}", **ns)
105 106 assert s == "12 3 hello"
106 s = f.format(' '.join(['{n//%i}'%i for i in range(1,8)]), **ns)
107 s = f.format(" ".join(["{n//%i}" % i for i in range(1, 8)]), **ns)
107 108 assert s == "12 6 4 3 2 2 1"
108 s = f.format('{[n//i for i in range(1,8)]}', **ns)
109 s = f.format("{[n//i for i in range(1,8)]}", **ns)
109 110 assert s == "[12, 6, 4, 3, 2, 2, 1]"
110 111 s = f.format("{stuff!s}", **ns)
111 112 assert s == ns["stuff"]
112 113 s = f.format("{stuff!r}", **ns)
113 114 assert s == repr(ns["stuff"])
114 115
115 116 # Check with unicode:
116 117 s = f.format("{u}", **ns)
117 118 assert s == ns["u"]
118 119 # This decodes in a platform dependent manner, but it shouldn't error out
119 120 s = f.format("{b}", **ns)
120 121
121 122 pytest.raises(NameError, f.format, "{dne}", **ns)
122 123
123 124
124 125 def eval_formatter_slicing_check(f):
125 126 ns = dict(n=12, pi=math.pi, stuff='hello there', os=os)
126 127 s = f.format(" {stuff.split()[:]} ", **ns)
127 128 assert s == " ['hello', 'there'] "
128 129 s = f.format(" {stuff.split()[::-1]} ", **ns)
129 130 assert s == " ['there', 'hello'] "
130 131 s = f.format("{stuff[::2]}", **ns)
131 132 assert s == ns["stuff"][::2]
132 133
133 134 pytest.raises(SyntaxError, f.format, "{n:x}", **ns)
134 135
135 136 def eval_formatter_no_slicing_check(f):
136 ns = dict(n=12, pi=math.pi, stuff='hello there', os=os)
137
138 s = f.format('{n:x} {pi**2:+f}', **ns)
137 ns = dict(n=12, pi=math.pi, stuff="hello there", os=os)
138
139 s = f.format("{n:x} {pi**2:+f}", **ns)
139 140 assert s == "c +9.869604"
140 141
141 142 s = f.format("{stuff[slice(1,4)]}", **ns)
142 143 assert s == "ell"
143 144
144 145 s = f.format("{a[:]}", a=[1, 2])
145 146 assert s == "[1, 2]"
146 147
147 148 def test_eval_formatter():
148 149 f = text.EvalFormatter()
149 150 eval_formatter_check(f)
150 151 eval_formatter_no_slicing_check(f)
151 152
152 153 def test_full_eval_formatter():
153 154 f = text.FullEvalFormatter()
154 155 eval_formatter_check(f)
155 156 eval_formatter_slicing_check(f)
156 157
157 158 def test_dollar_formatter():
158 159 f = text.DollarFormatter()
159 160 eval_formatter_check(f)
160 161 eval_formatter_slicing_check(f)
161 162
162 163 ns = dict(n=12, pi=math.pi, stuff='hello there', os=os)
163 164 s = f.format("$n", **ns)
164 165 assert s == "12"
165 166 s = f.format("$n.real", **ns)
166 167 assert s == "12"
167 168 s = f.format("$n/{stuff[:5]}", **ns)
168 169 assert s == "12/hello"
169 170 s = f.format("$n $$HOME", **ns)
170 171 assert s == "12 $HOME"
171 172 s = f.format("${foo}", foo="HOME")
172 173 assert s == "$HOME"
173 174
174 175
175 176 def test_strip_email():
176 177 src = """\
177 178 >> >>> def f(x):
178 179 >> ... return x+1
179 180 >> ...
180 181 >> >>> zz = f(2.5)"""
181 182 cln = """\
182 183 >>> def f(x):
183 184 ... return x+1
184 185 ...
185 186 >>> zz = f(2.5)"""
186 187 assert text.strip_email_quotes(src) == cln
187 188
188 189
189 190 def test_strip_email2():
190 src = '> > > list()'
191 cln = 'list()'
191 src = "> > > list()"
192 cln = "list()"
192 193 assert text.strip_email_quotes(src) == cln
193 194
195
194 196 def test_LSString():
195 197 lss = text.LSString("abc\ndef")
196 198 assert lss.l == ["abc", "def"]
197 199 assert lss.s == "abc def"
198 200 lss = text.LSString(os.getcwd())
199 201 assert isinstance(lss.p[0], Path)
200 202
203
201 204 def test_SList():
202 205 sl = text.SList(["a 11", "b 1", "a 2"])
203 206 assert sl.n == "a 11\nb 1\na 2"
204 207 assert sl.s == "a 11 b 1 a 2"
205 208 assert sl.grep(lambda x: x.startswith("a")) == text.SList(["a 11", "a 2"])
206 209 assert sl.fields(0) == text.SList(["a", "b", "a"])
207 210 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