##// END OF EJS Templates
Adding a -q option to the logstart magic to suppress output of log state. Also added a command line option
Joshua Storck -
Show More
@@ -1,183 +1,195
1 """Implementation of magic functions for IPython's own logging.
1 """Implementation of magic functions for IPython's own logging.
2 """
2 """
3 #-----------------------------------------------------------------------------
3 #-----------------------------------------------------------------------------
4 # Copyright (c) 2012 The IPython Development Team.
4 # Copyright (c) 2012 The IPython Development Team.
5 #
5 #
6 # Distributed under the terms of the Modified BSD License.
6 # Distributed under the terms of the Modified BSD License.
7 #
7 #
8 # The full license is in the file COPYING.txt, distributed with this software.
8 # The full license is in the file COPYING.txt, distributed with this software.
9 #-----------------------------------------------------------------------------
9 #-----------------------------------------------------------------------------
10
10
11 #-----------------------------------------------------------------------------
11 #-----------------------------------------------------------------------------
12 # Imports
12 # Imports
13 #-----------------------------------------------------------------------------
13 #-----------------------------------------------------------------------------
14
14
15 # Stdlib
15 # Stdlib
16 import os
16 import os
17 import sys
17 import sys
18
18
19 # Our own packages
19 # Our own packages
20 from IPython.core.magic import Magics, magics_class, line_magic
20 from IPython.core.magic import Magics, magics_class, line_magic
21 from warnings import warn
21 from warnings import warn
22 from traitlets import Bool
22
23
23 #-----------------------------------------------------------------------------
24 #-----------------------------------------------------------------------------
24 # Magic implementation classes
25 # Magic implementation classes
25 #-----------------------------------------------------------------------------
26 #-----------------------------------------------------------------------------
26
27
27 @magics_class
28 @magics_class
28 class LoggingMagics(Magics):
29 class LoggingMagics(Magics):
29 """Magics related to all logging machinery."""
30 """Magics related to all logging machinery."""
30
31
32 quiet = Bool(False, help=
33 """
34 Suppress output of log state when logging is enabled
35 """
36 ).tag(config=True)
37
31 @line_magic
38 @line_magic
32 def logstart(self, parameter_s=''):
39 def logstart(self, parameter_s=''):
33 """Start logging anywhere in a session.
40 """Start logging anywhere in a session.
34
41
35 %logstart [-o|-r|-t] [log_name [log_mode]]
42 %logstart [-o|-r|-t|-q] [log_name [log_mode]]
36
43
37 If no name is given, it defaults to a file named 'ipython_log.py' in your
44 If no name is given, it defaults to a file named 'ipython_log.py' in your
38 current directory, in 'rotate' mode (see below).
45 current directory, in 'rotate' mode (see below).
39
46
40 '%logstart name' saves to file 'name' in 'backup' mode. It saves your
47 '%logstart name' saves to file 'name' in 'backup' mode. It saves your
41 history up to that point and then continues logging.
48 history up to that point and then continues logging.
42
49
43 %logstart takes a second optional parameter: logging mode. This can be one
50 %logstart takes a second optional parameter: logging mode. This can be one
44 of (note that the modes are given unquoted):
51 of (note that the modes are given unquoted):
45
52
46 append
53 append
47 Keep logging at the end of any existing file.
54 Keep logging at the end of any existing file.
48
55
49 backup
56 backup
50 Rename any existing file to name~ and start name.
57 Rename any existing file to name~ and start name.
51
58
52 global
59 global
53 Append to a single logfile in your home directory.
60 Append to a single logfile in your home directory.
54
61
55 over
62 over
56 Overwrite any existing log.
63 Overwrite any existing log.
57
64
58 rotate
65 rotate
59 Create rotating logs: name.1~, name.2~, etc.
66 Create rotating logs: name.1~, name.2~, etc.
60
67
61 Options:
68 Options:
62
69
63 -o
70 -o
64 log also IPython's output. In this mode, all commands which
71 log also IPython's output. In this mode, all commands which
65 generate an Out[NN] prompt are recorded to the logfile, right after
72 generate an Out[NN] prompt are recorded to the logfile, right after
66 their corresponding input line. The output lines are always
73 their corresponding input line. The output lines are always
67 prepended with a '#[Out]# ' marker, so that the log remains valid
74 prepended with a '#[Out]# ' marker, so that the log remains valid
68 Python code.
75 Python code.
69
76
70 Since this marker is always the same, filtering only the output from
77 Since this marker is always the same, filtering only the output from
71 a log is very easy, using for example a simple awk call::
78 a log is very easy, using for example a simple awk call::
72
79
73 awk -F'#\\[Out\\]# ' '{if($2) {print $2}}' ipython_log.py
80 awk -F'#\\[Out\\]# ' '{if($2) {print $2}}' ipython_log.py
74
81
75 -r
82 -r
76 log 'raw' input. Normally, IPython's logs contain the processed
83 log 'raw' input. Normally, IPython's logs contain the processed
77 input, so that user lines are logged in their final form, converted
84 input, so that user lines are logged in their final form, converted
78 into valid Python. For example, %Exit is logged as
85 into valid Python. For example, %Exit is logged as
79 _ip.magic("Exit"). If the -r flag is given, all input is logged
86 _ip.magic("Exit"). If the -r flag is given, all input is logged
80 exactly as typed, with no transformations applied.
87 exactly as typed, with no transformations applied.
81
88
82 -t
89 -t
83 put timestamps before each input line logged (these are put in
90 put timestamps before each input line logged (these are put in
84 comments).
91 comments).
92
93 -q
94 suppress output of logstate message when logging is invoked
85 """
95 """
86
96
87 opts,par = self.parse_options(parameter_s,'ort')
97 opts,par = self.parse_options(parameter_s,'ortq')
88 log_output = 'o' in opts
98 log_output = 'o' in opts
89 log_raw_input = 'r' in opts
99 log_raw_input = 'r' in opts
90 timestamp = 't' in opts
100 timestamp = 't' in opts
101 quiet = 'q' in opts
91
102
92 logger = self.shell.logger
103 logger = self.shell.logger
93
104
94 # if no args are given, the defaults set in the logger constructor by
105 # if no args are given, the defaults set in the logger constructor by
95 # ipython remain valid
106 # ipython remain valid
96 if par:
107 if par:
97 try:
108 try:
98 logfname,logmode = par.split()
109 logfname,logmode = par.split()
99 except:
110 except:
100 logfname = par
111 logfname = par
101 logmode = 'backup'
112 logmode = 'backup'
102 else:
113 else:
103 logfname = logger.logfname
114 logfname = logger.logfname
104 logmode = logger.logmode
115 logmode = logger.logmode
105 # put logfname into rc struct as if it had been called on the command
116 # put logfname into rc struct as if it had been called on the command
106 # line, so it ends up saved in the log header Save it in case we need
117 # line, so it ends up saved in the log header Save it in case we need
107 # to restore it...
118 # to restore it...
108 old_logfile = self.shell.logfile
119 old_logfile = self.shell.logfile
109 if logfname:
120 if logfname:
110 logfname = os.path.expanduser(logfname)
121 logfname = os.path.expanduser(logfname)
111 self.shell.logfile = logfname
122 self.shell.logfile = logfname
112
123
113 loghead = u'# IPython log file\n\n'
124 loghead = u'# IPython log file\n\n'
114 try:
125 try:
115 logger.logstart(logfname, loghead, logmode, log_output, timestamp,
126 logger.logstart(logfname, loghead, logmode, log_output, timestamp,
116 log_raw_input)
127 log_raw_input)
117 except:
128 except:
118 self.shell.logfile = old_logfile
129 self.shell.logfile = old_logfile
119 warn("Couldn't start log: %s" % sys.exc_info()[1])
130 warn("Couldn't start log: %s" % sys.exc_info()[1])
120 else:
131 else:
121 # log input history up to this point, optionally interleaving
132 # log input history up to this point, optionally interleaving
122 # output if requested
133 # output if requested
123
134
124 if timestamp:
135 if timestamp:
125 # disable timestamping for the previous history, since we've
136 # disable timestamping for the previous history, since we've
126 # lost those already (no time machine here).
137 # lost those already (no time machine here).
127 logger.timestamp = False
138 logger.timestamp = False
128
139
129 if log_raw_input:
140 if log_raw_input:
130 input_hist = self.shell.history_manager.input_hist_raw
141 input_hist = self.shell.history_manager.input_hist_raw
131 else:
142 else:
132 input_hist = self.shell.history_manager.input_hist_parsed
143 input_hist = self.shell.history_manager.input_hist_parsed
133
144
134 if log_output:
145 if log_output:
135 log_write = logger.log_write
146 log_write = logger.log_write
136 output_hist = self.shell.history_manager.output_hist
147 output_hist = self.shell.history_manager.output_hist
137 for n in range(1,len(input_hist)-1):
148 for n in range(1,len(input_hist)-1):
138 log_write(input_hist[n].rstrip() + u'\n')
149 log_write(input_hist[n].rstrip() + u'\n')
139 if n in output_hist:
150 if n in output_hist:
140 log_write(repr(output_hist[n]),'output')
151 log_write(repr(output_hist[n]),'output')
141 else:
152 else:
142 logger.log_write(u'\n'.join(input_hist[1:]))
153 logger.log_write(u'\n'.join(input_hist[1:]))
143 logger.log_write(u'\n')
154 logger.log_write(u'\n')
144 if timestamp:
155 if timestamp:
145 # re-enable timestamping
156 # re-enable timestamping
146 logger.timestamp = True
157 logger.timestamp = True
147
158
148 print ('Activating auto-logging. '
159 if not (self.quiet or quiet):
149 'Current session state plus future input saved.')
160 print ('Activating auto-logging. '
150 logger.logstate()
161 'Current session state plus future input saved.')
162 logger.logstate()
151
163
152 @line_magic
164 @line_magic
153 def logstop(self, parameter_s=''):
165 def logstop(self, parameter_s=''):
154 """Fully stop logging and close log file.
166 """Fully stop logging and close log file.
155
167
156 In order to start logging again, a new %logstart call needs to be made,
168 In order to start logging again, a new %logstart call needs to be made,
157 possibly (though not necessarily) with a new filename, mode and other
169 possibly (though not necessarily) with a new filename, mode and other
158 options."""
170 options."""
159 self.shell.logger.logstop()
171 self.shell.logger.logstop()
160
172
161 @line_magic
173 @line_magic
162 def logoff(self, parameter_s=''):
174 def logoff(self, parameter_s=''):
163 """Temporarily stop logging.
175 """Temporarily stop logging.
164
176
165 You must have previously started logging."""
177 You must have previously started logging."""
166 self.shell.logger.switch_log(0)
178 self.shell.logger.switch_log(0)
167
179
168 @line_magic
180 @line_magic
169 def logon(self, parameter_s=''):
181 def logon(self, parameter_s=''):
170 """Restart logging.
182 """Restart logging.
171
183
172 This function is for restarting logging which you've temporarily
184 This function is for restarting logging which you've temporarily
173 stopped with %logoff. For starting logging for the first time, you
185 stopped with %logoff. For starting logging for the first time, you
174 must use the %logstart function, which allows you to specify an
186 must use the %logstart function, which allows you to specify an
175 optional log filename."""
187 optional log filename."""
176
188
177 self.shell.logger.switch_log(1)
189 self.shell.logger.switch_log(1)
178
190
179 @line_magic
191 @line_magic
180 def logstate(self, parameter_s=''):
192 def logstate(self, parameter_s=''):
181 """Print the status of the logging system."""
193 """Print the status of the logging system."""
182
194
183 self.shell.logger.logstate()
195 self.shell.logger.logstate()
@@ -1,979 +1,1012
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 sys
10 import sys
10 import warnings
11 import warnings
11 from unittest import TestCase
12 from unittest import TestCase
12 from importlib import invalidate_caches
13 from importlib import invalidate_caches
13 from io import StringIO
14 from io import StringIO
14
15
15 import nose.tools as nt
16 import nose.tools as nt
16
17
17 from IPython import get_ipython
18 from IPython import get_ipython
18 from IPython.core import magic
19 from IPython.core import magic
19 from IPython.core.error import UsageError
20 from IPython.core.error import UsageError
20 from IPython.core.magic import (Magics, magics_class, line_magic,
21 from IPython.core.magic import (Magics, magics_class, line_magic,
21 cell_magic,
22 cell_magic,
22 register_line_magic, register_cell_magic)
23 register_line_magic, register_cell_magic)
23 from IPython.core.magics import execution, script, code
24 from IPython.core.magics import execution, script, code, logging
24 from IPython.testing import decorators as dec
25 from IPython.testing import decorators as dec
25 from IPython.testing import tools as tt
26 from IPython.testing import tools as tt
26 from IPython.utils import py3compat
27 from IPython.utils import py3compat
27 from IPython.utils.io import capture_output
28 from IPython.utils.io import capture_output
28 from IPython.utils.tempdir import TemporaryDirectory
29 from IPython.utils.tempdir import TemporaryDirectory
29 from IPython.utils.process import find_cmd
30 from IPython.utils.process import find_cmd
30
31
31
32
32
33
33 _ip = get_ipython()
34 _ip = get_ipython()
34
35
35 @magic.magics_class
36 @magic.magics_class
36 class DummyMagics(magic.Magics): pass
37 class DummyMagics(magic.Magics): pass
37
38
38 def test_extract_code_ranges():
39 def test_extract_code_ranges():
39 instr = "1 3 5-6 7-9 10:15 17: :10 10- -13 :"
40 instr = "1 3 5-6 7-9 10:15 17: :10 10- -13 :"
40 expected = [(0, 1),
41 expected = [(0, 1),
41 (2, 3),
42 (2, 3),
42 (4, 6),
43 (4, 6),
43 (6, 9),
44 (6, 9),
44 (9, 14),
45 (9, 14),
45 (16, None),
46 (16, None),
46 (None, 9),
47 (None, 9),
47 (9, None),
48 (9, None),
48 (None, 13),
49 (None, 13),
49 (None, None)]
50 (None, None)]
50 actual = list(code.extract_code_ranges(instr))
51 actual = list(code.extract_code_ranges(instr))
51 nt.assert_equal(actual, expected)
52 nt.assert_equal(actual, expected)
52
53
53 def test_extract_symbols():
54 def test_extract_symbols():
54 source = """import foo\na = 10\ndef b():\n return 42\n\n\nclass A: pass\n\n\n"""
55 source = """import foo\na = 10\ndef b():\n return 42\n\n\nclass A: pass\n\n\n"""
55 symbols_args = ["a", "b", "A", "A,b", "A,a", "z"]
56 symbols_args = ["a", "b", "A", "A,b", "A,a", "z"]
56 expected = [([], ['a']),
57 expected = [([], ['a']),
57 (["def b():\n return 42\n"], []),
58 (["def b():\n return 42\n"], []),
58 (["class A: pass\n"], []),
59 (["class A: pass\n"], []),
59 (["class A: pass\n", "def b():\n return 42\n"], []),
60 (["class A: pass\n", "def b():\n return 42\n"], []),
60 (["class A: pass\n"], ['a']),
61 (["class A: pass\n"], ['a']),
61 ([], ['z'])]
62 ([], ['z'])]
62 for symbols, exp in zip(symbols_args, expected):
63 for symbols, exp in zip(symbols_args, expected):
63 nt.assert_equal(code.extract_symbols(source, symbols), exp)
64 nt.assert_equal(code.extract_symbols(source, symbols), exp)
64
65
65
66
66 def test_extract_symbols_raises_exception_with_non_python_code():
67 def test_extract_symbols_raises_exception_with_non_python_code():
67 source = ("=begin A Ruby program :)=end\n"
68 source = ("=begin A Ruby program :)=end\n"
68 "def hello\n"
69 "def hello\n"
69 "puts 'Hello world'\n"
70 "puts 'Hello world'\n"
70 "end")
71 "end")
71 with nt.assert_raises(SyntaxError):
72 with nt.assert_raises(SyntaxError):
72 code.extract_symbols(source, "hello")
73 code.extract_symbols(source, "hello")
73
74
74 def test_config():
75 def test_config():
75 """ test that config magic does not raise
76 """ test that config magic does not raise
76 can happen if Configurable init is moved too early into
77 can happen if Configurable init is moved too early into
77 Magics.__init__ as then a Config object will be registerd as a
78 Magics.__init__ as then a Config object will be registerd as a
78 magic.
79 magic.
79 """
80 """
80 ## should not raise.
81 ## should not raise.
81 _ip.magic('config')
82 _ip.magic('config')
82
83
83 def test_rehashx():
84 def test_rehashx():
84 # clear up everything
85 # clear up everything
85 _ip.alias_manager.clear_aliases()
86 _ip.alias_manager.clear_aliases()
86 del _ip.db['syscmdlist']
87 del _ip.db['syscmdlist']
87
88
88 _ip.magic('rehashx')
89 _ip.magic('rehashx')
89 # Practically ALL ipython development systems will have more than 10 aliases
90 # Practically ALL ipython development systems will have more than 10 aliases
90
91
91 nt.assert_true(len(_ip.alias_manager.aliases) > 10)
92 nt.assert_true(len(_ip.alias_manager.aliases) > 10)
92 for name, cmd in _ip.alias_manager.aliases:
93 for name, cmd in _ip.alias_manager.aliases:
93 # we must strip dots from alias names
94 # we must strip dots from alias names
94 nt.assert_not_in('.', name)
95 nt.assert_not_in('.', name)
95
96
96 # rehashx must fill up syscmdlist
97 # rehashx must fill up syscmdlist
97 scoms = _ip.db['syscmdlist']
98 scoms = _ip.db['syscmdlist']
98 nt.assert_true(len(scoms) > 10)
99 nt.assert_true(len(scoms) > 10)
99
100
100
101
101 def test_magic_parse_options():
102 def test_magic_parse_options():
102 """Test that we don't mangle paths when parsing magic options."""
103 """Test that we don't mangle paths when parsing magic options."""
103 ip = get_ipython()
104 ip = get_ipython()
104 path = 'c:\\x'
105 path = 'c:\\x'
105 m = DummyMagics(ip)
106 m = DummyMagics(ip)
106 opts = m.parse_options('-f %s' % path,'f:')[0]
107 opts = m.parse_options('-f %s' % path,'f:')[0]
107 # argv splitting is os-dependent
108 # argv splitting is os-dependent
108 if os.name == 'posix':
109 if os.name == 'posix':
109 expected = 'c:x'
110 expected = 'c:x'
110 else:
111 else:
111 expected = path
112 expected = path
112 nt.assert_equal(opts['f'], expected)
113 nt.assert_equal(opts['f'], expected)
113
114
114 def test_magic_parse_long_options():
115 def test_magic_parse_long_options():
115 """Magic.parse_options can handle --foo=bar long options"""
116 """Magic.parse_options can handle --foo=bar long options"""
116 ip = get_ipython()
117 ip = get_ipython()
117 m = DummyMagics(ip)
118 m = DummyMagics(ip)
118 opts, _ = m.parse_options('--foo --bar=bubble', 'a', 'foo', 'bar=')
119 opts, _ = m.parse_options('--foo --bar=bubble', 'a', 'foo', 'bar=')
119 nt.assert_in('foo', opts)
120 nt.assert_in('foo', opts)
120 nt.assert_in('bar', opts)
121 nt.assert_in('bar', opts)
121 nt.assert_equal(opts['bar'], "bubble")
122 nt.assert_equal(opts['bar'], "bubble")
122
123
123
124
124 @dec.skip_without('sqlite3')
125 @dec.skip_without('sqlite3')
125 def doctest_hist_f():
126 def doctest_hist_f():
126 """Test %hist -f with temporary filename.
127 """Test %hist -f with temporary filename.
127
128
128 In [9]: import tempfile
129 In [9]: import tempfile
129
130
130 In [10]: tfile = tempfile.mktemp('.py','tmp-ipython-')
131 In [10]: tfile = tempfile.mktemp('.py','tmp-ipython-')
131
132
132 In [11]: %hist -nl -f $tfile 3
133 In [11]: %hist -nl -f $tfile 3
133
134
134 In [13]: import os; os.unlink(tfile)
135 In [13]: import os; os.unlink(tfile)
135 """
136 """
136
137
137
138
138 @dec.skip_without('sqlite3')
139 @dec.skip_without('sqlite3')
139 def doctest_hist_r():
140 def doctest_hist_r():
140 """Test %hist -r
141 """Test %hist -r
141
142
142 XXX - This test is not recording the output correctly. For some reason, in
143 XXX - This test is not recording the output correctly. For some reason, in
143 testing mode the raw history isn't getting populated. No idea why.
144 testing mode the raw history isn't getting populated. No idea why.
144 Disabling the output checking for now, though at least we do run it.
145 Disabling the output checking for now, though at least we do run it.
145
146
146 In [1]: 'hist' in _ip.lsmagic()
147 In [1]: 'hist' in _ip.lsmagic()
147 Out[1]: True
148 Out[1]: True
148
149
149 In [2]: x=1
150 In [2]: x=1
150
151
151 In [3]: %hist -rl 2
152 In [3]: %hist -rl 2
152 x=1 # random
153 x=1 # random
153 %hist -r 2
154 %hist -r 2
154 """
155 """
155
156
156
157
157 @dec.skip_without('sqlite3')
158 @dec.skip_without('sqlite3')
158 def doctest_hist_op():
159 def doctest_hist_op():
159 """Test %hist -op
160 """Test %hist -op
160
161
161 In [1]: class b(float):
162 In [1]: class b(float):
162 ...: pass
163 ...: pass
163 ...:
164 ...:
164
165
165 In [2]: class s(object):
166 In [2]: class s(object):
166 ...: def __str__(self):
167 ...: def __str__(self):
167 ...: return 's'
168 ...: return 's'
168 ...:
169 ...:
169
170
170 In [3]:
171 In [3]:
171
172
172 In [4]: class r(b):
173 In [4]: class r(b):
173 ...: def __repr__(self):
174 ...: def __repr__(self):
174 ...: return 'r'
175 ...: return 'r'
175 ...:
176 ...:
176
177
177 In [5]: class sr(s,r): pass
178 In [5]: class sr(s,r): pass
178 ...:
179 ...:
179
180
180 In [6]:
181 In [6]:
181
182
182 In [7]: bb=b()
183 In [7]: bb=b()
183
184
184 In [8]: ss=s()
185 In [8]: ss=s()
185
186
186 In [9]: rr=r()
187 In [9]: rr=r()
187
188
188 In [10]: ssrr=sr()
189 In [10]: ssrr=sr()
189
190
190 In [11]: 4.5
191 In [11]: 4.5
191 Out[11]: 4.5
192 Out[11]: 4.5
192
193
193 In [12]: str(ss)
194 In [12]: str(ss)
194 Out[12]: 's'
195 Out[12]: 's'
195
196
196 In [13]:
197 In [13]:
197
198
198 In [14]: %hist -op
199 In [14]: %hist -op
199 >>> class b:
200 >>> class b:
200 ... pass
201 ... pass
201 ...
202 ...
202 >>> class s(b):
203 >>> class s(b):
203 ... def __str__(self):
204 ... def __str__(self):
204 ... return 's'
205 ... return 's'
205 ...
206 ...
206 >>>
207 >>>
207 >>> class r(b):
208 >>> class r(b):
208 ... def __repr__(self):
209 ... def __repr__(self):
209 ... return 'r'
210 ... return 'r'
210 ...
211 ...
211 >>> class sr(s,r): pass
212 >>> class sr(s,r): pass
212 >>>
213 >>>
213 >>> bb=b()
214 >>> bb=b()
214 >>> ss=s()
215 >>> ss=s()
215 >>> rr=r()
216 >>> rr=r()
216 >>> ssrr=sr()
217 >>> ssrr=sr()
217 >>> 4.5
218 >>> 4.5
218 4.5
219 4.5
219 >>> str(ss)
220 >>> str(ss)
220 's'
221 's'
221 >>>
222 >>>
222 """
223 """
223
224
224 def test_hist_pof():
225 def test_hist_pof():
225 ip = get_ipython()
226 ip = get_ipython()
226 ip.run_cell(u"1+2", store_history=True)
227 ip.run_cell(u"1+2", store_history=True)
227 #raise Exception(ip.history_manager.session_number)
228 #raise Exception(ip.history_manager.session_number)
228 #raise Exception(list(ip.history_manager._get_range_session()))
229 #raise Exception(list(ip.history_manager._get_range_session()))
229 with TemporaryDirectory() as td:
230 with TemporaryDirectory() as td:
230 tf = os.path.join(td, 'hist.py')
231 tf = os.path.join(td, 'hist.py')
231 ip.run_line_magic('history', '-pof %s' % tf)
232 ip.run_line_magic('history', '-pof %s' % tf)
232 assert os.path.isfile(tf)
233 assert os.path.isfile(tf)
233
234
234
235
235 @dec.skip_without('sqlite3')
236 @dec.skip_without('sqlite3')
236 def test_macro():
237 def test_macro():
237 ip = get_ipython()
238 ip = get_ipython()
238 ip.history_manager.reset() # Clear any existing history.
239 ip.history_manager.reset() # Clear any existing history.
239 cmds = ["a=1", "def b():\n return a**2", "print(a,b())"]
240 cmds = ["a=1", "def b():\n return a**2", "print(a,b())"]
240 for i, cmd in enumerate(cmds, start=1):
241 for i, cmd in enumerate(cmds, start=1):
241 ip.history_manager.store_inputs(i, cmd)
242 ip.history_manager.store_inputs(i, cmd)
242 ip.magic("macro test 1-3")
243 ip.magic("macro test 1-3")
243 nt.assert_equal(ip.user_ns["test"].value, "\n".join(cmds)+"\n")
244 nt.assert_equal(ip.user_ns["test"].value, "\n".join(cmds)+"\n")
244
245
245 # List macros
246 # List macros
246 nt.assert_in("test", ip.magic("macro"))
247 nt.assert_in("test", ip.magic("macro"))
247
248
248
249
249 @dec.skip_without('sqlite3')
250 @dec.skip_without('sqlite3')
250 def test_macro_run():
251 def test_macro_run():
251 """Test that we can run a multi-line macro successfully."""
252 """Test that we can run a multi-line macro successfully."""
252 ip = get_ipython()
253 ip = get_ipython()
253 ip.history_manager.reset()
254 ip.history_manager.reset()
254 cmds = ["a=10", "a+=1", py3compat.doctest_refactor_print("print a"),
255 cmds = ["a=10", "a+=1", py3compat.doctest_refactor_print("print a"),
255 "%macro test 2-3"]
256 "%macro test 2-3"]
256 for cmd in cmds:
257 for cmd in cmds:
257 ip.run_cell(cmd, store_history=True)
258 ip.run_cell(cmd, store_history=True)
258 nt.assert_equal(ip.user_ns["test"].value,
259 nt.assert_equal(ip.user_ns["test"].value,
259 py3compat.doctest_refactor_print("a+=1\nprint a\n"))
260 py3compat.doctest_refactor_print("a+=1\nprint a\n"))
260 with tt.AssertPrints("12"):
261 with tt.AssertPrints("12"):
261 ip.run_cell("test")
262 ip.run_cell("test")
262 with tt.AssertPrints("13"):
263 with tt.AssertPrints("13"):
263 ip.run_cell("test")
264 ip.run_cell("test")
264
265
265
266
266 def test_magic_magic():
267 def test_magic_magic():
267 """Test %magic"""
268 """Test %magic"""
268 ip = get_ipython()
269 ip = get_ipython()
269 with capture_output() as captured:
270 with capture_output() as captured:
270 ip.magic("magic")
271 ip.magic("magic")
271
272
272 stdout = captured.stdout
273 stdout = captured.stdout
273 nt.assert_in('%magic', stdout)
274 nt.assert_in('%magic', stdout)
274 nt.assert_in('IPython', stdout)
275 nt.assert_in('IPython', stdout)
275 nt.assert_in('Available', stdout)
276 nt.assert_in('Available', stdout)
276
277
277
278
278 @dec.skipif_not_numpy
279 @dec.skipif_not_numpy
279 def test_numpy_reset_array_undec():
280 def test_numpy_reset_array_undec():
280 "Test '%reset array' functionality"
281 "Test '%reset array' functionality"
281 _ip.ex('import numpy as np')
282 _ip.ex('import numpy as np')
282 _ip.ex('a = np.empty(2)')
283 _ip.ex('a = np.empty(2)')
283 nt.assert_in('a', _ip.user_ns)
284 nt.assert_in('a', _ip.user_ns)
284 _ip.magic('reset -f array')
285 _ip.magic('reset -f array')
285 nt.assert_not_in('a', _ip.user_ns)
286 nt.assert_not_in('a', _ip.user_ns)
286
287
287 def test_reset_out():
288 def test_reset_out():
288 "Test '%reset out' magic"
289 "Test '%reset out' magic"
289 _ip.run_cell("parrot = 'dead'", store_history=True)
290 _ip.run_cell("parrot = 'dead'", store_history=True)
290 # test '%reset -f out', make an Out prompt
291 # test '%reset -f out', make an Out prompt
291 _ip.run_cell("parrot", store_history=True)
292 _ip.run_cell("parrot", store_history=True)
292 nt.assert_true('dead' in [_ip.user_ns[x] for x in ('_','__','___')])
293 nt.assert_true('dead' in [_ip.user_ns[x] for x in ('_','__','___')])
293 _ip.magic('reset -f out')
294 _ip.magic('reset -f out')
294 nt.assert_false('dead' in [_ip.user_ns[x] for x in ('_','__','___')])
295 nt.assert_false('dead' in [_ip.user_ns[x] for x in ('_','__','___')])
295 nt.assert_equal(len(_ip.user_ns['Out']), 0)
296 nt.assert_equal(len(_ip.user_ns['Out']), 0)
296
297
297 def test_reset_in():
298 def test_reset_in():
298 "Test '%reset in' magic"
299 "Test '%reset in' magic"
299 # test '%reset -f in'
300 # test '%reset -f in'
300 _ip.run_cell("parrot", store_history=True)
301 _ip.run_cell("parrot", store_history=True)
301 nt.assert_true('parrot' in [_ip.user_ns[x] for x in ('_i','_ii','_iii')])
302 nt.assert_true('parrot' in [_ip.user_ns[x] for x in ('_i','_ii','_iii')])
302 _ip.magic('%reset -f in')
303 _ip.magic('%reset -f in')
303 nt.assert_false('parrot' in [_ip.user_ns[x] for x in ('_i','_ii','_iii')])
304 nt.assert_false('parrot' in [_ip.user_ns[x] for x in ('_i','_ii','_iii')])
304 nt.assert_equal(len(set(_ip.user_ns['In'])), 1)
305 nt.assert_equal(len(set(_ip.user_ns['In'])), 1)
305
306
306 def test_reset_dhist():
307 def test_reset_dhist():
307 "Test '%reset dhist' magic"
308 "Test '%reset dhist' magic"
308 _ip.run_cell("tmp = [d for d in _dh]") # copy before clearing
309 _ip.run_cell("tmp = [d for d in _dh]") # copy before clearing
309 _ip.magic('cd ' + os.path.dirname(nt.__file__))
310 _ip.magic('cd ' + os.path.dirname(nt.__file__))
310 _ip.magic('cd -')
311 _ip.magic('cd -')
311 nt.assert_true(len(_ip.user_ns['_dh']) > 0)
312 nt.assert_true(len(_ip.user_ns['_dh']) > 0)
312 _ip.magic('reset -f dhist')
313 _ip.magic('reset -f dhist')
313 nt.assert_equal(len(_ip.user_ns['_dh']), 0)
314 nt.assert_equal(len(_ip.user_ns['_dh']), 0)
314 _ip.run_cell("_dh = [d for d in tmp]") #restore
315 _ip.run_cell("_dh = [d for d in tmp]") #restore
315
316
316 def test_reset_in_length():
317 def test_reset_in_length():
317 "Test that '%reset in' preserves In[] length"
318 "Test that '%reset in' preserves In[] length"
318 _ip.run_cell("print 'foo'")
319 _ip.run_cell("print 'foo'")
319 _ip.run_cell("reset -f in")
320 _ip.run_cell("reset -f in")
320 nt.assert_equal(len(_ip.user_ns['In']), _ip.displayhook.prompt_count+1)
321 nt.assert_equal(len(_ip.user_ns['In']), _ip.displayhook.prompt_count+1)
321
322
322 def test_tb_syntaxerror():
323 def test_tb_syntaxerror():
323 """test %tb after a SyntaxError"""
324 """test %tb after a SyntaxError"""
324 ip = get_ipython()
325 ip = get_ipython()
325 ip.run_cell("for")
326 ip.run_cell("for")
326
327
327 # trap and validate stdout
328 # trap and validate stdout
328 save_stdout = sys.stdout
329 save_stdout = sys.stdout
329 try:
330 try:
330 sys.stdout = StringIO()
331 sys.stdout = StringIO()
331 ip.run_cell("%tb")
332 ip.run_cell("%tb")
332 out = sys.stdout.getvalue()
333 out = sys.stdout.getvalue()
333 finally:
334 finally:
334 sys.stdout = save_stdout
335 sys.stdout = save_stdout
335 # trim output, and only check the last line
336 # trim output, and only check the last line
336 last_line = out.rstrip().splitlines()[-1].strip()
337 last_line = out.rstrip().splitlines()[-1].strip()
337 nt.assert_equal(last_line, "SyntaxError: invalid syntax")
338 nt.assert_equal(last_line, "SyntaxError: invalid syntax")
338
339
339
340
340 def test_time():
341 def test_time():
341 ip = get_ipython()
342 ip = get_ipython()
342
343
343 with tt.AssertPrints("Wall time: "):
344 with tt.AssertPrints("Wall time: "):
344 ip.run_cell("%time None")
345 ip.run_cell("%time None")
345
346
346 ip.run_cell("def f(kmjy):\n"
347 ip.run_cell("def f(kmjy):\n"
347 " %time print (2*kmjy)")
348 " %time print (2*kmjy)")
348
349
349 with tt.AssertPrints("Wall time: "):
350 with tt.AssertPrints("Wall time: "):
350 with tt.AssertPrints("hihi", suppress=False):
351 with tt.AssertPrints("hihi", suppress=False):
351 ip.run_cell("f('hi')")
352 ip.run_cell("f('hi')")
352
353
353
354
354 @dec.skip_win32
355 @dec.skip_win32
355 def test_time2():
356 def test_time2():
356 ip = get_ipython()
357 ip = get_ipython()
357
358
358 with tt.AssertPrints("CPU times: user "):
359 with tt.AssertPrints("CPU times: user "):
359 ip.run_cell("%time None")
360 ip.run_cell("%time None")
360
361
361 def test_time3():
362 def test_time3():
362 """Erroneous magic function calls, issue gh-3334"""
363 """Erroneous magic function calls, issue gh-3334"""
363 ip = get_ipython()
364 ip = get_ipython()
364 ip.user_ns.pop('run', None)
365 ip.user_ns.pop('run', None)
365
366
366 with tt.AssertNotPrints("not found", channel='stderr'):
367 with tt.AssertNotPrints("not found", channel='stderr'):
367 ip.run_cell("%%time\n"
368 ip.run_cell("%%time\n"
368 "run = 0\n"
369 "run = 0\n"
369 "run += 1")
370 "run += 1")
370
371
371 def test_doctest_mode():
372 def test_doctest_mode():
372 "Toggle doctest_mode twice, it should be a no-op and run without error"
373 "Toggle doctest_mode twice, it should be a no-op and run without error"
373 _ip.magic('doctest_mode')
374 _ip.magic('doctest_mode')
374 _ip.magic('doctest_mode')
375 _ip.magic('doctest_mode')
375
376
376
377
377 def test_parse_options():
378 def test_parse_options():
378 """Tests for basic options parsing in magics."""
379 """Tests for basic options parsing in magics."""
379 # These are only the most minimal of tests, more should be added later. At
380 # These are only the most minimal of tests, more should be added later. At
380 # the very least we check that basic text/unicode calls work OK.
381 # the very least we check that basic text/unicode calls work OK.
381 m = DummyMagics(_ip)
382 m = DummyMagics(_ip)
382 nt.assert_equal(m.parse_options('foo', '')[1], 'foo')
383 nt.assert_equal(m.parse_options('foo', '')[1], 'foo')
383 nt.assert_equal(m.parse_options(u'foo', '')[1], u'foo')
384 nt.assert_equal(m.parse_options(u'foo', '')[1], u'foo')
384
385
385
386
386 def test_dirops():
387 def test_dirops():
387 """Test various directory handling operations."""
388 """Test various directory handling operations."""
388 # curpath = lambda :os.path.splitdrive(os.getcwd())[1].replace('\\','/')
389 # curpath = lambda :os.path.splitdrive(os.getcwd())[1].replace('\\','/')
389 curpath = os.getcwd
390 curpath = os.getcwd
390 startdir = os.getcwd()
391 startdir = os.getcwd()
391 ipdir = os.path.realpath(_ip.ipython_dir)
392 ipdir = os.path.realpath(_ip.ipython_dir)
392 try:
393 try:
393 _ip.magic('cd "%s"' % ipdir)
394 _ip.magic('cd "%s"' % ipdir)
394 nt.assert_equal(curpath(), ipdir)
395 nt.assert_equal(curpath(), ipdir)
395 _ip.magic('cd -')
396 _ip.magic('cd -')
396 nt.assert_equal(curpath(), startdir)
397 nt.assert_equal(curpath(), startdir)
397 _ip.magic('pushd "%s"' % ipdir)
398 _ip.magic('pushd "%s"' % ipdir)
398 nt.assert_equal(curpath(), ipdir)
399 nt.assert_equal(curpath(), ipdir)
399 _ip.magic('popd')
400 _ip.magic('popd')
400 nt.assert_equal(curpath(), startdir)
401 nt.assert_equal(curpath(), startdir)
401 finally:
402 finally:
402 os.chdir(startdir)
403 os.chdir(startdir)
403
404
404
405
405 def test_xmode():
406 def test_xmode():
406 # Calling xmode three times should be a no-op
407 # Calling xmode three times should be a no-op
407 xmode = _ip.InteractiveTB.mode
408 xmode = _ip.InteractiveTB.mode
408 for i in range(3):
409 for i in range(3):
409 _ip.magic("xmode")
410 _ip.magic("xmode")
410 nt.assert_equal(_ip.InteractiveTB.mode, xmode)
411 nt.assert_equal(_ip.InteractiveTB.mode, xmode)
411
412
412 def test_reset_hard():
413 def test_reset_hard():
413 monitor = []
414 monitor = []
414 class A(object):
415 class A(object):
415 def __del__(self):
416 def __del__(self):
416 monitor.append(1)
417 monitor.append(1)
417 def __repr__(self):
418 def __repr__(self):
418 return "<A instance>"
419 return "<A instance>"
419
420
420 _ip.user_ns["a"] = A()
421 _ip.user_ns["a"] = A()
421 _ip.run_cell("a")
422 _ip.run_cell("a")
422
423
423 nt.assert_equal(monitor, [])
424 nt.assert_equal(monitor, [])
424 _ip.magic("reset -f")
425 _ip.magic("reset -f")
425 nt.assert_equal(monitor, [1])
426 nt.assert_equal(monitor, [1])
426
427
427 class TestXdel(tt.TempFileMixin):
428 class TestXdel(tt.TempFileMixin):
428 def test_xdel(self):
429 def test_xdel(self):
429 """Test that references from %run are cleared by xdel."""
430 """Test that references from %run are cleared by xdel."""
430 src = ("class A(object):\n"
431 src = ("class A(object):\n"
431 " monitor = []\n"
432 " monitor = []\n"
432 " def __del__(self):\n"
433 " def __del__(self):\n"
433 " self.monitor.append(1)\n"
434 " self.monitor.append(1)\n"
434 "a = A()\n")
435 "a = A()\n")
435 self.mktmp(src)
436 self.mktmp(src)
436 # %run creates some hidden references...
437 # %run creates some hidden references...
437 _ip.magic("run %s" % self.fname)
438 _ip.magic("run %s" % self.fname)
438 # ... as does the displayhook.
439 # ... as does the displayhook.
439 _ip.run_cell("a")
440 _ip.run_cell("a")
440
441
441 monitor = _ip.user_ns["A"].monitor
442 monitor = _ip.user_ns["A"].monitor
442 nt.assert_equal(monitor, [])
443 nt.assert_equal(monitor, [])
443
444
444 _ip.magic("xdel a")
445 _ip.magic("xdel a")
445
446
446 # Check that a's __del__ method has been called.
447 # Check that a's __del__ method has been called.
447 nt.assert_equal(monitor, [1])
448 nt.assert_equal(monitor, [1])
448
449
449 def doctest_who():
450 def doctest_who():
450 """doctest for %who
451 """doctest for %who
451
452
452 In [1]: %reset -f
453 In [1]: %reset -f
453
454
454 In [2]: alpha = 123
455 In [2]: alpha = 123
455
456
456 In [3]: beta = 'beta'
457 In [3]: beta = 'beta'
457
458
458 In [4]: %who int
459 In [4]: %who int
459 alpha
460 alpha
460
461
461 In [5]: %who str
462 In [5]: %who str
462 beta
463 beta
463
464
464 In [6]: %whos
465 In [6]: %whos
465 Variable Type Data/Info
466 Variable Type Data/Info
466 ----------------------------
467 ----------------------------
467 alpha int 123
468 alpha int 123
468 beta str beta
469 beta str beta
469
470
470 In [7]: %who_ls
471 In [7]: %who_ls
471 Out[7]: ['alpha', 'beta']
472 Out[7]: ['alpha', 'beta']
472 """
473 """
473
474
474 def test_whos():
475 def test_whos():
475 """Check that whos is protected against objects where repr() fails."""
476 """Check that whos is protected against objects where repr() fails."""
476 class A(object):
477 class A(object):
477 def __repr__(self):
478 def __repr__(self):
478 raise Exception()
479 raise Exception()
479 _ip.user_ns['a'] = A()
480 _ip.user_ns['a'] = A()
480 _ip.magic("whos")
481 _ip.magic("whos")
481
482
482 @py3compat.u_format
483 @py3compat.u_format
483 def doctest_precision():
484 def doctest_precision():
484 """doctest for %precision
485 """doctest for %precision
485
486
486 In [1]: f = get_ipython().display_formatter.formatters['text/plain']
487 In [1]: f = get_ipython().display_formatter.formatters['text/plain']
487
488
488 In [2]: %precision 5
489 In [2]: %precision 5
489 Out[2]: {u}'%.5f'
490 Out[2]: {u}'%.5f'
490
491
491 In [3]: f.float_format
492 In [3]: f.float_format
492 Out[3]: {u}'%.5f'
493 Out[3]: {u}'%.5f'
493
494
494 In [4]: %precision %e
495 In [4]: %precision %e
495 Out[4]: {u}'%e'
496 Out[4]: {u}'%e'
496
497
497 In [5]: f(3.1415927)
498 In [5]: f(3.1415927)
498 Out[5]: {u}'3.141593e+00'
499 Out[5]: {u}'3.141593e+00'
499 """
500 """
500
501
501 def test_psearch():
502 def test_psearch():
502 with tt.AssertPrints("dict.fromkeys"):
503 with tt.AssertPrints("dict.fromkeys"):
503 _ip.run_cell("dict.fr*?")
504 _ip.run_cell("dict.fr*?")
504
505
505 def test_timeit_shlex():
506 def test_timeit_shlex():
506 """test shlex issues with timeit (#1109)"""
507 """test shlex issues with timeit (#1109)"""
507 _ip.ex("def f(*a,**kw): pass")
508 _ip.ex("def f(*a,**kw): pass")
508 _ip.magic('timeit -n1 "this is a bug".count(" ")')
509 _ip.magic('timeit -n1 "this is a bug".count(" ")')
509 _ip.magic('timeit -r1 -n1 f(" ", 1)')
510 _ip.magic('timeit -r1 -n1 f(" ", 1)')
510 _ip.magic('timeit -r1 -n1 f(" ", 1, " ", 2, " ")')
511 _ip.magic('timeit -r1 -n1 f(" ", 1, " ", 2, " ")')
511 _ip.magic('timeit -r1 -n1 ("a " + "b")')
512 _ip.magic('timeit -r1 -n1 ("a " + "b")')
512 _ip.magic('timeit -r1 -n1 f("a " + "b")')
513 _ip.magic('timeit -r1 -n1 f("a " + "b")')
513 _ip.magic('timeit -r1 -n1 f("a " + "b ")')
514 _ip.magic('timeit -r1 -n1 f("a " + "b ")')
514
515
515
516
516 def test_timeit_arguments():
517 def test_timeit_arguments():
517 "Test valid timeit arguments, should not cause SyntaxError (GH #1269)"
518 "Test valid timeit arguments, should not cause SyntaxError (GH #1269)"
518 _ip.magic("timeit ('#')")
519 _ip.magic("timeit ('#')")
519
520
520
521
521 def test_timeit_special_syntax():
522 def test_timeit_special_syntax():
522 "Test %%timeit with IPython special syntax"
523 "Test %%timeit with IPython special syntax"
523 @register_line_magic
524 @register_line_magic
524 def lmagic(line):
525 def lmagic(line):
525 ip = get_ipython()
526 ip = get_ipython()
526 ip.user_ns['lmagic_out'] = line
527 ip.user_ns['lmagic_out'] = line
527
528
528 # line mode test
529 # line mode test
529 _ip.run_line_magic('timeit', '-n1 -r1 %lmagic my line')
530 _ip.run_line_magic('timeit', '-n1 -r1 %lmagic my line')
530 nt.assert_equal(_ip.user_ns['lmagic_out'], 'my line')
531 nt.assert_equal(_ip.user_ns['lmagic_out'], 'my line')
531 # cell mode test
532 # cell mode test
532 _ip.run_cell_magic('timeit', '-n1 -r1', '%lmagic my line2')
533 _ip.run_cell_magic('timeit', '-n1 -r1', '%lmagic my line2')
533 nt.assert_equal(_ip.user_ns['lmagic_out'], 'my line2')
534 nt.assert_equal(_ip.user_ns['lmagic_out'], 'my line2')
534
535
535 def test_timeit_return():
536 def test_timeit_return():
536 """
537 """
537 test wether timeit -o return object
538 test wether timeit -o return object
538 """
539 """
539
540
540 res = _ip.run_line_magic('timeit','-n10 -r10 -o 1')
541 res = _ip.run_line_magic('timeit','-n10 -r10 -o 1')
541 assert(res is not None)
542 assert(res is not None)
542
543
543 def test_timeit_quiet():
544 def test_timeit_quiet():
544 """
545 """
545 test quiet option of timeit magic
546 test quiet option of timeit magic
546 """
547 """
547 with tt.AssertNotPrints("loops"):
548 with tt.AssertNotPrints("loops"):
548 _ip.run_cell("%timeit -n1 -r1 -q 1")
549 _ip.run_cell("%timeit -n1 -r1 -q 1")
549
550
550 def test_timeit_return_quiet():
551 def test_timeit_return_quiet():
551 with tt.AssertNotPrints("loops"):
552 with tt.AssertNotPrints("loops"):
552 res = _ip.run_line_magic('timeit', '-n1 -r1 -q -o 1')
553 res = _ip.run_line_magic('timeit', '-n1 -r1 -q -o 1')
553 assert (res is not None)
554 assert (res is not None)
554
555
555 @dec.skipif(execution.profile is None)
556 @dec.skipif(execution.profile is None)
556 def test_prun_special_syntax():
557 def test_prun_special_syntax():
557 "Test %%prun with IPython special syntax"
558 "Test %%prun with IPython special syntax"
558 @register_line_magic
559 @register_line_magic
559 def lmagic(line):
560 def lmagic(line):
560 ip = get_ipython()
561 ip = get_ipython()
561 ip.user_ns['lmagic_out'] = line
562 ip.user_ns['lmagic_out'] = line
562
563
563 # line mode test
564 # line mode test
564 _ip.run_line_magic('prun', '-q %lmagic my line')
565 _ip.run_line_magic('prun', '-q %lmagic my line')
565 nt.assert_equal(_ip.user_ns['lmagic_out'], 'my line')
566 nt.assert_equal(_ip.user_ns['lmagic_out'], 'my line')
566 # cell mode test
567 # cell mode test
567 _ip.run_cell_magic('prun', '-q', '%lmagic my line2')
568 _ip.run_cell_magic('prun', '-q', '%lmagic my line2')
568 nt.assert_equal(_ip.user_ns['lmagic_out'], 'my line2')
569 nt.assert_equal(_ip.user_ns['lmagic_out'], 'my line2')
569
570
570 @dec.skipif(execution.profile is None)
571 @dec.skipif(execution.profile is None)
571 def test_prun_quotes():
572 def test_prun_quotes():
572 "Test that prun does not clobber string escapes (GH #1302)"
573 "Test that prun does not clobber string escapes (GH #1302)"
573 _ip.magic(r"prun -q x = '\t'")
574 _ip.magic(r"prun -q x = '\t'")
574 nt.assert_equal(_ip.user_ns['x'], '\t')
575 nt.assert_equal(_ip.user_ns['x'], '\t')
575
576
576 def test_extension():
577 def test_extension():
577 # Debugging information for failures of this test
578 # Debugging information for failures of this test
578 print('sys.path:')
579 print('sys.path:')
579 for p in sys.path:
580 for p in sys.path:
580 print(' ', p)
581 print(' ', p)
581 print('CWD', os.getcwd())
582 print('CWD', os.getcwd())
582
583
583 nt.assert_raises(ImportError, _ip.magic, "load_ext daft_extension")
584 nt.assert_raises(ImportError, _ip.magic, "load_ext daft_extension")
584 daft_path = os.path.join(os.path.dirname(__file__), "daft_extension")
585 daft_path = os.path.join(os.path.dirname(__file__), "daft_extension")
585 sys.path.insert(0, daft_path)
586 sys.path.insert(0, daft_path)
586 try:
587 try:
587 _ip.user_ns.pop('arq', None)
588 _ip.user_ns.pop('arq', None)
588 invalidate_caches() # Clear import caches
589 invalidate_caches() # Clear import caches
589 _ip.magic("load_ext daft_extension")
590 _ip.magic("load_ext daft_extension")
590 nt.assert_equal(_ip.user_ns['arq'], 185)
591 nt.assert_equal(_ip.user_ns['arq'], 185)
591 _ip.magic("unload_ext daft_extension")
592 _ip.magic("unload_ext daft_extension")
592 assert 'arq' not in _ip.user_ns
593 assert 'arq' not in _ip.user_ns
593 finally:
594 finally:
594 sys.path.remove(daft_path)
595 sys.path.remove(daft_path)
595
596
596
597
597 def test_notebook_export_json():
598 def test_notebook_export_json():
598 _ip = get_ipython()
599 _ip = get_ipython()
599 _ip.history_manager.reset() # Clear any existing history.
600 _ip.history_manager.reset() # Clear any existing history.
600 cmds = [u"a=1", u"def b():\n return a**2", u"print('noΓ«l, Γ©tΓ©', b())"]
601 cmds = [u"a=1", u"def b():\n return a**2", u"print('noΓ«l, Γ©tΓ©', b())"]
601 for i, cmd in enumerate(cmds, start=1):
602 for i, cmd in enumerate(cmds, start=1):
602 _ip.history_manager.store_inputs(i, cmd)
603 _ip.history_manager.store_inputs(i, cmd)
603 with TemporaryDirectory() as td:
604 with TemporaryDirectory() as td:
604 outfile = os.path.join(td, "nb.ipynb")
605 outfile = os.path.join(td, "nb.ipynb")
605 _ip.magic("notebook -e %s" % outfile)
606 _ip.magic("notebook -e %s" % outfile)
606
607
607
608
608 class TestEnv(TestCase):
609 class TestEnv(TestCase):
609
610
610 def test_env(self):
611 def test_env(self):
611 env = _ip.magic("env")
612 env = _ip.magic("env")
612 self.assertTrue(isinstance(env, dict))
613 self.assertTrue(isinstance(env, dict))
613
614
614 def test_env_get_set_simple(self):
615 def test_env_get_set_simple(self):
615 env = _ip.magic("env var val1")
616 env = _ip.magic("env var val1")
616 self.assertEqual(env, None)
617 self.assertEqual(env, None)
617 self.assertEqual(os.environ['var'], 'val1')
618 self.assertEqual(os.environ['var'], 'val1')
618 self.assertEqual(_ip.magic("env var"), 'val1')
619 self.assertEqual(_ip.magic("env var"), 'val1')
619 env = _ip.magic("env var=val2")
620 env = _ip.magic("env var=val2")
620 self.assertEqual(env, None)
621 self.assertEqual(env, None)
621 self.assertEqual(os.environ['var'], 'val2')
622 self.assertEqual(os.environ['var'], 'val2')
622
623
623 def test_env_get_set_complex(self):
624 def test_env_get_set_complex(self):
624 env = _ip.magic("env var 'val1 '' 'val2")
625 env = _ip.magic("env var 'val1 '' 'val2")
625 self.assertEqual(env, None)
626 self.assertEqual(env, None)
626 self.assertEqual(os.environ['var'], "'val1 '' 'val2")
627 self.assertEqual(os.environ['var'], "'val1 '' 'val2")
627 self.assertEqual(_ip.magic("env var"), "'val1 '' 'val2")
628 self.assertEqual(_ip.magic("env var"), "'val1 '' 'val2")
628 env = _ip.magic('env var=val2 val3="val4')
629 env = _ip.magic('env var=val2 val3="val4')
629 self.assertEqual(env, None)
630 self.assertEqual(env, None)
630 self.assertEqual(os.environ['var'], 'val2 val3="val4')
631 self.assertEqual(os.environ['var'], 'val2 val3="val4')
631
632
632 def test_env_set_bad_input(self):
633 def test_env_set_bad_input(self):
633 self.assertRaises(UsageError, lambda: _ip.magic("set_env var"))
634 self.assertRaises(UsageError, lambda: _ip.magic("set_env var"))
634
635
635 def test_env_set_whitespace(self):
636 def test_env_set_whitespace(self):
636 self.assertRaises(UsageError, lambda: _ip.magic("env var A=B"))
637 self.assertRaises(UsageError, lambda: _ip.magic("env var A=B"))
637
638
638
639
639 class CellMagicTestCase(TestCase):
640 class CellMagicTestCase(TestCase):
640
641
641 def check_ident(self, magic):
642 def check_ident(self, magic):
642 # Manually called, we get the result
643 # Manually called, we get the result
643 out = _ip.run_cell_magic(magic, 'a', 'b')
644 out = _ip.run_cell_magic(magic, 'a', 'b')
644 nt.assert_equal(out, ('a','b'))
645 nt.assert_equal(out, ('a','b'))
645 # Via run_cell, it goes into the user's namespace via displayhook
646 # Via run_cell, it goes into the user's namespace via displayhook
646 _ip.run_cell('%%' + magic +' c\nd')
647 _ip.run_cell('%%' + magic +' c\nd')
647 nt.assert_equal(_ip.user_ns['_'], ('c','d'))
648 nt.assert_equal(_ip.user_ns['_'], ('c','d'))
648
649
649 def test_cell_magic_func_deco(self):
650 def test_cell_magic_func_deco(self):
650 "Cell magic using simple decorator"
651 "Cell magic using simple decorator"
651 @register_cell_magic
652 @register_cell_magic
652 def cellm(line, cell):
653 def cellm(line, cell):
653 return line, cell
654 return line, cell
654
655
655 self.check_ident('cellm')
656 self.check_ident('cellm')
656
657
657 def test_cell_magic_reg(self):
658 def test_cell_magic_reg(self):
658 "Cell magic manually registered"
659 "Cell magic manually registered"
659 def cellm(line, cell):
660 def cellm(line, cell):
660 return line, cell
661 return line, cell
661
662
662 _ip.register_magic_function(cellm, 'cell', 'cellm2')
663 _ip.register_magic_function(cellm, 'cell', 'cellm2')
663 self.check_ident('cellm2')
664 self.check_ident('cellm2')
664
665
665 def test_cell_magic_class(self):
666 def test_cell_magic_class(self):
666 "Cell magics declared via a class"
667 "Cell magics declared via a class"
667 @magics_class
668 @magics_class
668 class MyMagics(Magics):
669 class MyMagics(Magics):
669
670
670 @cell_magic
671 @cell_magic
671 def cellm3(self, line, cell):
672 def cellm3(self, line, cell):
672 return line, cell
673 return line, cell
673
674
674 _ip.register_magics(MyMagics)
675 _ip.register_magics(MyMagics)
675 self.check_ident('cellm3')
676 self.check_ident('cellm3')
676
677
677 def test_cell_magic_class2(self):
678 def test_cell_magic_class2(self):
678 "Cell magics declared via a class, #2"
679 "Cell magics declared via a class, #2"
679 @magics_class
680 @magics_class
680 class MyMagics2(Magics):
681 class MyMagics2(Magics):
681
682
682 @cell_magic('cellm4')
683 @cell_magic('cellm4')
683 def cellm33(self, line, cell):
684 def cellm33(self, line, cell):
684 return line, cell
685 return line, cell
685
686
686 _ip.register_magics(MyMagics2)
687 _ip.register_magics(MyMagics2)
687 self.check_ident('cellm4')
688 self.check_ident('cellm4')
688 # Check that nothing is registered as 'cellm33'
689 # Check that nothing is registered as 'cellm33'
689 c33 = _ip.find_cell_magic('cellm33')
690 c33 = _ip.find_cell_magic('cellm33')
690 nt.assert_equal(c33, None)
691 nt.assert_equal(c33, None)
691
692
692 def test_file():
693 def test_file():
693 """Basic %%file"""
694 """Basic %%file"""
694 ip = get_ipython()
695 ip = get_ipython()
695 with TemporaryDirectory() as td:
696 with TemporaryDirectory() as td:
696 fname = os.path.join(td, 'file1')
697 fname = os.path.join(td, 'file1')
697 ip.run_cell_magic("file", fname, u'\n'.join([
698 ip.run_cell_magic("file", fname, u'\n'.join([
698 'line1',
699 'line1',
699 'line2',
700 'line2',
700 ]))
701 ]))
701 with open(fname) as f:
702 with open(fname) as f:
702 s = f.read()
703 s = f.read()
703 nt.assert_in('line1\n', s)
704 nt.assert_in('line1\n', s)
704 nt.assert_in('line2', s)
705 nt.assert_in('line2', s)
705
706
706 def test_file_var_expand():
707 def test_file_var_expand():
707 """%%file $filename"""
708 """%%file $filename"""
708 ip = get_ipython()
709 ip = get_ipython()
709 with TemporaryDirectory() as td:
710 with TemporaryDirectory() as td:
710 fname = os.path.join(td, 'file1')
711 fname = os.path.join(td, 'file1')
711 ip.user_ns['filename'] = fname
712 ip.user_ns['filename'] = fname
712 ip.run_cell_magic("file", '$filename', u'\n'.join([
713 ip.run_cell_magic("file", '$filename', u'\n'.join([
713 'line1',
714 'line1',
714 'line2',
715 'line2',
715 ]))
716 ]))
716 with open(fname) as f:
717 with open(fname) as f:
717 s = f.read()
718 s = f.read()
718 nt.assert_in('line1\n', s)
719 nt.assert_in('line1\n', s)
719 nt.assert_in('line2', s)
720 nt.assert_in('line2', s)
720
721
721 def test_file_unicode():
722 def test_file_unicode():
722 """%%file with unicode cell"""
723 """%%file with unicode cell"""
723 ip = get_ipython()
724 ip = get_ipython()
724 with TemporaryDirectory() as td:
725 with TemporaryDirectory() as td:
725 fname = os.path.join(td, 'file1')
726 fname = os.path.join(td, 'file1')
726 ip.run_cell_magic("file", fname, u'\n'.join([
727 ip.run_cell_magic("file", fname, u'\n'.join([
727 u'linΓ©1',
728 u'linΓ©1',
728 u'linΓ©2',
729 u'linΓ©2',
729 ]))
730 ]))
730 with io.open(fname, encoding='utf-8') as f:
731 with io.open(fname, encoding='utf-8') as f:
731 s = f.read()
732 s = f.read()
732 nt.assert_in(u'linΓ©1\n', s)
733 nt.assert_in(u'linΓ©1\n', s)
733 nt.assert_in(u'linΓ©2', s)
734 nt.assert_in(u'linΓ©2', s)
734
735
735 def test_file_amend():
736 def test_file_amend():
736 """%%file -a amends files"""
737 """%%file -a amends files"""
737 ip = get_ipython()
738 ip = get_ipython()
738 with TemporaryDirectory() as td:
739 with TemporaryDirectory() as td:
739 fname = os.path.join(td, 'file2')
740 fname = os.path.join(td, 'file2')
740 ip.run_cell_magic("file", fname, u'\n'.join([
741 ip.run_cell_magic("file", fname, u'\n'.join([
741 'line1',
742 'line1',
742 'line2',
743 'line2',
743 ]))
744 ]))
744 ip.run_cell_magic("file", "-a %s" % fname, u'\n'.join([
745 ip.run_cell_magic("file", "-a %s" % fname, u'\n'.join([
745 'line3',
746 'line3',
746 'line4',
747 'line4',
747 ]))
748 ]))
748 with open(fname) as f:
749 with open(fname) as f:
749 s = f.read()
750 s = f.read()
750 nt.assert_in('line1\n', s)
751 nt.assert_in('line1\n', s)
751 nt.assert_in('line3\n', s)
752 nt.assert_in('line3\n', s)
752
753
753
754
754 def test_script_config():
755 def test_script_config():
755 ip = get_ipython()
756 ip = get_ipython()
756 ip.config.ScriptMagics.script_magics = ['whoda']
757 ip.config.ScriptMagics.script_magics = ['whoda']
757 sm = script.ScriptMagics(shell=ip)
758 sm = script.ScriptMagics(shell=ip)
758 nt.assert_in('whoda', sm.magics['cell'])
759 nt.assert_in('whoda', sm.magics['cell'])
759
760
760 @dec.skip_win32
761 @dec.skip_win32
761 def test_script_out():
762 def test_script_out():
762 ip = get_ipython()
763 ip = get_ipython()
763 ip.run_cell_magic("script", "--out output sh", "echo 'hi'")
764 ip.run_cell_magic("script", "--out output sh", "echo 'hi'")
764 nt.assert_equal(ip.user_ns['output'], 'hi\n')
765 nt.assert_equal(ip.user_ns['output'], 'hi\n')
765
766
766 @dec.skip_win32
767 @dec.skip_win32
767 def test_script_err():
768 def test_script_err():
768 ip = get_ipython()
769 ip = get_ipython()
769 ip.run_cell_magic("script", "--err error sh", "echo 'hello' >&2")
770 ip.run_cell_magic("script", "--err error sh", "echo 'hello' >&2")
770 nt.assert_equal(ip.user_ns['error'], 'hello\n')
771 nt.assert_equal(ip.user_ns['error'], 'hello\n')
771
772
772 @dec.skip_win32
773 @dec.skip_win32
773 def test_script_out_err():
774 def test_script_out_err():
774 ip = get_ipython()
775 ip = get_ipython()
775 ip.run_cell_magic("script", "--out output --err error sh", "echo 'hi'\necho 'hello' >&2")
776 ip.run_cell_magic("script", "--out output --err error sh", "echo 'hi'\necho 'hello' >&2")
776 nt.assert_equal(ip.user_ns['output'], 'hi\n')
777 nt.assert_equal(ip.user_ns['output'], 'hi\n')
777 nt.assert_equal(ip.user_ns['error'], 'hello\n')
778 nt.assert_equal(ip.user_ns['error'], 'hello\n')
778
779
779 @dec.skip_win32
780 @dec.skip_win32
780 def test_script_bg_out():
781 def test_script_bg_out():
781 ip = get_ipython()
782 ip = get_ipython()
782 ip.run_cell_magic("script", "--bg --out output sh", "echo 'hi'")
783 ip.run_cell_magic("script", "--bg --out output sh", "echo 'hi'")
783 nt.assert_equal(ip.user_ns['output'].read(), b'hi\n')
784 nt.assert_equal(ip.user_ns['output'].read(), b'hi\n')
784
785
785 @dec.skip_win32
786 @dec.skip_win32
786 def test_script_bg_err():
787 def test_script_bg_err():
787 ip = get_ipython()
788 ip = get_ipython()
788 ip.run_cell_magic("script", "--bg --err error sh", "echo 'hello' >&2")
789 ip.run_cell_magic("script", "--bg --err error sh", "echo 'hello' >&2")
789 nt.assert_equal(ip.user_ns['error'].read(), b'hello\n')
790 nt.assert_equal(ip.user_ns['error'].read(), b'hello\n')
790
791
791 @dec.skip_win32
792 @dec.skip_win32
792 def test_script_bg_out_err():
793 def test_script_bg_out_err():
793 ip = get_ipython()
794 ip = get_ipython()
794 ip.run_cell_magic("script", "--bg --out output --err error sh", "echo 'hi'\necho 'hello' >&2")
795 ip.run_cell_magic("script", "--bg --out output --err error sh", "echo 'hi'\necho 'hello' >&2")
795 nt.assert_equal(ip.user_ns['output'].read(), b'hi\n')
796 nt.assert_equal(ip.user_ns['output'].read(), b'hi\n')
796 nt.assert_equal(ip.user_ns['error'].read(), b'hello\n')
797 nt.assert_equal(ip.user_ns['error'].read(), b'hello\n')
797
798
798 def test_script_defaults():
799 def test_script_defaults():
799 ip = get_ipython()
800 ip = get_ipython()
800 for cmd in ['sh', 'bash', 'perl', 'ruby']:
801 for cmd in ['sh', 'bash', 'perl', 'ruby']:
801 try:
802 try:
802 find_cmd(cmd)
803 find_cmd(cmd)
803 except Exception:
804 except Exception:
804 pass
805 pass
805 else:
806 else:
806 nt.assert_in(cmd, ip.magics_manager.magics['cell'])
807 nt.assert_in(cmd, ip.magics_manager.magics['cell'])
807
808
808
809
809 @magics_class
810 @magics_class
810 class FooFoo(Magics):
811 class FooFoo(Magics):
811 """class with both %foo and %%foo magics"""
812 """class with both %foo and %%foo magics"""
812 @line_magic('foo')
813 @line_magic('foo')
813 def line_foo(self, line):
814 def line_foo(self, line):
814 "I am line foo"
815 "I am line foo"
815 pass
816 pass
816
817
817 @cell_magic("foo")
818 @cell_magic("foo")
818 def cell_foo(self, line, cell):
819 def cell_foo(self, line, cell):
819 "I am cell foo, not line foo"
820 "I am cell foo, not line foo"
820 pass
821 pass
821
822
822 def test_line_cell_info():
823 def test_line_cell_info():
823 """%%foo and %foo magics are distinguishable to inspect"""
824 """%%foo and %foo magics are distinguishable to inspect"""
824 ip = get_ipython()
825 ip = get_ipython()
825 ip.magics_manager.register(FooFoo)
826 ip.magics_manager.register(FooFoo)
826 oinfo = ip.object_inspect('foo')
827 oinfo = ip.object_inspect('foo')
827 nt.assert_true(oinfo['found'])
828 nt.assert_true(oinfo['found'])
828 nt.assert_true(oinfo['ismagic'])
829 nt.assert_true(oinfo['ismagic'])
829
830
830 oinfo = ip.object_inspect('%%foo')
831 oinfo = ip.object_inspect('%%foo')
831 nt.assert_true(oinfo['found'])
832 nt.assert_true(oinfo['found'])
832 nt.assert_true(oinfo['ismagic'])
833 nt.assert_true(oinfo['ismagic'])
833 nt.assert_equal(oinfo['docstring'], FooFoo.cell_foo.__doc__)
834 nt.assert_equal(oinfo['docstring'], FooFoo.cell_foo.__doc__)
834
835
835 oinfo = ip.object_inspect('%foo')
836 oinfo = ip.object_inspect('%foo')
836 nt.assert_true(oinfo['found'])
837 nt.assert_true(oinfo['found'])
837 nt.assert_true(oinfo['ismagic'])
838 nt.assert_true(oinfo['ismagic'])
838 nt.assert_equal(oinfo['docstring'], FooFoo.line_foo.__doc__)
839 nt.assert_equal(oinfo['docstring'], FooFoo.line_foo.__doc__)
839
840
840 def test_multiple_magics():
841 def test_multiple_magics():
841 ip = get_ipython()
842 ip = get_ipython()
842 foo1 = FooFoo(ip)
843 foo1 = FooFoo(ip)
843 foo2 = FooFoo(ip)
844 foo2 = FooFoo(ip)
844 mm = ip.magics_manager
845 mm = ip.magics_manager
845 mm.register(foo1)
846 mm.register(foo1)
846 nt.assert_true(mm.magics['line']['foo'].__self__ is foo1)
847 nt.assert_true(mm.magics['line']['foo'].__self__ is foo1)
847 mm.register(foo2)
848 mm.register(foo2)
848 nt.assert_true(mm.magics['line']['foo'].__self__ is foo2)
849 nt.assert_true(mm.magics['line']['foo'].__self__ is foo2)
849
850
850 def test_alias_magic():
851 def test_alias_magic():
851 """Test %alias_magic."""
852 """Test %alias_magic."""
852 ip = get_ipython()
853 ip = get_ipython()
853 mm = ip.magics_manager
854 mm = ip.magics_manager
854
855
855 # Basic operation: both cell and line magics are created, if possible.
856 # Basic operation: both cell and line magics are created, if possible.
856 ip.run_line_magic('alias_magic', 'timeit_alias timeit')
857 ip.run_line_magic('alias_magic', 'timeit_alias timeit')
857 nt.assert_in('timeit_alias', mm.magics['line'])
858 nt.assert_in('timeit_alias', mm.magics['line'])
858 nt.assert_in('timeit_alias', mm.magics['cell'])
859 nt.assert_in('timeit_alias', mm.magics['cell'])
859
860
860 # --cell is specified, line magic not created.
861 # --cell is specified, line magic not created.
861 ip.run_line_magic('alias_magic', '--cell timeit_cell_alias timeit')
862 ip.run_line_magic('alias_magic', '--cell timeit_cell_alias timeit')
862 nt.assert_not_in('timeit_cell_alias', mm.magics['line'])
863 nt.assert_not_in('timeit_cell_alias', mm.magics['line'])
863 nt.assert_in('timeit_cell_alias', mm.magics['cell'])
864 nt.assert_in('timeit_cell_alias', mm.magics['cell'])
864
865
865 # Test that line alias is created successfully.
866 # Test that line alias is created successfully.
866 ip.run_line_magic('alias_magic', '--line env_alias env')
867 ip.run_line_magic('alias_magic', '--line env_alias env')
867 nt.assert_equal(ip.run_line_magic('env', ''),
868 nt.assert_equal(ip.run_line_magic('env', ''),
868 ip.run_line_magic('env_alias', ''))
869 ip.run_line_magic('env_alias', ''))
869
870
870 def test_save():
871 def test_save():
871 """Test %save."""
872 """Test %save."""
872 ip = get_ipython()
873 ip = get_ipython()
873 ip.history_manager.reset() # Clear any existing history.
874 ip.history_manager.reset() # Clear any existing history.
874 cmds = [u"a=1", u"def b():\n return a**2", u"print(a, b())"]
875 cmds = [u"a=1", u"def b():\n return a**2", u"print(a, b())"]
875 for i, cmd in enumerate(cmds, start=1):
876 for i, cmd in enumerate(cmds, start=1):
876 ip.history_manager.store_inputs(i, cmd)
877 ip.history_manager.store_inputs(i, cmd)
877 with TemporaryDirectory() as tmpdir:
878 with TemporaryDirectory() as tmpdir:
878 file = os.path.join(tmpdir, "testsave.py")
879 file = os.path.join(tmpdir, "testsave.py")
879 ip.run_line_magic("save", "%s 1-10" % file)
880 ip.run_line_magic("save", "%s 1-10" % file)
880 with open(file) as f:
881 with open(file) as f:
881 content = f.read()
882 content = f.read()
882 nt.assert_equal(content.count(cmds[0]), 1)
883 nt.assert_equal(content.count(cmds[0]), 1)
883 nt.assert_in('coding: utf-8', content)
884 nt.assert_in('coding: utf-8', content)
884 ip.run_line_magic("save", "-a %s 1-10" % file)
885 ip.run_line_magic("save", "-a %s 1-10" % file)
885 with open(file) as f:
886 with open(file) as f:
886 content = f.read()
887 content = f.read()
887 nt.assert_equal(content.count(cmds[0]), 2)
888 nt.assert_equal(content.count(cmds[0]), 2)
888 nt.assert_in('coding: utf-8', content)
889 nt.assert_in('coding: utf-8', content)
889
890
890
891
891 def test_store():
892 def test_store():
892 """Test %store."""
893 """Test %store."""
893 ip = get_ipython()
894 ip = get_ipython()
894 ip.run_line_magic('load_ext', 'storemagic')
895 ip.run_line_magic('load_ext', 'storemagic')
895
896
896 # make sure the storage is empty
897 # make sure the storage is empty
897 ip.run_line_magic('store', '-z')
898 ip.run_line_magic('store', '-z')
898 ip.user_ns['var'] = 42
899 ip.user_ns['var'] = 42
899 ip.run_line_magic('store', 'var')
900 ip.run_line_magic('store', 'var')
900 ip.user_ns['var'] = 39
901 ip.user_ns['var'] = 39
901 ip.run_line_magic('store', '-r')
902 ip.run_line_magic('store', '-r')
902 nt.assert_equal(ip.user_ns['var'], 42)
903 nt.assert_equal(ip.user_ns['var'], 42)
903
904
904 ip.run_line_magic('store', '-d var')
905 ip.run_line_magic('store', '-d var')
905 ip.user_ns['var'] = 39
906 ip.user_ns['var'] = 39
906 ip.run_line_magic('store' , '-r')
907 ip.run_line_magic('store' , '-r')
907 nt.assert_equal(ip.user_ns['var'], 39)
908 nt.assert_equal(ip.user_ns['var'], 39)
908
909
909
910
910 def _run_edit_test(arg_s, exp_filename=None,
911 def _run_edit_test(arg_s, exp_filename=None,
911 exp_lineno=-1,
912 exp_lineno=-1,
912 exp_contents=None,
913 exp_contents=None,
913 exp_is_temp=None):
914 exp_is_temp=None):
914 ip = get_ipython()
915 ip = get_ipython()
915 M = code.CodeMagics(ip)
916 M = code.CodeMagics(ip)
916 last_call = ['','']
917 last_call = ['','']
917 opts,args = M.parse_options(arg_s,'prxn:')
918 opts,args = M.parse_options(arg_s,'prxn:')
918 filename, lineno, is_temp = M._find_edit_target(ip, args, opts, last_call)
919 filename, lineno, is_temp = M._find_edit_target(ip, args, opts, last_call)
919
920
920 if exp_filename is not None:
921 if exp_filename is not None:
921 nt.assert_equal(exp_filename, filename)
922 nt.assert_equal(exp_filename, filename)
922 if exp_contents is not None:
923 if exp_contents is not None:
923 with io.open(filename, 'r', encoding='utf-8') as f:
924 with io.open(filename, 'r', encoding='utf-8') as f:
924 contents = f.read()
925 contents = f.read()
925 nt.assert_equal(exp_contents, contents)
926 nt.assert_equal(exp_contents, contents)
926 if exp_lineno != -1:
927 if exp_lineno != -1:
927 nt.assert_equal(exp_lineno, lineno)
928 nt.assert_equal(exp_lineno, lineno)
928 if exp_is_temp is not None:
929 if exp_is_temp is not None:
929 nt.assert_equal(exp_is_temp, is_temp)
930 nt.assert_equal(exp_is_temp, is_temp)
930
931
931
932
932 def test_edit_interactive():
933 def test_edit_interactive():
933 """%edit on interactively defined objects"""
934 """%edit on interactively defined objects"""
934 ip = get_ipython()
935 ip = get_ipython()
935 n = ip.execution_count
936 n = ip.execution_count
936 ip.run_cell(u"def foo(): return 1", store_history=True)
937 ip.run_cell(u"def foo(): return 1", store_history=True)
937
938
938 try:
939 try:
939 _run_edit_test("foo")
940 _run_edit_test("foo")
940 except code.InteractivelyDefined as e:
941 except code.InteractivelyDefined as e:
941 nt.assert_equal(e.index, n)
942 nt.assert_equal(e.index, n)
942 else:
943 else:
943 raise AssertionError("Should have raised InteractivelyDefined")
944 raise AssertionError("Should have raised InteractivelyDefined")
944
945
945
946
946 def test_edit_cell():
947 def test_edit_cell():
947 """%edit [cell id]"""
948 """%edit [cell id]"""
948 ip = get_ipython()
949 ip = get_ipython()
949
950
950 ip.run_cell(u"def foo(): return 1", store_history=True)
951 ip.run_cell(u"def foo(): return 1", store_history=True)
951
952
952 # test
953 # test
953 _run_edit_test("1", exp_contents=ip.user_ns['In'][1], exp_is_temp=True)
954 _run_edit_test("1", exp_contents=ip.user_ns['In'][1], exp_is_temp=True)
954
955
955 def test_bookmark():
956 def test_bookmark():
956 ip = get_ipython()
957 ip = get_ipython()
957 ip.run_line_magic('bookmark', 'bmname')
958 ip.run_line_magic('bookmark', 'bmname')
958 with tt.AssertPrints('bmname'):
959 with tt.AssertPrints('bmname'):
959 ip.run_line_magic('bookmark', '-l')
960 ip.run_line_magic('bookmark', '-l')
960 ip.run_line_magic('bookmark', '-d bmname')
961 ip.run_line_magic('bookmark', '-d bmname')
961
962
962 def test_ls_magic():
963 def test_ls_magic():
963 ip = get_ipython()
964 ip = get_ipython()
964 json_formatter = ip.display_formatter.formatters['application/json']
965 json_formatter = ip.display_formatter.formatters['application/json']
965 json_formatter.enabled = True
966 json_formatter.enabled = True
966 lsmagic = ip.magic('lsmagic')
967 lsmagic = ip.magic('lsmagic')
967 with warnings.catch_warnings(record=True) as w:
968 with warnings.catch_warnings(record=True) as w:
968 j = json_formatter(lsmagic)
969 j = json_formatter(lsmagic)
969 nt.assert_equal(sorted(j), ['cell', 'line'])
970 nt.assert_equal(sorted(j), ['cell', 'line'])
970 nt.assert_equal(w, []) # no warnings
971 nt.assert_equal(w, []) # no warnings
971
972
972 def test_strip_initial_indent():
973 def test_strip_initial_indent():
973 def sii(s):
974 def sii(s):
974 lines = s.splitlines()
975 lines = s.splitlines()
975 return '\n'.join(code.strip_initial_indent(lines))
976 return '\n'.join(code.strip_initial_indent(lines))
976
977
977 nt.assert_equal(sii(" a = 1\nb = 2"), "a = 1\nb = 2")
978 nt.assert_equal(sii(" a = 1\nb = 2"), "a = 1\nb = 2")
978 nt.assert_equal(sii(" a\n b\nc"), "a\n b\nc")
979 nt.assert_equal(sii(" a\n b\nc"), "a\n b\nc")
979 nt.assert_equal(sii("a\n b"), "a\n b")
980 nt.assert_equal(sii("a\n b"), "a\n b")
981
982 def test_logging_magic_quiet_from_arg():
983 _ip.config.LoggingMagics.quiet = False
984 lm = logging.LoggingMagics(shell=_ip)
985 with TemporaryDirectory() as td:
986 try:
987 with tt.AssertNotPrints(re.compile("Activating.*")):
988 lm.logstart('-q {}'.format(
989 os.path.join(td, "quiet_from_arg.log")))
990 finally:
991 _ip.logger.logstop()
992
993 def test_logging_magic_quiet_from_config():
994 _ip.config.LoggingMagics.quiet = True
995 lm = logging.LoggingMagics(shell=_ip)
996 with TemporaryDirectory() as td:
997 try:
998 with tt.AssertNotPrints(re.compile("Activating.*")):
999 lm.logstart(os.path.join(td, "quiet_from_config.log"))
1000 finally:
1001 _ip.logger.logstop()
1002
1003 def test_logging_magic_not_quiet():
1004 _ip.config.LoggingMagics.quiet = False
1005 lm = logging.LoggingMagics(shell=_ip)
1006 with TemporaryDirectory() as td:
1007 try:
1008 with tt.AssertPrints(re.compile("Activating.*")):
1009 lm.logstart(os.path.join(td, "not_quiet.log"))
1010 finally:
1011 _ip.logger.logstop()
1012
@@ -1,377 +1,380
1 #!/usr/bin/env python
1 #!/usr/bin/env python
2 # encoding: utf-8
2 # encoding: utf-8
3 """
3 """
4 The :class:`~IPython.core.application.Application` object for the command
4 The :class:`~IPython.core.application.Application` object for the command
5 line :command:`ipython` program.
5 line :command:`ipython` program.
6 """
6 """
7
7
8 # Copyright (c) IPython Development Team.
8 # Copyright (c) IPython Development Team.
9 # Distributed under the terms of the Modified BSD License.
9 # Distributed under the terms of the Modified BSD License.
10
10
11
11
12 import logging
12 import logging
13 import os
13 import os
14 import sys
14 import sys
15 import warnings
15 import warnings
16
16
17 from traitlets.config.loader import Config
17 from traitlets.config.loader import Config
18 from traitlets.config.application import boolean_flag, catch_config_error, Application
18 from traitlets.config.application import boolean_flag, catch_config_error, Application
19 from IPython.core import release
19 from IPython.core import release
20 from IPython.core import usage
20 from IPython.core import usage
21 from IPython.core.completer import IPCompleter
21 from IPython.core.completer import IPCompleter
22 from IPython.core.crashhandler import CrashHandler
22 from IPython.core.crashhandler import CrashHandler
23 from IPython.core.formatters import PlainTextFormatter
23 from IPython.core.formatters import PlainTextFormatter
24 from IPython.core.history import HistoryManager
24 from IPython.core.history import HistoryManager
25 from IPython.core.application import (
25 from IPython.core.application import (
26 ProfileDir, BaseIPythonApplication, base_flags, base_aliases
26 ProfileDir, BaseIPythonApplication, base_flags, base_aliases
27 )
27 )
28 from IPython.core.magics import ScriptMagics
28 from IPython.core.magics import (
29 ScriptMagics, LoggingMagics
30 )
29 from IPython.core.shellapp import (
31 from IPython.core.shellapp import (
30 InteractiveShellApp, shell_flags, shell_aliases
32 InteractiveShellApp, shell_flags, shell_aliases
31 )
33 )
32 from IPython.extensions.storemagic import StoreMagics
34 from IPython.extensions.storemagic import StoreMagics
33 from .interactiveshell import TerminalInteractiveShell
35 from .interactiveshell import TerminalInteractiveShell
34 from IPython.paths import get_ipython_dir
36 from IPython.paths import get_ipython_dir
35 from traitlets import (
37 from traitlets import (
36 Bool, List, Dict, default, observe, Type
38 Bool, List, Dict, default, observe, Type
37 )
39 )
38
40
39 #-----------------------------------------------------------------------------
41 #-----------------------------------------------------------------------------
40 # Globals, utilities and helpers
42 # Globals, utilities and helpers
41 #-----------------------------------------------------------------------------
43 #-----------------------------------------------------------------------------
42
44
43 _examples = """
45 _examples = """
44 ipython --matplotlib # enable matplotlib integration
46 ipython --matplotlib # enable matplotlib integration
45 ipython --matplotlib=qt # enable matplotlib integration with qt4 backend
47 ipython --matplotlib=qt # enable matplotlib integration with qt4 backend
46
48
47 ipython --log-level=DEBUG # set logging to DEBUG
49 ipython --log-level=DEBUG # set logging to DEBUG
48 ipython --profile=foo # start with profile foo
50 ipython --profile=foo # start with profile foo
49
51
50 ipython profile create foo # create profile foo w/ default config files
52 ipython profile create foo # create profile foo w/ default config files
51 ipython help profile # show the help for the profile subcmd
53 ipython help profile # show the help for the profile subcmd
52
54
53 ipython locate # print the path to the IPython directory
55 ipython locate # print the path to the IPython directory
54 ipython locate profile foo # print the path to the directory for profile `foo`
56 ipython locate profile foo # print the path to the directory for profile `foo`
55 """
57 """
56
58
57 #-----------------------------------------------------------------------------
59 #-----------------------------------------------------------------------------
58 # Crash handler for this application
60 # Crash handler for this application
59 #-----------------------------------------------------------------------------
61 #-----------------------------------------------------------------------------
60
62
61 class IPAppCrashHandler(CrashHandler):
63 class IPAppCrashHandler(CrashHandler):
62 """sys.excepthook for IPython itself, leaves a detailed report on disk."""
64 """sys.excepthook for IPython itself, leaves a detailed report on disk."""
63
65
64 def __init__(self, app):
66 def __init__(self, app):
65 contact_name = release.author
67 contact_name = release.author
66 contact_email = release.author_email
68 contact_email = release.author_email
67 bug_tracker = 'https://github.com/ipython/ipython/issues'
69 bug_tracker = 'https://github.com/ipython/ipython/issues'
68 super(IPAppCrashHandler,self).__init__(
70 super(IPAppCrashHandler,self).__init__(
69 app, contact_name, contact_email, bug_tracker
71 app, contact_name, contact_email, bug_tracker
70 )
72 )
71
73
72 def make_report(self,traceback):
74 def make_report(self,traceback):
73 """Return a string containing a crash report."""
75 """Return a string containing a crash report."""
74
76
75 sec_sep = self.section_sep
77 sec_sep = self.section_sep
76 # Start with parent report
78 # Start with parent report
77 report = [super(IPAppCrashHandler, self).make_report(traceback)]
79 report = [super(IPAppCrashHandler, self).make_report(traceback)]
78 # Add interactive-specific info we may have
80 # Add interactive-specific info we may have
79 rpt_add = report.append
81 rpt_add = report.append
80 try:
82 try:
81 rpt_add(sec_sep+"History of session input:")
83 rpt_add(sec_sep+"History of session input:")
82 for line in self.app.shell.user_ns['_ih']:
84 for line in self.app.shell.user_ns['_ih']:
83 rpt_add(line)
85 rpt_add(line)
84 rpt_add('\n*** Last line of input (may not be in above history):\n')
86 rpt_add('\n*** Last line of input (may not be in above history):\n')
85 rpt_add(self.app.shell._last_input_line+'\n')
87 rpt_add(self.app.shell._last_input_line+'\n')
86 except:
88 except:
87 pass
89 pass
88
90
89 return ''.join(report)
91 return ''.join(report)
90
92
91 #-----------------------------------------------------------------------------
93 #-----------------------------------------------------------------------------
92 # Aliases and Flags
94 # Aliases and Flags
93 #-----------------------------------------------------------------------------
95 #-----------------------------------------------------------------------------
94 flags = dict(base_flags)
96 flags = dict(base_flags)
95 flags.update(shell_flags)
97 flags.update(shell_flags)
96 frontend_flags = {}
98 frontend_flags = {}
97 addflag = lambda *args: frontend_flags.update(boolean_flag(*args))
99 addflag = lambda *args: frontend_flags.update(boolean_flag(*args))
98 addflag('autoedit-syntax', 'TerminalInteractiveShell.autoedit_syntax',
100 addflag('autoedit-syntax', 'TerminalInteractiveShell.autoedit_syntax',
99 'Turn on auto editing of files with syntax errors.',
101 'Turn on auto editing of files with syntax errors.',
100 'Turn off auto editing of files with syntax errors.'
102 'Turn off auto editing of files with syntax errors.'
101 )
103 )
102 addflag('simple-prompt', 'TerminalInteractiveShell.simple_prompt',
104 addflag('simple-prompt', 'TerminalInteractiveShell.simple_prompt',
103 "Force simple minimal prompt using `raw_input`",
105 "Force simple minimal prompt using `raw_input`",
104 "Use a rich interactive prompt with prompt_toolkit",
106 "Use a rich interactive prompt with prompt_toolkit",
105 )
107 )
106
108
107 addflag('banner', 'TerminalIPythonApp.display_banner',
109 addflag('banner', 'TerminalIPythonApp.display_banner',
108 "Display a banner upon starting IPython.",
110 "Display a banner upon starting IPython.",
109 "Don't display a banner upon starting IPython."
111 "Don't display a banner upon starting IPython."
110 )
112 )
111 addflag('confirm-exit', 'TerminalInteractiveShell.confirm_exit',
113 addflag('confirm-exit', 'TerminalInteractiveShell.confirm_exit',
112 """Set to confirm when you try to exit IPython with an EOF (Control-D
114 """Set to confirm when you try to exit IPython with an EOF (Control-D
113 in Unix, Control-Z/Enter in Windows). By typing 'exit' or 'quit',
115 in Unix, Control-Z/Enter in Windows). By typing 'exit' or 'quit',
114 you can force a direct exit without any confirmation.""",
116 you can force a direct exit without any confirmation.""",
115 "Don't prompt the user when exiting."
117 "Don't prompt the user when exiting."
116 )
118 )
117 addflag('term-title', 'TerminalInteractiveShell.term_title',
119 addflag('term-title', 'TerminalInteractiveShell.term_title',
118 "Enable auto setting the terminal title.",
120 "Enable auto setting the terminal title.",
119 "Disable auto setting the terminal title."
121 "Disable auto setting the terminal title."
120 )
122 )
121 classic_config = Config()
123 classic_config = Config()
122 classic_config.InteractiveShell.cache_size = 0
124 classic_config.InteractiveShell.cache_size = 0
123 classic_config.PlainTextFormatter.pprint = False
125 classic_config.PlainTextFormatter.pprint = False
124 classic_config.TerminalInteractiveShell.prompts_class='IPython.terminal.prompts.ClassicPrompts'
126 classic_config.TerminalInteractiveShell.prompts_class='IPython.terminal.prompts.ClassicPrompts'
125 classic_config.InteractiveShell.separate_in = ''
127 classic_config.InteractiveShell.separate_in = ''
126 classic_config.InteractiveShell.separate_out = ''
128 classic_config.InteractiveShell.separate_out = ''
127 classic_config.InteractiveShell.separate_out2 = ''
129 classic_config.InteractiveShell.separate_out2 = ''
128 classic_config.InteractiveShell.colors = 'NoColor'
130 classic_config.InteractiveShell.colors = 'NoColor'
129 classic_config.InteractiveShell.xmode = 'Plain'
131 classic_config.InteractiveShell.xmode = 'Plain'
130
132
131 frontend_flags['classic']=(
133 frontend_flags['classic']=(
132 classic_config,
134 classic_config,
133 "Gives IPython a similar feel to the classic Python prompt."
135 "Gives IPython a similar feel to the classic Python prompt."
134 )
136 )
135 # # log doesn't make so much sense this way anymore
137 # # log doesn't make so much sense this way anymore
136 # paa('--log','-l',
138 # paa('--log','-l',
137 # action='store_true', dest='InteractiveShell.logstart',
139 # action='store_true', dest='InteractiveShell.logstart',
138 # help="Start logging to the default log file (./ipython_log.py).")
140 # help="Start logging to the default log file (./ipython_log.py).")
139 #
141 #
140 # # quick is harder to implement
142 # # quick is harder to implement
141 frontend_flags['quick']=(
143 frontend_flags['quick']=(
142 {'TerminalIPythonApp' : {'quick' : True}},
144 {'TerminalIPythonApp' : {'quick' : True}},
143 "Enable quick startup with no config files."
145 "Enable quick startup with no config files."
144 )
146 )
145
147
146 frontend_flags['i'] = (
148 frontend_flags['i'] = (
147 {'TerminalIPythonApp' : {'force_interact' : True}},
149 {'TerminalIPythonApp' : {'force_interact' : True}},
148 """If running code from the command line, become interactive afterwards.
150 """If running code from the command line, become interactive afterwards.
149 It is often useful to follow this with `--` to treat remaining flags as
151 It is often useful to follow this with `--` to treat remaining flags as
150 script arguments.
152 script arguments.
151 """
153 """
152 )
154 )
153 flags.update(frontend_flags)
155 flags.update(frontend_flags)
154
156
155 aliases = dict(base_aliases)
157 aliases = dict(base_aliases)
156 aliases.update(shell_aliases)
158 aliases.update(shell_aliases)
157
159
158 #-----------------------------------------------------------------------------
160 #-----------------------------------------------------------------------------
159 # Main classes and functions
161 # Main classes and functions
160 #-----------------------------------------------------------------------------
162 #-----------------------------------------------------------------------------
161
163
162
164
163 class LocateIPythonApp(BaseIPythonApplication):
165 class LocateIPythonApp(BaseIPythonApplication):
164 description = """print the path to the IPython dir"""
166 description = """print the path to the IPython dir"""
165 subcommands = Dict(dict(
167 subcommands = Dict(dict(
166 profile=('IPython.core.profileapp.ProfileLocate',
168 profile=('IPython.core.profileapp.ProfileLocate',
167 "print the path to an IPython profile directory",
169 "print the path to an IPython profile directory",
168 ),
170 ),
169 ))
171 ))
170 def start(self):
172 def start(self):
171 if self.subapp is not None:
173 if self.subapp is not None:
172 return self.subapp.start()
174 return self.subapp.start()
173 else:
175 else:
174 print(self.ipython_dir)
176 print(self.ipython_dir)
175
177
176
178
177 class TerminalIPythonApp(BaseIPythonApplication, InteractiveShellApp):
179 class TerminalIPythonApp(BaseIPythonApplication, InteractiveShellApp):
178 name = u'ipython'
180 name = u'ipython'
179 description = usage.cl_usage
181 description = usage.cl_usage
180 crash_handler_class = IPAppCrashHandler
182 crash_handler_class = IPAppCrashHandler
181 examples = _examples
183 examples = _examples
182
184
183 flags = Dict(flags)
185 flags = Dict(flags)
184 aliases = Dict(aliases)
186 aliases = Dict(aliases)
185 classes = List()
187 classes = List()
186
188
187 interactive_shell_class = Type(
189 interactive_shell_class = Type(
188 klass=object, # use default_value otherwise which only allow subclasses.
190 klass=object, # use default_value otherwise which only allow subclasses.
189 default_value=TerminalInteractiveShell,
191 default_value=TerminalInteractiveShell,
190 help="Class to use to instantiate the TerminalInteractiveShell object. Useful for custom Frontends"
192 help="Class to use to instantiate the TerminalInteractiveShell object. Useful for custom Frontends"
191 ).tag(config=True)
193 ).tag(config=True)
192
194
193 @default('classes')
195 @default('classes')
194 def _classes_default(self):
196 def _classes_default(self):
195 """This has to be in a method, for TerminalIPythonApp to be available."""
197 """This has to be in a method, for TerminalIPythonApp to be available."""
196 return [
198 return [
197 InteractiveShellApp, # ShellApp comes before TerminalApp, because
199 InteractiveShellApp, # ShellApp comes before TerminalApp, because
198 self.__class__, # it will also affect subclasses (e.g. QtConsole)
200 self.__class__, # it will also affect subclasses (e.g. QtConsole)
199 TerminalInteractiveShell,
201 TerminalInteractiveShell,
200 HistoryManager,
202 HistoryManager,
201 ProfileDir,
203 ProfileDir,
202 PlainTextFormatter,
204 PlainTextFormatter,
203 IPCompleter,
205 IPCompleter,
204 ScriptMagics,
206 ScriptMagics,
207 LoggingMagics,
205 StoreMagics,
208 StoreMagics,
206 ]
209 ]
207
210
208 deprecated_subcommands = dict(
211 deprecated_subcommands = dict(
209 qtconsole=('qtconsole.qtconsoleapp.JupyterQtConsoleApp',
212 qtconsole=('qtconsole.qtconsoleapp.JupyterQtConsoleApp',
210 """DEPRECATED, Will be removed in IPython 6.0 : Launch the Jupyter Qt Console."""
213 """DEPRECATED, Will be removed in IPython 6.0 : Launch the Jupyter Qt Console."""
211 ),
214 ),
212 notebook=('notebook.notebookapp.NotebookApp',
215 notebook=('notebook.notebookapp.NotebookApp',
213 """DEPRECATED, Will be removed in IPython 6.0 : Launch the Jupyter HTML Notebook Server."""
216 """DEPRECATED, Will be removed in IPython 6.0 : Launch the Jupyter HTML Notebook Server."""
214 ),
217 ),
215 console=('jupyter_console.app.ZMQTerminalIPythonApp',
218 console=('jupyter_console.app.ZMQTerminalIPythonApp',
216 """DEPRECATED, Will be removed in IPython 6.0 : Launch the Jupyter terminal-based Console."""
219 """DEPRECATED, Will be removed in IPython 6.0 : Launch the Jupyter terminal-based Console."""
217 ),
220 ),
218 nbconvert=('nbconvert.nbconvertapp.NbConvertApp',
221 nbconvert=('nbconvert.nbconvertapp.NbConvertApp',
219 "DEPRECATED, Will be removed in IPython 6.0 : Convert notebooks to/from other formats."
222 "DEPRECATED, Will be removed in IPython 6.0 : Convert notebooks to/from other formats."
220 ),
223 ),
221 trust=('nbformat.sign.TrustNotebookApp',
224 trust=('nbformat.sign.TrustNotebookApp',
222 "DEPRECATED, Will be removed in IPython 6.0 : Sign notebooks to trust their potentially unsafe contents at load."
225 "DEPRECATED, Will be removed in IPython 6.0 : Sign notebooks to trust their potentially unsafe contents at load."
223 ),
226 ),
224 kernelspec=('jupyter_client.kernelspecapp.KernelSpecApp',
227 kernelspec=('jupyter_client.kernelspecapp.KernelSpecApp',
225 "DEPRECATED, Will be removed in IPython 6.0 : Manage Jupyter kernel specifications."
228 "DEPRECATED, Will be removed in IPython 6.0 : Manage Jupyter kernel specifications."
226 ),
229 ),
227 )
230 )
228 subcommands = dict(
231 subcommands = dict(
229 profile = ("IPython.core.profileapp.ProfileApp",
232 profile = ("IPython.core.profileapp.ProfileApp",
230 "Create and manage IPython profiles."
233 "Create and manage IPython profiles."
231 ),
234 ),
232 kernel = ("ipykernel.kernelapp.IPKernelApp",
235 kernel = ("ipykernel.kernelapp.IPKernelApp",
233 "Start a kernel without an attached frontend."
236 "Start a kernel without an attached frontend."
234 ),
237 ),
235 locate=('IPython.terminal.ipapp.LocateIPythonApp',
238 locate=('IPython.terminal.ipapp.LocateIPythonApp',
236 LocateIPythonApp.description
239 LocateIPythonApp.description
237 ),
240 ),
238 history=('IPython.core.historyapp.HistoryApp',
241 history=('IPython.core.historyapp.HistoryApp',
239 "Manage the IPython history database."
242 "Manage the IPython history database."
240 ),
243 ),
241 )
244 )
242 deprecated_subcommands['install-nbextension'] = (
245 deprecated_subcommands['install-nbextension'] = (
243 "notebook.nbextensions.InstallNBExtensionApp",
246 "notebook.nbextensions.InstallNBExtensionApp",
244 "DEPRECATED, Will be removed in IPython 6.0 : Install Jupyter notebook extension files"
247 "DEPRECATED, Will be removed in IPython 6.0 : Install Jupyter notebook extension files"
245 )
248 )
246 subcommands.update(deprecated_subcommands)
249 subcommands.update(deprecated_subcommands)
247
250
248 # *do* autocreate requested profile, but don't create the config file.
251 # *do* autocreate requested profile, but don't create the config file.
249 auto_create=Bool(True)
252 auto_create=Bool(True)
250 # configurables
253 # configurables
251 quick = Bool(False,
254 quick = Bool(False,
252 help="""Start IPython quickly by skipping the loading of config files."""
255 help="""Start IPython quickly by skipping the loading of config files."""
253 ).tag(config=True)
256 ).tag(config=True)
254 @observe('quick')
257 @observe('quick')
255 def _quick_changed(self, change):
258 def _quick_changed(self, change):
256 if change['new']:
259 if change['new']:
257 self.load_config_file = lambda *a, **kw: None
260 self.load_config_file = lambda *a, **kw: None
258
261
259 display_banner = Bool(True,
262 display_banner = Bool(True,
260 help="Whether to display a banner upon starting IPython."
263 help="Whether to display a banner upon starting IPython."
261 ).tag(config=True)
264 ).tag(config=True)
262
265
263 # if there is code of files to run from the cmd line, don't interact
266 # if there is code of files to run from the cmd line, don't interact
264 # unless the --i flag (App.force_interact) is true.
267 # unless the --i flag (App.force_interact) is true.
265 force_interact = Bool(False,
268 force_interact = Bool(False,
266 help="""If a command or file is given via the command-line,
269 help="""If a command or file is given via the command-line,
267 e.g. 'ipython foo.py', start an interactive shell after executing the
270 e.g. 'ipython foo.py', start an interactive shell after executing the
268 file or command."""
271 file or command."""
269 ).tag(config=True)
272 ).tag(config=True)
270 @observe('force_interact')
273 @observe('force_interact')
271 def _force_interact_changed(self, change):
274 def _force_interact_changed(self, change):
272 if change['new']:
275 if change['new']:
273 self.interact = True
276 self.interact = True
274
277
275 @observe('file_to_run', 'code_to_run', 'module_to_run')
278 @observe('file_to_run', 'code_to_run', 'module_to_run')
276 def _file_to_run_changed(self, change):
279 def _file_to_run_changed(self, change):
277 new = change['new']
280 new = change['new']
278 if new:
281 if new:
279 self.something_to_run = True
282 self.something_to_run = True
280 if new and not self.force_interact:
283 if new and not self.force_interact:
281 self.interact = False
284 self.interact = False
282
285
283 # internal, not-configurable
286 # internal, not-configurable
284 something_to_run=Bool(False)
287 something_to_run=Bool(False)
285
288
286 def parse_command_line(self, argv=None):
289 def parse_command_line(self, argv=None):
287 """override to allow old '-pylab' flag with deprecation warning"""
290 """override to allow old '-pylab' flag with deprecation warning"""
288
291
289 argv = sys.argv[1:] if argv is None else argv
292 argv = sys.argv[1:] if argv is None else argv
290
293
291 if '-pylab' in argv:
294 if '-pylab' in argv:
292 # deprecated `-pylab` given,
295 # deprecated `-pylab` given,
293 # warn and transform into current syntax
296 # warn and transform into current syntax
294 argv = argv[:] # copy, don't clobber
297 argv = argv[:] # copy, don't clobber
295 idx = argv.index('-pylab')
298 idx = argv.index('-pylab')
296 warnings.warn("`-pylab` flag has been deprecated.\n"
299 warnings.warn("`-pylab` flag has been deprecated.\n"
297 " Use `--matplotlib <backend>` and import pylab manually.")
300 " Use `--matplotlib <backend>` and import pylab manually.")
298 argv[idx] = '--pylab'
301 argv[idx] = '--pylab'
299
302
300 return super(TerminalIPythonApp, self).parse_command_line(argv)
303 return super(TerminalIPythonApp, self).parse_command_line(argv)
301
304
302 @catch_config_error
305 @catch_config_error
303 def initialize(self, argv=None):
306 def initialize(self, argv=None):
304 """Do actions after construct, but before starting the app."""
307 """Do actions after construct, but before starting the app."""
305 super(TerminalIPythonApp, self).initialize(argv)
308 super(TerminalIPythonApp, self).initialize(argv)
306 if self.subapp is not None:
309 if self.subapp is not None:
307 # don't bother initializing further, starting subapp
310 # don't bother initializing further, starting subapp
308 return
311 return
309 # print self.extra_args
312 # print self.extra_args
310 if self.extra_args and not self.something_to_run:
313 if self.extra_args and not self.something_to_run:
311 self.file_to_run = self.extra_args[0]
314 self.file_to_run = self.extra_args[0]
312 self.init_path()
315 self.init_path()
313 # create the shell
316 # create the shell
314 self.init_shell()
317 self.init_shell()
315 # and draw the banner
318 # and draw the banner
316 self.init_banner()
319 self.init_banner()
317 # Now a variety of things that happen after the banner is printed.
320 # Now a variety of things that happen after the banner is printed.
318 self.init_gui_pylab()
321 self.init_gui_pylab()
319 self.init_extensions()
322 self.init_extensions()
320 self.init_code()
323 self.init_code()
321
324
322 def init_shell(self):
325 def init_shell(self):
323 """initialize the InteractiveShell instance"""
326 """initialize the InteractiveShell instance"""
324 # Create an InteractiveShell instance.
327 # Create an InteractiveShell instance.
325 # shell.display_banner should always be False for the terminal
328 # shell.display_banner should always be False for the terminal
326 # based app, because we call shell.show_banner() by hand below
329 # based app, because we call shell.show_banner() by hand below
327 # so the banner shows *before* all extension loading stuff.
330 # so the banner shows *before* all extension loading stuff.
328 self.shell = self.interactive_shell_class.instance(parent=self,
331 self.shell = self.interactive_shell_class.instance(parent=self,
329 profile_dir=self.profile_dir,
332 profile_dir=self.profile_dir,
330 ipython_dir=self.ipython_dir, user_ns=self.user_ns)
333 ipython_dir=self.ipython_dir, user_ns=self.user_ns)
331 self.shell.configurables.append(self)
334 self.shell.configurables.append(self)
332
335
333 def init_banner(self):
336 def init_banner(self):
334 """optionally display the banner"""
337 """optionally display the banner"""
335 if self.display_banner and self.interact:
338 if self.display_banner and self.interact:
336 self.shell.show_banner()
339 self.shell.show_banner()
337 # Make sure there is a space below the banner.
340 # Make sure there is a space below the banner.
338 if self.log_level <= logging.INFO: print()
341 if self.log_level <= logging.INFO: print()
339
342
340 def _pylab_changed(self, name, old, new):
343 def _pylab_changed(self, name, old, new):
341 """Replace --pylab='inline' with --pylab='auto'"""
344 """Replace --pylab='inline' with --pylab='auto'"""
342 if new == 'inline':
345 if new == 'inline':
343 warnings.warn("'inline' not available as pylab backend, "
346 warnings.warn("'inline' not available as pylab backend, "
344 "using 'auto' instead.")
347 "using 'auto' instead.")
345 self.pylab = 'auto'
348 self.pylab = 'auto'
346
349
347 def start(self):
350 def start(self):
348 if self.subapp is not None:
351 if self.subapp is not None:
349 return self.subapp.start()
352 return self.subapp.start()
350 # perform any prexec steps:
353 # perform any prexec steps:
351 if self.interact:
354 if self.interact:
352 self.log.debug("Starting IPython's mainloop...")
355 self.log.debug("Starting IPython's mainloop...")
353 self.shell.mainloop()
356 self.shell.mainloop()
354 else:
357 else:
355 self.log.debug("IPython not interactive...")
358 self.log.debug("IPython not interactive...")
356
359
357 def load_default_config(ipython_dir=None):
360 def load_default_config(ipython_dir=None):
358 """Load the default config file from the default ipython_dir.
361 """Load the default config file from the default ipython_dir.
359
362
360 This is useful for embedded shells.
363 This is useful for embedded shells.
361 """
364 """
362 if ipython_dir is None:
365 if ipython_dir is None:
363 ipython_dir = get_ipython_dir()
366 ipython_dir = get_ipython_dir()
364
367
365 profile_dir = os.path.join(ipython_dir, 'profile_default')
368 profile_dir = os.path.join(ipython_dir, 'profile_default')
366
369
367 config = Config()
370 config = Config()
368 for cf in Application._load_config_files("ipython_config", path=profile_dir):
371 for cf in Application._load_config_files("ipython_config", path=profile_dir):
369 config.update(cf)
372 config.update(cf)
370
373
371 return config
374 return config
372
375
373 launch_new_instance = TerminalIPythonApp.launch_instance
376 launch_new_instance = TerminalIPythonApp.launch_instance
374
377
375
378
376 if __name__ == '__main__':
379 if __name__ == '__main__':
377 launch_new_instance()
380 launch_new_instance()
General Comments 0
You need to be logged in to leave comments. Login now