##// END OF EJS Templates
format
Quentin Peter -
Show More
@@ -1,1546 +1,1548 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 719 def test_debug_magic():
719 720 """Test debugging a small code with %debug
720 721
721 722 In [1]: with PdbTestInput(['c']):
722 723 ...: %debug print("a b") #doctest: +ELLIPSIS
723 724 ...:
724 725 ...
725 726 ipdb> c
726 727 a b
727 728 In [2]:
728 729 """
729 730
731
730 732 def test_debug_magic_locals():
731 733 """Test debugging a small code with %debug with locals
732 734
733 735 In [1]: with PdbTestInput(['c']):
734 736 ...: def fun():
735 737 ...: res = 1
736 738 ...: %debug print(res)
737 739 ...: fun()
738 740 ...:
739 741 ...
740 742 ipdb> c
741 743 1
742 744 In [2]:
743 745 """
744 746
745 747 def test_psearch():
746 748 with tt.AssertPrints("dict.fromkeys"):
747 749 _ip.run_cell("dict.fr*?")
748 750 with tt.AssertPrints("Ο€.is_integer"):
749 751 _ip.run_cell("Ο€ = 3.14;\nΟ€.is_integ*?")
750 752
751 753 def test_timeit_shlex():
752 754 """test shlex issues with timeit (#1109)"""
753 755 _ip.ex("def f(*a,**kw): pass")
754 756 _ip.run_line_magic("timeit", '-n1 "this is a bug".count(" ")')
755 757 _ip.run_line_magic("timeit", '-r1 -n1 f(" ", 1)')
756 758 _ip.run_line_magic("timeit", '-r1 -n1 f(" ", 1, " ", 2, " ")')
757 759 _ip.run_line_magic("timeit", '-r1 -n1 ("a " + "b")')
758 760 _ip.run_line_magic("timeit", '-r1 -n1 f("a " + "b")')
759 761 _ip.run_line_magic("timeit", '-r1 -n1 f("a " + "b ")')
760 762
761 763
762 764 def test_timeit_special_syntax():
763 765 "Test %%timeit with IPython special syntax"
764 766 @register_line_magic
765 767 def lmagic(line):
766 768 ip = get_ipython()
767 769 ip.user_ns['lmagic_out'] = line
768 770
769 771 # line mode test
770 772 _ip.run_line_magic("timeit", "-n1 -r1 %lmagic my line")
771 773 assert _ip.user_ns["lmagic_out"] == "my line"
772 774 # cell mode test
773 775 _ip.run_cell_magic("timeit", "-n1 -r1", "%lmagic my line2")
774 776 assert _ip.user_ns["lmagic_out"] == "my line2"
775 777
776 778
777 779 def test_timeit_return():
778 780 """
779 781 test whether timeit -o return object
780 782 """
781 783
782 784 res = _ip.run_line_magic('timeit','-n10 -r10 -o 1')
783 785 assert(res is not None)
784 786
785 787 def test_timeit_quiet():
786 788 """
787 789 test quiet option of timeit magic
788 790 """
789 791 with tt.AssertNotPrints("loops"):
790 792 _ip.run_cell("%timeit -n1 -r1 -q 1")
791 793
792 794 def test_timeit_return_quiet():
793 795 with tt.AssertNotPrints("loops"):
794 796 res = _ip.run_line_magic('timeit', '-n1 -r1 -q -o 1')
795 797 assert (res is not None)
796 798
797 799 def test_timeit_invalid_return():
798 800 with pytest.raises(SyntaxError):
799 801 _ip.run_line_magic('timeit', 'return')
800 802
801 803 @dec.skipif(execution.profile is None)
802 804 def test_prun_special_syntax():
803 805 "Test %%prun with IPython special syntax"
804 806 @register_line_magic
805 807 def lmagic(line):
806 808 ip = get_ipython()
807 809 ip.user_ns['lmagic_out'] = line
808 810
809 811 # line mode test
810 812 _ip.run_line_magic("prun", "-q %lmagic my line")
811 813 assert _ip.user_ns["lmagic_out"] == "my line"
812 814 # cell mode test
813 815 _ip.run_cell_magic("prun", "-q", "%lmagic my line2")
814 816 assert _ip.user_ns["lmagic_out"] == "my line2"
815 817
816 818
817 819 @dec.skipif(execution.profile is None)
818 820 def test_prun_quotes():
819 821 "Test that prun does not clobber string escapes (GH #1302)"
820 822 _ip.magic(r"prun -q x = '\t'")
821 823 assert _ip.user_ns["x"] == "\t"
822 824
823 825
824 826 def test_extension():
825 827 # Debugging information for failures of this test
826 828 print('sys.path:')
827 829 for p in sys.path:
828 830 print(' ', p)
829 831 print('CWD', os.getcwd())
830 832
831 833 pytest.raises(ImportError, _ip.magic, "load_ext daft_extension")
832 834 daft_path = os.path.join(os.path.dirname(__file__), "daft_extension")
833 835 sys.path.insert(0, daft_path)
834 836 try:
835 837 _ip.user_ns.pop('arq', None)
836 838 invalidate_caches() # Clear import caches
837 839 _ip.run_line_magic("load_ext", "daft_extension")
838 840 assert _ip.user_ns["arq"] == 185
839 841 _ip.run_line_magic("unload_ext", "daft_extension")
840 842 assert 'arq' not in _ip.user_ns
841 843 finally:
842 844 sys.path.remove(daft_path)
843 845
844 846
845 847 def test_notebook_export_json():
846 848 pytest.importorskip("nbformat")
847 849 _ip = get_ipython()
848 850 _ip.history_manager.reset() # Clear any existing history.
849 851 cmds = ["a=1", "def b():\n return a**2", "print('noΓ«l, Γ©tΓ©', b())"]
850 852 for i, cmd in enumerate(cmds, start=1):
851 853 _ip.history_manager.store_inputs(i, cmd)
852 854 with TemporaryDirectory() as td:
853 855 outfile = os.path.join(td, "nb.ipynb")
854 856 _ip.run_line_magic("notebook", "%s" % outfile)
855 857
856 858
857 859 class TestEnv(TestCase):
858 860
859 861 def test_env(self):
860 862 env = _ip.run_line_magic("env", "")
861 863 self.assertTrue(isinstance(env, dict))
862 864
863 865 def test_env_secret(self):
864 866 env = _ip.run_line_magic("env", "")
865 867 hidden = "<hidden>"
866 868 with mock.patch.dict(
867 869 os.environ,
868 870 {
869 871 "API_KEY": "abc123",
870 872 "SECRET_THING": "ssshhh",
871 873 "JUPYTER_TOKEN": "",
872 874 "VAR": "abc"
873 875 }
874 876 ):
875 877 env = _ip.run_line_magic("env", "")
876 878 assert env["API_KEY"] == hidden
877 879 assert env["SECRET_THING"] == hidden
878 880 assert env["JUPYTER_TOKEN"] == hidden
879 881 assert env["VAR"] == "abc"
880 882
881 883 def test_env_get_set_simple(self):
882 884 env = _ip.run_line_magic("env", "var val1")
883 885 self.assertEqual(env, None)
884 886 self.assertEqual(os.environ["var"], "val1")
885 887 self.assertEqual(_ip.run_line_magic("env", "var"), "val1")
886 888 env = _ip.run_line_magic("env", "var=val2")
887 889 self.assertEqual(env, None)
888 890 self.assertEqual(os.environ['var'], 'val2')
889 891
890 892 def test_env_get_set_complex(self):
891 893 env = _ip.run_line_magic("env", "var 'val1 '' 'val2")
892 894 self.assertEqual(env, None)
893 895 self.assertEqual(os.environ['var'], "'val1 '' 'val2")
894 896 self.assertEqual(_ip.run_line_magic("env", "var"), "'val1 '' 'val2")
895 897 env = _ip.run_line_magic("env", 'var=val2 val3="val4')
896 898 self.assertEqual(env, None)
897 899 self.assertEqual(os.environ['var'], 'val2 val3="val4')
898 900
899 901 def test_env_set_bad_input(self):
900 902 self.assertRaises(UsageError, lambda: _ip.run_line_magic("set_env", "var"))
901 903
902 904 def test_env_set_whitespace(self):
903 905 self.assertRaises(UsageError, lambda: _ip.run_line_magic("env", "var A=B"))
904 906
905 907
906 908 class CellMagicTestCase(TestCase):
907 909
908 910 def check_ident(self, magic):
909 911 # Manually called, we get the result
910 912 out = _ip.run_cell_magic(magic, "a", "b")
911 913 assert out == ("a", "b")
912 914 # Via run_cell, it goes into the user's namespace via displayhook
913 915 _ip.run_cell("%%" + magic + " c\nd\n")
914 916 assert _ip.user_ns["_"] == ("c", "d\n")
915 917
916 918 def test_cell_magic_func_deco(self):
917 919 "Cell magic using simple decorator"
918 920 @register_cell_magic
919 921 def cellm(line, cell):
920 922 return line, cell
921 923
922 924 self.check_ident('cellm')
923 925
924 926 def test_cell_magic_reg(self):
925 927 "Cell magic manually registered"
926 928 def cellm(line, cell):
927 929 return line, cell
928 930
929 931 _ip.register_magic_function(cellm, 'cell', 'cellm2')
930 932 self.check_ident('cellm2')
931 933
932 934 def test_cell_magic_class(self):
933 935 "Cell magics declared via a class"
934 936 @magics_class
935 937 class MyMagics(Magics):
936 938
937 939 @cell_magic
938 940 def cellm3(self, line, cell):
939 941 return line, cell
940 942
941 943 _ip.register_magics(MyMagics)
942 944 self.check_ident('cellm3')
943 945
944 946 def test_cell_magic_class2(self):
945 947 "Cell magics declared via a class, #2"
946 948 @magics_class
947 949 class MyMagics2(Magics):
948 950
949 951 @cell_magic('cellm4')
950 952 def cellm33(self, line, cell):
951 953 return line, cell
952 954
953 955 _ip.register_magics(MyMagics2)
954 956 self.check_ident('cellm4')
955 957 # Check that nothing is registered as 'cellm33'
956 958 c33 = _ip.find_cell_magic('cellm33')
957 959 assert c33 == None
958 960
959 961 def test_file():
960 962 """Basic %%writefile"""
961 963 ip = get_ipython()
962 964 with TemporaryDirectory() as td:
963 965 fname = os.path.join(td, "file1")
964 966 ip.run_cell_magic(
965 967 "writefile",
966 968 fname,
967 969 "\n".join(
968 970 [
969 971 "line1",
970 972 "line2",
971 973 ]
972 974 ),
973 975 )
974 976 s = Path(fname).read_text(encoding="utf-8")
975 977 assert "line1\n" in s
976 978 assert "line2" in s
977 979
978 980
979 981 @dec.skip_win32
980 982 def test_file_single_quote():
981 983 """Basic %%writefile with embedded single quotes"""
982 984 ip = get_ipython()
983 985 with TemporaryDirectory() as td:
984 986 fname = os.path.join(td, "'file1'")
985 987 ip.run_cell_magic(
986 988 "writefile",
987 989 fname,
988 990 "\n".join(
989 991 [
990 992 "line1",
991 993 "line2",
992 994 ]
993 995 ),
994 996 )
995 997 s = Path(fname).read_text(encoding="utf-8")
996 998 assert "line1\n" in s
997 999 assert "line2" in s
998 1000
999 1001
1000 1002 @dec.skip_win32
1001 1003 def test_file_double_quote():
1002 1004 """Basic %%writefile with embedded double quotes"""
1003 1005 ip = get_ipython()
1004 1006 with TemporaryDirectory() as td:
1005 1007 fname = os.path.join(td, '"file1"')
1006 1008 ip.run_cell_magic(
1007 1009 "writefile",
1008 1010 fname,
1009 1011 "\n".join(
1010 1012 [
1011 1013 "line1",
1012 1014 "line2",
1013 1015 ]
1014 1016 ),
1015 1017 )
1016 1018 s = Path(fname).read_text(encoding="utf-8")
1017 1019 assert "line1\n" in s
1018 1020 assert "line2" in s
1019 1021
1020 1022
1021 1023 def test_file_var_expand():
1022 1024 """%%writefile $filename"""
1023 1025 ip = get_ipython()
1024 1026 with TemporaryDirectory() as td:
1025 1027 fname = os.path.join(td, "file1")
1026 1028 ip.user_ns["filename"] = fname
1027 1029 ip.run_cell_magic(
1028 1030 "writefile",
1029 1031 "$filename",
1030 1032 "\n".join(
1031 1033 [
1032 1034 "line1",
1033 1035 "line2",
1034 1036 ]
1035 1037 ),
1036 1038 )
1037 1039 s = Path(fname).read_text(encoding="utf-8")
1038 1040 assert "line1\n" in s
1039 1041 assert "line2" in s
1040 1042
1041 1043
1042 1044 def test_file_unicode():
1043 1045 """%%writefile with unicode cell"""
1044 1046 ip = get_ipython()
1045 1047 with TemporaryDirectory() as td:
1046 1048 fname = os.path.join(td, 'file1')
1047 1049 ip.run_cell_magic("writefile", fname, u'\n'.join([
1048 1050 u'linΓ©1',
1049 1051 u'linΓ©2',
1050 1052 ]))
1051 1053 with io.open(fname, encoding='utf-8') as f:
1052 1054 s = f.read()
1053 1055 assert "linΓ©1\n" in s
1054 1056 assert "linΓ©2" in s
1055 1057
1056 1058
1057 1059 def test_file_amend():
1058 1060 """%%writefile -a amends files"""
1059 1061 ip = get_ipython()
1060 1062 with TemporaryDirectory() as td:
1061 1063 fname = os.path.join(td, "file2")
1062 1064 ip.run_cell_magic(
1063 1065 "writefile",
1064 1066 fname,
1065 1067 "\n".join(
1066 1068 [
1067 1069 "line1",
1068 1070 "line2",
1069 1071 ]
1070 1072 ),
1071 1073 )
1072 1074 ip.run_cell_magic(
1073 1075 "writefile",
1074 1076 "-a %s" % fname,
1075 1077 "\n".join(
1076 1078 [
1077 1079 "line3",
1078 1080 "line4",
1079 1081 ]
1080 1082 ),
1081 1083 )
1082 1084 s = Path(fname).read_text(encoding="utf-8")
1083 1085 assert "line1\n" in s
1084 1086 assert "line3\n" in s
1085 1087
1086 1088
1087 1089 def test_file_spaces():
1088 1090 """%%file with spaces in filename"""
1089 1091 ip = get_ipython()
1090 1092 with TemporaryWorkingDirectory() as td:
1091 1093 fname = "file name"
1092 1094 ip.run_cell_magic(
1093 1095 "file",
1094 1096 '"%s"' % fname,
1095 1097 "\n".join(
1096 1098 [
1097 1099 "line1",
1098 1100 "line2",
1099 1101 ]
1100 1102 ),
1101 1103 )
1102 1104 s = Path(fname).read_text(encoding="utf-8")
1103 1105 assert "line1\n" in s
1104 1106 assert "line2" in s
1105 1107
1106 1108
1107 1109 def test_script_config():
1108 1110 ip = get_ipython()
1109 1111 ip.config.ScriptMagics.script_magics = ['whoda']
1110 1112 sm = script.ScriptMagics(shell=ip)
1111 1113 assert "whoda" in sm.magics["cell"]
1112 1114
1113 1115
1114 1116 def test_script_out():
1115 1117 ip = get_ipython()
1116 1118 ip.run_cell_magic("script", f"--out output {sys.executable}", "print('hi')")
1117 1119 assert ip.user_ns["output"].strip() == "hi"
1118 1120
1119 1121
1120 1122 def test_script_err():
1121 1123 ip = get_ipython()
1122 1124 ip.run_cell_magic(
1123 1125 "script",
1124 1126 f"--err error {sys.executable}",
1125 1127 "import sys; print('hello', file=sys.stderr)",
1126 1128 )
1127 1129 assert ip.user_ns["error"].strip() == "hello"
1128 1130
1129 1131
1130 1132 def test_script_out_err():
1131 1133 ip = get_ipython()
1132 1134 ip.run_cell_magic(
1133 1135 "script",
1134 1136 f"--out output --err error {sys.executable}",
1135 1137 "\n".join(
1136 1138 [
1137 1139 "import sys",
1138 1140 "print('hi')",
1139 1141 "print('hello', file=sys.stderr)",
1140 1142 ]
1141 1143 ),
1142 1144 )
1143 1145 assert ip.user_ns["output"].strip() == "hi"
1144 1146 assert ip.user_ns["error"].strip() == "hello"
1145 1147
1146 1148
1147 1149 async def test_script_bg_out():
1148 1150 ip = get_ipython()
1149 1151 ip.run_cell_magic("script", f"--bg --out output {sys.executable}", "print('hi')")
1150 1152 assert (await ip.user_ns["output"].read()).strip() == b"hi"
1151 1153 assert ip.user_ns["output"].at_eof()
1152 1154
1153 1155
1154 1156 async def test_script_bg_err():
1155 1157 ip = get_ipython()
1156 1158 ip.run_cell_magic(
1157 1159 "script",
1158 1160 f"--bg --err error {sys.executable}",
1159 1161 "import sys; print('hello', file=sys.stderr)",
1160 1162 )
1161 1163 assert (await ip.user_ns["error"].read()).strip() == b"hello"
1162 1164 assert ip.user_ns["error"].at_eof()
1163 1165
1164 1166
1165 1167 async def test_script_bg_out_err():
1166 1168 ip = get_ipython()
1167 1169 ip.run_cell_magic(
1168 1170 "script",
1169 1171 f"--bg --out output --err error {sys.executable}",
1170 1172 "\n".join(
1171 1173 [
1172 1174 "import sys",
1173 1175 "print('hi')",
1174 1176 "print('hello', file=sys.stderr)",
1175 1177 ]
1176 1178 ),
1177 1179 )
1178 1180 assert (await ip.user_ns["output"].read()).strip() == b"hi"
1179 1181 assert (await ip.user_ns["error"].read()).strip() == b"hello"
1180 1182 assert ip.user_ns["output"].at_eof()
1181 1183 assert ip.user_ns["error"].at_eof()
1182 1184
1183 1185
1184 1186 async def test_script_bg_proc():
1185 1187 ip = get_ipython()
1186 1188 ip.run_cell_magic(
1187 1189 "script",
1188 1190 f"--bg --out output --proc p {sys.executable}",
1189 1191 "\n".join(
1190 1192 [
1191 1193 "import sys",
1192 1194 "print('hi')",
1193 1195 "print('hello', file=sys.stderr)",
1194 1196 ]
1195 1197 ),
1196 1198 )
1197 1199 p = ip.user_ns["p"]
1198 1200 await p.wait()
1199 1201 assert p.returncode == 0
1200 1202 assert (await p.stdout.read()).strip() == b"hi"
1201 1203 # not captured, so empty
1202 1204 assert (await p.stderr.read()) == b""
1203 1205 assert p.stdout.at_eof()
1204 1206 assert p.stderr.at_eof()
1205 1207
1206 1208
1207 1209 def test_script_defaults():
1208 1210 ip = get_ipython()
1209 1211 for cmd in ['sh', 'bash', 'perl', 'ruby']:
1210 1212 try:
1211 1213 find_cmd(cmd)
1212 1214 except Exception:
1213 1215 pass
1214 1216 else:
1215 1217 assert cmd in ip.magics_manager.magics["cell"]
1216 1218
1217 1219
1218 1220 @magics_class
1219 1221 class FooFoo(Magics):
1220 1222 """class with both %foo and %%foo magics"""
1221 1223 @line_magic('foo')
1222 1224 def line_foo(self, line):
1223 1225 "I am line foo"
1224 1226 pass
1225 1227
1226 1228 @cell_magic("foo")
1227 1229 def cell_foo(self, line, cell):
1228 1230 "I am cell foo, not line foo"
1229 1231 pass
1230 1232
1231 1233 def test_line_cell_info():
1232 1234 """%%foo and %foo magics are distinguishable to inspect"""
1233 1235 ip = get_ipython()
1234 1236 ip.magics_manager.register(FooFoo)
1235 1237 oinfo = ip.object_inspect("foo")
1236 1238 assert oinfo["found"] is True
1237 1239 assert oinfo["ismagic"] is True
1238 1240
1239 1241 oinfo = ip.object_inspect("%%foo")
1240 1242 assert oinfo["found"] is True
1241 1243 assert oinfo["ismagic"] is True
1242 1244 assert oinfo["docstring"] == FooFoo.cell_foo.__doc__
1243 1245
1244 1246 oinfo = ip.object_inspect("%foo")
1245 1247 assert oinfo["found"] is True
1246 1248 assert oinfo["ismagic"] is True
1247 1249 assert oinfo["docstring"] == FooFoo.line_foo.__doc__
1248 1250
1249 1251
1250 1252 def test_multiple_magics():
1251 1253 ip = get_ipython()
1252 1254 foo1 = FooFoo(ip)
1253 1255 foo2 = FooFoo(ip)
1254 1256 mm = ip.magics_manager
1255 1257 mm.register(foo1)
1256 1258 assert mm.magics["line"]["foo"].__self__ is foo1
1257 1259 mm.register(foo2)
1258 1260 assert mm.magics["line"]["foo"].__self__ is foo2
1259 1261
1260 1262
1261 1263 def test_alias_magic():
1262 1264 """Test %alias_magic."""
1263 1265 ip = get_ipython()
1264 1266 mm = ip.magics_manager
1265 1267
1266 1268 # Basic operation: both cell and line magics are created, if possible.
1267 1269 ip.run_line_magic("alias_magic", "timeit_alias timeit")
1268 1270 assert "timeit_alias" in mm.magics["line"]
1269 1271 assert "timeit_alias" in mm.magics["cell"]
1270 1272
1271 1273 # --cell is specified, line magic not created.
1272 1274 ip.run_line_magic("alias_magic", "--cell timeit_cell_alias timeit")
1273 1275 assert "timeit_cell_alias" not in mm.magics["line"]
1274 1276 assert "timeit_cell_alias" in mm.magics["cell"]
1275 1277
1276 1278 # Test that line alias is created successfully.
1277 1279 ip.run_line_magic("alias_magic", "--line env_alias env")
1278 1280 assert ip.run_line_magic("env", "") == ip.run_line_magic("env_alias", "")
1279 1281
1280 1282 # Test that line alias with parameters passed in is created successfully.
1281 1283 ip.run_line_magic(
1282 1284 "alias_magic", "--line history_alias history --params " + shlex.quote("3")
1283 1285 )
1284 1286 assert "history_alias" in mm.magics["line"]
1285 1287
1286 1288
1287 1289 def test_save():
1288 1290 """Test %save."""
1289 1291 ip = get_ipython()
1290 1292 ip.history_manager.reset() # Clear any existing history.
1291 1293 cmds = ["a=1", "def b():\n return a**2", "print(a, b())"]
1292 1294 for i, cmd in enumerate(cmds, start=1):
1293 1295 ip.history_manager.store_inputs(i, cmd)
1294 1296 with TemporaryDirectory() as tmpdir:
1295 1297 file = os.path.join(tmpdir, "testsave.py")
1296 1298 ip.run_line_magic("save", "%s 1-10" % file)
1297 1299 content = Path(file).read_text(encoding="utf-8")
1298 1300 assert content.count(cmds[0]) == 1
1299 1301 assert "coding: utf-8" in content
1300 1302 ip.run_line_magic("save", "-a %s 1-10" % file)
1301 1303 content = Path(file).read_text(encoding="utf-8")
1302 1304 assert content.count(cmds[0]) == 2
1303 1305 assert "coding: utf-8" in content
1304 1306
1305 1307
1306 1308 def test_save_with_no_args():
1307 1309 ip = get_ipython()
1308 1310 ip.history_manager.reset() # Clear any existing history.
1309 1311 cmds = ["a=1", "def b():\n return a**2", "print(a, b())", "%save"]
1310 1312 for i, cmd in enumerate(cmds, start=1):
1311 1313 ip.history_manager.store_inputs(i, cmd)
1312 1314
1313 1315 with TemporaryDirectory() as tmpdir:
1314 1316 path = os.path.join(tmpdir, "testsave.py")
1315 1317 ip.run_line_magic("save", path)
1316 1318 content = Path(path).read_text(encoding="utf-8")
1317 1319 expected_content = dedent(
1318 1320 """\
1319 1321 # coding: utf-8
1320 1322 a=1
1321 1323 def b():
1322 1324 return a**2
1323 1325 print(a, b())
1324 1326 """
1325 1327 )
1326 1328 assert content == expected_content
1327 1329
1328 1330
1329 1331 def test_store():
1330 1332 """Test %store."""
1331 1333 ip = get_ipython()
1332 1334 ip.run_line_magic('load_ext', 'storemagic')
1333 1335
1334 1336 # make sure the storage is empty
1335 1337 ip.run_line_magic("store", "-z")
1336 1338 ip.user_ns["var"] = 42
1337 1339 ip.run_line_magic("store", "var")
1338 1340 ip.user_ns["var"] = 39
1339 1341 ip.run_line_magic("store", "-r")
1340 1342 assert ip.user_ns["var"] == 42
1341 1343
1342 1344 ip.run_line_magic("store", "-d var")
1343 1345 ip.user_ns["var"] = 39
1344 1346 ip.run_line_magic("store", "-r")
1345 1347 assert ip.user_ns["var"] == 39
1346 1348
1347 1349
1348 1350 def _run_edit_test(arg_s, exp_filename=None,
1349 1351 exp_lineno=-1,
1350 1352 exp_contents=None,
1351 1353 exp_is_temp=None):
1352 1354 ip = get_ipython()
1353 1355 M = code.CodeMagics(ip)
1354 1356 last_call = ['','']
1355 1357 opts,args = M.parse_options(arg_s,'prxn:')
1356 1358 filename, lineno, is_temp = M._find_edit_target(ip, args, opts, last_call)
1357 1359
1358 1360 if exp_filename is not None:
1359 1361 assert exp_filename == filename
1360 1362 if exp_contents is not None:
1361 1363 with io.open(filename, 'r', encoding='utf-8') as f:
1362 1364 contents = f.read()
1363 1365 assert exp_contents == contents
1364 1366 if exp_lineno != -1:
1365 1367 assert exp_lineno == lineno
1366 1368 if exp_is_temp is not None:
1367 1369 assert exp_is_temp == is_temp
1368 1370
1369 1371
1370 1372 def test_edit_interactive():
1371 1373 """%edit on interactively defined objects"""
1372 1374 ip = get_ipython()
1373 1375 n = ip.execution_count
1374 1376 ip.run_cell("def foo(): return 1", store_history=True)
1375 1377
1376 1378 with pytest.raises(code.InteractivelyDefined) as e:
1377 1379 _run_edit_test("foo")
1378 1380 assert e.value.index == n
1379 1381
1380 1382
1381 1383 def test_edit_cell():
1382 1384 """%edit [cell id]"""
1383 1385 ip = get_ipython()
1384 1386
1385 1387 ip.run_cell("def foo(): return 1", store_history=True)
1386 1388
1387 1389 # test
1388 1390 _run_edit_test("1", exp_contents=ip.user_ns['In'][1], exp_is_temp=True)
1389 1391
1390 1392 def test_edit_fname():
1391 1393 """%edit file"""
1392 1394 # test
1393 1395 _run_edit_test("test file.py", exp_filename="test file.py")
1394 1396
1395 1397 def test_bookmark():
1396 1398 ip = get_ipython()
1397 1399 ip.run_line_magic('bookmark', 'bmname')
1398 1400 with tt.AssertPrints('bmname'):
1399 1401 ip.run_line_magic('bookmark', '-l')
1400 1402 ip.run_line_magic('bookmark', '-d bmname')
1401 1403
1402 1404 def test_ls_magic():
1403 1405 ip = get_ipython()
1404 1406 json_formatter = ip.display_formatter.formatters['application/json']
1405 1407 json_formatter.enabled = True
1406 1408 lsmagic = ip.run_line_magic("lsmagic", "")
1407 1409 with warnings.catch_warnings(record=True) as w:
1408 1410 j = json_formatter(lsmagic)
1409 1411 assert sorted(j) == ["cell", "line"]
1410 1412 assert w == [] # no warnings
1411 1413
1412 1414
1413 1415 def test_strip_initial_indent():
1414 1416 def sii(s):
1415 1417 lines = s.splitlines()
1416 1418 return '\n'.join(code.strip_initial_indent(lines))
1417 1419
1418 1420 assert sii(" a = 1\nb = 2") == "a = 1\nb = 2"
1419 1421 assert sii(" a\n b\nc") == "a\n b\nc"
1420 1422 assert sii("a\n b") == "a\n b"
1421 1423
1422 1424 def test_logging_magic_quiet_from_arg():
1423 1425 _ip.config.LoggingMagics.quiet = False
1424 1426 lm = logging.LoggingMagics(shell=_ip)
1425 1427 with TemporaryDirectory() as td:
1426 1428 try:
1427 1429 with tt.AssertNotPrints(re.compile("Activating.*")):
1428 1430 lm.logstart('-q {}'.format(
1429 1431 os.path.join(td, "quiet_from_arg.log")))
1430 1432 finally:
1431 1433 _ip.logger.logstop()
1432 1434
1433 1435 def test_logging_magic_quiet_from_config():
1434 1436 _ip.config.LoggingMagics.quiet = True
1435 1437 lm = logging.LoggingMagics(shell=_ip)
1436 1438 with TemporaryDirectory() as td:
1437 1439 try:
1438 1440 with tt.AssertNotPrints(re.compile("Activating.*")):
1439 1441 lm.logstart(os.path.join(td, "quiet_from_config.log"))
1440 1442 finally:
1441 1443 _ip.logger.logstop()
1442 1444
1443 1445
1444 1446 def test_logging_magic_not_quiet():
1445 1447 _ip.config.LoggingMagics.quiet = False
1446 1448 lm = logging.LoggingMagics(shell=_ip)
1447 1449 with TemporaryDirectory() as td:
1448 1450 try:
1449 1451 with tt.AssertPrints(re.compile("Activating.*")):
1450 1452 lm.logstart(os.path.join(td, "not_quiet.log"))
1451 1453 finally:
1452 1454 _ip.logger.logstop()
1453 1455
1454 1456
1455 1457 def test_time_no_var_expand():
1456 1458 _ip.user_ns["a"] = 5
1457 1459 _ip.user_ns["b"] = []
1458 1460 _ip.run_line_magic("time", 'b.append("{a}")')
1459 1461 assert _ip.user_ns["b"] == ["{a}"]
1460 1462
1461 1463
1462 1464 # this is slow, put at the end for local testing.
1463 1465 def test_timeit_arguments():
1464 1466 "Test valid timeit arguments, should not cause SyntaxError (GH #1269)"
1465 1467 _ip.run_line_magic("timeit", "-n1 -r1 a=('#')")
1466 1468
1467 1469
1468 1470 MINIMAL_LAZY_MAGIC = """
1469 1471 from IPython.core.magic import (
1470 1472 Magics,
1471 1473 magics_class,
1472 1474 line_magic,
1473 1475 cell_magic,
1474 1476 )
1475 1477
1476 1478
1477 1479 @magics_class
1478 1480 class LazyMagics(Magics):
1479 1481 @line_magic
1480 1482 def lazy_line(self, line):
1481 1483 print("Lazy Line")
1482 1484
1483 1485 @cell_magic
1484 1486 def lazy_cell(self, line, cell):
1485 1487 print("Lazy Cell")
1486 1488
1487 1489
1488 1490 def load_ipython_extension(ipython):
1489 1491 ipython.register_magics(LazyMagics)
1490 1492 """
1491 1493
1492 1494
1493 1495 def test_lazy_magics():
1494 1496 with pytest.raises(UsageError):
1495 1497 ip.run_line_magic("lazy_line", "")
1496 1498
1497 1499 startdir = os.getcwd()
1498 1500
1499 1501 with TemporaryDirectory() as tmpdir:
1500 1502 with prepended_to_syspath(tmpdir):
1501 1503 ptempdir = Path(tmpdir)
1502 1504 tf = ptempdir / "lazy_magic_module.py"
1503 1505 tf.write_text(MINIMAL_LAZY_MAGIC)
1504 1506 ip.magics_manager.register_lazy("lazy_line", Path(tf.name).name[:-3])
1505 1507 with tt.AssertPrints("Lazy Line"):
1506 1508 ip.run_line_magic("lazy_line", "")
1507 1509
1508 1510
1509 1511 TEST_MODULE = """
1510 1512 print('Loaded my_tmp')
1511 1513 if __name__ == "__main__":
1512 1514 print('I just ran a script')
1513 1515 """
1514 1516
1515 1517 def test_run_module_from_import_hook():
1516 1518 "Test that a module can be loaded via an import hook"
1517 1519 with TemporaryDirectory() as tmpdir:
1518 1520 fullpath = os.path.join(tmpdir, "my_tmp.py")
1519 1521 Path(fullpath).write_text(TEST_MODULE, encoding="utf-8")
1520 1522
1521 1523 import importlib.abc
1522 1524 import importlib.util
1523 1525
1524 1526 class MyTempImporter(importlib.abc.MetaPathFinder, importlib.abc.SourceLoader):
1525 1527 def find_spec(self, fullname, path, target=None):
1526 1528 if fullname == "my_tmp":
1527 1529 return importlib.util.spec_from_loader(fullname, self)
1528 1530
1529 1531 def get_filename(self, fullname):
1530 1532 assert fullname == "my_tmp"
1531 1533 return fullpath
1532 1534
1533 1535 def get_data(self, path):
1534 1536 assert Path(path).samefile(fullpath)
1535 1537 return Path(fullpath).read_text(encoding="utf-8")
1536 1538
1537 1539 sys.meta_path.insert(0, MyTempImporter())
1538 1540
1539 1541 with capture_output() as captured:
1540 1542 _ip.run_line_magic("run", "-m my_tmp")
1541 1543 _ip.run_cell("import my_tmp")
1542 1544
1543 1545 output = "Loaded my_tmp\nI just ran a script\nLoaded my_tmp\n"
1544 1546 assert output == captured.stdout
1545 1547
1546 1548 sys.meta_path.pop(0)
General Comments 0
You need to be logged in to leave comments. Login now