1 # -*- coding: utf-8 -*- 2 """Tests for various magic functions.""" 3 4 import gc 5 import io 6 import os 7 import re 8 import shlex 9 import signal 10 import sys 11 import warnings 12 from importlib import invalidate_caches 13 from io import StringIO 14 from pathlib import Path 15 from time import sleep 16 from threading import Thread 17 from subprocess import CalledProcessError 18 from textwrap import dedent 19 from time import sleep 20 from threading import Thread 21 from unittest import TestCase, mock 22 23 import pytest 24 25 from IPython import get_ipython 26 from IPython.core import magic 27 from IPython.core.error import UsageError 28 from IPython.core.magic import ( 29 Magics, 30 cell_magic, 31 line_magic, 32 magics_class, 33 register_cell_magic, 34 register_line_magic, 35 ) 36 from IPython.core.magics import code, execution, logging, osm, script 37 from IPython.testing import decorators as dec 38 from IPython.testing import tools as tt 39 from IPython.utils.io import capture_output 40 from IPython.utils.process import find_cmd 41 from IPython.utils.tempdir import TemporaryDirectory, TemporaryWorkingDirectory 42 from IPython.utils.syspathcontext import prepended_to_syspath 43 44 from .test_debugger import PdbTestInput 45 46 from tempfile import NamedTemporaryFile 47 48 @magic.magics_class 49 class DummyMagics(magic.Magics): pass 50 51 def test_extract_code_ranges(): 52 instr = "1 3 5-6 7-9 10:15 17: :10 10- -13 :" 53 expected = [ 54 (0, 1), 55 (2, 3), 56 (4, 6), 57 (6, 9), 58 (9, 14), 59 (16, None), 60 (None, 9), 61 (9, None), 62 (None, 13), 63 (None, None), 64 ] 65 actual = list(code.extract_code_ranges(instr)) 66 assert actual == expected 67 68 def test_extract_symbols(): 69 source = """import foo\na = 10\ndef b():\n return 42\n\n\nclass A: pass\n\n\n""" 70 symbols_args = ["a", "b", "A", "A,b", "A,a", "z"] 71 expected = [([], ['a']), 72 (["def b():\n return 42\n"], []), 73 (["class A: pass\n"], []), 74 (["class A: pass\n", "def b():\n return 42\n"], []), 75 (["class A: pass\n"], ['a']), 76 ([], ['z'])] 77 for symbols, exp in zip(symbols_args, expected): 78 assert code.extract_symbols(source, symbols) == exp 79 80 81 def test_extract_symbols_raises_exception_with_non_python_code(): 82 source = ("=begin A Ruby program :)=end\n" 83 "def hello\n" 84 "puts 'Hello world'\n" 85 "end") 86 with pytest.raises(SyntaxError): 87 code.extract_symbols(source, "hello") 88 89 90 def test_magic_not_found(): 91 # magic not found raises UsageError 92 with pytest.raises(UsageError): 93 _ip.run_line_magic("doesntexist", "") 94 95 # ensure result isn't success when a magic isn't found 96 result = _ip.run_cell('%doesntexist') 97 assert isinstance(result.error_in_exec, UsageError) 98 99 100 def test_cell_magic_not_found(): 101 # magic not found raises UsageError 102 with pytest.raises(UsageError): 103 _ip.run_cell_magic('doesntexist', 'line', 'cell') 104 105 # ensure result isn't success when a magic isn't found 106 result = _ip.run_cell('%%doesntexist') 107 assert isinstance(result.error_in_exec, UsageError) 108 109 110 def test_magic_error_status(): 111 def fail(shell): 112 1/0 113 _ip.register_magic_function(fail) 114 result = _ip.run_cell('%fail') 115 assert isinstance(result.error_in_exec, ZeroDivisionError) 116 117 118 def test_config(): 119 """ test that config magic does not raise 120 can happen if Configurable init is moved too early into 121 Magics.__init__ as then a Config object will be registered as a 122 magic. 123 """ 124 ## should not raise. 125 _ip.run_line_magic("config", "") 126 127 128 def test_config_available_configs(): 129 """ test that config magic prints available configs in unique and 130 sorted order. """ 131 with capture_output() as captured: 132 _ip.run_line_magic("config", "") 133 134 stdout = captured.stdout 135 config_classes = stdout.strip().split('\n')[1:] 136 assert config_classes == sorted(set(config_classes)) 137 138 def test_config_print_class(): 139 """ test that config with a classname prints the class's options. """ 140 with capture_output() as captured: 141 _ip.run_line_magic("config", "TerminalInteractiveShell") 142 143 stdout = captured.stdout 144 assert re.match( 145 "TerminalInteractiveShell.* options", stdout.splitlines()[0] 146 ), f"{stdout}\n\n1st line of stdout not like 'TerminalInteractiveShell.* options'" 147 148 149 def test_rehashx(): 150 # clear up everything 151 _ip.alias_manager.clear_aliases() 152 del _ip.db['syscmdlist'] 153 154 _ip.run_line_magic("rehashx", "") 155 # Practically ALL ipython development systems will have more than 10 aliases 156 157 assert len(_ip.alias_manager.aliases) > 10 158 for name, cmd in _ip.alias_manager.aliases: 159 # we must strip dots from alias names 160 assert "." not in name 161 162 # rehashx must fill up syscmdlist 163 scoms = _ip.db['syscmdlist'] 164 assert len(scoms) > 10 165 166 167 def test_magic_parse_options(): 168 """Test that we don't mangle paths when parsing magic options.""" 169 ip = get_ipython() 170 path = 'c:\\x' 171 m = DummyMagics(ip) 172 opts = m.parse_options('-f %s' % path,'f:')[0] 173 # argv splitting is os-dependent 174 if os.name == 'posix': 175 expected = 'c:x' 176 else: 177 expected = path 178 assert opts["f"] == expected 179 180 181 def test_magic_parse_long_options(): 182 """Magic.parse_options can handle --foo=bar long options""" 183 ip = get_ipython() 184 m = DummyMagics(ip) 185 opts, _ = m.parse_options("--foo --bar=bubble", "a", "foo", "bar=") 186 assert "foo" in opts 187 assert "bar" in opts 188 assert opts["bar"] == "bubble" 189 190 191 def doctest_hist_f(): 192 """Test %hist -f with temporary filename. 193 194 In [9]: import tempfile 195 196 In [10]: tfile = tempfile.mktemp('.py','tmp-ipython-') 197 198 In [11]: %hist -nl -f $tfile 3 199 200 In [13]: import os; os.unlink(tfile) 201 """ 202 203 204 def doctest_hist_op(): 205 """Test %hist -op 206 207 In [1]: class b(float): 208 ...: pass 209 ...: 210 211 In [2]: class s(object): 212 ...: def __str__(self): 213 ...: return 's' 214 ...: 215 216 In [3]: 217 218 In [4]: class r(b): 219 ...: def __repr__(self): 220 ...: return 'r' 221 ...: 222 223 In [5]: class sr(s,r): pass 224 ...: 225 226 In [6]: 227 228 In [7]: bb=b() 229 230 In [8]: ss=s() 231 232 In [9]: rr=r() 233 234 In [10]: ssrr=sr() 235 236 In [11]: 4.5 237 Out[11]: 4.5 238 239 In [12]: str(ss) 240 Out[12]: 's' 241 242 In [13]: 243 244 In [14]: %hist -op 245 >>> class b: 246 ... pass 247 ... 248 >>> class s(b): 249 ... def __str__(self): 250 ... return 's' 251 ... 252 >>> 253 >>> class r(b): 254 ... def __repr__(self): 255 ... return 'r' 256 ... 257 >>> class sr(s,r): pass 258 >>> 259 >>> bb=b() 260 >>> ss=s() 261 >>> rr=r() 262 >>> ssrr=sr() 263 >>> 4.5 264 4.5 265 >>> str(ss) 266 's' 267 >>> 268 """ 269 270 def test_hist_pof(): 271 ip = get_ipython() 272 ip.run_cell("1+2", store_history=True) 273 #raise Exception(ip.history_manager.session_number) 274 #raise Exception(list(ip.history_manager._get_range_session())) 275 with TemporaryDirectory() as td: 276 tf = os.path.join(td, 'hist.py') 277 ip.run_line_magic('history', '-pof %s' % tf) 278 assert os.path.isfile(tf) 279 280 281 def test_macro(): 282 ip = get_ipython() 283 ip.history_manager.reset() # Clear any existing history. 284 cmds = ["a=1", "def b():\n return a**2", "print(a,b())"] 285 for i, cmd in enumerate(cmds, start=1): 286 ip.history_manager.store_inputs(i, cmd) 287 ip.run_line_magic("macro", "test 1-3") 288 assert ip.user_ns["test"].value == "\n".join(cmds) + "\n" 289 290 # List macros 291 assert "test" in ip.run_line_magic("macro", "") 292 293 294 def test_macro_run(): 295 """Test that we can run a multi-line macro successfully.""" 296 ip = get_ipython() 297 ip.history_manager.reset() 298 cmds = ["a=10", "a+=1", "print(a)", "%macro test 2-3"] 299 for cmd in cmds: 300 ip.run_cell(cmd, store_history=True) 301 assert ip.user_ns["test"].value == "a+=1\nprint(a)\n" 302 with tt.AssertPrints("12"): 303 ip.run_cell("test") 304 with tt.AssertPrints("13"): 305 ip.run_cell("test") 306 307 308 def test_magic_magic(): 309 """Test %magic""" 310 ip = get_ipython() 311 with capture_output() as captured: 312 ip.run_line_magic("magic", "") 313 314 stdout = captured.stdout 315 assert "%magic" in stdout 316 assert "IPython" in stdout 317 assert "Available" in stdout 318 319 320 @dec.skipif_not_numpy 321 def test_numpy_reset_array_undec(): 322 "Test '%reset array' functionality" 323 _ip.ex("import numpy as np") 324 _ip.ex("a = np.empty(2)") 325 assert "a" in _ip.user_ns 326 _ip.run_line_magic("reset", "-f array") 327 assert "a" not in _ip.user_ns 328 329 330 def test_reset_out(): 331 "Test '%reset out' magic" 332 _ip.run_cell("parrot = 'dead'", store_history=True) 333 # test '%reset -f out', make an Out prompt 334 _ip.run_cell("parrot", store_history=True) 335 assert "dead" in [_ip.user_ns[x] for x in ("_", "__", "___")] 336 _ip.run_line_magic("reset", "-f out") 337 assert "dead" not in [_ip.user_ns[x] for x in ("_", "__", "___")] 338 assert len(_ip.user_ns["Out"]) == 0 339 340 341 def test_reset_in(): 342 "Test '%reset in' magic" 343 # test '%reset -f in' 344 _ip.run_cell("parrot", store_history=True) 345 assert "parrot" in [_ip.user_ns[x] for x in ("_i", "_ii", "_iii")] 346 _ip.run_line_magic("reset", "-f in") 347 assert "parrot" not in [_ip.user_ns[x] for x in ("_i", "_ii", "_iii")] 348 assert len(set(_ip.user_ns["In"])) == 1 349 350 351 def test_reset_dhist(): 352 "Test '%reset dhist' magic" 353 _ip.run_cell("tmp = [d for d in _dh]") # copy before clearing 354 _ip.run_line_magic("cd", os.path.dirname(pytest.__file__)) 355 _ip.run_line_magic("cd", "-") 356 assert len(_ip.user_ns["_dh"]) > 0 357 _ip.run_line_magic("reset", "-f dhist") 358 assert len(_ip.user_ns["_dh"]) == 0 359 _ip.run_cell("_dh = [d for d in tmp]") # restore 360 361 362 def test_reset_in_length(): 363 "Test that '%reset in' preserves In[] length" 364 _ip.run_cell("print 'foo'") 365 _ip.run_cell("reset -f in") 366 assert len(_ip.user_ns["In"]) == _ip.displayhook.prompt_count + 1 367 368 369 class TestResetErrors(TestCase): 370 371 def test_reset_redefine(self): 372 373 @magics_class 374 class KernelMagics(Magics): 375 @line_magic 376 def less(self, shell): pass 377 378 _ip.register_magics(KernelMagics) 379 380 with self.assertLogs() as cm: 381 # hack, we want to just capture logs, but assertLogs fails if not 382 # logs get produce. 383 # so log one things we ignore. 384 import logging as log_mod 385 log = log_mod.getLogger() 386 log.info('Nothing') 387 # end hack. 388 _ip.run_cell("reset -f") 389 390 assert len(cm.output) == 1 391 for out in cm.output: 392 assert "Invalid alias" not in out 393 394 def test_tb_syntaxerror(): 395 """test %tb after a SyntaxError""" 396 ip = get_ipython() 397 ip.run_cell("for") 398 399 # trap and validate stdout 400 save_stdout = sys.stdout 401 try: 402 sys.stdout = StringIO() 403 ip.run_cell("%tb") 404 out = sys.stdout.getvalue() 405 finally: 406 sys.stdout = save_stdout 407 # trim output, and only check the last line 408 last_line = out.rstrip().splitlines()[-1].strip() 409 assert last_line == "SyntaxError: invalid syntax" 410 411 412 def test_time(): 413 ip = get_ipython() 414 415 with tt.AssertPrints("Wall time: "): 416 ip.run_cell("%time None") 417 418 ip.run_cell("def f(kmjy):\n" 419 " %time print (2*kmjy)") 420 421 with tt.AssertPrints("Wall time: "): 422 with tt.AssertPrints("hihi", suppress=False): 423 ip.run_cell("f('hi')") 424 425 426 # ';' at the end of %time prevents instruction value to be printed. 427 # This tests fix for #13837. 428 def test_time_no_output_with_semicolon(): 429 ip = get_ipython() 430 431 # Test %time cases 432 with tt.AssertPrints(" 123456"): 433 with tt.AssertPrints("Wall time: ", suppress=False): 434 with tt.AssertPrints("CPU times: ", suppress=False): 435 ip.run_cell("%time 123000+456") 436 437 with tt.AssertNotPrints(" 123456"): 438 with tt.AssertPrints("Wall time: ", suppress=False): 439 with tt.AssertPrints("CPU times: ", suppress=False): 440 ip.run_cell("%time 123000+456;") 441 442 with tt.AssertPrints(" 123456"): 443 with tt.AssertPrints("Wall time: ", suppress=False): 444 with tt.AssertPrints("CPU times: ", suppress=False): 445 ip.run_cell("%time 123000+456 # Comment") 446 447 with tt.AssertNotPrints(" 123456"): 448 with tt.AssertPrints("Wall time: ", suppress=False): 449 with tt.AssertPrints("CPU times: ", suppress=False): 450 ip.run_cell("%time 123000+456; # Comment") 451 452 with tt.AssertPrints(" 123456"): 453 with tt.AssertPrints("Wall time: ", suppress=False): 454 with tt.AssertPrints("CPU times: ", suppress=False): 455 ip.run_cell("%time 123000+456 # ;Comment") 456 457 # Test %%time cases 458 with tt.AssertPrints("123456"): 459 with tt.AssertPrints("Wall time: ", suppress=False): 460 with tt.AssertPrints("CPU times: ", suppress=False): 461 ip.run_cell("%%time\n123000+456\n\n\n") 462 463 with tt.AssertNotPrints("123456"): 464 with tt.AssertPrints("Wall time: ", suppress=False): 465 with tt.AssertPrints("CPU times: ", suppress=False): 466 ip.run_cell("%%time\n123000+456;\n\n\n") 467 468 with tt.AssertPrints("123456"): 469 with tt.AssertPrints("Wall time: ", suppress=False): 470 with tt.AssertPrints("CPU times: ", suppress=False): 471 ip.run_cell("%%time\n123000+456 # Comment\n\n\n") 472 473 with tt.AssertNotPrints("123456"): 474 with tt.AssertPrints("Wall time: ", suppress=False): 475 with tt.AssertPrints("CPU times: ", suppress=False): 476 ip.run_cell("%%time\n123000+456; # Comment\n\n\n") 477 478 with tt.AssertPrints("123456"): 479 with tt.AssertPrints("Wall time: ", suppress=False): 480 with tt.AssertPrints("CPU times: ", suppress=False): 481 ip.run_cell("%%time\n123000+456 # ;Comment\n\n\n") 482 483 484 def test_time_last_not_expression(): 485 ip.run_cell("%%time\n" 486 "var_1 = 1\n" 487 "var_2 = 2\n") 488 assert ip.user_ns['var_1'] == 1 489 del ip.user_ns['var_1'] 490 assert ip.user_ns['var_2'] == 2 491 del ip.user_ns['var_2'] 492 493 494 @dec.skip_win32 495 def test_time2(): 496 ip = get_ipython() 497 498 with tt.AssertPrints("CPU times: user "): 499 ip.run_cell("%time None") 500 501 def test_time3(): 502 """Erroneous magic function calls, issue gh-3334""" 503 ip = get_ipython() 504 ip.user_ns.pop('run', None) 505 506 with tt.AssertNotPrints("not found", channel='stderr'): 507 ip.run_cell("%%time\n" 508 "run = 0\n" 509 "run += 1") 510 511 def test_multiline_time(): 512 """Make sure last statement from time return a value.""" 513 ip = get_ipython() 514 ip.user_ns.pop('run', None) 515 516 ip.run_cell( 517 dedent( 518 """\ 519 %%time 520 a = "ho" 521 b = "hey" 522 a+b 523 """ 524 ) 525 ) 526 assert ip.user_ns_hidden["_"] == "hohey" 527 528 529 def test_time_local_ns(): 530 """ 531 Test that local_ns is actually global_ns when running a cell magic 532 """ 533 ip = get_ipython() 534 ip.run_cell("%%time\n" "myvar = 1") 535 assert ip.user_ns["myvar"] == 1 536 del ip.user_ns["myvar"] 537 538 539 def test_time_microseconds_display(): 540 """Ensure ASCII is used when necessary""" 541 with mock.patch("sys.stdout", io.TextIOWrapper(StringIO(), encoding="utf-8")): 542 assert execution._format_time(0.000001) == "1 \u03bcs" 543 with mock.patch("sys.stdout", io.TextIOWrapper(StringIO(), encoding="ascii")): 544 assert execution._format_time(0.000001) == "1 us" 545 546 547 # Test %%capture magic. Added to test issue #13926 548 def test_capture(): 549 ip = get_ipython() 550 551 # Test %%capture nominal case 552 ip.run_cell("%%capture abc\n1+2") 553 with tt.AssertPrints("True", suppress=False): 554 ip.run_cell("'abc' in locals()") 555 with tt.AssertPrints("True", suppress=False): 556 ip.run_cell("'outputs' in dir(abc)") 557 with tt.AssertPrints("3", suppress=False): 558 ip.run_cell("abc.outputs[0]") 559 560 # Test %%capture with ';' at end of expression 561 ip.run_cell("%%capture abc\n7+8;") 562 with tt.AssertPrints("False", suppress=False): 563 ip.run_cell("'abc' in locals()") 564 565 566 def test_doctest_mode(): 567 "Toggle doctest_mode twice, it should be a no-op and run without error" 568 _ip.run_line_magic("doctest_mode", "") 569 _ip.run_line_magic("doctest_mode", "") 570 571 572 def test_parse_options(): 573 """Tests for basic options parsing in magics.""" 574 # These are only the most minimal of tests, more should be added later. At 575 # the very least we check that basic text/unicode calls work OK. 576 m = DummyMagics(_ip) 577 assert m.parse_options("foo", "")[1] == "foo" 578 assert m.parse_options("foo", "")[1] == "foo" 579 580 581 def test_parse_options_preserve_non_option_string(): 582 """Test to assert preservation of non-option part of magic-block, while parsing magic options.""" 583 m = DummyMagics(_ip) 584 opts, stmt = m.parse_options( 585 " -n1 -r 13 _ = 314 + foo", "n:r:", preserve_non_opts=True 586 ) 587 assert opts == {"n": "1", "r": "13"} 588 assert stmt == "_ = 314 + foo" 589 590 591 def test_run_magic_preserve_code_block(): 592 """Test to assert preservation of non-option part of magic-block, while running magic.""" 593 _ip.user_ns["spaces"] = [] 594 _ip.run_line_magic( 595 "timeit", "-n1 -r1 spaces.append([s.count(' ') for s in ['document']])" 596 ) 597 assert _ip.user_ns["spaces"] == [[0]] 598 599 600 def test_dirops(): 601 """Test various directory handling operations.""" 602 # curpath = lambda :os.path.splitdrive(os.getcwd())[1].replace('\\','/') 603 curpath = os.getcwd 604 startdir = os.getcwd() 605 ipdir = os.path.realpath(_ip.ipython_dir) 606 try: 607 _ip.run_line_magic("cd", '"%s"' % ipdir) 608 assert curpath() == ipdir 609 _ip.run_line_magic("cd", "-") 610 assert curpath() == startdir 611 _ip.run_line_magic("pushd", '"%s"' % ipdir) 612 assert curpath() == ipdir 613 _ip.run_line_magic("popd", "") 614 assert curpath() == startdir 615 finally: 616 os.chdir(startdir) 617 618 619 def test_cd_force_quiet(): 620 """Test OSMagics.cd_force_quiet option""" 621 _ip.config.OSMagics.cd_force_quiet = True 622 osmagics = osm.OSMagics(shell=_ip) 623 624 startdir = os.getcwd() 625 ipdir = os.path.realpath(_ip.ipython_dir) 626 627 try: 628 with tt.AssertNotPrints(ipdir): 629 osmagics.cd('"%s"' % ipdir) 630 with tt.AssertNotPrints(startdir): 631 osmagics.cd('-') 632 finally: 633 os.chdir(startdir) 634 635 636 def test_xmode(): 637 # Calling xmode three times should be a no-op 638 xmode = _ip.InteractiveTB.mode 639 for i in range(4): 640 _ip.run_line_magic("xmode", "") 641 assert _ip.InteractiveTB.mode == xmode 642 643 def test_reset_hard(): 644 monitor = [] 645 class A(object): 646 def __del__(self): 647 monitor.append(1) 648 def __repr__(self): 649 return "<A instance>" 650 651 _ip.user_ns["a"] = A() 652 _ip.run_cell("a") 653 654 assert monitor == [] 655 _ip.run_line_magic("reset", "-f") 656 assert monitor == [1] 657 658 class TestXdel(tt.TempFileMixin): 659 def test_xdel(self): 660 """Test that references from %run are cleared by xdel.""" 661 src = ("class A(object):\n" 662 " monitor = []\n" 663 " def __del__(self):\n" 664 " self.monitor.append(1)\n" 665 "a = A()\n") 666 self.mktmp(src) 667 # %run creates some hidden references... 668 _ip.run_line_magic("run", "%s" % self.fname) 669 # ... as does the displayhook. 670 _ip.run_cell("a") 671 672 monitor = _ip.user_ns["A"].monitor 673 assert monitor == [] 674 675 _ip.run_line_magic("xdel", "a") 676 677 # Check that a's __del__ method has been called. 678 gc.collect(0) 679 assert monitor == [1] 680 681 def doctest_who(): 682 """doctest for %who 683 684 In [1]: %reset -sf 685 686 In [2]: alpha = 123 687 688 In [3]: beta = 'beta' 689 690 In [4]: %who int 691 alpha 692 693 In [5]: %who str 694 beta 695 696 In [6]: %whos 697 Variable Type Data/Info 698 ---------------------------- 699 alpha int 123 700 beta str beta 701 702 In [7]: %who_ls 703 Out[7]: ['alpha', 'beta'] 704 """ 705 706 def test_whos(): 707 """Check that whos is protected against objects where repr() fails.""" 708 class A(object): 709 def __repr__(self): 710 raise Exception() 711 _ip.user_ns['a'] = A() 712 _ip.run_line_magic("whos", "") 713 714 def doctest_precision(): 715 """doctest for %precision 716 717 In [1]: f = get_ipython().display_formatter.formatters['text/plain'] 718 719 In [2]: %precision 5 720 Out[2]: '%.5f' 721 722 In [3]: f.float_format 723 Out[3]: '%.5f' 724 725 In [4]: %precision %e 726 Out[4]: '%e' 727 728 In [5]: f(3.1415927) 729 Out[5]: '3.141593e+00' 730 """ 731 732 733 def test_debug_magic(): 734 """Test debugging a small code with %debug 735 736 In [1]: with PdbTestInput(['c']): 737 ...: %debug print("a b") #doctest: +ELLIPSIS 738 ...: 739 ... 740 ipdb> c 741 a b 742 In [2]: 743 """ 744 745 746 def test_debug_magic_locals(): 747 """Test debugging a small code with %debug with locals 748 749 In [1]: with PdbTestInput(['c']): 750 ...: def fun(): 751 ...: res = 1 752 ...: %debug print(res) 753 ...: fun() 754 ...: 755 ... 756 ipdb> c 757 1 758 In [2]: 759 """ 760 761 def test_psearch(): 762 with tt.AssertPrints("dict.fromkeys"): 763 _ip.run_cell("dict.fr*?") 764 with tt.AssertPrints("π.is_integer"): 765 _ip.run_cell("π = 3.14;\nπ.is_integ*?") 766 767 def test_timeit_shlex(): 768 """test shlex issues with timeit (#1109)""" 769 _ip.ex("def f(*a,**kw): pass") 770 _ip.run_line_magic("timeit", '-n1 "this is a bug".count(" ")') 771 _ip.run_line_magic("timeit", '-r1 -n1 f(" ", 1)') 772 _ip.run_line_magic("timeit", '-r1 -n1 f(" ", 1, " ", 2, " ")') 773 _ip.run_line_magic("timeit", '-r1 -n1 ("a " + "b")') 774 _ip.run_line_magic("timeit", '-r1 -n1 f("a " + "b")') 775 _ip.run_line_magic("timeit", '-r1 -n1 f("a " + "b ")') 776 777 778 def test_timeit_special_syntax(): 779 "Test %%timeit with IPython special syntax" 780 @register_line_magic 781 def lmagic(line): 782 ip = get_ipython() 783 ip.user_ns['lmagic_out'] = line 784 785 # line mode test 786 _ip.run_line_magic("timeit", "-n1 -r1 %lmagic my line") 787 assert _ip.user_ns["lmagic_out"] == "my line" 788 # cell mode test 789 _ip.run_cell_magic("timeit", "-n1 -r1", "%lmagic my line2") 790 assert _ip.user_ns["lmagic_out"] == "my line2" 791 792 793 def test_timeit_return(): 794 """ 795 test whether timeit -o return object 796 """ 797 798 res = _ip.run_line_magic('timeit','-n10 -r10 -o 1') 799 assert(res is not None) 800 801 def test_timeit_quiet(): 802 """ 803 test quiet option of timeit magic 804 """ 805 with tt.AssertNotPrints("loops"): 806 _ip.run_cell("%timeit -n1 -r1 -q 1") 807 808 def test_timeit_return_quiet(): 809 with tt.AssertNotPrints("loops"): 810 res = _ip.run_line_magic('timeit', '-n1 -r1 -q -o 1') 811 assert (res is not None) 812 813 def test_timeit_invalid_return(): 814 with pytest.raises(SyntaxError): 815 _ip.run_line_magic('timeit', 'return') 816 817 @dec.skipif(execution.profile is None) 818 def test_prun_special_syntax(): 819 "Test %%prun with IPython special syntax" 820 @register_line_magic 821 def lmagic(line): 822 ip = get_ipython() 823 ip.user_ns['lmagic_out'] = line 824 825 # line mode test 826 _ip.run_line_magic("prun", "-q %lmagic my line") 827 assert _ip.user_ns["lmagic_out"] == "my line" 828 # cell mode test 829 _ip.run_cell_magic("prun", "-q", "%lmagic my line2") 830 assert _ip.user_ns["lmagic_out"] == "my line2" 831 832 833 @dec.skipif(execution.profile is None) 834 def test_prun_quotes(): 835 "Test that prun does not clobber string escapes (GH #1302)" 836 _ip.run_line_magic("prun", r"-q x = '\t'") 837 assert _ip.user_ns["x"] == "\t" 838 839 840 def test_extension(): 841 # Debugging information for failures of this test 842 print('sys.path:') 843 for p in sys.path: 844 print(' ', p) 845 print('CWD', os.getcwd()) 846 847 pytest.raises(ImportError, _ip.run_line_magic, "load_ext", "daft_extension") 848 daft_path = os.path.join(os.path.dirname(__file__), "daft_extension") 849 sys.path.insert(0, daft_path) 850 try: 851 _ip.user_ns.pop('arq', None) 852 invalidate_caches() # Clear import caches 853 _ip.run_line_magic("load_ext", "daft_extension") 854 assert _ip.user_ns["arq"] == 185 855 _ip.run_line_magic("unload_ext", "daft_extension") 856 assert 'arq' not in _ip.user_ns 857 finally: 858 sys.path.remove(daft_path) 859 860 861 def test_notebook_export_json(): 862 pytest.importorskip("nbformat") 863 _ip = get_ipython() 864 _ip.history_manager.reset() # Clear any existing history. 865 cmds = ["a=1", "def b():\n return a**2", "print('noël, été', b())"] 866 for i, cmd in enumerate(cmds, start=1): 867 _ip.history_manager.store_inputs(i, cmd) 868 with TemporaryDirectory() as td: 869 outfile = os.path.join(td, "nb.ipynb") 870 _ip.run_line_magic("notebook", "%s" % outfile) 871 872 873 class TestEnv(TestCase): 874 875 def test_env(self): 876 env = _ip.run_line_magic("env", "") 877 self.assertTrue(isinstance(env, dict)) 878 879 def test_env_secret(self): 880 env = _ip.run_line_magic("env", "") 881 hidden = "<hidden>" 882 with mock.patch.dict( 883 os.environ, 884 { 885 "API_KEY": "abc123", 886 "SECRET_THING": "ssshhh", 887 "JUPYTER_TOKEN": "", 888 "VAR": "abc" 889 } 890 ): 891 env = _ip.run_line_magic("env", "") 892 assert env["API_KEY"] == hidden 893 assert env["SECRET_THING"] == hidden 894 assert env["JUPYTER_TOKEN"] == hidden 895 assert env["VAR"] == "abc" 896 897 def test_env_get_set_simple(self): 898 env = _ip.run_line_magic("env", "var val1") 899 self.assertEqual(env, None) 900 self.assertEqual(os.environ["var"], "val1") 901 self.assertEqual(_ip.run_line_magic("env", "var"), "val1") 902 env = _ip.run_line_magic("env", "var=val2") 903 self.assertEqual(env, None) 904 self.assertEqual(os.environ['var'], 'val2') 905 906 def test_env_get_set_complex(self): 907 env = _ip.run_line_magic("env", "var 'val1 '' 'val2") 908 self.assertEqual(env, None) 909 self.assertEqual(os.environ['var'], "'val1 '' 'val2") 910 self.assertEqual(_ip.run_line_magic("env", "var"), "'val1 '' 'val2") 911 env = _ip.run_line_magic("env", 'var=val2 val3="val4') 912 self.assertEqual(env, None) 913 self.assertEqual(os.environ['var'], 'val2 val3="val4') 914 915 def test_env_set_bad_input(self): 916 self.assertRaises(UsageError, lambda: _ip.run_line_magic("set_env", "var")) 917 918 def test_env_set_whitespace(self): 919 self.assertRaises(UsageError, lambda: _ip.run_line_magic("env", "var A=B")) 920 921 922 class CellMagicTestCase(TestCase): 923 924 def check_ident(self, magic): 925 # Manually called, we get the result 926 out = _ip.run_cell_magic(magic, "a", "b") 927 assert out == ("a", "b") 928 # Via run_cell, it goes into the user's namespace via displayhook 929 _ip.run_cell("%%" + magic + " c\nd\n") 930 assert _ip.user_ns["_"] == ("c", "d\n") 931 932 def test_cell_magic_func_deco(self): 933 "Cell magic using simple decorator" 934 @register_cell_magic 935 def cellm(line, cell): 936 return line, cell 937 938 self.check_ident('cellm') 939 940 def test_cell_magic_reg(self): 941 "Cell magic manually registered" 942 def cellm(line, cell): 943 return line, cell 944 945 _ip.register_magic_function(cellm, 'cell', 'cellm2') 946 self.check_ident('cellm2') 947 948 def test_cell_magic_class(self): 949 "Cell magics declared via a class" 950 @magics_class 951 class MyMagics(Magics): 952 953 @cell_magic 954 def cellm3(self, line, cell): 955 return line, cell 956 957 _ip.register_magics(MyMagics) 958 self.check_ident('cellm3') 959 960 def test_cell_magic_class2(self): 961 "Cell magics declared via a class, #2" 962 @magics_class 963 class MyMagics2(Magics): 964 965 @cell_magic('cellm4') 966 def cellm33(self, line, cell): 967 return line, cell 968 969 _ip.register_magics(MyMagics2) 970 self.check_ident('cellm4') 971 # Check that nothing is registered as 'cellm33' 972 c33 = _ip.find_cell_magic('cellm33') 973 assert c33 == None 974 975 def test_file(): 976 """Basic %%writefile""" 977 ip = get_ipython() 978 with TemporaryDirectory() as td: 979 fname = os.path.join(td, "file1") 980 ip.run_cell_magic( 981 "writefile", 982 fname, 983 "\n".join( 984 [ 985 "line1", 986 "line2", 987 ] 988 ), 989 ) 990 s = Path(fname).read_text(encoding="utf-8") 991 assert "line1\n" in s 992 assert "line2" in s 993 994 995 @dec.skip_win32 996 def test_file_single_quote(): 997 """Basic %%writefile with embedded single quotes""" 998 ip = get_ipython() 999 with TemporaryDirectory() as td: 1000 fname = os.path.join(td, "'file1'") 1001 ip.run_cell_magic( 1002 "writefile", 1003 fname, 1004 "\n".join( 1005 [ 1006 "line1", 1007 "line2", 1008 ] 1009 ), 1010 ) 1011 s = Path(fname).read_text(encoding="utf-8") 1012 assert "line1\n" in s 1013 assert "line2" in s 1014 1015 1016 @dec.skip_win32 1017 def test_file_double_quote(): 1018 """Basic %%writefile with embedded double quotes""" 1019 ip = get_ipython() 1020 with TemporaryDirectory() as td: 1021 fname = os.path.join(td, '"file1"') 1022 ip.run_cell_magic( 1023 "writefile", 1024 fname, 1025 "\n".join( 1026 [ 1027 "line1", 1028 "line2", 1029 ] 1030 ), 1031 ) 1032 s = Path(fname).read_text(encoding="utf-8") 1033 assert "line1\n" in s 1034 assert "line2" in s 1035 1036 1037 def test_file_var_expand(): 1038 """%%writefile $filename""" 1039 ip = get_ipython() 1040 with TemporaryDirectory() as td: 1041 fname = os.path.join(td, "file1") 1042 ip.user_ns["filename"] = fname 1043 ip.run_cell_magic( 1044 "writefile", 1045 "$filename", 1046 "\n".join( 1047 [ 1048 "line1", 1049 "line2", 1050 ] 1051 ), 1052 ) 1053 s = Path(fname).read_text(encoding="utf-8") 1054 assert "line1\n" in s 1055 assert "line2" in s 1056 1057 1058 def test_file_unicode(): 1059 """%%writefile with unicode cell""" 1060 ip = get_ipython() 1061 with TemporaryDirectory() as td: 1062 fname = os.path.join(td, 'file1') 1063 ip.run_cell_magic("writefile", fname, u'\n'.join([ 1064 u'liné1', 1065 u'liné2', 1066 ])) 1067 with io.open(fname, encoding='utf-8') as f: 1068 s = f.read() 1069 assert "liné1\n" in s 1070 assert "liné2" in s 1071 1072 1073 def test_file_amend(): 1074 """%%writefile -a amends files""" 1075 ip = get_ipython() 1076 with TemporaryDirectory() as td: 1077 fname = os.path.join(td, "file2") 1078 ip.run_cell_magic( 1079 "writefile", 1080 fname, 1081 "\n".join( 1082 [ 1083 "line1", 1084 "line2", 1085 ] 1086 ), 1087 ) 1088 ip.run_cell_magic( 1089 "writefile", 1090 "-a %s" % fname, 1091 "\n".join( 1092 [ 1093 "line3", 1094 "line4", 1095 ] 1096 ), 1097 ) 1098 s = Path(fname).read_text(encoding="utf-8") 1099 assert "line1\n" in s 1100 assert "line3\n" in s 1101 1102 1103 def test_file_spaces(): 1104 """%%file with spaces in filename""" 1105 ip = get_ipython() 1106 with TemporaryWorkingDirectory() as td: 1107 fname = "file name" 1108 ip.run_cell_magic( 1109 "file", 1110 '"%s"' % fname, 1111 "\n".join( 1112 [ 1113 "line1", 1114 "line2", 1115 ] 1116 ), 1117 ) 1118 s = Path(fname).read_text(encoding="utf-8") 1119 assert "line1\n" in s 1120 assert "line2" in s 1121 1122 1123 def test_script_config(): 1124 ip = get_ipython() 1125 ip.config.ScriptMagics.script_magics = ['whoda'] 1126 sm = script.ScriptMagics(shell=ip) 1127 assert "whoda" in sm.magics["cell"] 1128 1129 1130 def _interrupt_after_1s(): 1131 sleep(1) 1132 signal.raise_signal(signal.SIGINT) 1133 1134 1135 def test_script_raise_on_interrupt(): 1136 ip = get_ipython() 1137 1138 with pytest.raises(CalledProcessError): 1139 thread = Thread(target=_interrupt_after_1s) 1140 thread.start() 1141 ip.run_cell_magic( 1142 "script", f"{sys.executable}", "from time import sleep; sleep(2)" 1143 ) 1144 thread.join() 1145 1146 1147 def test_script_do_not_raise_on_interrupt(): 1148 ip = get_ipython() 1149 1150 thread = Thread(target=_interrupt_after_1s) 1151 thread.start() 1152 ip.run_cell_magic( 1153 "script", 1154 f"--no-raise-error {sys.executable}", 1155 "from time import sleep; sleep(2)", 1156 ) 1157 thread.join() 1158 1159 1160 def test_script_out(): 1161 ip = get_ipython() 1162 ip.run_cell_magic("script", f"--out output {sys.executable}", "print('hi')") 1163 assert ip.user_ns["output"].strip() == "hi" 1164 1165 1166 def test_script_err(): 1167 ip = get_ipython() 1168 ip.run_cell_magic( 1169 "script", 1170 f"--err error {sys.executable}", 1171 "import sys; print('hello', file=sys.stderr)", 1172 ) 1173 assert ip.user_ns["error"].strip() == "hello" 1174 1175 1176 def test_script_out_err(): 1177 ip = get_ipython() 1178 ip.run_cell_magic( 1179 "script", 1180 f"--out output --err error {sys.executable}", 1181 "\n".join( 1182 [ 1183 "import sys", 1184 "print('hi')", 1185 "print('hello', file=sys.stderr)", 1186 ] 1187 ), 1188 ) 1189 assert ip.user_ns["output"].strip() == "hi" 1190 assert ip.user_ns["error"].strip() == "hello" 1191 1192 1193 async def test_script_bg_out(): 1194 ip = get_ipython() 1195 ip.run_cell_magic("script", f"--bg --out output {sys.executable}", "print('hi')") 1196 assert (await ip.user_ns["output"].read()).strip() == b"hi" 1197 assert ip.user_ns["output"].at_eof() 1198 1199 1200 async def test_script_bg_err(): 1201 ip = get_ipython() 1202 ip.run_cell_magic( 1203 "script", 1204 f"--bg --err error {sys.executable}", 1205 "import sys; print('hello', file=sys.stderr)", 1206 ) 1207 assert (await ip.user_ns["error"].read()).strip() == b"hello" 1208 assert ip.user_ns["error"].at_eof() 1209 1210 1211 async def test_script_bg_out_err(): 1212 ip = get_ipython() 1213 ip.run_cell_magic( 1214 "script", 1215 f"--bg --out output --err error {sys.executable}", 1216 "\n".join( 1217 [ 1218 "import sys", 1219 "print('hi')", 1220 "print('hello', file=sys.stderr)", 1221 ] 1222 ), 1223 ) 1224 assert (await ip.user_ns["output"].read()).strip() == b"hi" 1225 assert (await ip.user_ns["error"].read()).strip() == b"hello" 1226 assert ip.user_ns["output"].at_eof() 1227 assert ip.user_ns["error"].at_eof() 1228 1229 1230 async def test_script_bg_proc(): 1231 ip = get_ipython() 1232 ip.run_cell_magic( 1233 "script", 1234 f"--bg --out output --proc p {sys.executable}", 1235 "\n".join( 1236 [ 1237 "import sys", 1238 "print('hi')", 1239 "print('hello', file=sys.stderr)", 1240 ] 1241 ), 1242 ) 1243 p = ip.user_ns["p"] 1244 await p.wait() 1245 assert p.returncode == 0 1246 assert (await p.stdout.read()).strip() == b"hi" 1247 # not captured, so empty 1248 assert (await p.stderr.read()) == b"" 1249 assert p.stdout.at_eof() 1250 assert p.stderr.at_eof() 1251 1252 1253 def test_script_defaults(): 1254 ip = get_ipython() 1255 for cmd in ['sh', 'bash', 'perl', 'ruby']: 1256 try: 1257 find_cmd(cmd) 1258 except Exception: 1259 pass 1260 else: 1261 assert cmd in ip.magics_manager.magics["cell"] 1262 1263 1264 async def test_script_streams_continiously(capsys): 1265 ip = get_ipython() 1266 # Windows is slow to start up a thread on CI 1267 is_windows = os.name == "nt" 1268 step = 3 if is_windows else 1 1269 code = dedent( 1270 f"""\ 1271 import time 1272 for _ in range(3): 1273 time.sleep({step}) 1274 print(".", flush=True, end="") 1275 """ 1276 ) 1277 1278 def print_numbers(): 1279 for i in range(3): 1280 sleep(step) 1281 print(i, flush=True, end="") 1282 1283 thread = Thread(target=print_numbers) 1284 thread.start() 1285 sleep(step / 2) 1286 ip.run_cell_magic("script", f"{sys.executable}", code) 1287 thread.join() 1288 1289 captured = capsys.readouterr() 1290 # If the streaming was line-wise or broken 1291 # we would get `012...` 1292 assert captured.out == "0.1.2." 1293 1294 1295 @magics_class 1296 class FooFoo(Magics): 1297 """class with both %foo and %%foo magics""" 1298 @line_magic('foo') 1299 def line_foo(self, line): 1300 "I am line foo" 1301 pass 1302 1303 @cell_magic("foo") 1304 def cell_foo(self, line, cell): 1305 "I am cell foo, not line foo" 1306 pass 1307 1308 def test_line_cell_info(): 1309 """%%foo and %foo magics are distinguishable to inspect""" 1310 ip = get_ipython() 1311 ip.magics_manager.register(FooFoo) 1312 oinfo = ip.object_inspect("foo") 1313 assert oinfo["found"] is True 1314 assert oinfo["ismagic"] is True 1315 1316 oinfo = ip.object_inspect("%%foo") 1317 assert oinfo["found"] is True 1318 assert oinfo["ismagic"] is True 1319 assert oinfo["docstring"] == FooFoo.cell_foo.__doc__ 1320 1321 oinfo = ip.object_inspect("%foo") 1322 assert oinfo["found"] is True 1323 assert oinfo["ismagic"] is True 1324 assert oinfo["docstring"] == FooFoo.line_foo.__doc__ 1325 1326 1327 def test_multiple_magics(): 1328 ip = get_ipython() 1329 foo1 = FooFoo(ip) 1330 foo2 = FooFoo(ip) 1331 mm = ip.magics_manager 1332 mm.register(foo1) 1333 assert mm.magics["line"]["foo"].__self__ is foo1 1334 mm.register(foo2) 1335 assert mm.magics["line"]["foo"].__self__ is foo2 1336 1337 1338 def test_alias_magic(): 1339 """Test %alias_magic.""" 1340 ip = get_ipython() 1341 mm = ip.magics_manager 1342 1343 # Basic operation: both cell and line magics are created, if possible. 1344 ip.run_line_magic("alias_magic", "timeit_alias timeit") 1345 assert "timeit_alias" in mm.magics["line"] 1346 assert "timeit_alias" in mm.magics["cell"] 1347 1348 # --cell is specified, line magic not created. 1349 ip.run_line_magic("alias_magic", "--cell timeit_cell_alias timeit") 1350 assert "timeit_cell_alias" not in mm.magics["line"] 1351 assert "timeit_cell_alias" in mm.magics["cell"] 1352 1353 # Test that line alias is created successfully. 1354 ip.run_line_magic("alias_magic", "--line env_alias env") 1355 assert ip.run_line_magic("env", "") == ip.run_line_magic("env_alias", "") 1356 1357 # Test that line alias with parameters passed in is created successfully. 1358 ip.run_line_magic( 1359 "alias_magic", "--line history_alias history --params " + shlex.quote("3") 1360 ) 1361 assert "history_alias" in mm.magics["line"] 1362 1363 1364 def test_save(): 1365 """Test %save.""" 1366 ip = get_ipython() 1367 ip.history_manager.reset() # Clear any existing history. 1368 cmds = ["a=1", "def b():\n return a**2", "print(a, b())"] 1369 for i, cmd in enumerate(cmds, start=1): 1370 ip.history_manager.store_inputs(i, cmd) 1371 with TemporaryDirectory() as tmpdir: 1372 file = os.path.join(tmpdir, "testsave.py") 1373 ip.run_line_magic("save", "%s 1-10" % file) 1374 content = Path(file).read_text(encoding="utf-8") 1375 assert content.count(cmds[0]) == 1 1376 assert "coding: utf-8" in content 1377 ip.run_line_magic("save", "-a %s 1-10" % file) 1378 content = Path(file).read_text(encoding="utf-8") 1379 assert content.count(cmds[0]) == 2 1380 assert "coding: utf-8" in content 1381 1382 1383 def test_save_with_no_args(): 1384 ip = get_ipython() 1385 ip.history_manager.reset() # Clear any existing history. 1386 cmds = ["a=1", "def b():\n return a**2", "print(a, b())", "%save"] 1387 for i, cmd in enumerate(cmds, start=1): 1388 ip.history_manager.store_inputs(i, cmd) 1389 1390 with TemporaryDirectory() as tmpdir: 1391 path = os.path.join(tmpdir, "testsave.py") 1392 ip.run_line_magic("save", path) 1393 content = Path(path).read_text(encoding="utf-8") 1394 expected_content = dedent( 1395 """\ 1396 # coding: utf-8 1397 a=1 1398 def b(): 1399 return a**2 1400 print(a, b()) 1401 """ 1402 ) 1403 assert content == expected_content 1404 1405 1406 def test_store(): 1407 """Test %store.""" 1408 ip = get_ipython() 1409 ip.run_line_magic('load_ext', 'storemagic') 1410 1411 # make sure the storage is empty 1412 ip.run_line_magic("store", "-z") 1413 ip.user_ns["var"] = 42 1414 ip.run_line_magic("store", "var") 1415 ip.user_ns["var"] = 39 1416 ip.run_line_magic("store", "-r") 1417 assert ip.user_ns["var"] == 42 1418 1419 ip.run_line_magic("store", "-d var") 1420 ip.user_ns["var"] = 39 1421 ip.run_line_magic("store", "-r") 1422 assert ip.user_ns["var"] == 39 1423 1424 1425 def _run_edit_test(arg_s, exp_filename=None, 1426 exp_lineno=-1, 1427 exp_contents=None, 1428 exp_is_temp=None): 1429 ip = get_ipython() 1430 M = code.CodeMagics(ip) 1431 last_call = ['',''] 1432 opts,args = M.parse_options(arg_s,'prxn:') 1433 filename, lineno, is_temp = M._find_edit_target(ip, args, opts, last_call) 1434 1435 if exp_filename is not None: 1436 assert exp_filename == filename 1437 if exp_contents is not None: 1438 with io.open(filename, 'r', encoding='utf-8') as f: 1439 contents = f.read() 1440 assert exp_contents == contents 1441 if exp_lineno != -1: 1442 assert exp_lineno == lineno 1443 if exp_is_temp is not None: 1444 assert exp_is_temp == is_temp 1445 1446 1447 def test_edit_interactive(): 1448 """%edit on interactively defined objects""" 1449 ip = get_ipython() 1450 n = ip.execution_count 1451 ip.run_cell("def foo(): return 1", store_history=True) 1452 1453 with pytest.raises(code.InteractivelyDefined) as e: 1454 _run_edit_test("foo") 1455 assert e.value.index == n 1456 1457 1458 def test_edit_cell(): 1459 """%edit [cell id]""" 1460 ip = get_ipython() 1461 1462 ip.run_cell("def foo(): return 1", store_history=True) 1463 1464 # test 1465 _run_edit_test("1", exp_contents=ip.user_ns['In'][1], exp_is_temp=True) 1466 1467 def test_edit_fname(): 1468 """%edit file""" 1469 # test 1470 _run_edit_test("test file.py", exp_filename="test file.py") 1471 1472 def test_bookmark(): 1473 ip = get_ipython() 1474 ip.run_line_magic('bookmark', 'bmname') 1475 with tt.AssertPrints('bmname'): 1476 ip.run_line_magic('bookmark', '-l') 1477 ip.run_line_magic('bookmark', '-d bmname') 1478 1479 def test_ls_magic(): 1480 ip = get_ipython() 1481 json_formatter = ip.display_formatter.formatters['application/json'] 1482 json_formatter.enabled = True 1483 lsmagic = ip.run_line_magic("lsmagic", "") 1484 with warnings.catch_warnings(record=True) as w: 1485 j = json_formatter(lsmagic) 1486 assert sorted(j) == ["cell", "line"] 1487 assert w == [] # no warnings 1488 1489 1490 def test_strip_initial_indent(): 1491 def sii(s): 1492 lines = s.splitlines() 1493 return '\n'.join(code.strip_initial_indent(lines)) 1494 1495 assert sii(" a = 1\nb = 2") == "a = 1\nb = 2" 1496 assert sii(" a\n b\nc") == "a\n b\nc" 1497 assert sii("a\n b") == "a\n b" 1498 1499 def test_logging_magic_quiet_from_arg(): 1500 _ip.config.LoggingMagics.quiet = False 1501 lm = logging.LoggingMagics(shell=_ip) 1502 with TemporaryDirectory() as td: 1503 try: 1504 with tt.AssertNotPrints(re.compile("Activating.*")): 1505 lm.logstart('-q {}'.format( 1506 os.path.join(td, "quiet_from_arg.log"))) 1507 finally: 1508 _ip.logger.logstop() 1509 1510 def test_logging_magic_quiet_from_config(): 1511 _ip.config.LoggingMagics.quiet = True 1512 lm = logging.LoggingMagics(shell=_ip) 1513 with TemporaryDirectory() as td: 1514 try: 1515 with tt.AssertNotPrints(re.compile("Activating.*")): 1516 lm.logstart(os.path.join(td, "quiet_from_config.log")) 1517 finally: 1518 _ip.logger.logstop() 1519 1520 1521 def test_logging_magic_not_quiet(): 1522 _ip.config.LoggingMagics.quiet = False 1523 lm = logging.LoggingMagics(shell=_ip) 1524 with TemporaryDirectory() as td: 1525 try: 1526 with tt.AssertPrints(re.compile("Activating.*")): 1527 lm.logstart(os.path.join(td, "not_quiet.log")) 1528 finally: 1529 _ip.logger.logstop() 1530 1531 1532 def test_time_no_var_expand(): 1533 _ip.user_ns["a"] = 5 1534 _ip.user_ns["b"] = [] 1535 _ip.run_line_magic("time", 'b.append("{a}")') 1536 assert _ip.user_ns["b"] == ["{a}"] 1537 1538 1539 # this is slow, put at the end for local testing. 1540 def test_timeit_arguments(): 1541 "Test valid timeit arguments, should not cause SyntaxError (GH #1269)" 1542 _ip.run_line_magic("timeit", "-n1 -r1 a=('#')") 1543 1544 1545 MINIMAL_LAZY_MAGIC = """ 1546 from IPython.core.magic import ( 1547 Magics, 1548 magics_class, 1549 line_magic, 1550 cell_magic, 1551 ) 1552 1553 1554 @magics_class 1555 class LazyMagics(Magics): 1556 @line_magic 1557 def lazy_line(self, line): 1558 print("Lazy Line") 1559 1560 @cell_magic 1561 def lazy_cell(self, line, cell): 1562 print("Lazy Cell") 1563 1564 1565 def load_ipython_extension(ipython): 1566 ipython.register_magics(LazyMagics) 1567 """ 1568 1569 1570 def test_lazy_magics(): 1571 with pytest.raises(UsageError): 1572 ip.run_line_magic("lazy_line", "") 1573 1574 startdir = os.getcwd() 1575 1576 with TemporaryDirectory() as tmpdir: 1577 with prepended_to_syspath(tmpdir): 1578 ptempdir = Path(tmpdir) 1579 tf = ptempdir / "lazy_magic_module.py" 1580 tf.write_text(MINIMAL_LAZY_MAGIC) 1581 ip.magics_manager.register_lazy("lazy_line", Path(tf.name).name[:-3]) 1582 with tt.AssertPrints("Lazy Line"): 1583 ip.run_line_magic("lazy_line", "") 1584 1585 1586 TEST_MODULE = """ 1587 print('Loaded my_tmp') 1588 if __name__ == "__main__": 1589 print('I just ran a script') 1590 """ 1591 1592 def test_run_module_from_import_hook(): 1593 "Test that a module can be loaded via an import hook" 1594 with TemporaryDirectory() as tmpdir: 1595 fullpath = os.path.join(tmpdir, "my_tmp.py") 1596 Path(fullpath).write_text(TEST_MODULE, encoding="utf-8") 1597 1598 import importlib.abc 1599 import importlib.util 1600 1601 class MyTempImporter(importlib.abc.MetaPathFinder, importlib.abc.SourceLoader): 1602 def find_spec(self, fullname, path, target=None): 1603 if fullname == "my_tmp": 1604 return importlib.util.spec_from_loader(fullname, self) 1605 1606 def get_filename(self, fullname): 1607 assert fullname == "my_tmp" 1608 return fullpath 1609 1610 def get_data(self, path): 1611 assert Path(path).samefile(fullpath) 1612 return Path(fullpath).read_text(encoding="utf-8") 1613 1614 sys.meta_path.insert(0, MyTempImporter()) 1615 1616 with capture_output() as captured: 1617 _ip.run_line_magic("run", "-m my_tmp") 1618 _ip.run_cell("import my_tmp") 1619 1620 output = "Loaded my_tmp\nI just ran a script\nLoaded my_tmp\n" 1621 assert output == captured.stdout 1622 1623 sys.meta_path.pop(0) 1624