##// END OF EJS Templates
Fix failing tests in core and zmq
Fernando Perez -
Show More
@@ -1,487 +1,487 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2 """Tests for various magic functions.
2 """Tests for various magic functions.
3
3
4 Needs to be run by nose (to make ipython session available).
4 Needs to be run by nose (to make ipython session available).
5 """
5 """
6 from __future__ import absolute_import
6 from __future__ import absolute_import
7
7
8 #-----------------------------------------------------------------------------
8 #-----------------------------------------------------------------------------
9 # Imports
9 # Imports
10 #-----------------------------------------------------------------------------
10 #-----------------------------------------------------------------------------
11
11
12 import io
12 import io
13 import os
13 import os
14 import sys
14 import sys
15 from StringIO import StringIO
15 from StringIO import StringIO
16
16
17 import nose.tools as nt
17 import nose.tools as nt
18
18
19 from IPython.core import magic
19 from IPython.core import magic
20 from IPython.core import magic_functions as mf
20 from IPython.core.magics import execution
21 from IPython.nbformat.v3.tests.nbexamples import nb0
21 from IPython.nbformat.v3.tests.nbexamples import nb0
22 from IPython.nbformat import current
22 from IPython.nbformat import current
23 from IPython.testing import decorators as dec
23 from IPython.testing import decorators as dec
24 from IPython.testing import tools as tt
24 from IPython.testing import tools as tt
25 from IPython.utils import py3compat
25 from IPython.utils import py3compat
26 from IPython.utils.tempdir import TemporaryDirectory
26 from IPython.utils.tempdir import TemporaryDirectory
27
27
28 #-----------------------------------------------------------------------------
28 #-----------------------------------------------------------------------------
29 # Test functions begin
29 # Test functions begin
30 #-----------------------------------------------------------------------------
30 #-----------------------------------------------------------------------------
31
31
32 @magic.register_magics
32 @magic.register_magics
33 class DummyMagics(magic.Magics): pass
33 class DummyMagics(magic.Magics): pass
34
34
35 def test_rehashx():
35 def test_rehashx():
36 # clear up everything
36 # clear up everything
37 _ip = get_ipython()
37 _ip = get_ipython()
38 _ip.alias_manager.alias_table.clear()
38 _ip.alias_manager.alias_table.clear()
39 del _ip.db['syscmdlist']
39 del _ip.db['syscmdlist']
40
40
41 _ip.magic('rehashx')
41 _ip.magic('rehashx')
42 # Practically ALL ipython development systems will have more than 10 aliases
42 # Practically ALL ipython development systems will have more than 10 aliases
43
43
44 yield (nt.assert_true, len(_ip.alias_manager.alias_table) > 10)
44 yield (nt.assert_true, len(_ip.alias_manager.alias_table) > 10)
45 for key, val in _ip.alias_manager.alias_table.iteritems():
45 for key, val in _ip.alias_manager.alias_table.iteritems():
46 # we must strip dots from alias names
46 # we must strip dots from alias names
47 nt.assert_true('.' not in key)
47 nt.assert_true('.' not in key)
48
48
49 # rehashx must fill up syscmdlist
49 # rehashx must fill up syscmdlist
50 scoms = _ip.db['syscmdlist']
50 scoms = _ip.db['syscmdlist']
51 yield (nt.assert_true, len(scoms) > 10)
51 yield (nt.assert_true, len(scoms) > 10)
52
52
53
53
54 def test_magic_parse_options():
54 def test_magic_parse_options():
55 """Test that we don't mangle paths when parsing magic options."""
55 """Test that we don't mangle paths when parsing magic options."""
56 ip = get_ipython()
56 ip = get_ipython()
57 path = 'c:\\x'
57 path = 'c:\\x'
58 m = DummyMagics(ip)
58 m = DummyMagics(ip)
59 opts = m.parse_options('-f %s' % path,'f:')[0]
59 opts = m.parse_options('-f %s' % path,'f:')[0]
60 # argv splitting is os-dependent
60 # argv splitting is os-dependent
61 if os.name == 'posix':
61 if os.name == 'posix':
62 expected = 'c:x'
62 expected = 'c:x'
63 else:
63 else:
64 expected = path
64 expected = path
65 nt.assert_equals(opts['f'], expected)
65 nt.assert_equals(opts['f'], expected)
66
66
67
67
68 @dec.skip_without('sqlite3')
68 @dec.skip_without('sqlite3')
69 def doctest_hist_f():
69 def doctest_hist_f():
70 """Test %hist -f with temporary filename.
70 """Test %hist -f with temporary filename.
71
71
72 In [9]: import tempfile
72 In [9]: import tempfile
73
73
74 In [10]: tfile = tempfile.mktemp('.py','tmp-ipython-')
74 In [10]: tfile = tempfile.mktemp('.py','tmp-ipython-')
75
75
76 In [11]: %hist -nl -f $tfile 3
76 In [11]: %hist -nl -f $tfile 3
77
77
78 In [13]: import os; os.unlink(tfile)
78 In [13]: import os; os.unlink(tfile)
79 """
79 """
80
80
81
81
82 @dec.skip_without('sqlite3')
82 @dec.skip_without('sqlite3')
83 def doctest_hist_r():
83 def doctest_hist_r():
84 """Test %hist -r
84 """Test %hist -r
85
85
86 XXX - This test is not recording the output correctly. For some reason, in
86 XXX - This test is not recording the output correctly. For some reason, in
87 testing mode the raw history isn't getting populated. No idea why.
87 testing mode the raw history isn't getting populated. No idea why.
88 Disabling the output checking for now, though at least we do run it.
88 Disabling the output checking for now, though at least we do run it.
89
89
90 In [1]: 'hist' in _ip.lsmagic()
90 In [1]: 'hist' in _ip.lsmagic()
91 Out[1]: True
91 Out[1]: True
92
92
93 In [2]: x=1
93 In [2]: x=1
94
94
95 In [3]: %hist -rl 2
95 In [3]: %hist -rl 2
96 x=1 # random
96 x=1 # random
97 %hist -r 2
97 %hist -r 2
98 """
98 """
99
99
100
100
101 @dec.skip_without('sqlite3')
101 @dec.skip_without('sqlite3')
102 def doctest_hist_op():
102 def doctest_hist_op():
103 """Test %hist -op
103 """Test %hist -op
104
104
105 In [1]: class b(float):
105 In [1]: class b(float):
106 ...: pass
106 ...: pass
107 ...:
107 ...:
108
108
109 In [2]: class s(object):
109 In [2]: class s(object):
110 ...: def __str__(self):
110 ...: def __str__(self):
111 ...: return 's'
111 ...: return 's'
112 ...:
112 ...:
113
113
114 In [3]:
114 In [3]:
115
115
116 In [4]: class r(b):
116 In [4]: class r(b):
117 ...: def __repr__(self):
117 ...: def __repr__(self):
118 ...: return 'r'
118 ...: return 'r'
119 ...:
119 ...:
120
120
121 In [5]: class sr(s,r): pass
121 In [5]: class sr(s,r): pass
122 ...:
122 ...:
123
123
124 In [6]:
124 In [6]:
125
125
126 In [7]: bb=b()
126 In [7]: bb=b()
127
127
128 In [8]: ss=s()
128 In [8]: ss=s()
129
129
130 In [9]: rr=r()
130 In [9]: rr=r()
131
131
132 In [10]: ssrr=sr()
132 In [10]: ssrr=sr()
133
133
134 In [11]: 4.5
134 In [11]: 4.5
135 Out[11]: 4.5
135 Out[11]: 4.5
136
136
137 In [12]: str(ss)
137 In [12]: str(ss)
138 Out[12]: 's'
138 Out[12]: 's'
139
139
140 In [13]:
140 In [13]:
141
141
142 In [14]: %hist -op
142 In [14]: %hist -op
143 >>> class b:
143 >>> class b:
144 ... pass
144 ... pass
145 ...
145 ...
146 >>> class s(b):
146 >>> class s(b):
147 ... def __str__(self):
147 ... def __str__(self):
148 ... return 's'
148 ... return 's'
149 ...
149 ...
150 >>>
150 >>>
151 >>> class r(b):
151 >>> class r(b):
152 ... def __repr__(self):
152 ... def __repr__(self):
153 ... return 'r'
153 ... return 'r'
154 ...
154 ...
155 >>> class sr(s,r): pass
155 >>> class sr(s,r): pass
156 >>>
156 >>>
157 >>> bb=b()
157 >>> bb=b()
158 >>> ss=s()
158 >>> ss=s()
159 >>> rr=r()
159 >>> rr=r()
160 >>> ssrr=sr()
160 >>> ssrr=sr()
161 >>> 4.5
161 >>> 4.5
162 4.5
162 4.5
163 >>> str(ss)
163 >>> str(ss)
164 's'
164 's'
165 >>>
165 >>>
166 """
166 """
167
167
168
168
169 @dec.skip_without('sqlite3')
169 @dec.skip_without('sqlite3')
170 def test_macro():
170 def test_macro():
171 ip = get_ipython()
171 ip = get_ipython()
172 ip.history_manager.reset() # Clear any existing history.
172 ip.history_manager.reset() # Clear any existing history.
173 cmds = ["a=1", "def b():\n return a**2", "print(a,b())"]
173 cmds = ["a=1", "def b():\n return a**2", "print(a,b())"]
174 for i, cmd in enumerate(cmds, start=1):
174 for i, cmd in enumerate(cmds, start=1):
175 ip.history_manager.store_inputs(i, cmd)
175 ip.history_manager.store_inputs(i, cmd)
176 ip.magic("macro test 1-3")
176 ip.magic("macro test 1-3")
177 nt.assert_equal(ip.user_ns["test"].value, "\n".join(cmds)+"\n")
177 nt.assert_equal(ip.user_ns["test"].value, "\n".join(cmds)+"\n")
178
178
179 # List macros.
179 # List macros.
180 assert "test" in ip.magic("macro")
180 assert "test" in ip.magic("macro")
181
181
182
182
183 @dec.skip_without('sqlite3')
183 @dec.skip_without('sqlite3')
184 def test_macro_run():
184 def test_macro_run():
185 """Test that we can run a multi-line macro successfully."""
185 """Test that we can run a multi-line macro successfully."""
186 ip = get_ipython()
186 ip = get_ipython()
187 ip.history_manager.reset()
187 ip.history_manager.reset()
188 cmds = ["a=10", "a+=1", py3compat.doctest_refactor_print("print a"),
188 cmds = ["a=10", "a+=1", py3compat.doctest_refactor_print("print a"),
189 "%macro test 2-3"]
189 "%macro test 2-3"]
190 for cmd in cmds:
190 for cmd in cmds:
191 ip.run_cell(cmd, store_history=True)
191 ip.run_cell(cmd, store_history=True)
192 nt.assert_equal(ip.user_ns["test"].value,
192 nt.assert_equal(ip.user_ns["test"].value,
193 py3compat.doctest_refactor_print("a+=1\nprint a\n"))
193 py3compat.doctest_refactor_print("a+=1\nprint a\n"))
194 with tt.AssertPrints("12"):
194 with tt.AssertPrints("12"):
195 ip.run_cell("test")
195 ip.run_cell("test")
196 with tt.AssertPrints("13"):
196 with tt.AssertPrints("13"):
197 ip.run_cell("test")
197 ip.run_cell("test")
198
198
199
199
200 @dec.skipif_not_numpy
200 @dec.skipif_not_numpy
201 def test_numpy_reset_array_undec():
201 def test_numpy_reset_array_undec():
202 "Test '%reset array' functionality"
202 "Test '%reset array' functionality"
203 _ip.ex('import numpy as np')
203 _ip.ex('import numpy as np')
204 _ip.ex('a = np.empty(2)')
204 _ip.ex('a = np.empty(2)')
205 yield (nt.assert_true, 'a' in _ip.user_ns)
205 yield (nt.assert_true, 'a' in _ip.user_ns)
206 _ip.magic('reset -f array')
206 _ip.magic('reset -f array')
207 yield (nt.assert_false, 'a' in _ip.user_ns)
207 yield (nt.assert_false, 'a' in _ip.user_ns)
208
208
209 def test_reset_out():
209 def test_reset_out():
210 "Test '%reset out' magic"
210 "Test '%reset out' magic"
211 _ip.run_cell("parrot = 'dead'", store_history=True)
211 _ip.run_cell("parrot = 'dead'", store_history=True)
212 # test '%reset -f out', make an Out prompt
212 # test '%reset -f out', make an Out prompt
213 _ip.run_cell("parrot", store_history=True)
213 _ip.run_cell("parrot", store_history=True)
214 nt.assert_true('dead' in [_ip.user_ns[x] for x in '_','__','___'])
214 nt.assert_true('dead' in [_ip.user_ns[x] for x in '_','__','___'])
215 _ip.magic('reset -f out')
215 _ip.magic('reset -f out')
216 nt.assert_false('dead' in [_ip.user_ns[x] for x in '_','__','___'])
216 nt.assert_false('dead' in [_ip.user_ns[x] for x in '_','__','___'])
217 nt.assert_true(len(_ip.user_ns['Out']) == 0)
217 nt.assert_true(len(_ip.user_ns['Out']) == 0)
218
218
219 def test_reset_in():
219 def test_reset_in():
220 "Test '%reset in' magic"
220 "Test '%reset in' magic"
221 # test '%reset -f in'
221 # test '%reset -f in'
222 _ip.run_cell("parrot", store_history=True)
222 _ip.run_cell("parrot", store_history=True)
223 nt.assert_true('parrot' in [_ip.user_ns[x] for x in '_i','_ii','_iii'])
223 nt.assert_true('parrot' in [_ip.user_ns[x] for x in '_i','_ii','_iii'])
224 _ip.magic('%reset -f in')
224 _ip.magic('%reset -f in')
225 nt.assert_false('parrot' in [_ip.user_ns[x] for x in '_i','_ii','_iii'])
225 nt.assert_false('parrot' in [_ip.user_ns[x] for x in '_i','_ii','_iii'])
226 nt.assert_true(len(set(_ip.user_ns['In'])) == 1)
226 nt.assert_true(len(set(_ip.user_ns['In'])) == 1)
227
227
228 def test_reset_dhist():
228 def test_reset_dhist():
229 "Test '%reset dhist' magic"
229 "Test '%reset dhist' magic"
230 _ip.run_cell("tmp = [d for d in _dh]") # copy before clearing
230 _ip.run_cell("tmp = [d for d in _dh]") # copy before clearing
231 _ip.magic('cd ' + os.path.dirname(nt.__file__))
231 _ip.magic('cd ' + os.path.dirname(nt.__file__))
232 _ip.magic('cd -')
232 _ip.magic('cd -')
233 nt.assert_true(len(_ip.user_ns['_dh']) > 0)
233 nt.assert_true(len(_ip.user_ns['_dh']) > 0)
234 _ip.magic('reset -f dhist')
234 _ip.magic('reset -f dhist')
235 nt.assert_true(len(_ip.user_ns['_dh']) == 0)
235 nt.assert_true(len(_ip.user_ns['_dh']) == 0)
236 _ip.run_cell("_dh = [d for d in tmp]") #restore
236 _ip.run_cell("_dh = [d for d in tmp]") #restore
237
237
238 def test_reset_in_length():
238 def test_reset_in_length():
239 "Test that '%reset in' preserves In[] length"
239 "Test that '%reset in' preserves In[] length"
240 _ip.run_cell("print 'foo'")
240 _ip.run_cell("print 'foo'")
241 _ip.run_cell("reset -f in")
241 _ip.run_cell("reset -f in")
242 nt.assert_true(len(_ip.user_ns['In']) == _ip.displayhook.prompt_count+1)
242 nt.assert_true(len(_ip.user_ns['In']) == _ip.displayhook.prompt_count+1)
243
243
244 def test_time():
244 def test_time():
245 _ip.magic('time None')
245 _ip.magic('time None')
246
246
247 def test_tb_syntaxerror():
247 def test_tb_syntaxerror():
248 """test %tb after a SyntaxError"""
248 """test %tb after a SyntaxError"""
249 ip = get_ipython()
249 ip = get_ipython()
250 ip.run_cell("for")
250 ip.run_cell("for")
251
251
252 # trap and validate stdout
252 # trap and validate stdout
253 save_stdout = sys.stdout
253 save_stdout = sys.stdout
254 try:
254 try:
255 sys.stdout = StringIO()
255 sys.stdout = StringIO()
256 ip.run_cell("%tb")
256 ip.run_cell("%tb")
257 out = sys.stdout.getvalue()
257 out = sys.stdout.getvalue()
258 finally:
258 finally:
259 sys.stdout = save_stdout
259 sys.stdout = save_stdout
260 # trim output, and only check the last line
260 # trim output, and only check the last line
261 last_line = out.rstrip().splitlines()[-1].strip()
261 last_line = out.rstrip().splitlines()[-1].strip()
262 nt.assert_equals(last_line, "SyntaxError: invalid syntax")
262 nt.assert_equals(last_line, "SyntaxError: invalid syntax")
263
263
264
264
265 @py3compat.doctest_refactor_print
265 @py3compat.doctest_refactor_print
266 def doctest_time():
266 def doctest_time():
267 """
267 """
268 In [10]: %time None
268 In [10]: %time None
269 CPU times: user 0.00 s, sys: 0.00 s, total: 0.00 s
269 CPU times: user 0.00 s, sys: 0.00 s, total: 0.00 s
270 Wall time: 0.00 s
270 Wall time: 0.00 s
271
271
272 In [11]: def f(kmjy):
272 In [11]: def f(kmjy):
273 ....: %time print 2*kmjy
273 ....: %time print 2*kmjy
274
274
275 In [12]: f(3)
275 In [12]: f(3)
276 6
276 6
277 CPU times: user 0.00 s, sys: 0.00 s, total: 0.00 s
277 CPU times: user 0.00 s, sys: 0.00 s, total: 0.00 s
278 Wall time: 0.00 s
278 Wall time: 0.00 s
279 """
279 """
280
280
281
281
282 def test_doctest_mode():
282 def test_doctest_mode():
283 "Toggle doctest_mode twice, it should be a no-op and run without error"
283 "Toggle doctest_mode twice, it should be a no-op and run without error"
284 _ip.magic('doctest_mode')
284 _ip.magic('doctest_mode')
285 _ip.magic('doctest_mode')
285 _ip.magic('doctest_mode')
286
286
287
287
288 def test_parse_options():
288 def test_parse_options():
289 """Tests for basic options parsing in magics."""
289 """Tests for basic options parsing in magics."""
290 # These are only the most minimal of tests, more should be added later. At
290 # These are only the most minimal of tests, more should be added later. At
291 # the very least we check that basic text/unicode calls work OK.
291 # the very least we check that basic text/unicode calls work OK.
292 m = DummyMagics(_ip)
292 m = DummyMagics(_ip)
293 nt.assert_equal(m.parse_options('foo', '')[1], 'foo')
293 nt.assert_equal(m.parse_options('foo', '')[1], 'foo')
294 nt.assert_equal(m.parse_options(u'foo', '')[1], u'foo')
294 nt.assert_equal(m.parse_options(u'foo', '')[1], u'foo')
295
295
296
296
297 def test_dirops():
297 def test_dirops():
298 """Test various directory handling operations."""
298 """Test various directory handling operations."""
299 # curpath = lambda :os.path.splitdrive(os.getcwdu())[1].replace('\\','/')
299 # curpath = lambda :os.path.splitdrive(os.getcwdu())[1].replace('\\','/')
300 curpath = os.getcwdu
300 curpath = os.getcwdu
301 startdir = os.getcwdu()
301 startdir = os.getcwdu()
302 ipdir = os.path.realpath(_ip.ipython_dir)
302 ipdir = os.path.realpath(_ip.ipython_dir)
303 try:
303 try:
304 _ip.magic('cd "%s"' % ipdir)
304 _ip.magic('cd "%s"' % ipdir)
305 nt.assert_equal(curpath(), ipdir)
305 nt.assert_equal(curpath(), ipdir)
306 _ip.magic('cd -')
306 _ip.magic('cd -')
307 nt.assert_equal(curpath(), startdir)
307 nt.assert_equal(curpath(), startdir)
308 _ip.magic('pushd "%s"' % ipdir)
308 _ip.magic('pushd "%s"' % ipdir)
309 nt.assert_equal(curpath(), ipdir)
309 nt.assert_equal(curpath(), ipdir)
310 _ip.magic('popd')
310 _ip.magic('popd')
311 nt.assert_equal(curpath(), startdir)
311 nt.assert_equal(curpath(), startdir)
312 finally:
312 finally:
313 os.chdir(startdir)
313 os.chdir(startdir)
314
314
315
315
316 def test_xmode():
316 def test_xmode():
317 # Calling xmode three times should be a no-op
317 # Calling xmode three times should be a no-op
318 xmode = _ip.InteractiveTB.mode
318 xmode = _ip.InteractiveTB.mode
319 for i in range(3):
319 for i in range(3):
320 _ip.magic("xmode")
320 _ip.magic("xmode")
321 nt.assert_equal(_ip.InteractiveTB.mode, xmode)
321 nt.assert_equal(_ip.InteractiveTB.mode, xmode)
322
322
323 def test_reset_hard():
323 def test_reset_hard():
324 monitor = []
324 monitor = []
325 class A(object):
325 class A(object):
326 def __del__(self):
326 def __del__(self):
327 monitor.append(1)
327 monitor.append(1)
328 def __repr__(self):
328 def __repr__(self):
329 return "<A instance>"
329 return "<A instance>"
330
330
331 _ip.user_ns["a"] = A()
331 _ip.user_ns["a"] = A()
332 _ip.run_cell("a")
332 _ip.run_cell("a")
333
333
334 nt.assert_equal(monitor, [])
334 nt.assert_equal(monitor, [])
335 _ip.magic("reset -f")
335 _ip.magic("reset -f")
336 nt.assert_equal(monitor, [1])
336 nt.assert_equal(monitor, [1])
337
337
338 class TestXdel(tt.TempFileMixin):
338 class TestXdel(tt.TempFileMixin):
339 def test_xdel(self):
339 def test_xdel(self):
340 """Test that references from %run are cleared by xdel."""
340 """Test that references from %run are cleared by xdel."""
341 src = ("class A(object):\n"
341 src = ("class A(object):\n"
342 " monitor = []\n"
342 " monitor = []\n"
343 " def __del__(self):\n"
343 " def __del__(self):\n"
344 " self.monitor.append(1)\n"
344 " self.monitor.append(1)\n"
345 "a = A()\n")
345 "a = A()\n")
346 self.mktmp(src)
346 self.mktmp(src)
347 # %run creates some hidden references...
347 # %run creates some hidden references...
348 _ip.magic("run %s" % self.fname)
348 _ip.magic("run %s" % self.fname)
349 # ... as does the displayhook.
349 # ... as does the displayhook.
350 _ip.run_cell("a")
350 _ip.run_cell("a")
351
351
352 monitor = _ip.user_ns["A"].monitor
352 monitor = _ip.user_ns["A"].monitor
353 nt.assert_equal(monitor, [])
353 nt.assert_equal(monitor, [])
354
354
355 _ip.magic("xdel a")
355 _ip.magic("xdel a")
356
356
357 # Check that a's __del__ method has been called.
357 # Check that a's __del__ method has been called.
358 nt.assert_equal(monitor, [1])
358 nt.assert_equal(monitor, [1])
359
359
360 def doctest_who():
360 def doctest_who():
361 """doctest for %who
361 """doctest for %who
362
362
363 In [1]: %reset -f
363 In [1]: %reset -f
364
364
365 In [2]: alpha = 123
365 In [2]: alpha = 123
366
366
367 In [3]: beta = 'beta'
367 In [3]: beta = 'beta'
368
368
369 In [4]: %who int
369 In [4]: %who int
370 alpha
370 alpha
371
371
372 In [5]: %who str
372 In [5]: %who str
373 beta
373 beta
374
374
375 In [6]: %whos
375 In [6]: %whos
376 Variable Type Data/Info
376 Variable Type Data/Info
377 ----------------------------
377 ----------------------------
378 alpha int 123
378 alpha int 123
379 beta str beta
379 beta str beta
380
380
381 In [7]: %who_ls
381 In [7]: %who_ls
382 Out[7]: ['alpha', 'beta']
382 Out[7]: ['alpha', 'beta']
383 """
383 """
384
384
385 def test_whos():
385 def test_whos():
386 """Check that whos is protected against objects where repr() fails."""
386 """Check that whos is protected against objects where repr() fails."""
387 class A(object):
387 class A(object):
388 def __repr__(self):
388 def __repr__(self):
389 raise Exception()
389 raise Exception()
390 _ip.user_ns['a'] = A()
390 _ip.user_ns['a'] = A()
391 _ip.magic("whos")
391 _ip.magic("whos")
392
392
393 @py3compat.u_format
393 @py3compat.u_format
394 def doctest_precision():
394 def doctest_precision():
395 """doctest for %precision
395 """doctest for %precision
396
396
397 In [1]: f = get_ipython().display_formatter.formatters['text/plain']
397 In [1]: f = get_ipython().display_formatter.formatters['text/plain']
398
398
399 In [2]: %precision 5
399 In [2]: %precision 5
400 Out[2]: {u}'%.5f'
400 Out[2]: {u}'%.5f'
401
401
402 In [3]: f.float_format
402 In [3]: f.float_format
403 Out[3]: {u}'%.5f'
403 Out[3]: {u}'%.5f'
404
404
405 In [4]: %precision %e
405 In [4]: %precision %e
406 Out[4]: {u}'%e'
406 Out[4]: {u}'%e'
407
407
408 In [5]: f(3.1415927)
408 In [5]: f(3.1415927)
409 Out[5]: {u}'3.141593e+00'
409 Out[5]: {u}'3.141593e+00'
410 """
410 """
411
411
412 def test_psearch():
412 def test_psearch():
413 with tt.AssertPrints("dict.fromkeys"):
413 with tt.AssertPrints("dict.fromkeys"):
414 _ip.run_cell("dict.fr*?")
414 _ip.run_cell("dict.fr*?")
415
415
416 def test_timeit_shlex():
416 def test_timeit_shlex():
417 """test shlex issues with timeit (#1109)"""
417 """test shlex issues with timeit (#1109)"""
418 _ip.ex("def f(*a,**kw): pass")
418 _ip.ex("def f(*a,**kw): pass")
419 _ip.magic('timeit -n1 "this is a bug".count(" ")')
419 _ip.magic('timeit -n1 "this is a bug".count(" ")')
420 _ip.magic('timeit -r1 -n1 f(" ", 1)')
420 _ip.magic('timeit -r1 -n1 f(" ", 1)')
421 _ip.magic('timeit -r1 -n1 f(" ", 1, " ", 2, " ")')
421 _ip.magic('timeit -r1 -n1 f(" ", 1, " ", 2, " ")')
422 _ip.magic('timeit -r1 -n1 ("a " + "b")')
422 _ip.magic('timeit -r1 -n1 ("a " + "b")')
423 _ip.magic('timeit -r1 -n1 f("a " + "b")')
423 _ip.magic('timeit -r1 -n1 f("a " + "b")')
424 _ip.magic('timeit -r1 -n1 f("a " + "b ")')
424 _ip.magic('timeit -r1 -n1 f("a " + "b ")')
425
425
426
426
427 def test_timeit_arguments():
427 def test_timeit_arguments():
428 "Test valid timeit arguments, should not cause SyntaxError (GH #1269)"
428 "Test valid timeit arguments, should not cause SyntaxError (GH #1269)"
429 _ip.magic("timeit ('#')")
429 _ip.magic("timeit ('#')")
430
430
431
431
432 @dec.skipif(mf.profile is None)
432 @dec.skipif(execution.profile is None)
433 def test_prun_quotes():
433 def test_prun_quotes():
434 "Test that prun does not clobber string escapes (GH #1302)"
434 "Test that prun does not clobber string escapes (GH #1302)"
435 _ip.magic("prun -q x = '\t'")
435 _ip.magic("prun -q x = '\t'")
436 nt.assert_equal(_ip.user_ns['x'], '\t')
436 nt.assert_equal(_ip.user_ns['x'], '\t')
437
437
438 def test_extension():
438 def test_extension():
439 tmpdir = TemporaryDirectory()
439 tmpdir = TemporaryDirectory()
440 orig_ipython_dir = _ip.ipython_dir
440 orig_ipython_dir = _ip.ipython_dir
441 try:
441 try:
442 _ip.ipython_dir = tmpdir.name
442 _ip.ipython_dir = tmpdir.name
443 nt.assert_raises(ImportError, _ip.magic, "load_ext daft_extension")
443 nt.assert_raises(ImportError, _ip.magic, "load_ext daft_extension")
444 url = os.path.join(os.path.dirname(__file__), "daft_extension.py")
444 url = os.path.join(os.path.dirname(__file__), "daft_extension.py")
445 _ip.magic("install_ext %s" % url)
445 _ip.magic("install_ext %s" % url)
446 _ip.user_ns.pop('arq', None)
446 _ip.user_ns.pop('arq', None)
447 _ip.magic("load_ext daft_extension")
447 _ip.magic("load_ext daft_extension")
448 tt.assert_equal(_ip.user_ns['arq'], 185)
448 tt.assert_equal(_ip.user_ns['arq'], 185)
449 _ip.magic("unload_ext daft_extension")
449 _ip.magic("unload_ext daft_extension")
450 assert 'arq' not in _ip.user_ns
450 assert 'arq' not in _ip.user_ns
451 finally:
451 finally:
452 _ip.ipython_dir = orig_ipython_dir
452 _ip.ipython_dir = orig_ipython_dir
453
453
454 def test_notebook_export_json():
454 def test_notebook_export_json():
455 with TemporaryDirectory() as td:
455 with TemporaryDirectory() as td:
456 outfile = os.path.join(td, "nb.ipynb")
456 outfile = os.path.join(td, "nb.ipynb")
457 _ip.ex(py3compat.u_format(u"u = {u}'hΓ©llo'"))
457 _ip.ex(py3compat.u_format(u"u = {u}'hΓ©llo'"))
458 _ip.magic("notebook -e %s" % outfile)
458 _ip.magic("notebook -e %s" % outfile)
459
459
460 def test_notebook_export_py():
460 def test_notebook_export_py():
461 with TemporaryDirectory() as td:
461 with TemporaryDirectory() as td:
462 outfile = os.path.join(td, "nb.py")
462 outfile = os.path.join(td, "nb.py")
463 _ip.ex(py3compat.u_format(u"u = {u}'hΓ©llo'"))
463 _ip.ex(py3compat.u_format(u"u = {u}'hΓ©llo'"))
464 _ip.magic("notebook -e %s" % outfile)
464 _ip.magic("notebook -e %s" % outfile)
465
465
466 def test_notebook_reformat_py():
466 def test_notebook_reformat_py():
467 with TemporaryDirectory() as td:
467 with TemporaryDirectory() as td:
468 infile = os.path.join(td, "nb.ipynb")
468 infile = os.path.join(td, "nb.ipynb")
469 with io.open(infile, 'w', encoding='utf-8') as f:
469 with io.open(infile, 'w', encoding='utf-8') as f:
470 current.write(nb0, f, 'json')
470 current.write(nb0, f, 'json')
471
471
472 _ip.ex(py3compat.u_format(u"u = {u}'hΓ©llo'"))
472 _ip.ex(py3compat.u_format(u"u = {u}'hΓ©llo'"))
473 _ip.magic("notebook -f py %s" % infile)
473 _ip.magic("notebook -f py %s" % infile)
474
474
475 def test_notebook_reformat_json():
475 def test_notebook_reformat_json():
476 with TemporaryDirectory() as td:
476 with TemporaryDirectory() as td:
477 infile = os.path.join(td, "nb.py")
477 infile = os.path.join(td, "nb.py")
478 with io.open(infile, 'w', encoding='utf-8') as f:
478 with io.open(infile, 'w', encoding='utf-8') as f:
479 current.write(nb0, f, 'py')
479 current.write(nb0, f, 'py')
480
480
481 _ip.ex(py3compat.u_format(u"u = {u}'hΓ©llo'"))
481 _ip.ex(py3compat.u_format(u"u = {u}'hΓ©llo'"))
482 _ip.magic("notebook -f ipynb %s" % infile)
482 _ip.magic("notebook -f ipynb %s" % infile)
483 _ip.magic("notebook -f json %s" % infile)
483 _ip.magic("notebook -f json %s" % infile)
484
484
485 def test_env():
485 def test_env():
486 env = _ip.magic("env")
486 env = _ip.magic("env")
487 assert isinstance(env, dict), type(env)
487 assert isinstance(env, dict), type(env)
@@ -1,541 +1,540 b''
1 """A ZMQ-based subclass of InteractiveShell.
1 """A ZMQ-based subclass of InteractiveShell.
2
2
3 This code is meant to ease the refactoring of the base InteractiveShell into
3 This code is meant to ease the refactoring of the base InteractiveShell into
4 something with a cleaner architecture for 2-process use, without actually
4 something with a cleaner architecture for 2-process use, without actually
5 breaking InteractiveShell itself. So we're doing something a bit ugly, where
5 breaking InteractiveShell itself. So we're doing something a bit ugly, where
6 we subclass and override what we want to fix. Once this is working well, we
6 we subclass and override what we want to fix. Once this is working well, we
7 can go back to the base class and refactor the code for a cleaner inheritance
7 can go back to the base class and refactor the code for a cleaner inheritance
8 implementation that doesn't rely on so much monkeypatching.
8 implementation that doesn't rely on so much monkeypatching.
9
9
10 But this lets us maintain a fully working IPython as we develop the new
10 But this lets us maintain a fully working IPython as we develop the new
11 machinery. This should thus be thought of as scaffolding.
11 machinery. This should thus be thought of as scaffolding.
12 """
12 """
13 #-----------------------------------------------------------------------------
13 #-----------------------------------------------------------------------------
14 # Imports
14 # Imports
15 #-----------------------------------------------------------------------------
15 #-----------------------------------------------------------------------------
16 from __future__ import print_function
16 from __future__ import print_function
17
17
18 # Stdlib
18 # Stdlib
19 import inspect
19 import inspect
20 import os
20 import os
21 import sys
21 import sys
22 import time
22 import time
23 from subprocess import Popen, PIPE
23 from subprocess import Popen, PIPE
24
24
25 # System library imports
25 # System library imports
26 from zmq.eventloop import ioloop
26 from zmq.eventloop import ioloop
27
27
28 # Our own
28 # Our own
29 from IPython.core.interactiveshell import (
29 from IPython.core.interactiveshell import (
30 InteractiveShell, InteractiveShellABC
30 InteractiveShell, InteractiveShellABC
31 )
31 )
32 from IPython.core import page, pylabtools
32 from IPython.core import page, pylabtools
33 from IPython.core.autocall import ZMQExitAutocall
33 from IPython.core.autocall import ZMQExitAutocall
34 from IPython.core.displaypub import DisplayPublisher
34 from IPython.core.displaypub import DisplayPublisher
35 from IPython.core.macro import Macro
35 from IPython.core.macro import Macro
36 from IPython.core.magic_functions import MacroToEdit
36 from IPython.core.magics import MacroToEdit
37 from IPython.core.payloadpage import install_payload_page
37 from IPython.core.payloadpage import install_payload_page
38 from IPython.lib.kernel import (
38 from IPython.lib.kernel import (
39 get_connection_file, get_connection_info, connect_qtconsole
39 get_connection_file, get_connection_info, connect_qtconsole
40 )
40 )
41 from IPython.testing.skipdoctest import skip_doctest
41 from IPython.testing.skipdoctest import skip_doctest
42 from IPython.utils import io
42 from IPython.utils import io
43 from IPython.utils.jsonutil import json_clean
43 from IPython.utils.jsonutil import json_clean
44 from IPython.utils.path import get_py_filename
44 from IPython.utils.path import get_py_filename
45 from IPython.utils.process import arg_split
45 from IPython.utils.process import arg_split
46 from IPython.utils.traitlets import Instance, Type, Dict, CBool, CBytes
46 from IPython.utils.traitlets import Instance, Type, Dict, CBool, CBytes
47 from IPython.utils.warn import warn, error
47 from IPython.utils.warn import warn, error
48 from IPython.zmq.displayhook import ZMQShellDisplayHook, _encode_binary
48 from IPython.zmq.displayhook import ZMQShellDisplayHook, _encode_binary
49 from IPython.zmq.session import extract_header
49 from IPython.zmq.session import extract_header
50 from session import Session
50 from session import Session
51
51
52
53 #-----------------------------------------------------------------------------
52 #-----------------------------------------------------------------------------
54 # Functions and classes
53 # Functions and classes
55 #-----------------------------------------------------------------------------
54 #-----------------------------------------------------------------------------
56
55
57 class ZMQDisplayPublisher(DisplayPublisher):
56 class ZMQDisplayPublisher(DisplayPublisher):
58 """A display publisher that publishes data using a ZeroMQ PUB socket."""
57 """A display publisher that publishes data using a ZeroMQ PUB socket."""
59
58
60 session = Instance(Session)
59 session = Instance(Session)
61 pub_socket = Instance('zmq.Socket')
60 pub_socket = Instance('zmq.Socket')
62 parent_header = Dict({})
61 parent_header = Dict({})
63 topic = CBytes(b'displaypub')
62 topic = CBytes(b'displaypub')
64
63
65 def set_parent(self, parent):
64 def set_parent(self, parent):
66 """Set the parent for outbound messages."""
65 """Set the parent for outbound messages."""
67 self.parent_header = extract_header(parent)
66 self.parent_header = extract_header(parent)
68
67
69 def _flush_streams(self):
68 def _flush_streams(self):
70 """flush IO Streams prior to display"""
69 """flush IO Streams prior to display"""
71 sys.stdout.flush()
70 sys.stdout.flush()
72 sys.stderr.flush()
71 sys.stderr.flush()
73
72
74 def publish(self, source, data, metadata=None):
73 def publish(self, source, data, metadata=None):
75 self._flush_streams()
74 self._flush_streams()
76 if metadata is None:
75 if metadata is None:
77 metadata = {}
76 metadata = {}
78 self._validate_data(source, data, metadata)
77 self._validate_data(source, data, metadata)
79 content = {}
78 content = {}
80 content['source'] = source
79 content['source'] = source
81 _encode_binary(data)
80 _encode_binary(data)
82 content['data'] = data
81 content['data'] = data
83 content['metadata'] = metadata
82 content['metadata'] = metadata
84 self.session.send(
83 self.session.send(
85 self.pub_socket, u'display_data', json_clean(content),
84 self.pub_socket, u'display_data', json_clean(content),
86 parent=self.parent_header, ident=self.topic,
85 parent=self.parent_header, ident=self.topic,
87 )
86 )
88
87
89 def clear_output(self, stdout=True, stderr=True, other=True):
88 def clear_output(self, stdout=True, stderr=True, other=True):
90 content = dict(stdout=stdout, stderr=stderr, other=other)
89 content = dict(stdout=stdout, stderr=stderr, other=other)
91
90
92 if stdout:
91 if stdout:
93 print('\r', file=sys.stdout, end='')
92 print('\r', file=sys.stdout, end='')
94 if stderr:
93 if stderr:
95 print('\r', file=sys.stderr, end='')
94 print('\r', file=sys.stderr, end='')
96
95
97 self._flush_streams()
96 self._flush_streams()
98
97
99 self.session.send(
98 self.session.send(
100 self.pub_socket, u'clear_output', content,
99 self.pub_socket, u'clear_output', content,
101 parent=self.parent_header, ident=self.topic,
100 parent=self.parent_header, ident=self.topic,
102 )
101 )
103
102
104 class ZMQInteractiveShell(InteractiveShell):
103 class ZMQInteractiveShell(InteractiveShell):
105 """A subclass of InteractiveShell for ZMQ."""
104 """A subclass of InteractiveShell for ZMQ."""
106
105
107 displayhook_class = Type(ZMQShellDisplayHook)
106 displayhook_class = Type(ZMQShellDisplayHook)
108 display_pub_class = Type(ZMQDisplayPublisher)
107 display_pub_class = Type(ZMQDisplayPublisher)
109
108
110 # Override the traitlet in the parent class, because there's no point using
109 # Override the traitlet in the parent class, because there's no point using
111 # readline for the kernel. Can be removed when the readline code is moved
110 # readline for the kernel. Can be removed when the readline code is moved
112 # to the terminal frontend.
111 # to the terminal frontend.
113 colors_force = CBool(True)
112 colors_force = CBool(True)
114 readline_use = CBool(False)
113 readline_use = CBool(False)
115 # autoindent has no meaning in a zmqshell, and attempting to enable it
114 # autoindent has no meaning in a zmqshell, and attempting to enable it
116 # will print a warning in the absence of readline.
115 # will print a warning in the absence of readline.
117 autoindent = CBool(False)
116 autoindent = CBool(False)
118
117
119 exiter = Instance(ZMQExitAutocall)
118 exiter = Instance(ZMQExitAutocall)
120 def _exiter_default(self):
119 def _exiter_default(self):
121 return ZMQExitAutocall(self)
120 return ZMQExitAutocall(self)
122
121
123 def _exit_now_changed(self, name, old, new):
122 def _exit_now_changed(self, name, old, new):
124 """stop eventloop when exit_now fires"""
123 """stop eventloop when exit_now fires"""
125 if new:
124 if new:
126 loop = ioloop.IOLoop.instance()
125 loop = ioloop.IOLoop.instance()
127 loop.add_timeout(time.time()+0.1, loop.stop)
126 loop.add_timeout(time.time()+0.1, loop.stop)
128
127
129 keepkernel_on_exit = None
128 keepkernel_on_exit = None
130
129
131 # Over ZeroMQ, GUI control isn't done with PyOS_InputHook as there is no
130 # Over ZeroMQ, GUI control isn't done with PyOS_InputHook as there is no
132 # interactive input being read; we provide event loop support in ipkernel
131 # interactive input being read; we provide event loop support in ipkernel
133 from .eventloops import enable_gui
132 from .eventloops import enable_gui
134 enable_gui = staticmethod(enable_gui)
133 enable_gui = staticmethod(enable_gui)
135
134
136 def init_environment(self):
135 def init_environment(self):
137 """Configure the user's environment.
136 """Configure the user's environment.
138
137
139 """
138 """
140 env = os.environ
139 env = os.environ
141 # These two ensure 'ls' produces nice coloring on BSD-derived systems
140 # These two ensure 'ls' produces nice coloring on BSD-derived systems
142 env['TERM'] = 'xterm-color'
141 env['TERM'] = 'xterm-color'
143 env['CLICOLOR'] = '1'
142 env['CLICOLOR'] = '1'
144 # Since normal pagers don't work at all (over pexpect we don't have
143 # Since normal pagers don't work at all (over pexpect we don't have
145 # single-key control of the subprocess), try to disable paging in
144 # single-key control of the subprocess), try to disable paging in
146 # subprocesses as much as possible.
145 # subprocesses as much as possible.
147 env['PAGER'] = 'cat'
146 env['PAGER'] = 'cat'
148 env['GIT_PAGER'] = 'cat'
147 env['GIT_PAGER'] = 'cat'
149
148
150 # And install the payload version of page.
149 # And install the payload version of page.
151 install_payload_page()
150 install_payload_page()
152
151
153 def auto_rewrite_input(self, cmd):
152 def auto_rewrite_input(self, cmd):
154 """Called to show the auto-rewritten input for autocall and friends.
153 """Called to show the auto-rewritten input for autocall and friends.
155
154
156 FIXME: this payload is currently not correctly processed by the
155 FIXME: this payload is currently not correctly processed by the
157 frontend.
156 frontend.
158 """
157 """
159 new = self.prompt_manager.render('rewrite') + cmd
158 new = self.prompt_manager.render('rewrite') + cmd
160 payload = dict(
159 payload = dict(
161 source='IPython.zmq.zmqshell.ZMQInteractiveShell.auto_rewrite_input',
160 source='IPython.zmq.zmqshell.ZMQInteractiveShell.auto_rewrite_input',
162 transformed_input=new,
161 transformed_input=new,
163 )
162 )
164 self.payload_manager.write_payload(payload)
163 self.payload_manager.write_payload(payload)
165
164
166 def ask_exit(self):
165 def ask_exit(self):
167 """Engage the exit actions."""
166 """Engage the exit actions."""
168 self.exit_now = True
167 self.exit_now = True
169 payload = dict(
168 payload = dict(
170 source='IPython.zmq.zmqshell.ZMQInteractiveShell.ask_exit',
169 source='IPython.zmq.zmqshell.ZMQInteractiveShell.ask_exit',
171 exit=True,
170 exit=True,
172 keepkernel=self.keepkernel_on_exit,
171 keepkernel=self.keepkernel_on_exit,
173 )
172 )
174 self.payload_manager.write_payload(payload)
173 self.payload_manager.write_payload(payload)
175
174
176 def _showtraceback(self, etype, evalue, stb):
175 def _showtraceback(self, etype, evalue, stb):
177
176
178 exc_content = {
177 exc_content = {
179 u'traceback' : stb,
178 u'traceback' : stb,
180 u'ename' : unicode(etype.__name__),
179 u'ename' : unicode(etype.__name__),
181 u'evalue' : unicode(evalue)
180 u'evalue' : unicode(evalue)
182 }
181 }
183
182
184 dh = self.displayhook
183 dh = self.displayhook
185 # Send exception info over pub socket for other clients than the caller
184 # Send exception info over pub socket for other clients than the caller
186 # to pick up
185 # to pick up
187 topic = None
186 topic = None
188 if dh.topic:
187 if dh.topic:
189 topic = dh.topic.replace(b'pyout', b'pyerr')
188 topic = dh.topic.replace(b'pyout', b'pyerr')
190
189
191 exc_msg = dh.session.send(dh.pub_socket, u'pyerr', json_clean(exc_content), dh.parent_header, ident=topic)
190 exc_msg = dh.session.send(dh.pub_socket, u'pyerr', json_clean(exc_content), dh.parent_header, ident=topic)
192
191
193 # FIXME - Hack: store exception info in shell object. Right now, the
192 # FIXME - Hack: store exception info in shell object. Right now, the
194 # caller is reading this info after the fact, we need to fix this logic
193 # caller is reading this info after the fact, we need to fix this logic
195 # to remove this hack. Even uglier, we need to store the error status
194 # to remove this hack. Even uglier, we need to store the error status
196 # here, because in the main loop, the logic that sets it is being
195 # here, because in the main loop, the logic that sets it is being
197 # skipped because runlines swallows the exceptions.
196 # skipped because runlines swallows the exceptions.
198 exc_content[u'status'] = u'error'
197 exc_content[u'status'] = u'error'
199 self._reply_content = exc_content
198 self._reply_content = exc_content
200 # /FIXME
199 # /FIXME
201
200
202 return exc_content
201 return exc_content
203
202
204 #------------------------------------------------------------------------
203 #------------------------------------------------------------------------
205 # Magic overrides
204 # Magic overrides
206 #------------------------------------------------------------------------
205 #------------------------------------------------------------------------
207 # Once the base class stops inheriting from magic, this code needs to be
206 # Once the base class stops inheriting from magic, this code needs to be
208 # moved into a separate machinery as well. For now, at least isolate here
207 # moved into a separate machinery as well. For now, at least isolate here
209 # the magics which this class needs to implement differently from the base
208 # the magics which this class needs to implement differently from the base
210 # class, or that are unique to it.
209 # class, or that are unique to it.
211
210
212 def magic_doctest_mode(self,parameter_s=''):
211 def magic_doctest_mode(self,parameter_s=''):
213 """Toggle doctest mode on and off.
212 """Toggle doctest mode on and off.
214
213
215 This mode is intended to make IPython behave as much as possible like a
214 This mode is intended to make IPython behave as much as possible like a
216 plain Python shell, from the perspective of how its prompts, exceptions
215 plain Python shell, from the perspective of how its prompts, exceptions
217 and output look. This makes it easy to copy and paste parts of a
216 and output look. This makes it easy to copy and paste parts of a
218 session into doctests. It does so by:
217 session into doctests. It does so by:
219
218
220 - Changing the prompts to the classic ``>>>`` ones.
219 - Changing the prompts to the classic ``>>>`` ones.
221 - Changing the exception reporting mode to 'Plain'.
220 - Changing the exception reporting mode to 'Plain'.
222 - Disabling pretty-printing of output.
221 - Disabling pretty-printing of output.
223
222
224 Note that IPython also supports the pasting of code snippets that have
223 Note that IPython also supports the pasting of code snippets that have
225 leading '>>>' and '...' prompts in them. This means that you can paste
224 leading '>>>' and '...' prompts in them. This means that you can paste
226 doctests from files or docstrings (even if they have leading
225 doctests from files or docstrings (even if they have leading
227 whitespace), and the code will execute correctly. You can then use
226 whitespace), and the code will execute correctly. You can then use
228 '%history -t' to see the translated history; this will give you the
227 '%history -t' to see the translated history; this will give you the
229 input after removal of all the leading prompts and whitespace, which
228 input after removal of all the leading prompts and whitespace, which
230 can be pasted back into an editor.
229 can be pasted back into an editor.
231
230
232 With these features, you can switch into this mode easily whenever you
231 With these features, you can switch into this mode easily whenever you
233 need to do testing and changes to doctests, without having to leave
232 need to do testing and changes to doctests, without having to leave
234 your existing IPython session.
233 your existing IPython session.
235 """
234 """
236
235
237 from IPython.utils.ipstruct import Struct
236 from IPython.utils.ipstruct import Struct
238
237
239 # Shorthands
238 # Shorthands
240 shell = self.shell
239 shell = self.shell
241 disp_formatter = self.shell.display_formatter
240 disp_formatter = self.shell.display_formatter
242 ptformatter = disp_formatter.formatters['text/plain']
241 ptformatter = disp_formatter.formatters['text/plain']
243 # dstore is a data store kept in the instance metadata bag to track any
242 # dstore is a data store kept in the instance metadata bag to track any
244 # changes we make, so we can undo them later.
243 # changes we make, so we can undo them later.
245 dstore = shell.meta.setdefault('doctest_mode', Struct())
244 dstore = shell.meta.setdefault('doctest_mode', Struct())
246 save_dstore = dstore.setdefault
245 save_dstore = dstore.setdefault
247
246
248 # save a few values we'll need to recover later
247 # save a few values we'll need to recover later
249 mode = save_dstore('mode', False)
248 mode = save_dstore('mode', False)
250 save_dstore('rc_pprint', ptformatter.pprint)
249 save_dstore('rc_pprint', ptformatter.pprint)
251 save_dstore('rc_plain_text_only',disp_formatter.plain_text_only)
250 save_dstore('rc_plain_text_only',disp_formatter.plain_text_only)
252 save_dstore('xmode', shell.InteractiveTB.mode)
251 save_dstore('xmode', shell.InteractiveTB.mode)
253
252
254 if mode == False:
253 if mode == False:
255 # turn on
254 # turn on
256 ptformatter.pprint = False
255 ptformatter.pprint = False
257 disp_formatter.plain_text_only = True
256 disp_formatter.plain_text_only = True
258 shell.magic_xmode('Plain')
257 shell.magic_xmode('Plain')
259 else:
258 else:
260 # turn off
259 # turn off
261 ptformatter.pprint = dstore.rc_pprint
260 ptformatter.pprint = dstore.rc_pprint
262 disp_formatter.plain_text_only = dstore.rc_plain_text_only
261 disp_formatter.plain_text_only = dstore.rc_plain_text_only
263 shell.magic_xmode(dstore.xmode)
262 shell.magic_xmode(dstore.xmode)
264
263
265 # Store new mode and inform on console
264 # Store new mode and inform on console
266 dstore.mode = bool(1-int(mode))
265 dstore.mode = bool(1-int(mode))
267 mode_label = ['OFF','ON'][dstore.mode]
266 mode_label = ['OFF','ON'][dstore.mode]
268 print('Doctest mode is:', mode_label)
267 print('Doctest mode is:', mode_label)
269
268
270 # Send the payload back so that clients can modify their prompt display
269 # Send the payload back so that clients can modify their prompt display
271 payload = dict(
270 payload = dict(
272 source='IPython.zmq.zmqshell.ZMQInteractiveShell.magic_doctest_mode',
271 source='IPython.zmq.zmqshell.ZMQInteractiveShell.magic_doctest_mode',
273 mode=dstore.mode)
272 mode=dstore.mode)
274 self.payload_manager.write_payload(payload)
273 self.payload_manager.write_payload(payload)
275
274
276 @skip_doctest
275 @skip_doctest
277 def magic_edit(self,parameter_s='',last_call=['','']):
276 def magic_edit(self,parameter_s='',last_call=['','']):
278 """Bring up an editor and execute the resulting code.
277 """Bring up an editor and execute the resulting code.
279
278
280 Usage:
279 Usage:
281 %edit [options] [args]
280 %edit [options] [args]
282
281
283 %edit runs an external text editor. You will need to set the command for
282 %edit runs an external text editor. You will need to set the command for
284 this editor via the ``TerminalInteractiveShell.editor`` option in your
283 this editor via the ``TerminalInteractiveShell.editor`` option in your
285 configuration file before it will work.
284 configuration file before it will work.
286
285
287 This command allows you to conveniently edit multi-line code right in
286 This command allows you to conveniently edit multi-line code right in
288 your IPython session.
287 your IPython session.
289
288
290 If called without arguments, %edit opens up an empty editor with a
289 If called without arguments, %edit opens up an empty editor with a
291 temporary file and will execute the contents of this file when you
290 temporary file and will execute the contents of this file when you
292 close it (don't forget to save it!).
291 close it (don't forget to save it!).
293
292
294
293
295 Options:
294 Options:
296
295
297 -n <number>: open the editor at a specified line number. By default,
296 -n <number>: open the editor at a specified line number. By default,
298 the IPython editor hook uses the unix syntax 'editor +N filename', but
297 the IPython editor hook uses the unix syntax 'editor +N filename', but
299 you can configure this by providing your own modified hook if your
298 you can configure this by providing your own modified hook if your
300 favorite editor supports line-number specifications with a different
299 favorite editor supports line-number specifications with a different
301 syntax.
300 syntax.
302
301
303 -p: this will call the editor with the same data as the previous time
302 -p: this will call the editor with the same data as the previous time
304 it was used, regardless of how long ago (in your current session) it
303 it was used, regardless of how long ago (in your current session) it
305 was.
304 was.
306
305
307 -r: use 'raw' input. This option only applies to input taken from the
306 -r: use 'raw' input. This option only applies to input taken from the
308 user's history. By default, the 'processed' history is used, so that
307 user's history. By default, the 'processed' history is used, so that
309 magics are loaded in their transformed version to valid Python. If
308 magics are loaded in their transformed version to valid Python. If
310 this option is given, the raw input as typed as the command line is
309 this option is given, the raw input as typed as the command line is
311 used instead. When you exit the editor, it will be executed by
310 used instead. When you exit the editor, it will be executed by
312 IPython's own processor.
311 IPython's own processor.
313
312
314 -x: do not execute the edited code immediately upon exit. This is
313 -x: do not execute the edited code immediately upon exit. This is
315 mainly useful if you are editing programs which need to be called with
314 mainly useful if you are editing programs which need to be called with
316 command line arguments, which you can then do using %run.
315 command line arguments, which you can then do using %run.
317
316
318
317
319 Arguments:
318 Arguments:
320
319
321 If arguments are given, the following possibilites exist:
320 If arguments are given, the following possibilites exist:
322
321
323 - The arguments are numbers or pairs of colon-separated numbers (like
322 - The arguments are numbers or pairs of colon-separated numbers (like
324 1 4:8 9). These are interpreted as lines of previous input to be
323 1 4:8 9). These are interpreted as lines of previous input to be
325 loaded into the editor. The syntax is the same of the %macro command.
324 loaded into the editor. The syntax is the same of the %macro command.
326
325
327 - If the argument doesn't start with a number, it is evaluated as a
326 - If the argument doesn't start with a number, it is evaluated as a
328 variable and its contents loaded into the editor. You can thus edit
327 variable and its contents loaded into the editor. You can thus edit
329 any string which contains python code (including the result of
328 any string which contains python code (including the result of
330 previous edits).
329 previous edits).
331
330
332 - If the argument is the name of an object (other than a string),
331 - If the argument is the name of an object (other than a string),
333 IPython will try to locate the file where it was defined and open the
332 IPython will try to locate the file where it was defined and open the
334 editor at the point where it is defined. You can use `%edit function`
333 editor at the point where it is defined. You can use `%edit function`
335 to load an editor exactly at the point where 'function' is defined,
334 to load an editor exactly at the point where 'function' is defined,
336 edit it and have the file be executed automatically.
335 edit it and have the file be executed automatically.
337
336
338 If the object is a macro (see %macro for details), this opens up your
337 If the object is a macro (see %macro for details), this opens up your
339 specified editor with a temporary file containing the macro's data.
338 specified editor with a temporary file containing the macro's data.
340 Upon exit, the macro is reloaded with the contents of the file.
339 Upon exit, the macro is reloaded with the contents of the file.
341
340
342 Note: opening at an exact line is only supported under Unix, and some
341 Note: opening at an exact line is only supported under Unix, and some
343 editors (like kedit and gedit up to Gnome 2.8) do not understand the
342 editors (like kedit and gedit up to Gnome 2.8) do not understand the
344 '+NUMBER' parameter necessary for this feature. Good editors like
343 '+NUMBER' parameter necessary for this feature. Good editors like
345 (X)Emacs, vi, jed, pico and joe all do.
344 (X)Emacs, vi, jed, pico and joe all do.
346
345
347 - If the argument is not found as a variable, IPython will look for a
346 - If the argument is not found as a variable, IPython will look for a
348 file with that name (adding .py if necessary) and load it into the
347 file with that name (adding .py if necessary) and load it into the
349 editor. It will execute its contents with execfile() when you exit,
348 editor. It will execute its contents with execfile() when you exit,
350 loading any code in the file into your interactive namespace.
349 loading any code in the file into your interactive namespace.
351
350
352 After executing your code, %edit will return as output the code you
351 After executing your code, %edit will return as output the code you
353 typed in the editor (except when it was an existing file). This way
352 typed in the editor (except when it was an existing file). This way
354 you can reload the code in further invocations of %edit as a variable,
353 you can reload the code in further invocations of %edit as a variable,
355 via _<NUMBER> or Out[<NUMBER>], where <NUMBER> is the prompt number of
354 via _<NUMBER> or Out[<NUMBER>], where <NUMBER> is the prompt number of
356 the output.
355 the output.
357
356
358 Note that %edit is also available through the alias %ed.
357 Note that %edit is also available through the alias %ed.
359
358
360 This is an example of creating a simple function inside the editor and
359 This is an example of creating a simple function inside the editor and
361 then modifying it. First, start up the editor:
360 then modifying it. First, start up the editor:
362
361
363 In [1]: ed
362 In [1]: ed
364 Editing... done. Executing edited code...
363 Editing... done. Executing edited code...
365 Out[1]: 'def foo():n print "foo() was defined in an editing session"n'
364 Out[1]: 'def foo():n print "foo() was defined in an editing session"n'
366
365
367 We can then call the function foo():
366 We can then call the function foo():
368
367
369 In [2]: foo()
368 In [2]: foo()
370 foo() was defined in an editing session
369 foo() was defined in an editing session
371
370
372 Now we edit foo. IPython automatically loads the editor with the
371 Now we edit foo. IPython automatically loads the editor with the
373 (temporary) file where foo() was previously defined:
372 (temporary) file where foo() was previously defined:
374
373
375 In [3]: ed foo
374 In [3]: ed foo
376 Editing... done. Executing edited code...
375 Editing... done. Executing edited code...
377
376
378 And if we call foo() again we get the modified version:
377 And if we call foo() again we get the modified version:
379
378
380 In [4]: foo()
379 In [4]: foo()
381 foo() has now been changed!
380 foo() has now been changed!
382
381
383 Here is an example of how to edit a code snippet successive
382 Here is an example of how to edit a code snippet successive
384 times. First we call the editor:
383 times. First we call the editor:
385
384
386 In [5]: ed
385 In [5]: ed
387 Editing... done. Executing edited code...
386 Editing... done. Executing edited code...
388 hello
387 hello
389 Out[5]: "print 'hello'n"
388 Out[5]: "print 'hello'n"
390
389
391 Now we call it again with the previous output (stored in _):
390 Now we call it again with the previous output (stored in _):
392
391
393 In [6]: ed _
392 In [6]: ed _
394 Editing... done. Executing edited code...
393 Editing... done. Executing edited code...
395 hello world
394 hello world
396 Out[6]: "print 'hello world'n"
395 Out[6]: "print 'hello world'n"
397
396
398 Now we call it with the output #8 (stored in _8, also as Out[8]):
397 Now we call it with the output #8 (stored in _8, also as Out[8]):
399
398
400 In [7]: ed _8
399 In [7]: ed _8
401 Editing... done. Executing edited code...
400 Editing... done. Executing edited code...
402 hello again
401 hello again
403 Out[7]: "print 'hello again'n"
402 Out[7]: "print 'hello again'n"
404 """
403 """
405
404
406 opts,args = self.parse_options(parameter_s,'prn:')
405 opts,args = self.parse_options(parameter_s,'prn:')
407
406
408 try:
407 try:
409 filename, lineno, _ = self._find_edit_target(args, opts, last_call)
408 filename, lineno, _ = self._find_edit_target(args, opts, last_call)
410 except MacroToEdit as e:
409 except MacroToEdit as e:
411 # TODO: Implement macro editing over 2 processes.
410 # TODO: Implement macro editing over 2 processes.
412 print("Macro editing not yet implemented in 2-process model.")
411 print("Macro editing not yet implemented in 2-process model.")
413 return
412 return
414
413
415 # Make sure we send to the client an absolute path, in case the working
414 # Make sure we send to the client an absolute path, in case the working
416 # directory of client and kernel don't match
415 # directory of client and kernel don't match
417 filename = os.path.abspath(filename)
416 filename = os.path.abspath(filename)
418
417
419 payload = {
418 payload = {
420 'source' : 'IPython.zmq.zmqshell.ZMQInteractiveShell.edit_magic',
419 'source' : 'IPython.zmq.zmqshell.ZMQInteractiveShell.edit_magic',
421 'filename' : filename,
420 'filename' : filename,
422 'line_number' : lineno
421 'line_number' : lineno
423 }
422 }
424 self.payload_manager.write_payload(payload)
423 self.payload_manager.write_payload(payload)
425
424
426 # A few magics that are adapted to the specifics of using pexpect and a
425 # A few magics that are adapted to the specifics of using pexpect and a
427 # remote terminal
426 # remote terminal
428
427
429 def magic_clear(self, arg_s):
428 def magic_clear(self, arg_s):
430 """Clear the terminal."""
429 """Clear the terminal."""
431 if os.name == 'posix':
430 if os.name == 'posix':
432 self.shell.system("clear")
431 self.shell.system("clear")
433 else:
432 else:
434 self.shell.system("cls")
433 self.shell.system("cls")
435
434
436 if os.name == 'nt':
435 if os.name == 'nt':
437 # This is the usual name in windows
436 # This is the usual name in windows
438 magic_cls = magic_clear
437 magic_cls = magic_clear
439
438
440 # Terminal pagers won't work over pexpect, but we do have our own pager
439 # Terminal pagers won't work over pexpect, but we do have our own pager
441
440
442 def magic_less(self, arg_s):
441 def magic_less(self, arg_s):
443 """Show a file through the pager.
442 """Show a file through the pager.
444
443
445 Files ending in .py are syntax-highlighted."""
444 Files ending in .py are syntax-highlighted."""
446 cont = open(arg_s).read()
445 cont = open(arg_s).read()
447 if arg_s.endswith('.py'):
446 if arg_s.endswith('.py'):
448 cont = self.shell.pycolorize(cont)
447 cont = self.shell.pycolorize(cont)
449 page.page(cont)
448 page.page(cont)
450
449
451 magic_more = magic_less
450 magic_more = magic_less
452
451
453 # Man calls a pager, so we also need to redefine it
452 # Man calls a pager, so we also need to redefine it
454 if os.name == 'posix':
453 if os.name == 'posix':
455 def magic_man(self, arg_s):
454 def magic_man(self, arg_s):
456 """Find the man page for the given command and display in pager."""
455 """Find the man page for the given command and display in pager."""
457 page.page(self.shell.getoutput('man %s | col -b' % arg_s,
456 page.page(self.shell.getoutput('man %s | col -b' % arg_s,
458 split=False))
457 split=False))
459
458
460 # FIXME: this is specific to the GUI, so we should let the gui app load
459 # FIXME: this is specific to the GUI, so we should let the gui app load
461 # magics at startup that are only for the gui. Once the gui app has proper
460 # magics at startup that are only for the gui. Once the gui app has proper
462 # profile and configuration management, we can have it initialize a kernel
461 # profile and configuration management, we can have it initialize a kernel
463 # with a special config file that provides these.
462 # with a special config file that provides these.
464 def magic_guiref(self, arg_s):
463 def magic_guiref(self, arg_s):
465 """Show a basic reference about the GUI console."""
464 """Show a basic reference about the GUI console."""
466 from IPython.core.usage import gui_reference
465 from IPython.core.usage import gui_reference
467 page.page(gui_reference, auto_html=True)
466 page.page(gui_reference, auto_html=True)
468
467
469 def magic_connect_info(self, arg_s):
468 def magic_connect_info(self, arg_s):
470 """Print information for connecting other clients to this kernel
469 """Print information for connecting other clients to this kernel
471
470
472 It will print the contents of this session's connection file, as well as
471 It will print the contents of this session's connection file, as well as
473 shortcuts for local clients.
472 shortcuts for local clients.
474
473
475 In the simplest case, when called from the most recently launched kernel,
474 In the simplest case, when called from the most recently launched kernel,
476 secondary clients can be connected, simply with:
475 secondary clients can be connected, simply with:
477
476
478 $> ipython <app> --existing
477 $> ipython <app> --existing
479
478
480 """
479 """
481
480
482 from IPython.core.application import BaseIPythonApplication as BaseIPApp
481 from IPython.core.application import BaseIPythonApplication as BaseIPApp
483
482
484 if BaseIPApp.initialized():
483 if BaseIPApp.initialized():
485 app = BaseIPApp.instance()
484 app = BaseIPApp.instance()
486 security_dir = app.profile_dir.security_dir
485 security_dir = app.profile_dir.security_dir
487 profile = app.profile
486 profile = app.profile
488 else:
487 else:
489 profile = 'default'
488 profile = 'default'
490 security_dir = ''
489 security_dir = ''
491
490
492 try:
491 try:
493 connection_file = get_connection_file()
492 connection_file = get_connection_file()
494 info = get_connection_info(unpack=False)
493 info = get_connection_info(unpack=False)
495 except Exception as e:
494 except Exception as e:
496 error("Could not get connection info: %r" % e)
495 error("Could not get connection info: %r" % e)
497 return
496 return
498
497
499 # add profile flag for non-default profile
498 # add profile flag for non-default profile
500 profile_flag = "--profile %s" % profile if profile != 'default' else ""
499 profile_flag = "--profile %s" % profile if profile != 'default' else ""
501
500
502 # if it's in the security dir, truncate to basename
501 # if it's in the security dir, truncate to basename
503 if security_dir == os.path.dirname(connection_file):
502 if security_dir == os.path.dirname(connection_file):
504 connection_file = os.path.basename(connection_file)
503 connection_file = os.path.basename(connection_file)
505
504
506
505
507 print (info + '\n')
506 print (info + '\n')
508 print ("Paste the above JSON into a file, and connect with:\n"
507 print ("Paste the above JSON into a file, and connect with:\n"
509 " $> ipython <app> --existing <file>\n"
508 " $> ipython <app> --existing <file>\n"
510 "or, if you are local, you can connect with just:\n"
509 "or, if you are local, you can connect with just:\n"
511 " $> ipython <app> --existing {0} {1}\n"
510 " $> ipython <app> --existing {0} {1}\n"
512 "or even just:\n"
511 "or even just:\n"
513 " $> ipython <app> --existing {1}\n"
512 " $> ipython <app> --existing {1}\n"
514 "if this is the most recent IPython session you have started.".format(
513 "if this is the most recent IPython session you have started.".format(
515 connection_file, profile_flag
514 connection_file, profile_flag
516 )
515 )
517 )
516 )
518
517
519 def magic_qtconsole(self, arg_s):
518 def magic_qtconsole(self, arg_s):
520 """Open a qtconsole connected to this kernel.
519 """Open a qtconsole connected to this kernel.
521
520
522 Useful for connecting a qtconsole to running notebooks, for better
521 Useful for connecting a qtconsole to running notebooks, for better
523 debugging.
522 debugging.
524 """
523 """
525 try:
524 try:
526 p = connect_qtconsole(argv=arg_split(arg_s, os.name=='posix'))
525 p = connect_qtconsole(argv=arg_split(arg_s, os.name=='posix'))
527 except Exception as e:
526 except Exception as e:
528 error("Could not start qtconsole: %r" % e)
527 error("Could not start qtconsole: %r" % e)
529 return
528 return
530
529
531 def set_next_input(self, text):
530 def set_next_input(self, text):
532 """Send the specified text to the frontend to be presented at the next
531 """Send the specified text to the frontend to be presented at the next
533 input cell."""
532 input cell."""
534 payload = dict(
533 payload = dict(
535 source='IPython.zmq.zmqshell.ZMQInteractiveShell.set_next_input',
534 source='IPython.zmq.zmqshell.ZMQInteractiveShell.set_next_input',
536 text=text
535 text=text
537 )
536 )
538 self.payload_manager.write_payload(payload)
537 self.payload_manager.write_payload(payload)
539
538
540
539
541 InteractiveShellABC.register(ZMQInteractiveShell)
540 InteractiveShellABC.register(ZMQInteractiveShell)
General Comments 0
You need to be logged in to leave comments. Login now