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