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