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