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