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