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