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