##// END OF EJS Templates
Again
nfgf -
Show More
@@ -1,1471 +1,1471 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_outputwith_semicolon():
422 def test_time_no_outputwith_semicolon():
423 ip = get_ipython()
423 ip = get_ipython()
424
424
425 with tt.AssertPrints(" 123456"):
425 with tt.AssertPrints(" 123456"):
426 with tt.AssertPrints("Wall time: ", suppress=False):
426 with tt.AssertPrints("Wall time: ", suppress=False):
427 with tt.AssertPrints("CPU times: ", suppress=False):
427 with tt.AssertPrints("CPU times: ", suppress=False):
428 ip.run_cell("%time 123000+456")
428 ip.run_cell("%time 123000+456")
429
429
430 with tt.AssertNotPrints(" 123456"):
430 with tt.AssertNotPrints(" 123456"):
431 with tt.AssertPrints("Wall time: ", suppress=False):
431 with tt.AssertPrints("Wall time: ", suppress=False):
432 with tt.AssertPrints("CPU times: ", suppress=False):
432 with tt.AssertPrints("CPU times: ", suppress=False):
433 ip.run_cell("%time 123000+456;")
433 ip.run_cell("%time 123000+456;")
434
434
435
435
436 def test_time_last_not_expression():
436 def test_time_last_not_expression():
437 ip.run_cell("%%time\n"
437 ip.run_cell("%%time\n"
438 "var_1 = 1\n"
438 "var_1 = 1\n"
439 "var_2 = 2\n")
439 "var_2 = 2\n")
440 assert ip.user_ns['var_1'] == 1
440 assert ip.user_ns['var_1'] == 1
441 del ip.user_ns['var_1']
441 del ip.user_ns['var_1']
442 assert ip.user_ns['var_2'] == 2
442 assert ip.user_ns['var_2'] == 2
443 del ip.user_ns['var_2']
443 del ip.user_ns['var_2']
444
444
445
445
446 @dec.skip_win32
446 @dec.skip_win32
447 def test_time2():
447 def test_time2():
448 ip = get_ipython()
448 ip = get_ipython()
449
449
450 with tt.AssertPrints("CPU times: user "):
450 with tt.AssertPrints("CPU times: user "):
451 ip.run_cell("%time None")
451 ip.run_cell("%time None")
452
452
453 def test_time3():
453 def test_time3():
454 """Erroneous magic function calls, issue gh-3334"""
454 """Erroneous magic function calls, issue gh-3334"""
455 ip = get_ipython()
455 ip = get_ipython()
456 ip.user_ns.pop('run', None)
456 ip.user_ns.pop('run', None)
457
457
458 with tt.AssertNotPrints("not found", channel='stderr'):
458 with tt.AssertNotPrints("not found", channel='stderr'):
459 ip.run_cell("%%time\n"
459 ip.run_cell("%%time\n"
460 "run = 0\n"
460 "run = 0\n"
461 "run += 1")
461 "run += 1")
462
462
463 def test_multiline_time():
463 def test_multiline_time():
464 """Make sure last statement from time return a value."""
464 """Make sure last statement from time return a value."""
465 ip = get_ipython()
465 ip = get_ipython()
466 ip.user_ns.pop('run', None)
466 ip.user_ns.pop('run', None)
467
467
468 ip.run_cell(
468 ip.run_cell(
469 dedent(
469 dedent(
470 """\
470 """\
471 %%time
471 %%time
472 a = "ho"
472 a = "ho"
473 b = "hey"
473 b = "hey"
474 a+b
474 a+b
475 """
475 """
476 )
476 )
477 )
477 )
478 assert ip.user_ns_hidden["_"] == "hohey"
478 assert ip.user_ns_hidden["_"] == "hohey"
479
479
480
480
481 def test_time_local_ns():
481 def test_time_local_ns():
482 """
482 """
483 Test that local_ns is actually global_ns when running a cell magic
483 Test that local_ns is actually global_ns when running a cell magic
484 """
484 """
485 ip = get_ipython()
485 ip = get_ipython()
486 ip.run_cell("%%time\n" "myvar = 1")
486 ip.run_cell("%%time\n" "myvar = 1")
487 assert ip.user_ns["myvar"] == 1
487 assert ip.user_ns["myvar"] == 1
488 del ip.user_ns["myvar"]
488 del ip.user_ns["myvar"]
489
489
490
490
491 def test_doctest_mode():
491 def test_doctest_mode():
492 "Toggle doctest_mode twice, it should be a no-op and run without error"
492 "Toggle doctest_mode twice, it should be a no-op and run without error"
493 _ip.run_line_magic("doctest_mode", "")
493 _ip.run_line_magic("doctest_mode", "")
494 _ip.run_line_magic("doctest_mode", "")
494 _ip.run_line_magic("doctest_mode", "")
495
495
496
496
497 def test_parse_options():
497 def test_parse_options():
498 """Tests for basic options parsing in magics."""
498 """Tests for basic options parsing in magics."""
499 # These are only the most minimal of tests, more should be added later. At
499 # These are only the most minimal of tests, more should be added later. At
500 # the very least we check that basic text/unicode calls work OK.
500 # the very least we check that basic text/unicode calls work OK.
501 m = DummyMagics(_ip)
501 m = DummyMagics(_ip)
502 assert m.parse_options("foo", "")[1] == "foo"
502 assert m.parse_options("foo", "")[1] == "foo"
503 assert m.parse_options("foo", "")[1] == "foo"
503 assert m.parse_options("foo", "")[1] == "foo"
504
504
505
505
506 def test_parse_options_preserve_non_option_string():
506 def test_parse_options_preserve_non_option_string():
507 """Test to assert preservation of non-option part of magic-block, while parsing magic options."""
507 """Test to assert preservation of non-option part of magic-block, while parsing magic options."""
508 m = DummyMagics(_ip)
508 m = DummyMagics(_ip)
509 opts, stmt = m.parse_options(
509 opts, stmt = m.parse_options(
510 " -n1 -r 13 _ = 314 + foo", "n:r:", preserve_non_opts=True
510 " -n1 -r 13 _ = 314 + foo", "n:r:", preserve_non_opts=True
511 )
511 )
512 assert opts == {"n": "1", "r": "13"}
512 assert opts == {"n": "1", "r": "13"}
513 assert stmt == "_ = 314 + foo"
513 assert stmt == "_ = 314 + foo"
514
514
515
515
516 def test_run_magic_preserve_code_block():
516 def test_run_magic_preserve_code_block():
517 """Test to assert preservation of non-option part of magic-block, while running magic."""
517 """Test to assert preservation of non-option part of magic-block, while running magic."""
518 _ip.user_ns["spaces"] = []
518 _ip.user_ns["spaces"] = []
519 _ip.run_line_magic(
519 _ip.run_line_magic(
520 "timeit", "-n1 -r1 spaces.append([s.count(' ') for s in ['document']])"
520 "timeit", "-n1 -r1 spaces.append([s.count(' ') for s in ['document']])"
521 )
521 )
522 assert _ip.user_ns["spaces"] == [[0]]
522 assert _ip.user_ns["spaces"] == [[0]]
523
523
524
524
525 def test_dirops():
525 def test_dirops():
526 """Test various directory handling operations."""
526 """Test various directory handling operations."""
527 # curpath = lambda :os.path.splitdrive(os.getcwd())[1].replace('\\','/')
527 # curpath = lambda :os.path.splitdrive(os.getcwd())[1].replace('\\','/')
528 curpath = os.getcwd
528 curpath = os.getcwd
529 startdir = os.getcwd()
529 startdir = os.getcwd()
530 ipdir = os.path.realpath(_ip.ipython_dir)
530 ipdir = os.path.realpath(_ip.ipython_dir)
531 try:
531 try:
532 _ip.run_line_magic("cd", '"%s"' % ipdir)
532 _ip.run_line_magic("cd", '"%s"' % ipdir)
533 assert curpath() == ipdir
533 assert curpath() == ipdir
534 _ip.run_line_magic("cd", "-")
534 _ip.run_line_magic("cd", "-")
535 assert curpath() == startdir
535 assert curpath() == startdir
536 _ip.run_line_magic("pushd", '"%s"' % ipdir)
536 _ip.run_line_magic("pushd", '"%s"' % ipdir)
537 assert curpath() == ipdir
537 assert curpath() == ipdir
538 _ip.run_line_magic("popd", "")
538 _ip.run_line_magic("popd", "")
539 assert curpath() == startdir
539 assert curpath() == startdir
540 finally:
540 finally:
541 os.chdir(startdir)
541 os.chdir(startdir)
542
542
543
543
544 def test_cd_force_quiet():
544 def test_cd_force_quiet():
545 """Test OSMagics.cd_force_quiet option"""
545 """Test OSMagics.cd_force_quiet option"""
546 _ip.config.OSMagics.cd_force_quiet = True
546 _ip.config.OSMagics.cd_force_quiet = True
547 osmagics = osm.OSMagics(shell=_ip)
547 osmagics = osm.OSMagics(shell=_ip)
548
548
549 startdir = os.getcwd()
549 startdir = os.getcwd()
550 ipdir = os.path.realpath(_ip.ipython_dir)
550 ipdir = os.path.realpath(_ip.ipython_dir)
551
551
552 try:
552 try:
553 with tt.AssertNotPrints(ipdir):
553 with tt.AssertNotPrints(ipdir):
554 osmagics.cd('"%s"' % ipdir)
554 osmagics.cd('"%s"' % ipdir)
555 with tt.AssertNotPrints(startdir):
555 with tt.AssertNotPrints(startdir):
556 osmagics.cd('-')
556 osmagics.cd('-')
557 finally:
557 finally:
558 os.chdir(startdir)
558 os.chdir(startdir)
559
559
560
560
561 def test_xmode():
561 def test_xmode():
562 # Calling xmode three times should be a no-op
562 # Calling xmode three times should be a no-op
563 xmode = _ip.InteractiveTB.mode
563 xmode = _ip.InteractiveTB.mode
564 for i in range(4):
564 for i in range(4):
565 _ip.run_line_magic("xmode", "")
565 _ip.run_line_magic("xmode", "")
566 assert _ip.InteractiveTB.mode == xmode
566 assert _ip.InteractiveTB.mode == xmode
567
567
568 def test_reset_hard():
568 def test_reset_hard():
569 monitor = []
569 monitor = []
570 class A(object):
570 class A(object):
571 def __del__(self):
571 def __del__(self):
572 monitor.append(1)
572 monitor.append(1)
573 def __repr__(self):
573 def __repr__(self):
574 return "<A instance>"
574 return "<A instance>"
575
575
576 _ip.user_ns["a"] = A()
576 _ip.user_ns["a"] = A()
577 _ip.run_cell("a")
577 _ip.run_cell("a")
578
578
579 assert monitor == []
579 assert monitor == []
580 _ip.run_line_magic("reset", "-f")
580 _ip.run_line_magic("reset", "-f")
581 assert monitor == [1]
581 assert monitor == [1]
582
582
583 class TestXdel(tt.TempFileMixin):
583 class TestXdel(tt.TempFileMixin):
584 def test_xdel(self):
584 def test_xdel(self):
585 """Test that references from %run are cleared by xdel."""
585 """Test that references from %run are cleared by xdel."""
586 src = ("class A(object):\n"
586 src = ("class A(object):\n"
587 " monitor = []\n"
587 " monitor = []\n"
588 " def __del__(self):\n"
588 " def __del__(self):\n"
589 " self.monitor.append(1)\n"
589 " self.monitor.append(1)\n"
590 "a = A()\n")
590 "a = A()\n")
591 self.mktmp(src)
591 self.mktmp(src)
592 # %run creates some hidden references...
592 # %run creates some hidden references...
593 _ip.run_line_magic("run", "%s" % self.fname)
593 _ip.run_line_magic("run", "%s" % self.fname)
594 # ... as does the displayhook.
594 # ... as does the displayhook.
595 _ip.run_cell("a")
595 _ip.run_cell("a")
596
596
597 monitor = _ip.user_ns["A"].monitor
597 monitor = _ip.user_ns["A"].monitor
598 assert monitor == []
598 assert monitor == []
599
599
600 _ip.run_line_magic("xdel", "a")
600 _ip.run_line_magic("xdel", "a")
601
601
602 # Check that a's __del__ method has been called.
602 # Check that a's __del__ method has been called.
603 gc.collect(0)
603 gc.collect(0)
604 assert monitor == [1]
604 assert monitor == [1]
605
605
606 def doctest_who():
606 def doctest_who():
607 """doctest for %who
607 """doctest for %who
608
608
609 In [1]: %reset -sf
609 In [1]: %reset -sf
610
610
611 In [2]: alpha = 123
611 In [2]: alpha = 123
612
612
613 In [3]: beta = 'beta'
613 In [3]: beta = 'beta'
614
614
615 In [4]: %who int
615 In [4]: %who int
616 alpha
616 alpha
617
617
618 In [5]: %who str
618 In [5]: %who str
619 beta
619 beta
620
620
621 In [6]: %whos
621 In [6]: %whos
622 Variable Type Data/Info
622 Variable Type Data/Info
623 ----------------------------
623 ----------------------------
624 alpha int 123
624 alpha int 123
625 beta str beta
625 beta str beta
626
626
627 In [7]: %who_ls
627 In [7]: %who_ls
628 Out[7]: ['alpha', 'beta']
628 Out[7]: ['alpha', 'beta']
629 """
629 """
630
630
631 def test_whos():
631 def test_whos():
632 """Check that whos is protected against objects where repr() fails."""
632 """Check that whos is protected against objects where repr() fails."""
633 class A(object):
633 class A(object):
634 def __repr__(self):
634 def __repr__(self):
635 raise Exception()
635 raise Exception()
636 _ip.user_ns['a'] = A()
636 _ip.user_ns['a'] = A()
637 _ip.run_line_magic("whos", "")
637 _ip.run_line_magic("whos", "")
638
638
639 def doctest_precision():
639 def doctest_precision():
640 """doctest for %precision
640 """doctest for %precision
641
641
642 In [1]: f = get_ipython().display_formatter.formatters['text/plain']
642 In [1]: f = get_ipython().display_formatter.formatters['text/plain']
643
643
644 In [2]: %precision 5
644 In [2]: %precision 5
645 Out[2]: '%.5f'
645 Out[2]: '%.5f'
646
646
647 In [3]: f.float_format
647 In [3]: f.float_format
648 Out[3]: '%.5f'
648 Out[3]: '%.5f'
649
649
650 In [4]: %precision %e
650 In [4]: %precision %e
651 Out[4]: '%e'
651 Out[4]: '%e'
652
652
653 In [5]: f(3.1415927)
653 In [5]: f(3.1415927)
654 Out[5]: '3.141593e+00'
654 Out[5]: '3.141593e+00'
655 """
655 """
656
656
657 def test_debug_magic():
657 def test_debug_magic():
658 """Test debugging a small code with %debug
658 """Test debugging a small code with %debug
659
659
660 In [1]: with PdbTestInput(['c']):
660 In [1]: with PdbTestInput(['c']):
661 ...: %debug print("a b") #doctest: +ELLIPSIS
661 ...: %debug print("a b") #doctest: +ELLIPSIS
662 ...:
662 ...:
663 ...
663 ...
664 ipdb> c
664 ipdb> c
665 a b
665 a b
666 In [2]:
666 In [2]:
667 """
667 """
668
668
669 def test_psearch():
669 def test_psearch():
670 with tt.AssertPrints("dict.fromkeys"):
670 with tt.AssertPrints("dict.fromkeys"):
671 _ip.run_cell("dict.fr*?")
671 _ip.run_cell("dict.fr*?")
672 with tt.AssertPrints("Ο€.is_integer"):
672 with tt.AssertPrints("Ο€.is_integer"):
673 _ip.run_cell("Ο€ = 3.14;\nΟ€.is_integ*?")
673 _ip.run_cell("Ο€ = 3.14;\nΟ€.is_integ*?")
674
674
675 def test_timeit_shlex():
675 def test_timeit_shlex():
676 """test shlex issues with timeit (#1109)"""
676 """test shlex issues with timeit (#1109)"""
677 _ip.ex("def f(*a,**kw): pass")
677 _ip.ex("def f(*a,**kw): pass")
678 _ip.run_line_magic("timeit", '-n1 "this is a bug".count(" ")')
678 _ip.run_line_magic("timeit", '-n1 "this is a bug".count(" ")')
679 _ip.run_line_magic("timeit", '-r1 -n1 f(" ", 1)')
679 _ip.run_line_magic("timeit", '-r1 -n1 f(" ", 1)')
680 _ip.run_line_magic("timeit", '-r1 -n1 f(" ", 1, " ", 2, " ")')
680 _ip.run_line_magic("timeit", '-r1 -n1 f(" ", 1, " ", 2, " ")')
681 _ip.run_line_magic("timeit", '-r1 -n1 ("a " + "b")')
681 _ip.run_line_magic("timeit", '-r1 -n1 ("a " + "b")')
682 _ip.run_line_magic("timeit", '-r1 -n1 f("a " + "b")')
682 _ip.run_line_magic("timeit", '-r1 -n1 f("a " + "b")')
683 _ip.run_line_magic("timeit", '-r1 -n1 f("a " + "b ")')
683 _ip.run_line_magic("timeit", '-r1 -n1 f("a " + "b ")')
684
684
685
685
686 def test_timeit_special_syntax():
686 def test_timeit_special_syntax():
687 "Test %%timeit with IPython special syntax"
687 "Test %%timeit with IPython special syntax"
688 @register_line_magic
688 @register_line_magic
689 def lmagic(line):
689 def lmagic(line):
690 ip = get_ipython()
690 ip = get_ipython()
691 ip.user_ns['lmagic_out'] = line
691 ip.user_ns['lmagic_out'] = line
692
692
693 # line mode test
693 # line mode test
694 _ip.run_line_magic("timeit", "-n1 -r1 %lmagic my line")
694 _ip.run_line_magic("timeit", "-n1 -r1 %lmagic my line")
695 assert _ip.user_ns["lmagic_out"] == "my line"
695 assert _ip.user_ns["lmagic_out"] == "my line"
696 # cell mode test
696 # cell mode test
697 _ip.run_cell_magic("timeit", "-n1 -r1", "%lmagic my line2")
697 _ip.run_cell_magic("timeit", "-n1 -r1", "%lmagic my line2")
698 assert _ip.user_ns["lmagic_out"] == "my line2"
698 assert _ip.user_ns["lmagic_out"] == "my line2"
699
699
700
700
701 def test_timeit_return():
701 def test_timeit_return():
702 """
702 """
703 test whether timeit -o return object
703 test whether timeit -o return object
704 """
704 """
705
705
706 res = _ip.run_line_magic('timeit','-n10 -r10 -o 1')
706 res = _ip.run_line_magic('timeit','-n10 -r10 -o 1')
707 assert(res is not None)
707 assert(res is not None)
708
708
709 def test_timeit_quiet():
709 def test_timeit_quiet():
710 """
710 """
711 test quiet option of timeit magic
711 test quiet option of timeit magic
712 """
712 """
713 with tt.AssertNotPrints("loops"):
713 with tt.AssertNotPrints("loops"):
714 _ip.run_cell("%timeit -n1 -r1 -q 1")
714 _ip.run_cell("%timeit -n1 -r1 -q 1")
715
715
716 def test_timeit_return_quiet():
716 def test_timeit_return_quiet():
717 with tt.AssertNotPrints("loops"):
717 with tt.AssertNotPrints("loops"):
718 res = _ip.run_line_magic('timeit', '-n1 -r1 -q -o 1')
718 res = _ip.run_line_magic('timeit', '-n1 -r1 -q -o 1')
719 assert (res is not None)
719 assert (res is not None)
720
720
721 def test_timeit_invalid_return():
721 def test_timeit_invalid_return():
722 with pytest.raises(SyntaxError):
722 with pytest.raises(SyntaxError):
723 _ip.run_line_magic('timeit', 'return')
723 _ip.run_line_magic('timeit', 'return')
724
724
725 @dec.skipif(execution.profile is None)
725 @dec.skipif(execution.profile is None)
726 def test_prun_special_syntax():
726 def test_prun_special_syntax():
727 "Test %%prun with IPython special syntax"
727 "Test %%prun with IPython special syntax"
728 @register_line_magic
728 @register_line_magic
729 def lmagic(line):
729 def lmagic(line):
730 ip = get_ipython()
730 ip = get_ipython()
731 ip.user_ns['lmagic_out'] = line
731 ip.user_ns['lmagic_out'] = line
732
732
733 # line mode test
733 # line mode test
734 _ip.run_line_magic("prun", "-q %lmagic my line")
734 _ip.run_line_magic("prun", "-q %lmagic my line")
735 assert _ip.user_ns["lmagic_out"] == "my line"
735 assert _ip.user_ns["lmagic_out"] == "my line"
736 # cell mode test
736 # cell mode test
737 _ip.run_cell_magic("prun", "-q", "%lmagic my line2")
737 _ip.run_cell_magic("prun", "-q", "%lmagic my line2")
738 assert _ip.user_ns["lmagic_out"] == "my line2"
738 assert _ip.user_ns["lmagic_out"] == "my line2"
739
739
740
740
741 @dec.skipif(execution.profile is None)
741 @dec.skipif(execution.profile is None)
742 def test_prun_quotes():
742 def test_prun_quotes():
743 "Test that prun does not clobber string escapes (GH #1302)"
743 "Test that prun does not clobber string escapes (GH #1302)"
744 _ip.magic(r"prun -q x = '\t'")
744 _ip.magic(r"prun -q x = '\t'")
745 assert _ip.user_ns["x"] == "\t"
745 assert _ip.user_ns["x"] == "\t"
746
746
747
747
748 def test_extension():
748 def test_extension():
749 # Debugging information for failures of this test
749 # Debugging information for failures of this test
750 print('sys.path:')
750 print('sys.path:')
751 for p in sys.path:
751 for p in sys.path:
752 print(' ', p)
752 print(' ', p)
753 print('CWD', os.getcwd())
753 print('CWD', os.getcwd())
754
754
755 pytest.raises(ImportError, _ip.magic, "load_ext daft_extension")
755 pytest.raises(ImportError, _ip.magic, "load_ext daft_extension")
756 daft_path = os.path.join(os.path.dirname(__file__), "daft_extension")
756 daft_path = os.path.join(os.path.dirname(__file__), "daft_extension")
757 sys.path.insert(0, daft_path)
757 sys.path.insert(0, daft_path)
758 try:
758 try:
759 _ip.user_ns.pop('arq', None)
759 _ip.user_ns.pop('arq', None)
760 invalidate_caches() # Clear import caches
760 invalidate_caches() # Clear import caches
761 _ip.run_line_magic("load_ext", "daft_extension")
761 _ip.run_line_magic("load_ext", "daft_extension")
762 assert _ip.user_ns["arq"] == 185
762 assert _ip.user_ns["arq"] == 185
763 _ip.run_line_magic("unload_ext", "daft_extension")
763 _ip.run_line_magic("unload_ext", "daft_extension")
764 assert 'arq' not in _ip.user_ns
764 assert 'arq' not in _ip.user_ns
765 finally:
765 finally:
766 sys.path.remove(daft_path)
766 sys.path.remove(daft_path)
767
767
768
768
769 def test_notebook_export_json():
769 def test_notebook_export_json():
770 pytest.importorskip("nbformat")
770 pytest.importorskip("nbformat")
771 _ip = get_ipython()
771 _ip = get_ipython()
772 _ip.history_manager.reset() # Clear any existing history.
772 _ip.history_manager.reset() # Clear any existing history.
773 cmds = ["a=1", "def b():\n return a**2", "print('noΓ«l, Γ©tΓ©', b())"]
773 cmds = ["a=1", "def b():\n return a**2", "print('noΓ«l, Γ©tΓ©', b())"]
774 for i, cmd in enumerate(cmds, start=1):
774 for i, cmd in enumerate(cmds, start=1):
775 _ip.history_manager.store_inputs(i, cmd)
775 _ip.history_manager.store_inputs(i, cmd)
776 with TemporaryDirectory() as td:
776 with TemporaryDirectory() as td:
777 outfile = os.path.join(td, "nb.ipynb")
777 outfile = os.path.join(td, "nb.ipynb")
778 _ip.run_line_magic("notebook", "%s" % outfile)
778 _ip.run_line_magic("notebook", "%s" % outfile)
779
779
780
780
781 class TestEnv(TestCase):
781 class TestEnv(TestCase):
782
782
783 def test_env(self):
783 def test_env(self):
784 env = _ip.run_line_magic("env", "")
784 env = _ip.run_line_magic("env", "")
785 self.assertTrue(isinstance(env, dict))
785 self.assertTrue(isinstance(env, dict))
786
786
787 def test_env_secret(self):
787 def test_env_secret(self):
788 env = _ip.run_line_magic("env", "")
788 env = _ip.run_line_magic("env", "")
789 hidden = "<hidden>"
789 hidden = "<hidden>"
790 with mock.patch.dict(
790 with mock.patch.dict(
791 os.environ,
791 os.environ,
792 {
792 {
793 "API_KEY": "abc123",
793 "API_KEY": "abc123",
794 "SECRET_THING": "ssshhh",
794 "SECRET_THING": "ssshhh",
795 "JUPYTER_TOKEN": "",
795 "JUPYTER_TOKEN": "",
796 "VAR": "abc"
796 "VAR": "abc"
797 }
797 }
798 ):
798 ):
799 env = _ip.run_line_magic("env", "")
799 env = _ip.run_line_magic("env", "")
800 assert env["API_KEY"] == hidden
800 assert env["API_KEY"] == hidden
801 assert env["SECRET_THING"] == hidden
801 assert env["SECRET_THING"] == hidden
802 assert env["JUPYTER_TOKEN"] == hidden
802 assert env["JUPYTER_TOKEN"] == hidden
803 assert env["VAR"] == "abc"
803 assert env["VAR"] == "abc"
804
804
805 def test_env_get_set_simple(self):
805 def test_env_get_set_simple(self):
806 env = _ip.run_line_magic("env", "var val1")
806 env = _ip.run_line_magic("env", "var val1")
807 self.assertEqual(env, None)
807 self.assertEqual(env, None)
808 self.assertEqual(os.environ["var"], "val1")
808 self.assertEqual(os.environ["var"], "val1")
809 self.assertEqual(_ip.run_line_magic("env", "var"), "val1")
809 self.assertEqual(_ip.run_line_magic("env", "var"), "val1")
810 env = _ip.run_line_magic("env", "var=val2")
810 env = _ip.run_line_magic("env", "var=val2")
811 self.assertEqual(env, None)
811 self.assertEqual(env, None)
812 self.assertEqual(os.environ['var'], 'val2')
812 self.assertEqual(os.environ['var'], 'val2')
813
813
814 def test_env_get_set_complex(self):
814 def test_env_get_set_complex(self):
815 env = _ip.run_line_magic("env", "var 'val1 '' 'val2")
815 env = _ip.run_line_magic("env", "var 'val1 '' 'val2")
816 self.assertEqual(env, None)
816 self.assertEqual(env, None)
817 self.assertEqual(os.environ['var'], "'val1 '' 'val2")
817 self.assertEqual(os.environ['var'], "'val1 '' 'val2")
818 self.assertEqual(_ip.run_line_magic("env", "var"), "'val1 '' 'val2")
818 self.assertEqual(_ip.run_line_magic("env", "var"), "'val1 '' 'val2")
819 env = _ip.run_line_magic("env", 'var=val2 val3="val4')
819 env = _ip.run_line_magic("env", 'var=val2 val3="val4')
820 self.assertEqual(env, None)
820 self.assertEqual(env, None)
821 self.assertEqual(os.environ['var'], 'val2 val3="val4')
821 self.assertEqual(os.environ['var'], 'val2 val3="val4')
822
822
823 def test_env_set_bad_input(self):
823 def test_env_set_bad_input(self):
824 self.assertRaises(UsageError, lambda: _ip.run_line_magic("set_env", "var"))
824 self.assertRaises(UsageError, lambda: _ip.run_line_magic("set_env", "var"))
825
825
826 def test_env_set_whitespace(self):
826 def test_env_set_whitespace(self):
827 self.assertRaises(UsageError, lambda: _ip.run_line_magic("env", "var A=B"))
827 self.assertRaises(UsageError, lambda: _ip.run_line_magic("env", "var A=B"))
828
828
829
829
830 class CellMagicTestCase(TestCase):
830 class CellMagicTestCase(TestCase):
831
831
832 def check_ident(self, magic):
832 def check_ident(self, magic):
833 # Manually called, we get the result
833 # Manually called, we get the result
834 out = _ip.run_cell_magic(magic, "a", "b")
834 out = _ip.run_cell_magic(magic, "a", "b")
835 assert out == ("a", "b")
835 assert out == ("a", "b")
836 # Via run_cell, it goes into the user's namespace via displayhook
836 # Via run_cell, it goes into the user's namespace via displayhook
837 _ip.run_cell("%%" + magic + " c\nd\n")
837 _ip.run_cell("%%" + magic + " c\nd\n")
838 assert _ip.user_ns["_"] == ("c", "d\n")
838 assert _ip.user_ns["_"] == ("c", "d\n")
839
839
840 def test_cell_magic_func_deco(self):
840 def test_cell_magic_func_deco(self):
841 "Cell magic using simple decorator"
841 "Cell magic using simple decorator"
842 @register_cell_magic
842 @register_cell_magic
843 def cellm(line, cell):
843 def cellm(line, cell):
844 return line, cell
844 return line, cell
845
845
846 self.check_ident('cellm')
846 self.check_ident('cellm')
847
847
848 def test_cell_magic_reg(self):
848 def test_cell_magic_reg(self):
849 "Cell magic manually registered"
849 "Cell magic manually registered"
850 def cellm(line, cell):
850 def cellm(line, cell):
851 return line, cell
851 return line, cell
852
852
853 _ip.register_magic_function(cellm, 'cell', 'cellm2')
853 _ip.register_magic_function(cellm, 'cell', 'cellm2')
854 self.check_ident('cellm2')
854 self.check_ident('cellm2')
855
855
856 def test_cell_magic_class(self):
856 def test_cell_magic_class(self):
857 "Cell magics declared via a class"
857 "Cell magics declared via a class"
858 @magics_class
858 @magics_class
859 class MyMagics(Magics):
859 class MyMagics(Magics):
860
860
861 @cell_magic
861 @cell_magic
862 def cellm3(self, line, cell):
862 def cellm3(self, line, cell):
863 return line, cell
863 return line, cell
864
864
865 _ip.register_magics(MyMagics)
865 _ip.register_magics(MyMagics)
866 self.check_ident('cellm3')
866 self.check_ident('cellm3')
867
867
868 def test_cell_magic_class2(self):
868 def test_cell_magic_class2(self):
869 "Cell magics declared via a class, #2"
869 "Cell magics declared via a class, #2"
870 @magics_class
870 @magics_class
871 class MyMagics2(Magics):
871 class MyMagics2(Magics):
872
872
873 @cell_magic('cellm4')
873 @cell_magic('cellm4')
874 def cellm33(self, line, cell):
874 def cellm33(self, line, cell):
875 return line, cell
875 return line, cell
876
876
877 _ip.register_magics(MyMagics2)
877 _ip.register_magics(MyMagics2)
878 self.check_ident('cellm4')
878 self.check_ident('cellm4')
879 # Check that nothing is registered as 'cellm33'
879 # Check that nothing is registered as 'cellm33'
880 c33 = _ip.find_cell_magic('cellm33')
880 c33 = _ip.find_cell_magic('cellm33')
881 assert c33 == None
881 assert c33 == None
882
882
883 def test_file():
883 def test_file():
884 """Basic %%writefile"""
884 """Basic %%writefile"""
885 ip = get_ipython()
885 ip = get_ipython()
886 with TemporaryDirectory() as td:
886 with TemporaryDirectory() as td:
887 fname = os.path.join(td, "file1")
887 fname = os.path.join(td, "file1")
888 ip.run_cell_magic(
888 ip.run_cell_magic(
889 "writefile",
889 "writefile",
890 fname,
890 fname,
891 "\n".join(
891 "\n".join(
892 [
892 [
893 "line1",
893 "line1",
894 "line2",
894 "line2",
895 ]
895 ]
896 ),
896 ),
897 )
897 )
898 s = Path(fname).read_text(encoding="utf-8")
898 s = Path(fname).read_text(encoding="utf-8")
899 assert "line1\n" in s
899 assert "line1\n" in s
900 assert "line2" in s
900 assert "line2" in s
901
901
902
902
903 @dec.skip_win32
903 @dec.skip_win32
904 def test_file_single_quote():
904 def test_file_single_quote():
905 """Basic %%writefile with embedded single quotes"""
905 """Basic %%writefile with embedded single quotes"""
906 ip = get_ipython()
906 ip = get_ipython()
907 with TemporaryDirectory() as td:
907 with TemporaryDirectory() as td:
908 fname = os.path.join(td, "'file1'")
908 fname = os.path.join(td, "'file1'")
909 ip.run_cell_magic(
909 ip.run_cell_magic(
910 "writefile",
910 "writefile",
911 fname,
911 fname,
912 "\n".join(
912 "\n".join(
913 [
913 [
914 "line1",
914 "line1",
915 "line2",
915 "line2",
916 ]
916 ]
917 ),
917 ),
918 )
918 )
919 s = Path(fname).read_text(encoding="utf-8")
919 s = Path(fname).read_text(encoding="utf-8")
920 assert "line1\n" in s
920 assert "line1\n" in s
921 assert "line2" in s
921 assert "line2" in s
922
922
923
923
924 @dec.skip_win32
924 @dec.skip_win32
925 def test_file_double_quote():
925 def test_file_double_quote():
926 """Basic %%writefile with embedded double quotes"""
926 """Basic %%writefile with embedded double quotes"""
927 ip = get_ipython()
927 ip = get_ipython()
928 with TemporaryDirectory() as td:
928 with TemporaryDirectory() as td:
929 fname = os.path.join(td, '"file1"')
929 fname = os.path.join(td, '"file1"')
930 ip.run_cell_magic(
930 ip.run_cell_magic(
931 "writefile",
931 "writefile",
932 fname,
932 fname,
933 "\n".join(
933 "\n".join(
934 [
934 [
935 "line1",
935 "line1",
936 "line2",
936 "line2",
937 ]
937 ]
938 ),
938 ),
939 )
939 )
940 s = Path(fname).read_text(encoding="utf-8")
940 s = Path(fname).read_text(encoding="utf-8")
941 assert "line1\n" in s
941 assert "line1\n" in s
942 assert "line2" in s
942 assert "line2" in s
943
943
944
944
945 def test_file_var_expand():
945 def test_file_var_expand():
946 """%%writefile $filename"""
946 """%%writefile $filename"""
947 ip = get_ipython()
947 ip = get_ipython()
948 with TemporaryDirectory() as td:
948 with TemporaryDirectory() as td:
949 fname = os.path.join(td, "file1")
949 fname = os.path.join(td, "file1")
950 ip.user_ns["filename"] = fname
950 ip.user_ns["filename"] = fname
951 ip.run_cell_magic(
951 ip.run_cell_magic(
952 "writefile",
952 "writefile",
953 "$filename",
953 "$filename",
954 "\n".join(
954 "\n".join(
955 [
955 [
956 "line1",
956 "line1",
957 "line2",
957 "line2",
958 ]
958 ]
959 ),
959 ),
960 )
960 )
961 s = Path(fname).read_text(encoding="utf-8")
961 s = Path(fname).read_text(encoding="utf-8")
962 assert "line1\n" in s
962 assert "line1\n" in s
963 assert "line2" in s
963 assert "line2" in s
964
964
965
965
966 def test_file_unicode():
966 def test_file_unicode():
967 """%%writefile with unicode cell"""
967 """%%writefile with unicode cell"""
968 ip = get_ipython()
968 ip = get_ipython()
969 with TemporaryDirectory() as td:
969 with TemporaryDirectory() as td:
970 fname = os.path.join(td, 'file1')
970 fname = os.path.join(td, 'file1')
971 ip.run_cell_magic("writefile", fname, u'\n'.join([
971 ip.run_cell_magic("writefile", fname, u'\n'.join([
972 u'linΓ©1',
972 u'linΓ©1',
973 u'linΓ©2',
973 u'linΓ©2',
974 ]))
974 ]))
975 with io.open(fname, encoding='utf-8') as f:
975 with io.open(fname, encoding='utf-8') as f:
976 s = f.read()
976 s = f.read()
977 assert "linΓ©1\n" in s
977 assert "linΓ©1\n" in s
978 assert "linΓ©2" in s
978 assert "linΓ©2" in s
979
979
980
980
981 def test_file_amend():
981 def test_file_amend():
982 """%%writefile -a amends files"""
982 """%%writefile -a amends files"""
983 ip = get_ipython()
983 ip = get_ipython()
984 with TemporaryDirectory() as td:
984 with TemporaryDirectory() as td:
985 fname = os.path.join(td, "file2")
985 fname = os.path.join(td, "file2")
986 ip.run_cell_magic(
986 ip.run_cell_magic(
987 "writefile",
987 "writefile",
988 fname,
988 fname,
989 "\n".join(
989 "\n".join(
990 [
990 [
991 "line1",
991 "line1",
992 "line2",
992 "line2",
993 ]
993 ]
994 ),
994 ),
995 )
995 )
996 ip.run_cell_magic(
996 ip.run_cell_magic(
997 "writefile",
997 "writefile",
998 "-a %s" % fname,
998 "-a %s" % fname,
999 "\n".join(
999 "\n".join(
1000 [
1000 [
1001 "line3",
1001 "line3",
1002 "line4",
1002 "line4",
1003 ]
1003 ]
1004 ),
1004 ),
1005 )
1005 )
1006 s = Path(fname).read_text(encoding="utf-8")
1006 s = Path(fname).read_text(encoding="utf-8")
1007 assert "line1\n" in s
1007 assert "line1\n" in s
1008 assert "line3\n" in s
1008 assert "line3\n" in s
1009
1009
1010
1010
1011 def test_file_spaces():
1011 def test_file_spaces():
1012 """%%file with spaces in filename"""
1012 """%%file with spaces in filename"""
1013 ip = get_ipython()
1013 ip = get_ipython()
1014 with TemporaryWorkingDirectory() as td:
1014 with TemporaryWorkingDirectory() as td:
1015 fname = "file name"
1015 fname = "file name"
1016 ip.run_cell_magic(
1016 ip.run_cell_magic(
1017 "file",
1017 "file",
1018 '"%s"' % fname,
1018 '"%s"' % fname,
1019 "\n".join(
1019 "\n".join(
1020 [
1020 [
1021 "line1",
1021 "line1",
1022 "line2",
1022 "line2",
1023 ]
1023 ]
1024 ),
1024 ),
1025 )
1025 )
1026 s = Path(fname).read_text(encoding="utf-8")
1026 s = Path(fname).read_text(encoding="utf-8")
1027 assert "line1\n" in s
1027 assert "line1\n" in s
1028 assert "line2" in s
1028 assert "line2" in s
1029
1029
1030
1030
1031 def test_script_config():
1031 def test_script_config():
1032 ip = get_ipython()
1032 ip = get_ipython()
1033 ip.config.ScriptMagics.script_magics = ['whoda']
1033 ip.config.ScriptMagics.script_magics = ['whoda']
1034 sm = script.ScriptMagics(shell=ip)
1034 sm = script.ScriptMagics(shell=ip)
1035 assert "whoda" in sm.magics["cell"]
1035 assert "whoda" in sm.magics["cell"]
1036
1036
1037
1037
1038 def test_script_out():
1038 def test_script_out():
1039 ip = get_ipython()
1039 ip = get_ipython()
1040 ip.run_cell_magic("script", f"--out output {sys.executable}", "print('hi')")
1040 ip.run_cell_magic("script", f"--out output {sys.executable}", "print('hi')")
1041 assert ip.user_ns["output"].strip() == "hi"
1041 assert ip.user_ns["output"].strip() == "hi"
1042
1042
1043
1043
1044 def test_script_err():
1044 def test_script_err():
1045 ip = get_ipython()
1045 ip = get_ipython()
1046 ip.run_cell_magic(
1046 ip.run_cell_magic(
1047 "script",
1047 "script",
1048 f"--err error {sys.executable}",
1048 f"--err error {sys.executable}",
1049 "import sys; print('hello', file=sys.stderr)",
1049 "import sys; print('hello', file=sys.stderr)",
1050 )
1050 )
1051 assert ip.user_ns["error"].strip() == "hello"
1051 assert ip.user_ns["error"].strip() == "hello"
1052
1052
1053
1053
1054 def test_script_out_err():
1054 def test_script_out_err():
1055
1055
1056 ip = get_ipython()
1056 ip = get_ipython()
1057 ip.run_cell_magic(
1057 ip.run_cell_magic(
1058 "script",
1058 "script",
1059 f"--out output --err error {sys.executable}",
1059 f"--out output --err error {sys.executable}",
1060 "\n".join(
1060 "\n".join(
1061 [
1061 [
1062 "import sys",
1062 "import sys",
1063 "print('hi')",
1063 "print('hi')",
1064 "print('hello', file=sys.stderr)",
1064 "print('hello', file=sys.stderr)",
1065 ]
1065 ]
1066 ),
1066 ),
1067 )
1067 )
1068 assert ip.user_ns["output"].strip() == "hi"
1068 assert ip.user_ns["output"].strip() == "hi"
1069 assert ip.user_ns["error"].strip() == "hello"
1069 assert ip.user_ns["error"].strip() == "hello"
1070
1070
1071
1071
1072 async def test_script_bg_out():
1072 async def test_script_bg_out():
1073 ip = get_ipython()
1073 ip = get_ipython()
1074 ip.run_cell_magic("script", f"--bg --out output {sys.executable}", "print('hi')")
1074 ip.run_cell_magic("script", f"--bg --out output {sys.executable}", "print('hi')")
1075 assert (await ip.user_ns["output"].read()).strip() == b"hi"
1075 assert (await ip.user_ns["output"].read()).strip() == b"hi"
1076 assert ip.user_ns["output"].at_eof()
1076 assert ip.user_ns["output"].at_eof()
1077
1077
1078
1078
1079 async def test_script_bg_err():
1079 async def test_script_bg_err():
1080 ip = get_ipython()
1080 ip = get_ipython()
1081 ip.run_cell_magic(
1081 ip.run_cell_magic(
1082 "script",
1082 "script",
1083 f"--bg --err error {sys.executable}",
1083 f"--bg --err error {sys.executable}",
1084 "import sys; print('hello', file=sys.stderr)",
1084 "import sys; print('hello', file=sys.stderr)",
1085 )
1085 )
1086 assert (await ip.user_ns["error"].read()).strip() == b"hello"
1086 assert (await ip.user_ns["error"].read()).strip() == b"hello"
1087 assert ip.user_ns["error"].at_eof()
1087 assert ip.user_ns["error"].at_eof()
1088
1088
1089
1089
1090 async def test_script_bg_out_err():
1090 async def test_script_bg_out_err():
1091 ip = get_ipython()
1091 ip = get_ipython()
1092 ip.run_cell_magic(
1092 ip.run_cell_magic(
1093 "script",
1093 "script",
1094 f"--bg --out output --err error {sys.executable}",
1094 f"--bg --out output --err error {sys.executable}",
1095 "\n".join(
1095 "\n".join(
1096 [
1096 [
1097 "import sys",
1097 "import sys",
1098 "print('hi')",
1098 "print('hi')",
1099 "print('hello', file=sys.stderr)",
1099 "print('hello', file=sys.stderr)",
1100 ]
1100 ]
1101 ),
1101 ),
1102 )
1102 )
1103 assert (await ip.user_ns["output"].read()).strip() == b"hi"
1103 assert (await ip.user_ns["output"].read()).strip() == b"hi"
1104 assert (await ip.user_ns["error"].read()).strip() == b"hello"
1104 assert (await ip.user_ns["error"].read()).strip() == b"hello"
1105 assert ip.user_ns["output"].at_eof()
1105 assert ip.user_ns["output"].at_eof()
1106 assert ip.user_ns["error"].at_eof()
1106 assert ip.user_ns["error"].at_eof()
1107
1107
1108
1108
1109 async def test_script_bg_proc():
1109 async def test_script_bg_proc():
1110 ip = get_ipython()
1110 ip = get_ipython()
1111 ip.run_cell_magic(
1111 ip.run_cell_magic(
1112 "script",
1112 "script",
1113 f"--bg --out output --proc p {sys.executable}",
1113 f"--bg --out output --proc p {sys.executable}",
1114 "\n".join(
1114 "\n".join(
1115 [
1115 [
1116 "import sys",
1116 "import sys",
1117 "print('hi')",
1117 "print('hi')",
1118 "print('hello', file=sys.stderr)",
1118 "print('hello', file=sys.stderr)",
1119 ]
1119 ]
1120 ),
1120 ),
1121 )
1121 )
1122 p = ip.user_ns["p"]
1122 p = ip.user_ns["p"]
1123 await p.wait()
1123 await p.wait()
1124 assert p.returncode == 0
1124 assert p.returncode == 0
1125 assert (await p.stdout.read()).strip() == b"hi"
1125 assert (await p.stdout.read()).strip() == b"hi"
1126 # not captured, so empty
1126 # not captured, so empty
1127 assert (await p.stderr.read()) == b""
1127 assert (await p.stderr.read()) == b""
1128 assert p.stdout.at_eof()
1128 assert p.stdout.at_eof()
1129 assert p.stderr.at_eof()
1129 assert p.stderr.at_eof()
1130
1130
1131
1131
1132 def test_script_defaults():
1132 def test_script_defaults():
1133 ip = get_ipython()
1133 ip = get_ipython()
1134 for cmd in ['sh', 'bash', 'perl', 'ruby']:
1134 for cmd in ['sh', 'bash', 'perl', 'ruby']:
1135 try:
1135 try:
1136 find_cmd(cmd)
1136 find_cmd(cmd)
1137 except Exception:
1137 except Exception:
1138 pass
1138 pass
1139 else:
1139 else:
1140 assert cmd in ip.magics_manager.magics["cell"]
1140 assert cmd in ip.magics_manager.magics["cell"]
1141
1141
1142
1142
1143 @magics_class
1143 @magics_class
1144 class FooFoo(Magics):
1144 class FooFoo(Magics):
1145 """class with both %foo and %%foo magics"""
1145 """class with both %foo and %%foo magics"""
1146 @line_magic('foo')
1146 @line_magic('foo')
1147 def line_foo(self, line):
1147 def line_foo(self, line):
1148 "I am line foo"
1148 "I am line foo"
1149 pass
1149 pass
1150
1150
1151 @cell_magic("foo")
1151 @cell_magic("foo")
1152 def cell_foo(self, line, cell):
1152 def cell_foo(self, line, cell):
1153 "I am cell foo, not line foo"
1153 "I am cell foo, not line foo"
1154 pass
1154 pass
1155
1155
1156 def test_line_cell_info():
1156 def test_line_cell_info():
1157 """%%foo and %foo magics are distinguishable to inspect"""
1157 """%%foo and %foo magics are distinguishable to inspect"""
1158 ip = get_ipython()
1158 ip = get_ipython()
1159 ip.magics_manager.register(FooFoo)
1159 ip.magics_manager.register(FooFoo)
1160 oinfo = ip.object_inspect("foo")
1160 oinfo = ip.object_inspect("foo")
1161 assert oinfo["found"] is True
1161 assert oinfo["found"] is True
1162 assert oinfo["ismagic"] is True
1162 assert oinfo["ismagic"] is True
1163
1163
1164 oinfo = ip.object_inspect("%%foo")
1164 oinfo = ip.object_inspect("%%foo")
1165 assert oinfo["found"] is True
1165 assert oinfo["found"] is True
1166 assert oinfo["ismagic"] is True
1166 assert oinfo["ismagic"] is True
1167 assert oinfo["docstring"] == FooFoo.cell_foo.__doc__
1167 assert oinfo["docstring"] == FooFoo.cell_foo.__doc__
1168
1168
1169 oinfo = ip.object_inspect("%foo")
1169 oinfo = ip.object_inspect("%foo")
1170 assert oinfo["found"] is True
1170 assert oinfo["found"] is True
1171 assert oinfo["ismagic"] is True
1171 assert oinfo["ismagic"] is True
1172 assert oinfo["docstring"] == FooFoo.line_foo.__doc__
1172 assert oinfo["docstring"] == FooFoo.line_foo.__doc__
1173
1173
1174
1174
1175 def test_multiple_magics():
1175 def test_multiple_magics():
1176 ip = get_ipython()
1176 ip = get_ipython()
1177 foo1 = FooFoo(ip)
1177 foo1 = FooFoo(ip)
1178 foo2 = FooFoo(ip)
1178 foo2 = FooFoo(ip)
1179 mm = ip.magics_manager
1179 mm = ip.magics_manager
1180 mm.register(foo1)
1180 mm.register(foo1)
1181 assert mm.magics["line"]["foo"].__self__ is foo1
1181 assert mm.magics["line"]["foo"].__self__ is foo1
1182 mm.register(foo2)
1182 mm.register(foo2)
1183 assert mm.magics["line"]["foo"].__self__ is foo2
1183 assert mm.magics["line"]["foo"].__self__ is foo2
1184
1184
1185
1185
1186 def test_alias_magic():
1186 def test_alias_magic():
1187 """Test %alias_magic."""
1187 """Test %alias_magic."""
1188 ip = get_ipython()
1188 ip = get_ipython()
1189 mm = ip.magics_manager
1189 mm = ip.magics_manager
1190
1190
1191 # Basic operation: both cell and line magics are created, if possible.
1191 # Basic operation: both cell and line magics are created, if possible.
1192 ip.run_line_magic("alias_magic", "timeit_alias timeit")
1192 ip.run_line_magic("alias_magic", "timeit_alias timeit")
1193 assert "timeit_alias" in mm.magics["line"]
1193 assert "timeit_alias" in mm.magics["line"]
1194 assert "timeit_alias" in mm.magics["cell"]
1194 assert "timeit_alias" in mm.magics["cell"]
1195
1195
1196 # --cell is specified, line magic not created.
1196 # --cell is specified, line magic not created.
1197 ip.run_line_magic("alias_magic", "--cell timeit_cell_alias timeit")
1197 ip.run_line_magic("alias_magic", "--cell timeit_cell_alias timeit")
1198 assert "timeit_cell_alias" not in mm.magics["line"]
1198 assert "timeit_cell_alias" not in mm.magics["line"]
1199 assert "timeit_cell_alias" in mm.magics["cell"]
1199 assert "timeit_cell_alias" in mm.magics["cell"]
1200
1200
1201 # Test that line alias is created successfully.
1201 # Test that line alias is created successfully.
1202 ip.run_line_magic("alias_magic", "--line env_alias env")
1202 ip.run_line_magic("alias_magic", "--line env_alias env")
1203 assert ip.run_line_magic("env", "") == ip.run_line_magic("env_alias", "")
1203 assert ip.run_line_magic("env", "") == ip.run_line_magic("env_alias", "")
1204
1204
1205 # Test that line alias with parameters passed in is created successfully.
1205 # Test that line alias with parameters passed in is created successfully.
1206 ip.run_line_magic(
1206 ip.run_line_magic(
1207 "alias_magic", "--line history_alias history --params " + shlex.quote("3")
1207 "alias_magic", "--line history_alias history --params " + shlex.quote("3")
1208 )
1208 )
1209 assert "history_alias" in mm.magics["line"]
1209 assert "history_alias" in mm.magics["line"]
1210
1210
1211
1211
1212 def test_save():
1212 def test_save():
1213 """Test %save."""
1213 """Test %save."""
1214 ip = get_ipython()
1214 ip = get_ipython()
1215 ip.history_manager.reset() # Clear any existing history.
1215 ip.history_manager.reset() # Clear any existing history.
1216 cmds = ["a=1", "def b():\n return a**2", "print(a, b())"]
1216 cmds = ["a=1", "def b():\n return a**2", "print(a, b())"]
1217 for i, cmd in enumerate(cmds, start=1):
1217 for i, cmd in enumerate(cmds, start=1):
1218 ip.history_manager.store_inputs(i, cmd)
1218 ip.history_manager.store_inputs(i, cmd)
1219 with TemporaryDirectory() as tmpdir:
1219 with TemporaryDirectory() as tmpdir:
1220 file = os.path.join(tmpdir, "testsave.py")
1220 file = os.path.join(tmpdir, "testsave.py")
1221 ip.run_line_magic("save", "%s 1-10" % file)
1221 ip.run_line_magic("save", "%s 1-10" % file)
1222 content = Path(file).read_text(encoding="utf-8")
1222 content = Path(file).read_text(encoding="utf-8")
1223 assert content.count(cmds[0]) == 1
1223 assert content.count(cmds[0]) == 1
1224 assert "coding: utf-8" in content
1224 assert "coding: utf-8" in content
1225 ip.run_line_magic("save", "-a %s 1-10" % file)
1225 ip.run_line_magic("save", "-a %s 1-10" % file)
1226 content = Path(file).read_text(encoding="utf-8")
1226 content = Path(file).read_text(encoding="utf-8")
1227 assert content.count(cmds[0]) == 2
1227 assert content.count(cmds[0]) == 2
1228 assert "coding: utf-8" in content
1228 assert "coding: utf-8" in content
1229
1229
1230
1230
1231 def test_save_with_no_args():
1231 def test_save_with_no_args():
1232 ip = get_ipython()
1232 ip = get_ipython()
1233 ip.history_manager.reset() # Clear any existing history.
1233 ip.history_manager.reset() # Clear any existing history.
1234 cmds = ["a=1", "def b():\n return a**2", "print(a, b())", "%save"]
1234 cmds = ["a=1", "def b():\n return a**2", "print(a, b())", "%save"]
1235 for i, cmd in enumerate(cmds, start=1):
1235 for i, cmd in enumerate(cmds, start=1):
1236 ip.history_manager.store_inputs(i, cmd)
1236 ip.history_manager.store_inputs(i, cmd)
1237
1237
1238 with TemporaryDirectory() as tmpdir:
1238 with TemporaryDirectory() as tmpdir:
1239 path = os.path.join(tmpdir, "testsave.py")
1239 path = os.path.join(tmpdir, "testsave.py")
1240 ip.run_line_magic("save", path)
1240 ip.run_line_magic("save", path)
1241 content = Path(path).read_text(encoding="utf-8")
1241 content = Path(path).read_text(encoding="utf-8")
1242 expected_content = dedent(
1242 expected_content = dedent(
1243 """\
1243 """\
1244 # coding: utf-8
1244 # coding: utf-8
1245 a=1
1245 a=1
1246 def b():
1246 def b():
1247 return a**2
1247 return a**2
1248 print(a, b())
1248 print(a, b())
1249 """
1249 """
1250 )
1250 )
1251 assert content == expected_content
1251 assert content == expected_content
1252
1252
1253
1253
1254 def test_store():
1254 def test_store():
1255 """Test %store."""
1255 """Test %store."""
1256 ip = get_ipython()
1256 ip = get_ipython()
1257 ip.run_line_magic('load_ext', 'storemagic')
1257 ip.run_line_magic('load_ext', 'storemagic')
1258
1258
1259 # make sure the storage is empty
1259 # make sure the storage is empty
1260 ip.run_line_magic("store", "-z")
1260 ip.run_line_magic("store", "-z")
1261 ip.user_ns["var"] = 42
1261 ip.user_ns["var"] = 42
1262 ip.run_line_magic("store", "var")
1262 ip.run_line_magic("store", "var")
1263 ip.user_ns["var"] = 39
1263 ip.user_ns["var"] = 39
1264 ip.run_line_magic("store", "-r")
1264 ip.run_line_magic("store", "-r")
1265 assert ip.user_ns["var"] == 42
1265 assert ip.user_ns["var"] == 42
1266
1266
1267 ip.run_line_magic("store", "-d var")
1267 ip.run_line_magic("store", "-d var")
1268 ip.user_ns["var"] = 39
1268 ip.user_ns["var"] = 39
1269 ip.run_line_magic("store", "-r")
1269 ip.run_line_magic("store", "-r")
1270 assert ip.user_ns["var"] == 39
1270 assert ip.user_ns["var"] == 39
1271
1271
1272
1272
1273 def _run_edit_test(arg_s, exp_filename=None,
1273 def _run_edit_test(arg_s, exp_filename=None,
1274 exp_lineno=-1,
1274 exp_lineno=-1,
1275 exp_contents=None,
1275 exp_contents=None,
1276 exp_is_temp=None):
1276 exp_is_temp=None):
1277 ip = get_ipython()
1277 ip = get_ipython()
1278 M = code.CodeMagics(ip)
1278 M = code.CodeMagics(ip)
1279 last_call = ['','']
1279 last_call = ['','']
1280 opts,args = M.parse_options(arg_s,'prxn:')
1280 opts,args = M.parse_options(arg_s,'prxn:')
1281 filename, lineno, is_temp = M._find_edit_target(ip, args, opts, last_call)
1281 filename, lineno, is_temp = M._find_edit_target(ip, args, opts, last_call)
1282
1282
1283 if exp_filename is not None:
1283 if exp_filename is not None:
1284 assert exp_filename == filename
1284 assert exp_filename == filename
1285 if exp_contents is not None:
1285 if exp_contents is not None:
1286 with io.open(filename, 'r', encoding='utf-8') as f:
1286 with io.open(filename, 'r', encoding='utf-8') as f:
1287 contents = f.read()
1287 contents = f.read()
1288 assert exp_contents == contents
1288 assert exp_contents == contents
1289 if exp_lineno != -1:
1289 if exp_lineno != -1:
1290 assert exp_lineno == lineno
1290 assert exp_lineno == lineno
1291 if exp_is_temp is not None:
1291 if exp_is_temp is not None:
1292 assert exp_is_temp == is_temp
1292 assert exp_is_temp == is_temp
1293
1293
1294
1294
1295 def test_edit_interactive():
1295 def test_edit_interactive():
1296 """%edit on interactively defined objects"""
1296 """%edit on interactively defined objects"""
1297 ip = get_ipython()
1297 ip = get_ipython()
1298 n = ip.execution_count
1298 n = ip.execution_count
1299 ip.run_cell("def foo(): return 1", store_history=True)
1299 ip.run_cell("def foo(): return 1", store_history=True)
1300
1300
1301 with pytest.raises(code.InteractivelyDefined) as e:
1301 with pytest.raises(code.InteractivelyDefined) as e:
1302 _run_edit_test("foo")
1302 _run_edit_test("foo")
1303 assert e.value.index == n
1303 assert e.value.index == n
1304
1304
1305
1305
1306 def test_edit_cell():
1306 def test_edit_cell():
1307 """%edit [cell id]"""
1307 """%edit [cell id]"""
1308 ip = get_ipython()
1308 ip = get_ipython()
1309
1309
1310 ip.run_cell("def foo(): return 1", store_history=True)
1310 ip.run_cell("def foo(): return 1", store_history=True)
1311
1311
1312 # test
1312 # test
1313 _run_edit_test("1", exp_contents=ip.user_ns['In'][1], exp_is_temp=True)
1313 _run_edit_test("1", exp_contents=ip.user_ns['In'][1], exp_is_temp=True)
1314
1314
1315 def test_edit_fname():
1315 def test_edit_fname():
1316 """%edit file"""
1316 """%edit file"""
1317 # test
1317 # test
1318 _run_edit_test("test file.py", exp_filename="test file.py")
1318 _run_edit_test("test file.py", exp_filename="test file.py")
1319
1319
1320 def test_bookmark():
1320 def test_bookmark():
1321 ip = get_ipython()
1321 ip = get_ipython()
1322 ip.run_line_magic('bookmark', 'bmname')
1322 ip.run_line_magic('bookmark', 'bmname')
1323 with tt.AssertPrints('bmname'):
1323 with tt.AssertPrints('bmname'):
1324 ip.run_line_magic('bookmark', '-l')
1324 ip.run_line_magic('bookmark', '-l')
1325 ip.run_line_magic('bookmark', '-d bmname')
1325 ip.run_line_magic('bookmark', '-d bmname')
1326
1326
1327 def test_ls_magic():
1327 def test_ls_magic():
1328 ip = get_ipython()
1328 ip = get_ipython()
1329 json_formatter = ip.display_formatter.formatters['application/json']
1329 json_formatter = ip.display_formatter.formatters['application/json']
1330 json_formatter.enabled = True
1330 json_formatter.enabled = True
1331 lsmagic = ip.run_line_magic("lsmagic", "")
1331 lsmagic = ip.run_line_magic("lsmagic", "")
1332 with warnings.catch_warnings(record=True) as w:
1332 with warnings.catch_warnings(record=True) as w:
1333 j = json_formatter(lsmagic)
1333 j = json_formatter(lsmagic)
1334 assert sorted(j) == ["cell", "line"]
1334 assert sorted(j) == ["cell", "line"]
1335 assert w == [] # no warnings
1335 assert w == [] # no warnings
1336
1336
1337
1337
1338 def test_strip_initial_indent():
1338 def test_strip_initial_indent():
1339 def sii(s):
1339 def sii(s):
1340 lines = s.splitlines()
1340 lines = s.splitlines()
1341 return '\n'.join(code.strip_initial_indent(lines))
1341 return '\n'.join(code.strip_initial_indent(lines))
1342
1342
1343 assert sii(" a = 1\nb = 2") == "a = 1\nb = 2"
1343 assert sii(" a = 1\nb = 2") == "a = 1\nb = 2"
1344 assert sii(" a\n b\nc") == "a\n b\nc"
1344 assert sii(" a\n b\nc") == "a\n b\nc"
1345 assert sii("a\n b") == "a\n b"
1345 assert sii("a\n b") == "a\n b"
1346
1346
1347 def test_logging_magic_quiet_from_arg():
1347 def test_logging_magic_quiet_from_arg():
1348 _ip.config.LoggingMagics.quiet = False
1348 _ip.config.LoggingMagics.quiet = False
1349 lm = logging.LoggingMagics(shell=_ip)
1349 lm = logging.LoggingMagics(shell=_ip)
1350 with TemporaryDirectory() as td:
1350 with TemporaryDirectory() as td:
1351 try:
1351 try:
1352 with tt.AssertNotPrints(re.compile("Activating.*")):
1352 with tt.AssertNotPrints(re.compile("Activating.*")):
1353 lm.logstart('-q {}'.format(
1353 lm.logstart('-q {}'.format(
1354 os.path.join(td, "quiet_from_arg.log")))
1354 os.path.join(td, "quiet_from_arg.log")))
1355 finally:
1355 finally:
1356 _ip.logger.logstop()
1356 _ip.logger.logstop()
1357
1357
1358 def test_logging_magic_quiet_from_config():
1358 def test_logging_magic_quiet_from_config():
1359 _ip.config.LoggingMagics.quiet = True
1359 _ip.config.LoggingMagics.quiet = True
1360 lm = logging.LoggingMagics(shell=_ip)
1360 lm = logging.LoggingMagics(shell=_ip)
1361 with TemporaryDirectory() as td:
1361 with TemporaryDirectory() as td:
1362 try:
1362 try:
1363 with tt.AssertNotPrints(re.compile("Activating.*")):
1363 with tt.AssertNotPrints(re.compile("Activating.*")):
1364 lm.logstart(os.path.join(td, "quiet_from_config.log"))
1364 lm.logstart(os.path.join(td, "quiet_from_config.log"))
1365 finally:
1365 finally:
1366 _ip.logger.logstop()
1366 _ip.logger.logstop()
1367
1367
1368
1368
1369 def test_logging_magic_not_quiet():
1369 def test_logging_magic_not_quiet():
1370 _ip.config.LoggingMagics.quiet = False
1370 _ip.config.LoggingMagics.quiet = False
1371 lm = logging.LoggingMagics(shell=_ip)
1371 lm = logging.LoggingMagics(shell=_ip)
1372 with TemporaryDirectory() as td:
1372 with TemporaryDirectory() as td:
1373 try:
1373 try:
1374 with tt.AssertPrints(re.compile("Activating.*")):
1374 with tt.AssertPrints(re.compile("Activating.*")):
1375 lm.logstart(os.path.join(td, "not_quiet.log"))
1375 lm.logstart(os.path.join(td, "not_quiet.log"))
1376 finally:
1376 finally:
1377 _ip.logger.logstop()
1377 _ip.logger.logstop()
1378
1378
1379
1379
1380 def test_time_no_var_expand():
1380 def test_time_no_var_expand():
1381 _ip.user_ns["a"] = 5
1381 _ip.user_ns["a"] = 5
1382 _ip.user_ns["b"] = []
1382 _ip.user_ns["b"] = []
1383 _ip.run_line_magic("time", 'b.append("{a}")')
1383 _ip.run_line_magic("time", 'b.append("{a}")')
1384 assert _ip.user_ns["b"] == ["{a}"]
1384 assert _ip.user_ns["b"] == ["{a}"]
1385
1385
1386
1386
1387 # this is slow, put at the end for local testing.
1387 # this is slow, put at the end for local testing.
1388 def test_timeit_arguments():
1388 def test_timeit_arguments():
1389 "Test valid timeit arguments, should not cause SyntaxError (GH #1269)"
1389 "Test valid timeit arguments, should not cause SyntaxError (GH #1269)"
1390 _ip.run_line_magic("timeit", "-n1 -r1 a=('#')")
1390 _ip.run_line_magic("timeit", "-n1 -r1 a=('#')")
1391
1391
1392
1392
1393 MINIMAL_LAZY_MAGIC = """
1393 MINIMAL_LAZY_MAGIC = """
1394 from IPython.core.magic import (
1394 from IPython.core.magic import (
1395 Magics,
1395 Magics,
1396 magics_class,
1396 magics_class,
1397 line_magic,
1397 line_magic,
1398 cell_magic,
1398 cell_magic,
1399 )
1399 )
1400
1400
1401
1401
1402 @magics_class
1402 @magics_class
1403 class LazyMagics(Magics):
1403 class LazyMagics(Magics):
1404 @line_magic
1404 @line_magic
1405 def lazy_line(self, line):
1405 def lazy_line(self, line):
1406 print("Lazy Line")
1406 print("Lazy Line")
1407
1407
1408 @cell_magic
1408 @cell_magic
1409 def lazy_cell(self, line, cell):
1409 def lazy_cell(self, line, cell):
1410 print("Lazy Cell")
1410 print("Lazy Cell")
1411
1411
1412
1412
1413 def load_ipython_extension(ipython):
1413 def load_ipython_extension(ipython):
1414 ipython.register_magics(LazyMagics)
1414 ipython.register_magics(LazyMagics)
1415 """
1415 """
1416
1416
1417
1417
1418 def test_lazy_magics():
1418 def test_lazy_magics():
1419 with pytest.raises(UsageError):
1419 with pytest.raises(UsageError):
1420 ip.run_line_magic("lazy_line", "")
1420 ip.run_line_magic("lazy_line", "")
1421
1421
1422 startdir = os.getcwd()
1422 startdir = os.getcwd()
1423
1423
1424 with TemporaryDirectory() as tmpdir:
1424 with TemporaryDirectory() as tmpdir:
1425 with prepended_to_syspath(tmpdir):
1425 with prepended_to_syspath(tmpdir):
1426 ptempdir = Path(tmpdir)
1426 ptempdir = Path(tmpdir)
1427 tf = ptempdir / "lazy_magic_module.py"
1427 tf = ptempdir / "lazy_magic_module.py"
1428 tf.write_text(MINIMAL_LAZY_MAGIC)
1428 tf.write_text(MINIMAL_LAZY_MAGIC)
1429 ip.magics_manager.register_lazy("lazy_line", Path(tf.name).name[:-3])
1429 ip.magics_manager.register_lazy("lazy_line", Path(tf.name).name[:-3])
1430 with tt.AssertPrints("Lazy Line"):
1430 with tt.AssertPrints("Lazy Line"):
1431 ip.run_line_magic("lazy_line", "")
1431 ip.run_line_magic("lazy_line", "")
1432
1432
1433
1433
1434 TEST_MODULE = """
1434 TEST_MODULE = """
1435 print('Loaded my_tmp')
1435 print('Loaded my_tmp')
1436 if __name__ == "__main__":
1436 if __name__ == "__main__":
1437 print('I just ran a script')
1437 print('I just ran a script')
1438 """
1438 """
1439
1439
1440 def test_run_module_from_import_hook():
1440 def test_run_module_from_import_hook():
1441 "Test that a module can be loaded via an import hook"
1441 "Test that a module can be loaded via an import hook"
1442 with TemporaryDirectory() as tmpdir:
1442 with TemporaryDirectory() as tmpdir:
1443 fullpath = os.path.join(tmpdir, "my_tmp.py")
1443 fullpath = os.path.join(tmpdir, "my_tmp.py")
1444 Path(fullpath).write_text(TEST_MODULE, encoding="utf-8")
1444 Path(fullpath).write_text(TEST_MODULE, encoding="utf-8")
1445
1445
1446 import importlib.abc
1446 import importlib.abc
1447 import importlib.util
1447 import importlib.util
1448
1448
1449 class MyTempImporter(importlib.abc.MetaPathFinder, importlib.abc.SourceLoader):
1449 class MyTempImporter(importlib.abc.MetaPathFinder, importlib.abc.SourceLoader):
1450 def find_spec(self, fullname, path, target=None):
1450 def find_spec(self, fullname, path, target=None):
1451 if fullname == "my_tmp":
1451 if fullname == "my_tmp":
1452 return importlib.util.spec_from_loader(fullname, self)
1452 return importlib.util.spec_from_loader(fullname, self)
1453
1453
1454 def get_filename(self, fullname):
1454 def get_filename(self, fullname):
1455 assert fullname == "my_tmp"
1455 assert fullname == "my_tmp"
1456 return fullpath
1456 return fullpath
1457
1457
1458 def get_data(self, path):
1458 def get_data(self, path):
1459 assert Path(path).samefile(fullpath)
1459 assert Path(path).samefile(fullpath)
1460 return Path(fullpath).read_text(encoding="utf-8")
1460 return Path(fullpath).read_text(encoding="utf-8")
1461
1461
1462 sys.meta_path.insert(0, MyTempImporter())
1462 sys.meta_path.insert(0, MyTempImporter())
1463
1463
1464 with capture_output() as captured:
1464 with capture_output() as captured:
1465 _ip.run_line_magic("run", "-m my_tmp")
1465 _ip.run_line_magic("run", "-m my_tmp")
1466 _ip.run_cell("import my_tmp")
1466 _ip.run_cell("import my_tmp")
1467
1467
1468 output = "Loaded my_tmp\nI just ran a script\nLoaded my_tmp\n"
1468 output = "Loaded my_tmp\nI just ran a script\nLoaded my_tmp\n"
1469 assert output == captured.stdout
1469 assert output == captured.stdout
1470
1470
1471 sys.meta_path.pop(0)
1471 sys.meta_path.pop(0)
General Comments 0
You need to be logged in to leave comments. Login now