##// END OF EJS Templates
Merge pull request #11174 from Carreau/close-bg...
Min RK -
r24393:ec3d1a11 merge
parent child Browse files
Show More
@@ -1,279 +1,286 b''
1 1 """Magic functions for running cells in various scripts."""
2 2
3 3 # Copyright (c) IPython Development Team.
4 4 # Distributed under the terms of the Modified BSD License.
5 5
6 6 import errno
7 7 import os
8 8 import sys
9 9 import signal
10 10 import time
11 11 from subprocess import Popen, PIPE
12 12 import atexit
13 13
14 14 from IPython.core import magic_arguments
15 15 from IPython.core.magic import (
16 16 Magics, magics_class, line_magic, cell_magic
17 17 )
18 18 from IPython.lib.backgroundjobs import BackgroundJobManager
19 19 from IPython.utils import py3compat
20 20 from IPython.utils.process import arg_split
21 21 from traitlets import List, Dict, default
22 22
23 23 #-----------------------------------------------------------------------------
24 24 # Magic implementation classes
25 25 #-----------------------------------------------------------------------------
26 26
27 27 def script_args(f):
28 28 """single decorator for adding script args"""
29 29 args = [
30 30 magic_arguments.argument(
31 31 '--out', type=str,
32 32 help="""The variable in which to store stdout from the script.
33 33 If the script is backgrounded, this will be the stdout *pipe*,
34 instead of the stderr text itself.
34 instead of the stderr text itself and will not be auto closed.
35 35 """
36 36 ),
37 37 magic_arguments.argument(
38 38 '--err', type=str,
39 39 help="""The variable in which to store stderr from the script.
40 40 If the script is backgrounded, this will be the stderr *pipe*,
41 instead of the stderr text itself.
41 instead of the stderr text itself and will not be autoclosed.
42 42 """
43 43 ),
44 44 magic_arguments.argument(
45 45 '--bg', action="store_true",
46 46 help="""Whether to run the script in the background.
47 47 If given, the only way to see the output of the command is
48 48 with --out/err.
49 49 """
50 50 ),
51 51 magic_arguments.argument(
52 52 '--proc', type=str,
53 53 help="""The variable in which to store Popen instance.
54 54 This is used only when --bg option is given.
55 55 """
56 56 ),
57 57 ]
58 58 for arg in args:
59 59 f = arg(f)
60 60 return f
61 61
62 62 @magics_class
63 63 class ScriptMagics(Magics):
64 64 """Magics for talking to scripts
65 65
66 66 This defines a base `%%script` cell magic for running a cell
67 67 with a program in a subprocess, and registers a few top-level
68 68 magics that call %%script with common interpreters.
69 69 """
70 70 script_magics = List(
71 71 help="""Extra script cell magics to define
72 72
73 73 This generates simple wrappers of `%%script foo` as `%%foo`.
74 74
75 75 If you want to add script magics that aren't on your path,
76 76 specify them in script_paths
77 77 """,
78 78 ).tag(config=True)
79 79 @default('script_magics')
80 80 def _script_magics_default(self):
81 81 """default to a common list of programs"""
82 82
83 83 defaults = [
84 84 'sh',
85 85 'bash',
86 86 'perl',
87 87 'ruby',
88 88 'python',
89 89 'python2',
90 90 'python3',
91 91 'pypy',
92 92 ]
93 93 if os.name == 'nt':
94 94 defaults.extend([
95 95 'cmd',
96 96 ])
97 97
98 98 return defaults
99 99
100 100 script_paths = Dict(
101 101 help="""Dict mapping short 'ruby' names to full paths, such as '/opt/secret/bin/ruby'
102 102
103 103 Only necessary for items in script_magics where the default path will not
104 104 find the right interpreter.
105 105 """
106 106 ).tag(config=True)
107 107
108 108 def __init__(self, shell=None):
109 109 super(ScriptMagics, self).__init__(shell=shell)
110 110 self._generate_script_magics()
111 111 self.job_manager = BackgroundJobManager()
112 112 self.bg_processes = []
113 113 atexit.register(self.kill_bg_processes)
114 114
115 115 def __del__(self):
116 116 self.kill_bg_processes()
117 117
118 118 def _generate_script_magics(self):
119 119 cell_magics = self.magics['cell']
120 120 for name in self.script_magics:
121 121 cell_magics[name] = self._make_script_magic(name)
122 122
123 123 def _make_script_magic(self, name):
124 124 """make a named magic, that calls %%script with a particular program"""
125 125 # expand to explicit path if necessary:
126 126 script = self.script_paths.get(name, name)
127 127
128 128 @magic_arguments.magic_arguments()
129 129 @script_args
130 130 def named_script_magic(line, cell):
131 131 # if line, add it as cl-flags
132 132 if line:
133 133 line = "%s %s" % (script, line)
134 134 else:
135 135 line = script
136 136 return self.shebang(line, cell)
137 137
138 138 # write a basic docstring:
139 139 named_script_magic.__doc__ = \
140 140 """%%{name} script magic
141 141
142 142 Run cells with {script} in a subprocess.
143 143
144 144 This is a shortcut for `%%script {script}`
145 145 """.format(**locals())
146 146
147 147 return named_script_magic
148 148
149 149 @magic_arguments.magic_arguments()
150 150 @script_args
151 151 @cell_magic("script")
152 152 def shebang(self, line, cell):
153 153 """Run a cell via a shell command
154 154
155 155 The `%%script` line is like the #! line of script,
156 156 specifying a program (bash, perl, ruby, etc.) with which to run.
157 157
158 158 The rest of the cell is run by that program.
159 159
160 160 Examples
161 161 --------
162 162 ::
163 163
164 164 In [1]: %%script bash
165 165 ...: for i in 1 2 3; do
166 166 ...: echo $i
167 167 ...: done
168 168 1
169 169 2
170 170 3
171 171 """
172 172 argv = arg_split(line, posix = not sys.platform.startswith('win'))
173 173 args, cmd = self.shebang.parser.parse_known_args(argv)
174 174
175 175 try:
176 176 p = Popen(cmd, stdout=PIPE, stderr=PIPE, stdin=PIPE)
177 177 except OSError as e:
178 178 if e.errno == errno.ENOENT:
179 179 print("Couldn't find program: %r" % cmd[0])
180 180 return
181 181 else:
182 182 raise
183 183
184 184 if not cell.endswith('\n'):
185 185 cell += '\n'
186 186 cell = cell.encode('utf8', 'replace')
187 187 if args.bg:
188 188 self.bg_processes.append(p)
189 189 self._gc_bg_processes()
190 to_close = []
190 191 if args.out:
191 192 self.shell.user_ns[args.out] = p.stdout
193 else:
194 to_close.append(p.stdout)
192 195 if args.err:
193 196 self.shell.user_ns[args.err] = p.stderr
194 self.job_manager.new(self._run_script, p, cell, daemon=True)
197 else:
198 to_close.append(p.stderr)
199 self.job_manager.new(self._run_script, p, cell, to_close, daemon=True)
195 200 if args.proc:
196 201 self.shell.user_ns[args.proc] = p
197 202 return
198 203
199 204 try:
200 205 out, err = p.communicate(cell)
201 206 except KeyboardInterrupt:
202 207 try:
203 208 p.send_signal(signal.SIGINT)
204 209 time.sleep(0.1)
205 210 if p.poll() is not None:
206 211 print("Process is interrupted.")
207 212 return
208 213 p.terminate()
209 214 time.sleep(0.1)
210 215 if p.poll() is not None:
211 216 print("Process is terminated.")
212 217 return
213 218 p.kill()
214 219 print("Process is killed.")
215 220 except OSError:
216 221 pass
217 222 except Exception as e:
218 223 print("Error while terminating subprocess (pid=%i): %s" \
219 224 % (p.pid, e))
220 225 return
221 226 out = py3compat.decode(out)
222 227 err = py3compat.decode(err)
223 228 if args.out:
224 229 self.shell.user_ns[args.out] = out
225 230 else:
226 231 sys.stdout.write(out)
227 232 sys.stdout.flush()
228 233 if args.err:
229 234 self.shell.user_ns[args.err] = err
230 235 else:
231 236 sys.stderr.write(err)
232 237 sys.stderr.flush()
233 238
234 def _run_script(self, p, cell):
239 def _run_script(self, p, cell, to_close):
235 240 """callback for running the script in the background"""
236 241 p.stdin.write(cell)
237 242 p.stdin.close()
243 for s in to_close:
244 s.close()
238 245 p.wait()
239 246
240 247 @line_magic("killbgscripts")
241 248 def killbgscripts(self, _nouse_=''):
242 249 """Kill all BG processes started by %%script and its family."""
243 250 self.kill_bg_processes()
244 251 print("All background processes were killed.")
245 252
246 253 def kill_bg_processes(self):
247 254 """Kill all BG processes which are still running."""
248 255 if not self.bg_processes:
249 256 return
250 257 for p in self.bg_processes:
251 258 if p.poll() is None:
252 259 try:
253 260 p.send_signal(signal.SIGINT)
254 261 except:
255 262 pass
256 263 time.sleep(0.1)
257 264 self._gc_bg_processes()
258 265 if not self.bg_processes:
259 266 return
260 267 for p in self.bg_processes:
261 268 if p.poll() is None:
262 269 try:
263 270 p.terminate()
264 271 except:
265 272 pass
266 273 time.sleep(0.1)
267 274 self._gc_bg_processes()
268 275 if not self.bg_processes:
269 276 return
270 277 for p in self.bg_processes:
271 278 if p.poll() is None:
272 279 try:
273 280 p.kill()
274 281 except:
275 282 pass
276 283 self._gc_bg_processes()
277 284
278 285 def _gc_bg_processes(self):
279 286 self.bg_processes = [p for p in self.bg_processes if p.poll() is None]
@@ -1,1075 +1,1080 b''
1 1 # -*- coding: utf-8 -*-
2 2 """Tests for various magic functions.
3 3
4 4 Needs to be run by nose (to make ipython session available).
5 5 """
6 6
7 7 import io
8 8 import os
9 9 import re
10 10 import sys
11 11 import warnings
12 12 from unittest import TestCase
13 13 from importlib import invalidate_caches
14 14 from io import StringIO
15 15
16 16 import nose.tools as nt
17 17
18 18 import shlex
19 19
20 20 from IPython import get_ipython
21 21 from IPython.core import magic
22 22 from IPython.core.error import UsageError
23 23 from IPython.core.magic import (Magics, magics_class, line_magic,
24 24 cell_magic,
25 25 register_line_magic, register_cell_magic)
26 26 from IPython.core.magics import execution, script, code, logging
27 27 from IPython.testing import decorators as dec
28 28 from IPython.testing import tools as tt
29 29 from IPython.utils.io import capture_output
30 30 from IPython.utils.tempdir import TemporaryDirectory
31 31 from IPython.utils.process import find_cmd
32 32
33 33
34 34
35 35 _ip = get_ipython()
36 36
37 37 @magic.magics_class
38 38 class DummyMagics(magic.Magics): pass
39 39
40 40 def test_extract_code_ranges():
41 41 instr = "1 3 5-6 7-9 10:15 17: :10 10- -13 :"
42 42 expected = [(0, 1),
43 43 (2, 3),
44 44 (4, 6),
45 45 (6, 9),
46 46 (9, 14),
47 47 (16, None),
48 48 (None, 9),
49 49 (9, None),
50 50 (None, 13),
51 51 (None, None)]
52 52 actual = list(code.extract_code_ranges(instr))
53 53 nt.assert_equal(actual, expected)
54 54
55 55 def test_extract_symbols():
56 56 source = """import foo\na = 10\ndef b():\n return 42\n\n\nclass A: pass\n\n\n"""
57 57 symbols_args = ["a", "b", "A", "A,b", "A,a", "z"]
58 58 expected = [([], ['a']),
59 59 (["def b():\n return 42\n"], []),
60 60 (["class A: pass\n"], []),
61 61 (["class A: pass\n", "def b():\n return 42\n"], []),
62 62 (["class A: pass\n"], ['a']),
63 63 ([], ['z'])]
64 64 for symbols, exp in zip(symbols_args, expected):
65 65 nt.assert_equal(code.extract_symbols(source, symbols), exp)
66 66
67 67
68 68 def test_extract_symbols_raises_exception_with_non_python_code():
69 69 source = ("=begin A Ruby program :)=end\n"
70 70 "def hello\n"
71 71 "puts 'Hello world'\n"
72 72 "end")
73 73 with nt.assert_raises(SyntaxError):
74 74 code.extract_symbols(source, "hello")
75 75
76 76
77 77 def test_magic_not_found():
78 78 # magic not found raises UsageError
79 79 with nt.assert_raises(UsageError):
80 80 _ip.magic('doesntexist')
81 81
82 82 # ensure result isn't success when a magic isn't found
83 83 result = _ip.run_cell('%doesntexist')
84 84 assert isinstance(result.error_in_exec, UsageError)
85 85
86 86
87 87 def test_cell_magic_not_found():
88 88 # magic not found raises UsageError
89 89 with nt.assert_raises(UsageError):
90 90 _ip.run_cell_magic('doesntexist', 'line', 'cell')
91 91
92 92 # ensure result isn't success when a magic isn't found
93 93 result = _ip.run_cell('%%doesntexist')
94 94 assert isinstance(result.error_in_exec, UsageError)
95 95
96 96
97 97 def test_magic_error_status():
98 98 def fail(shell):
99 99 1/0
100 100 _ip.register_magic_function(fail)
101 101 result = _ip.run_cell('%fail')
102 102 assert isinstance(result.error_in_exec, ZeroDivisionError)
103 103
104 104
105 105 def test_config():
106 106 """ test that config magic does not raise
107 107 can happen if Configurable init is moved too early into
108 108 Magics.__init__ as then a Config object will be registered as a
109 109 magic.
110 110 """
111 111 ## should not raise.
112 112 _ip.magic('config')
113 113
114 114 def test_config_available_configs():
115 115 """ test that config magic prints available configs in unique and
116 116 sorted order. """
117 117 with capture_output() as captured:
118 118 _ip.magic('config')
119 119
120 120 stdout = captured.stdout
121 121 config_classes = stdout.strip().split('\n')[1:]
122 122 nt.assert_list_equal(config_classes, sorted(set(config_classes)))
123 123
124 124 def test_config_print_class():
125 125 """ test that config with a classname prints the class's options. """
126 126 with capture_output() as captured:
127 127 _ip.magic('config TerminalInteractiveShell')
128 128
129 129 stdout = captured.stdout
130 130 if not re.match("TerminalInteractiveShell.* options", stdout.splitlines()[0]):
131 131 print(stdout)
132 132 raise AssertionError("1st line of stdout not like "
133 133 "'TerminalInteractiveShell.* options'")
134 134
135 135 def test_rehashx():
136 136 # clear up everything
137 137 _ip.alias_manager.clear_aliases()
138 138 del _ip.db['syscmdlist']
139 139
140 140 _ip.magic('rehashx')
141 141 # Practically ALL ipython development systems will have more than 10 aliases
142 142
143 143 nt.assert_true(len(_ip.alias_manager.aliases) > 10)
144 144 for name, cmd in _ip.alias_manager.aliases:
145 145 # we must strip dots from alias names
146 146 nt.assert_not_in('.', name)
147 147
148 148 # rehashx must fill up syscmdlist
149 149 scoms = _ip.db['syscmdlist']
150 150 nt.assert_true(len(scoms) > 10)
151 151
152 152
153 153 def test_magic_parse_options():
154 154 """Test that we don't mangle paths when parsing magic options."""
155 155 ip = get_ipython()
156 156 path = 'c:\\x'
157 157 m = DummyMagics(ip)
158 158 opts = m.parse_options('-f %s' % path,'f:')[0]
159 159 # argv splitting is os-dependent
160 160 if os.name == 'posix':
161 161 expected = 'c:x'
162 162 else:
163 163 expected = path
164 164 nt.assert_equal(opts['f'], expected)
165 165
166 166 def test_magic_parse_long_options():
167 167 """Magic.parse_options can handle --foo=bar long options"""
168 168 ip = get_ipython()
169 169 m = DummyMagics(ip)
170 170 opts, _ = m.parse_options('--foo --bar=bubble', 'a', 'foo', 'bar=')
171 171 nt.assert_in('foo', opts)
172 172 nt.assert_in('bar', opts)
173 173 nt.assert_equal(opts['bar'], "bubble")
174 174
175 175
176 176 @dec.skip_without('sqlite3')
177 177 def doctest_hist_f():
178 178 """Test %hist -f with temporary filename.
179 179
180 180 In [9]: import tempfile
181 181
182 182 In [10]: tfile = tempfile.mktemp('.py','tmp-ipython-')
183 183
184 184 In [11]: %hist -nl -f $tfile 3
185 185
186 186 In [13]: import os; os.unlink(tfile)
187 187 """
188 188
189 189
190 190 @dec.skip_without('sqlite3')
191 191 def doctest_hist_r():
192 192 """Test %hist -r
193 193
194 194 XXX - This test is not recording the output correctly. For some reason, in
195 195 testing mode the raw history isn't getting populated. No idea why.
196 196 Disabling the output checking for now, though at least we do run it.
197 197
198 198 In [1]: 'hist' in _ip.lsmagic()
199 199 Out[1]: True
200 200
201 201 In [2]: x=1
202 202
203 203 In [3]: %hist -rl 2
204 204 x=1 # random
205 205 %hist -r 2
206 206 """
207 207
208 208
209 209 @dec.skip_without('sqlite3')
210 210 def doctest_hist_op():
211 211 """Test %hist -op
212 212
213 213 In [1]: class b(float):
214 214 ...: pass
215 215 ...:
216 216
217 217 In [2]: class s(object):
218 218 ...: def __str__(self):
219 219 ...: return 's'
220 220 ...:
221 221
222 222 In [3]:
223 223
224 224 In [4]: class r(b):
225 225 ...: def __repr__(self):
226 226 ...: return 'r'
227 227 ...:
228 228
229 229 In [5]: class sr(s,r): pass
230 230 ...:
231 231
232 232 In [6]:
233 233
234 234 In [7]: bb=b()
235 235
236 236 In [8]: ss=s()
237 237
238 238 In [9]: rr=r()
239 239
240 240 In [10]: ssrr=sr()
241 241
242 242 In [11]: 4.5
243 243 Out[11]: 4.5
244 244
245 245 In [12]: str(ss)
246 246 Out[12]: 's'
247 247
248 248 In [13]:
249 249
250 250 In [14]: %hist -op
251 251 >>> class b:
252 252 ... pass
253 253 ...
254 254 >>> class s(b):
255 255 ... def __str__(self):
256 256 ... return 's'
257 257 ...
258 258 >>>
259 259 >>> class r(b):
260 260 ... def __repr__(self):
261 261 ... return 'r'
262 262 ...
263 263 >>> class sr(s,r): pass
264 264 >>>
265 265 >>> bb=b()
266 266 >>> ss=s()
267 267 >>> rr=r()
268 268 >>> ssrr=sr()
269 269 >>> 4.5
270 270 4.5
271 271 >>> str(ss)
272 272 's'
273 273 >>>
274 274 """
275 275
276 276 def test_hist_pof():
277 277 ip = get_ipython()
278 278 ip.run_cell(u"1+2", store_history=True)
279 279 #raise Exception(ip.history_manager.session_number)
280 280 #raise Exception(list(ip.history_manager._get_range_session()))
281 281 with TemporaryDirectory() as td:
282 282 tf = os.path.join(td, 'hist.py')
283 283 ip.run_line_magic('history', '-pof %s' % tf)
284 284 assert os.path.isfile(tf)
285 285
286 286
287 287 @dec.skip_without('sqlite3')
288 288 def test_macro():
289 289 ip = get_ipython()
290 290 ip.history_manager.reset() # Clear any existing history.
291 291 cmds = ["a=1", "def b():\n return a**2", "print(a,b())"]
292 292 for i, cmd in enumerate(cmds, start=1):
293 293 ip.history_manager.store_inputs(i, cmd)
294 294 ip.magic("macro test 1-3")
295 295 nt.assert_equal(ip.user_ns["test"].value, "\n".join(cmds)+"\n")
296 296
297 297 # List macros
298 298 nt.assert_in("test", ip.magic("macro"))
299 299
300 300
301 301 @dec.skip_without('sqlite3')
302 302 def test_macro_run():
303 303 """Test that we can run a multi-line macro successfully."""
304 304 ip = get_ipython()
305 305 ip.history_manager.reset()
306 306 cmds = ["a=10", "a+=1", "print(a)", "%macro test 2-3"]
307 307 for cmd in cmds:
308 308 ip.run_cell(cmd, store_history=True)
309 309 nt.assert_equal(ip.user_ns["test"].value, "a+=1\nprint(a)\n")
310 310 with tt.AssertPrints("12"):
311 311 ip.run_cell("test")
312 312 with tt.AssertPrints("13"):
313 313 ip.run_cell("test")
314 314
315 315
316 316 def test_magic_magic():
317 317 """Test %magic"""
318 318 ip = get_ipython()
319 319 with capture_output() as captured:
320 320 ip.magic("magic")
321 321
322 322 stdout = captured.stdout
323 323 nt.assert_in('%magic', stdout)
324 324 nt.assert_in('IPython', stdout)
325 325 nt.assert_in('Available', stdout)
326 326
327 327
328 328 @dec.skipif_not_numpy
329 329 def test_numpy_reset_array_undec():
330 330 "Test '%reset array' functionality"
331 331 _ip.ex('import numpy as np')
332 332 _ip.ex('a = np.empty(2)')
333 333 nt.assert_in('a', _ip.user_ns)
334 334 _ip.magic('reset -f array')
335 335 nt.assert_not_in('a', _ip.user_ns)
336 336
337 337 def test_reset_out():
338 338 "Test '%reset out' magic"
339 339 _ip.run_cell("parrot = 'dead'", store_history=True)
340 340 # test '%reset -f out', make an Out prompt
341 341 _ip.run_cell("parrot", store_history=True)
342 342 nt.assert_true('dead' in [_ip.user_ns[x] for x in ('_','__','___')])
343 343 _ip.magic('reset -f out')
344 344 nt.assert_false('dead' in [_ip.user_ns[x] for x in ('_','__','___')])
345 345 nt.assert_equal(len(_ip.user_ns['Out']), 0)
346 346
347 347 def test_reset_in():
348 348 "Test '%reset in' magic"
349 349 # test '%reset -f in'
350 350 _ip.run_cell("parrot", store_history=True)
351 351 nt.assert_true('parrot' in [_ip.user_ns[x] for x in ('_i','_ii','_iii')])
352 352 _ip.magic('%reset -f in')
353 353 nt.assert_false('parrot' in [_ip.user_ns[x] for x in ('_i','_ii','_iii')])
354 354 nt.assert_equal(len(set(_ip.user_ns['In'])), 1)
355 355
356 356 def test_reset_dhist():
357 357 "Test '%reset dhist' magic"
358 358 _ip.run_cell("tmp = [d for d in _dh]") # copy before clearing
359 359 _ip.magic('cd ' + os.path.dirname(nt.__file__))
360 360 _ip.magic('cd -')
361 361 nt.assert_true(len(_ip.user_ns['_dh']) > 0)
362 362 _ip.magic('reset -f dhist')
363 363 nt.assert_equal(len(_ip.user_ns['_dh']), 0)
364 364 _ip.run_cell("_dh = [d for d in tmp]") #restore
365 365
366 366 def test_reset_in_length():
367 367 "Test that '%reset in' preserves In[] length"
368 368 _ip.run_cell("print 'foo'")
369 369 _ip.run_cell("reset -f in")
370 370 nt.assert_equal(len(_ip.user_ns['In']), _ip.displayhook.prompt_count+1)
371 371
372 372 def test_tb_syntaxerror():
373 373 """test %tb after a SyntaxError"""
374 374 ip = get_ipython()
375 375 ip.run_cell("for")
376 376
377 377 # trap and validate stdout
378 378 save_stdout = sys.stdout
379 379 try:
380 380 sys.stdout = StringIO()
381 381 ip.run_cell("%tb")
382 382 out = sys.stdout.getvalue()
383 383 finally:
384 384 sys.stdout = save_stdout
385 385 # trim output, and only check the last line
386 386 last_line = out.rstrip().splitlines()[-1].strip()
387 387 nt.assert_equal(last_line, "SyntaxError: invalid syntax")
388 388
389 389
390 390 def test_time():
391 391 ip = get_ipython()
392 392
393 393 with tt.AssertPrints("Wall time: "):
394 394 ip.run_cell("%time None")
395 395
396 396 ip.run_cell("def f(kmjy):\n"
397 397 " %time print (2*kmjy)")
398 398
399 399 with tt.AssertPrints("Wall time: "):
400 400 with tt.AssertPrints("hihi", suppress=False):
401 401 ip.run_cell("f('hi')")
402 402
403 403
404 404 @dec.skip_win32
405 405 def test_time2():
406 406 ip = get_ipython()
407 407
408 408 with tt.AssertPrints("CPU times: user "):
409 409 ip.run_cell("%time None")
410 410
411 411 def test_time3():
412 412 """Erroneous magic function calls, issue gh-3334"""
413 413 ip = get_ipython()
414 414 ip.user_ns.pop('run', None)
415 415
416 416 with tt.AssertNotPrints("not found", channel='stderr'):
417 417 ip.run_cell("%%time\n"
418 418 "run = 0\n"
419 419 "run += 1")
420 420
421 421 def test_doctest_mode():
422 422 "Toggle doctest_mode twice, it should be a no-op and run without error"
423 423 _ip.magic('doctest_mode')
424 424 _ip.magic('doctest_mode')
425 425
426 426
427 427 def test_parse_options():
428 428 """Tests for basic options parsing in magics."""
429 429 # These are only the most minimal of tests, more should be added later. At
430 430 # the very least we check that basic text/unicode calls work OK.
431 431 m = DummyMagics(_ip)
432 432 nt.assert_equal(m.parse_options('foo', '')[1], 'foo')
433 433 nt.assert_equal(m.parse_options(u'foo', '')[1], u'foo')
434 434
435 435
436 436 def test_dirops():
437 437 """Test various directory handling operations."""
438 438 # curpath = lambda :os.path.splitdrive(os.getcwd())[1].replace('\\','/')
439 439 curpath = os.getcwd
440 440 startdir = os.getcwd()
441 441 ipdir = os.path.realpath(_ip.ipython_dir)
442 442 try:
443 443 _ip.magic('cd "%s"' % ipdir)
444 444 nt.assert_equal(curpath(), ipdir)
445 445 _ip.magic('cd -')
446 446 nt.assert_equal(curpath(), startdir)
447 447 _ip.magic('pushd "%s"' % ipdir)
448 448 nt.assert_equal(curpath(), ipdir)
449 449 _ip.magic('popd')
450 450 nt.assert_equal(curpath(), startdir)
451 451 finally:
452 452 os.chdir(startdir)
453 453
454 454
455 455 def test_xmode():
456 456 # Calling xmode three times should be a no-op
457 457 xmode = _ip.InteractiveTB.mode
458 458 for i in range(3):
459 459 _ip.magic("xmode")
460 460 nt.assert_equal(_ip.InteractiveTB.mode, xmode)
461 461
462 462 def test_reset_hard():
463 463 monitor = []
464 464 class A(object):
465 465 def __del__(self):
466 466 monitor.append(1)
467 467 def __repr__(self):
468 468 return "<A instance>"
469 469
470 470 _ip.user_ns["a"] = A()
471 471 _ip.run_cell("a")
472 472
473 473 nt.assert_equal(monitor, [])
474 474 _ip.magic("reset -f")
475 475 nt.assert_equal(monitor, [1])
476 476
477 477 class TestXdel(tt.TempFileMixin):
478 478 def test_xdel(self):
479 479 """Test that references from %run are cleared by xdel."""
480 480 src = ("class A(object):\n"
481 481 " monitor = []\n"
482 482 " def __del__(self):\n"
483 483 " self.monitor.append(1)\n"
484 484 "a = A()\n")
485 485 self.mktmp(src)
486 486 # %run creates some hidden references...
487 487 _ip.magic("run %s" % self.fname)
488 488 # ... as does the displayhook.
489 489 _ip.run_cell("a")
490 490
491 491 monitor = _ip.user_ns["A"].monitor
492 492 nt.assert_equal(monitor, [])
493 493
494 494 _ip.magic("xdel a")
495 495
496 496 # Check that a's __del__ method has been called.
497 497 nt.assert_equal(monitor, [1])
498 498
499 499 def doctest_who():
500 500 """doctest for %who
501 501
502 502 In [1]: %reset -f
503 503
504 504 In [2]: alpha = 123
505 505
506 506 In [3]: beta = 'beta'
507 507
508 508 In [4]: %who int
509 509 alpha
510 510
511 511 In [5]: %who str
512 512 beta
513 513
514 514 In [6]: %whos
515 515 Variable Type Data/Info
516 516 ----------------------------
517 517 alpha int 123
518 518 beta str beta
519 519
520 520 In [7]: %who_ls
521 521 Out[7]: ['alpha', 'beta']
522 522 """
523 523
524 524 def test_whos():
525 525 """Check that whos is protected against objects where repr() fails."""
526 526 class A(object):
527 527 def __repr__(self):
528 528 raise Exception()
529 529 _ip.user_ns['a'] = A()
530 530 _ip.magic("whos")
531 531
532 532 def doctest_precision():
533 533 """doctest for %precision
534 534
535 535 In [1]: f = get_ipython().display_formatter.formatters['text/plain']
536 536
537 537 In [2]: %precision 5
538 538 Out[2]: '%.5f'
539 539
540 540 In [3]: f.float_format
541 541 Out[3]: '%.5f'
542 542
543 543 In [4]: %precision %e
544 544 Out[4]: '%e'
545 545
546 546 In [5]: f(3.1415927)
547 547 Out[5]: '3.141593e+00'
548 548 """
549 549
550 550 def test_psearch():
551 551 with tt.AssertPrints("dict.fromkeys"):
552 552 _ip.run_cell("dict.fr*?")
553 553
554 554 def test_timeit_shlex():
555 555 """test shlex issues with timeit (#1109)"""
556 556 _ip.ex("def f(*a,**kw): pass")
557 557 _ip.magic('timeit -n1 "this is a bug".count(" ")')
558 558 _ip.magic('timeit -r1 -n1 f(" ", 1)')
559 559 _ip.magic('timeit -r1 -n1 f(" ", 1, " ", 2, " ")')
560 560 _ip.magic('timeit -r1 -n1 ("a " + "b")')
561 561 _ip.magic('timeit -r1 -n1 f("a " + "b")')
562 562 _ip.magic('timeit -r1 -n1 f("a " + "b ")')
563 563
564 564
565 def test_timeit_arguments():
566 "Test valid timeit arguments, should not cause SyntaxError (GH #1269)"
567 if sys.version_info < (3,7):
568 _ip.magic("timeit ('#')")
569 else:
570 # 3.7 optimize no-op statement like above out, and complain there is
571 # nothing in the for loop.
572 _ip.magic("timeit a=('#')")
573
574
575
576 565 def test_timeit_special_syntax():
577 566 "Test %%timeit with IPython special syntax"
578 567 @register_line_magic
579 568 def lmagic(line):
580 569 ip = get_ipython()
581 570 ip.user_ns['lmagic_out'] = line
582 571
583 572 # line mode test
584 573 _ip.run_line_magic('timeit', '-n1 -r1 %lmagic my line')
585 574 nt.assert_equal(_ip.user_ns['lmagic_out'], 'my line')
586 575 # cell mode test
587 576 _ip.run_cell_magic('timeit', '-n1 -r1', '%lmagic my line2')
588 577 nt.assert_equal(_ip.user_ns['lmagic_out'], 'my line2')
589 578
590 579 def test_timeit_return():
591 580 """
592 581 test whether timeit -o return object
593 582 """
594 583
595 584 res = _ip.run_line_magic('timeit','-n10 -r10 -o 1')
596 585 assert(res is not None)
597 586
598 587 def test_timeit_quiet():
599 588 """
600 589 test quiet option of timeit magic
601 590 """
602 591 with tt.AssertNotPrints("loops"):
603 592 _ip.run_cell("%timeit -n1 -r1 -q 1")
604 593
605 594 def test_timeit_return_quiet():
606 595 with tt.AssertNotPrints("loops"):
607 596 res = _ip.run_line_magic('timeit', '-n1 -r1 -q -o 1')
608 597 assert (res is not None)
609 598
610 599 def test_timeit_invalid_return():
611 600 with nt.assert_raises_regex(SyntaxError, "outside function"):
612 601 _ip.run_line_magic('timeit', 'return')
613 602
614 603 @dec.skipif(execution.profile is None)
615 604 def test_prun_special_syntax():
616 605 "Test %%prun with IPython special syntax"
617 606 @register_line_magic
618 607 def lmagic(line):
619 608 ip = get_ipython()
620 609 ip.user_ns['lmagic_out'] = line
621 610
622 611 # line mode test
623 612 _ip.run_line_magic('prun', '-q %lmagic my line')
624 613 nt.assert_equal(_ip.user_ns['lmagic_out'], 'my line')
625 614 # cell mode test
626 615 _ip.run_cell_magic('prun', '-q', '%lmagic my line2')
627 616 nt.assert_equal(_ip.user_ns['lmagic_out'], 'my line2')
628 617
629 618 @dec.skipif(execution.profile is None)
630 619 def test_prun_quotes():
631 620 "Test that prun does not clobber string escapes (GH #1302)"
632 621 _ip.magic(r"prun -q x = '\t'")
633 622 nt.assert_equal(_ip.user_ns['x'], '\t')
634 623
635 624 def test_extension():
636 625 # Debugging information for failures of this test
637 626 print('sys.path:')
638 627 for p in sys.path:
639 628 print(' ', p)
640 629 print('CWD', os.getcwd())
641 630
642 631 nt.assert_raises(ImportError, _ip.magic, "load_ext daft_extension")
643 632 daft_path = os.path.join(os.path.dirname(__file__), "daft_extension")
644 633 sys.path.insert(0, daft_path)
645 634 try:
646 635 _ip.user_ns.pop('arq', None)
647 636 invalidate_caches() # Clear import caches
648 637 _ip.magic("load_ext daft_extension")
649 638 nt.assert_equal(_ip.user_ns['arq'], 185)
650 639 _ip.magic("unload_ext daft_extension")
651 640 assert 'arq' not in _ip.user_ns
652 641 finally:
653 642 sys.path.remove(daft_path)
654 643
655 644
656 645 def test_notebook_export_json():
657 646 _ip = get_ipython()
658 647 _ip.history_manager.reset() # Clear any existing history.
659 648 cmds = [u"a=1", u"def b():\n return a**2", u"print('noΓ«l, Γ©tΓ©', b())"]
660 649 for i, cmd in enumerate(cmds, start=1):
661 650 _ip.history_manager.store_inputs(i, cmd)
662 651 with TemporaryDirectory() as td:
663 652 outfile = os.path.join(td, "nb.ipynb")
664 653 _ip.magic("notebook -e %s" % outfile)
665 654
666 655
667 656 class TestEnv(TestCase):
668 657
669 658 def test_env(self):
670 659 env = _ip.magic("env")
671 660 self.assertTrue(isinstance(env, dict))
672 661
673 662 def test_env_get_set_simple(self):
674 663 env = _ip.magic("env var val1")
675 664 self.assertEqual(env, None)
676 665 self.assertEqual(os.environ['var'], 'val1')
677 666 self.assertEqual(_ip.magic("env var"), 'val1')
678 667 env = _ip.magic("env var=val2")
679 668 self.assertEqual(env, None)
680 669 self.assertEqual(os.environ['var'], 'val2')
681 670
682 671 def test_env_get_set_complex(self):
683 672 env = _ip.magic("env var 'val1 '' 'val2")
684 673 self.assertEqual(env, None)
685 674 self.assertEqual(os.environ['var'], "'val1 '' 'val2")
686 675 self.assertEqual(_ip.magic("env var"), "'val1 '' 'val2")
687 676 env = _ip.magic('env var=val2 val3="val4')
688 677 self.assertEqual(env, None)
689 678 self.assertEqual(os.environ['var'], 'val2 val3="val4')
690 679
691 680 def test_env_set_bad_input(self):
692 681 self.assertRaises(UsageError, lambda: _ip.magic("set_env var"))
693 682
694 683 def test_env_set_whitespace(self):
695 684 self.assertRaises(UsageError, lambda: _ip.magic("env var A=B"))
696 685
697 686
698 687 class CellMagicTestCase(TestCase):
699 688
700 689 def check_ident(self, magic):
701 690 # Manually called, we get the result
702 691 out = _ip.run_cell_magic(magic, 'a', 'b')
703 692 nt.assert_equal(out, ('a','b'))
704 693 # Via run_cell, it goes into the user's namespace via displayhook
705 694 _ip.run_cell('%%' + magic +' c\nd')
706 695 nt.assert_equal(_ip.user_ns['_'], ('c','d'))
707 696
708 697 def test_cell_magic_func_deco(self):
709 698 "Cell magic using simple decorator"
710 699 @register_cell_magic
711 700 def cellm(line, cell):
712 701 return line, cell
713 702
714 703 self.check_ident('cellm')
715 704
716 705 def test_cell_magic_reg(self):
717 706 "Cell magic manually registered"
718 707 def cellm(line, cell):
719 708 return line, cell
720 709
721 710 _ip.register_magic_function(cellm, 'cell', 'cellm2')
722 711 self.check_ident('cellm2')
723 712
724 713 def test_cell_magic_class(self):
725 714 "Cell magics declared via a class"
726 715 @magics_class
727 716 class MyMagics(Magics):
728 717
729 718 @cell_magic
730 719 def cellm3(self, line, cell):
731 720 return line, cell
732 721
733 722 _ip.register_magics(MyMagics)
734 723 self.check_ident('cellm3')
735 724
736 725 def test_cell_magic_class2(self):
737 726 "Cell magics declared via a class, #2"
738 727 @magics_class
739 728 class MyMagics2(Magics):
740 729
741 730 @cell_magic('cellm4')
742 731 def cellm33(self, line, cell):
743 732 return line, cell
744 733
745 734 _ip.register_magics(MyMagics2)
746 735 self.check_ident('cellm4')
747 736 # Check that nothing is registered as 'cellm33'
748 737 c33 = _ip.find_cell_magic('cellm33')
749 738 nt.assert_equal(c33, None)
750 739
751 740 def test_file():
752 741 """Basic %%file"""
753 742 ip = get_ipython()
754 743 with TemporaryDirectory() as td:
755 744 fname = os.path.join(td, 'file1')
756 745 ip.run_cell_magic("file", fname, u'\n'.join([
757 746 'line1',
758 747 'line2',
759 748 ]))
760 749 with open(fname) as f:
761 750 s = f.read()
762 751 nt.assert_in('line1\n', s)
763 752 nt.assert_in('line2', s)
764 753
765 754 def test_file_var_expand():
766 755 """%%file $filename"""
767 756 ip = get_ipython()
768 757 with TemporaryDirectory() as td:
769 758 fname = os.path.join(td, 'file1')
770 759 ip.user_ns['filename'] = fname
771 760 ip.run_cell_magic("file", '$filename', u'\n'.join([
772 761 'line1',
773 762 'line2',
774 763 ]))
775 764 with open(fname) as f:
776 765 s = f.read()
777 766 nt.assert_in('line1\n', s)
778 767 nt.assert_in('line2', s)
779 768
780 769 def test_file_unicode():
781 770 """%%file with unicode cell"""
782 771 ip = get_ipython()
783 772 with TemporaryDirectory() as td:
784 773 fname = os.path.join(td, 'file1')
785 774 ip.run_cell_magic("file", fname, u'\n'.join([
786 775 u'linΓ©1',
787 776 u'linΓ©2',
788 777 ]))
789 778 with io.open(fname, encoding='utf-8') as f:
790 779 s = f.read()
791 780 nt.assert_in(u'linΓ©1\n', s)
792 781 nt.assert_in(u'linΓ©2', s)
793 782
794 783 def test_file_amend():
795 784 """%%file -a amends files"""
796 785 ip = get_ipython()
797 786 with TemporaryDirectory() as td:
798 787 fname = os.path.join(td, 'file2')
799 788 ip.run_cell_magic("file", fname, u'\n'.join([
800 789 'line1',
801 790 'line2',
802 791 ]))
803 792 ip.run_cell_magic("file", "-a %s" % fname, u'\n'.join([
804 793 'line3',
805 794 'line4',
806 795 ]))
807 796 with open(fname) as f:
808 797 s = f.read()
809 798 nt.assert_in('line1\n', s)
810 799 nt.assert_in('line3\n', s)
811 800
812 801
813 802 def test_script_config():
814 803 ip = get_ipython()
815 804 ip.config.ScriptMagics.script_magics = ['whoda']
816 805 sm = script.ScriptMagics(shell=ip)
817 806 nt.assert_in('whoda', sm.magics['cell'])
818 807
819 808 @dec.skip_win32
820 809 def test_script_out():
821 810 ip = get_ipython()
822 811 ip.run_cell_magic("script", "--out output sh", "echo 'hi'")
823 812 nt.assert_equal(ip.user_ns['output'], 'hi\n')
824 813
825 814 @dec.skip_win32
826 815 def test_script_err():
827 816 ip = get_ipython()
828 817 ip.run_cell_magic("script", "--err error sh", "echo 'hello' >&2")
829 818 nt.assert_equal(ip.user_ns['error'], 'hello\n')
830 819
831 820 @dec.skip_win32
832 821 def test_script_out_err():
833 822 ip = get_ipython()
834 823 ip.run_cell_magic("script", "--out output --err error sh", "echo 'hi'\necho 'hello' >&2")
835 824 nt.assert_equal(ip.user_ns['output'], 'hi\n')
836 825 nt.assert_equal(ip.user_ns['error'], 'hello\n')
837 826
838 827 @dec.skip_win32
839 828 def test_script_bg_out():
840 829 ip = get_ipython()
841 830 ip.run_cell_magic("script", "--bg --out output sh", "echo 'hi'")
831
842 832 nt.assert_equal(ip.user_ns['output'].read(), b'hi\n')
833 ip.user_ns['output'].close()
843 834
844 835 @dec.skip_win32
845 836 def test_script_bg_err():
846 837 ip = get_ipython()
847 838 ip.run_cell_magic("script", "--bg --err error sh", "echo 'hello' >&2")
848 839 nt.assert_equal(ip.user_ns['error'].read(), b'hello\n')
840 ip.user_ns['error'].close()
849 841
850 842 @dec.skip_win32
851 843 def test_script_bg_out_err():
852 844 ip = get_ipython()
853 845 ip.run_cell_magic("script", "--bg --out output --err error sh", "echo 'hi'\necho 'hello' >&2")
854 846 nt.assert_equal(ip.user_ns['output'].read(), b'hi\n')
855 847 nt.assert_equal(ip.user_ns['error'].read(), b'hello\n')
848 ip.user_ns['output'].close()
849 ip.user_ns['error'].close()
856 850
857 851 def test_script_defaults():
858 852 ip = get_ipython()
859 853 for cmd in ['sh', 'bash', 'perl', 'ruby']:
860 854 try:
861 855 find_cmd(cmd)
862 856 except Exception:
863 857 pass
864 858 else:
865 859 nt.assert_in(cmd, ip.magics_manager.magics['cell'])
866 860
867 861
868 862 @magics_class
869 863 class FooFoo(Magics):
870 864 """class with both %foo and %%foo magics"""
871 865 @line_magic('foo')
872 866 def line_foo(self, line):
873 867 "I am line foo"
874 868 pass
875 869
876 870 @cell_magic("foo")
877 871 def cell_foo(self, line, cell):
878 872 "I am cell foo, not line foo"
879 873 pass
880 874
881 875 def test_line_cell_info():
882 876 """%%foo and %foo magics are distinguishable to inspect"""
883 877 ip = get_ipython()
884 878 ip.magics_manager.register(FooFoo)
885 879 oinfo = ip.object_inspect('foo')
886 880 nt.assert_true(oinfo['found'])
887 881 nt.assert_true(oinfo['ismagic'])
888 882
889 883 oinfo = ip.object_inspect('%%foo')
890 884 nt.assert_true(oinfo['found'])
891 885 nt.assert_true(oinfo['ismagic'])
892 886 nt.assert_equal(oinfo['docstring'], FooFoo.cell_foo.__doc__)
893 887
894 888 oinfo = ip.object_inspect('%foo')
895 889 nt.assert_true(oinfo['found'])
896 890 nt.assert_true(oinfo['ismagic'])
897 891 nt.assert_equal(oinfo['docstring'], FooFoo.line_foo.__doc__)
898 892
899 893 def test_multiple_magics():
900 894 ip = get_ipython()
901 895 foo1 = FooFoo(ip)
902 896 foo2 = FooFoo(ip)
903 897 mm = ip.magics_manager
904 898 mm.register(foo1)
905 899 nt.assert_true(mm.magics['line']['foo'].__self__ is foo1)
906 900 mm.register(foo2)
907 901 nt.assert_true(mm.magics['line']['foo'].__self__ is foo2)
908 902
909 903 def test_alias_magic():
910 904 """Test %alias_magic."""
911 905 ip = get_ipython()
912 906 mm = ip.magics_manager
913 907
914 908 # Basic operation: both cell and line magics are created, if possible.
915 909 ip.run_line_magic('alias_magic', 'timeit_alias timeit')
916 910 nt.assert_in('timeit_alias', mm.magics['line'])
917 911 nt.assert_in('timeit_alias', mm.magics['cell'])
918 912
919 913 # --cell is specified, line magic not created.
920 914 ip.run_line_magic('alias_magic', '--cell timeit_cell_alias timeit')
921 915 nt.assert_not_in('timeit_cell_alias', mm.magics['line'])
922 916 nt.assert_in('timeit_cell_alias', mm.magics['cell'])
923 917
924 918 # Test that line alias is created successfully.
925 919 ip.run_line_magic('alias_magic', '--line env_alias env')
926 920 nt.assert_equal(ip.run_line_magic('env', ''),
927 921 ip.run_line_magic('env_alias', ''))
928 922
929 923 # Test that line alias with parameters passed in is created successfully.
930 924 ip.run_line_magic('alias_magic', '--line history_alias history --params ' + shlex.quote('3'))
931 925 nt.assert_in('history_alias', mm.magics['line'])
932 926
933 927
934 928 def test_save():
935 929 """Test %save."""
936 930 ip = get_ipython()
937 931 ip.history_manager.reset() # Clear any existing history.
938 932 cmds = [u"a=1", u"def b():\n return a**2", u"print(a, b())"]
939 933 for i, cmd in enumerate(cmds, start=1):
940 934 ip.history_manager.store_inputs(i, cmd)
941 935 with TemporaryDirectory() as tmpdir:
942 936 file = os.path.join(tmpdir, "testsave.py")
943 937 ip.run_line_magic("save", "%s 1-10" % file)
944 938 with open(file) as f:
945 939 content = f.read()
946 940 nt.assert_equal(content.count(cmds[0]), 1)
947 941 nt.assert_in('coding: utf-8', content)
948 942 ip.run_line_magic("save", "-a %s 1-10" % file)
949 943 with open(file) as f:
950 944 content = f.read()
951 945 nt.assert_equal(content.count(cmds[0]), 2)
952 946 nt.assert_in('coding: utf-8', content)
953 947
954 948
955 949 def test_store():
956 950 """Test %store."""
957 951 ip = get_ipython()
958 952 ip.run_line_magic('load_ext', 'storemagic')
959 953
960 954 # make sure the storage is empty
961 955 ip.run_line_magic('store', '-z')
962 956 ip.user_ns['var'] = 42
963 957 ip.run_line_magic('store', 'var')
964 958 ip.user_ns['var'] = 39
965 959 ip.run_line_magic('store', '-r')
966 960 nt.assert_equal(ip.user_ns['var'], 42)
967 961
968 962 ip.run_line_magic('store', '-d var')
969 963 ip.user_ns['var'] = 39
970 964 ip.run_line_magic('store' , '-r')
971 965 nt.assert_equal(ip.user_ns['var'], 39)
972 966
973 967
974 968 def _run_edit_test(arg_s, exp_filename=None,
975 969 exp_lineno=-1,
976 970 exp_contents=None,
977 971 exp_is_temp=None):
978 972 ip = get_ipython()
979 973 M = code.CodeMagics(ip)
980 974 last_call = ['','']
981 975 opts,args = M.parse_options(arg_s,'prxn:')
982 976 filename, lineno, is_temp = M._find_edit_target(ip, args, opts, last_call)
983 977
984 978 if exp_filename is not None:
985 979 nt.assert_equal(exp_filename, filename)
986 980 if exp_contents is not None:
987 981 with io.open(filename, 'r', encoding='utf-8') as f:
988 982 contents = f.read()
989 983 nt.assert_equal(exp_contents, contents)
990 984 if exp_lineno != -1:
991 985 nt.assert_equal(exp_lineno, lineno)
992 986 if exp_is_temp is not None:
993 987 nt.assert_equal(exp_is_temp, is_temp)
994 988
995 989
996 990 def test_edit_interactive():
997 991 """%edit on interactively defined objects"""
998 992 ip = get_ipython()
999 993 n = ip.execution_count
1000 994 ip.run_cell(u"def foo(): return 1", store_history=True)
1001 995
1002 996 try:
1003 997 _run_edit_test("foo")
1004 998 except code.InteractivelyDefined as e:
1005 999 nt.assert_equal(e.index, n)
1006 1000 else:
1007 1001 raise AssertionError("Should have raised InteractivelyDefined")
1008 1002
1009 1003
1010 1004 def test_edit_cell():
1011 1005 """%edit [cell id]"""
1012 1006 ip = get_ipython()
1013 1007
1014 1008 ip.run_cell(u"def foo(): return 1", store_history=True)
1015 1009
1016 1010 # test
1017 1011 _run_edit_test("1", exp_contents=ip.user_ns['In'][1], exp_is_temp=True)
1018 1012
1019 1013 def test_bookmark():
1020 1014 ip = get_ipython()
1021 1015 ip.run_line_magic('bookmark', 'bmname')
1022 1016 with tt.AssertPrints('bmname'):
1023 1017 ip.run_line_magic('bookmark', '-l')
1024 1018 ip.run_line_magic('bookmark', '-d bmname')
1025 1019
1026 1020 def test_ls_magic():
1027 1021 ip = get_ipython()
1028 1022 json_formatter = ip.display_formatter.formatters['application/json']
1029 1023 json_formatter.enabled = True
1030 1024 lsmagic = ip.magic('lsmagic')
1031 1025 with warnings.catch_warnings(record=True) as w:
1032 1026 j = json_formatter(lsmagic)
1033 1027 nt.assert_equal(sorted(j), ['cell', 'line'])
1034 1028 nt.assert_equal(w, []) # no warnings
1035 1029
1036 1030 def test_strip_initial_indent():
1037 1031 def sii(s):
1038 1032 lines = s.splitlines()
1039 1033 return '\n'.join(code.strip_initial_indent(lines))
1040 1034
1041 1035 nt.assert_equal(sii(" a = 1\nb = 2"), "a = 1\nb = 2")
1042 1036 nt.assert_equal(sii(" a\n b\nc"), "a\n b\nc")
1043 1037 nt.assert_equal(sii("a\n b"), "a\n b")
1044 1038
1045 1039 def test_logging_magic_quiet_from_arg():
1046 1040 _ip.config.LoggingMagics.quiet = False
1047 1041 lm = logging.LoggingMagics(shell=_ip)
1048 1042 with TemporaryDirectory() as td:
1049 1043 try:
1050 1044 with tt.AssertNotPrints(re.compile("Activating.*")):
1051 1045 lm.logstart('-q {}'.format(
1052 1046 os.path.join(td, "quiet_from_arg.log")))
1053 1047 finally:
1054 1048 _ip.logger.logstop()
1055 1049
1056 1050 def test_logging_magic_quiet_from_config():
1057 1051 _ip.config.LoggingMagics.quiet = True
1058 1052 lm = logging.LoggingMagics(shell=_ip)
1059 1053 with TemporaryDirectory() as td:
1060 1054 try:
1061 1055 with tt.AssertNotPrints(re.compile("Activating.*")):
1062 1056 lm.logstart(os.path.join(td, "quiet_from_config.log"))
1063 1057 finally:
1064 1058 _ip.logger.logstop()
1065 1059
1066 1060 def test_logging_magic_not_quiet():
1067 1061 _ip.config.LoggingMagics.quiet = False
1068 1062 lm = logging.LoggingMagics(shell=_ip)
1069 1063 with TemporaryDirectory() as td:
1070 1064 try:
1071 1065 with tt.AssertPrints(re.compile("Activating.*")):
1072 1066 lm.logstart(os.path.join(td, "not_quiet.log"))
1073 1067 finally:
1074 1068 _ip.logger.logstop()
1075 1069
1070 ##
1071 # this is slow, put at the end for local testing.
1072 ##
1073 def test_timeit_arguments():
1074 "Test valid timeit arguments, should not cause SyntaxError (GH #1269)"
1075 if sys.version_info < (3,7):
1076 _ip.magic("timeit ('#')")
1077 else:
1078 # 3.7 optimize no-op statement like above out, and complain there is
1079 # nothing in the for loop.
1080 _ip.magic("timeit a=('#')")
General Comments 0
You need to be logged in to leave comments. Login now