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