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